効率的な NumPy 配列乗算演算

NumPyBeginner
オンラインで実践に進む

はじめに

NumPy は、Python における科学的計算のための強力なライブラリです。NumPy の最も重要な機能の 1 つは、効率的にさまざまな種類の配列乗算を行う能力です。

このチュートリアルでは、NumPy で利用可能なさまざまな乗算演算を調べます。これには、numpy.multiplynumpy.dotnumpy.matmul*、および@演算子が含まれます。

これは Guided Lab です。学習と実践を支援するためのステップバイステップの指示を提供します。各ステップを完了し、実践的な経験を積むために、指示に注意深く従ってください。過去のデータによると、この 初級 レベルの実験の完了率は 97%です。学習者から 100% の好評価を得ています。

はじめに

NumPy のさまざまな乗算演算に入る前に、まずターミナルに次のコマンドを入力して Python シェルを開きましょう。

python3

そして、ライブラリをインポートして、デモ用に使用できるサンプル配列を作成します。

import numpy as np

## サンプル配列の作成
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])

2 行 2 列の 2 つの配列ABを作成しました。では、NumPy で利用可能なさまざまな乗算演算を調べてみましょう。

numpy.multiply

numpy.multiply関数は、2 つの配列間の要素ごとの乗算を行います。2 つの配列は同じ形状でなければなりません。結果の配列は入力配列と同じ形状になります。

C = np.multiply(A, B)

print(C)
## 出力:
## array([[ 5, 12],
##       [21, 32]])

この例では、Aの各要素がBの対応する要素と乗算され、2 つの配列の要素ごとの乗算が行われます。

numpy.dot

numpy.dot関数は、2 つの配列間の行列乗算を行います。最初の配列の列数は、2 番目の配列の行数と同じでなければなりません。結果の配列は、最初の配列と同じ行数を持ち、2 番目の配列と同じ列数を持ちます。

C = np.dot(A, B)

print(C)
## 出力:
## array([[19, 22],
##        [43, 50]])

この例では、配列ABの間で行列乗算を行いました。結果の配列Cは、予想通り 2 行 2 列です。

numpy.matmul

numpy.matmul関数も 2 つの配列間の行列乗算を行いますが、多次元配列を扱う際のルールが若干異なります。2 つの配列は、最後の 2 次元を除いて同じ形状でなければなりません。これらの最後の 2 次元は整合しなければなりません。どちらかの配列が 1 次元の場合、その形状に 1 を追加することで行列に昇格されます。

C = np.matmul(A, B)

print(C)
## 出力:
## array([[19, 22],
##        [43, 50]])

この例では、numpy.dotと同じ結果が得られます。これは、配列ABが同じ形状であるため、numpy.matmulnumpy.dotと同じように動作するからです。

そして、もう 1 つの異なる例があります。

## 2 つの 3 次元配列を定義する
a = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
b = np.array([[[9, 10], [11, 12]], [[13, 14], [15, 16]]])

c = np.matmul(a, b)
d = np.dot(a, b)

print(c)
## 出力:
## array([[[ 31,  34],
##        [ 71,  78]],
##        [[155, 166],
##        [211, 226]]])

print(d)
## 出力:
## array([[[[ 31,  34],
##         [ 43,  46]],
##        [[ 71,  78],
##         [ 99, 106]]],
##       [[[111, 122],
##         [155, 166]],
##        [[151, 166],
##         [211, 226]]]])

この例では、numpy.matmulがバッチ行列乗算演算を行っています。

abの両方が 3 次元配列であるため、numpy.dotの出力は次元数(2,2,2,2)になります。最初の 2 次元は、ab2\times2行列の 2 つのバッチに対応します。次の 2 次元は、バッチ内の各2\times2行列のペアのドット積に対応します。

## 最初の 2 × 2 の結果
dot(a[0], b[0]) =
dot([[1, 2],
 [3, 4]],
 [[9, 10],
 [11, 12]]
= [[1*9 + 2*11, 1*10 + 2*12],
   [3*9 + 4*11, 3*10 + 4*12]]
= [[31, 34],
   [43, 46]]

*演算子

*演算子も 2 つの配列間の要素ごとの乗算を行いますが、numpy.multiplyとはやや異なる動作をします。2 つの配列が同じ形状の場合、*演算子はnumpy.multiplyと同じように要素ごとの乗算を行います。ただし、もし一方の配列がスカラー値である場合、*演算子はもう一方の配列のすべての要素に対してスカラー乗算を行います。

C = A * B
D = A * 2

print(C)
## 出力:
#array([[ 5, 12],
##       [21, 32]])

print(D)
## 出力:
## array([[2, 4],
##       [6, 8]])

最初の例では、numpy.multiplyと同じ結果が得られます。2 番目の例では、配列Aのすべての要素に対してスカラー乗算を行っています。

@演算子

@演算子は、numpy.dotnumpy.matmulと同じように行列乗算を行います。Python 3.5 で導入され、numpy.matmulの省略形として使われます。

C = A @ B

print(C)
## 出力:
## array([[19, 22],
##       [43, 50]])

この例では、@演算子を使って配列ABの間で行列乗算を行っています。結果の配列Cは、numpy.dotnumpy.matmulと同じように 2 行 2 列です。

まとめ

このチュートリアルでは、NumPy で利用可能なさまざまな乗算演算を調べました。これらの演算はそれぞれ独自のルールと使用例を持っているため、特定のタスクに適したものを選ぶことが重要です。これらの演算をマスターすることで、Python で NumPy を使って効率的に配列と行列の乗算を行うことができます。