はじめに
NumPy は、Python における科学的計算のための強力なライブラリです。NumPy の最も重要な機能の 1 つは、効率的にさまざまな種類の配列乗算を行う能力です。
このチュートリアルでは、NumPy で利用可能なさまざまな乗算演算を調べます。これには、numpy.multiply、numpy.dot、numpy.matmul、*、および@演算子が含まれます。
NumPy は、Python における科学的計算のための強力なライブラリです。NumPy の最も重要な機能の 1 つは、効率的にさまざまな種類の配列乗算を行う能力です。
このチュートリアルでは、NumPy で利用可能なさまざまな乗算演算を調べます。これには、numpy.multiply、numpy.dot、numpy.matmul、*、および@演算子が含まれます。
NumPy のさまざまな乗算演算に入る前に、まずターミナルに次のコマンドを入力して Python シェルを開きましょう。
python3
そして、ライブラリをインポートして、デモ用に使用できるサンプル配列を作成します。
import numpy as np
## サンプル配列の作成
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
2 行 2 列の 2 つの配列AとBを作成しました。では、NumPy で利用可能なさまざまな乗算演算を調べてみましょう。
numpy.multiply関数は、2 つの配列間の要素ごとの乗算を行います。2 つの配列は同じ形状でなければなりません。結果の配列は入力配列と同じ形状になります。
C = np.multiply(A, B)
print(C)
## 出力:
## array([[ 5, 12],
## [21, 32]])
この例では、Aの各要素がBの対応する要素と乗算され、2 つの配列の要素ごとの乗算が行われます。
numpy.dot関数は、2 つの配列間の行列乗算を行います。最初の配列の列数は、2 番目の配列の行数と同じでなければなりません。結果の配列は、最初の配列と同じ行数を持ち、2 番目の配列と同じ列数を持ちます。
C = np.dot(A, B)
print(C)
## 出力:
## array([[19, 22],
## [43, 50]])
この例では、配列AとBの間で行列乗算を行いました。結果の配列Cは、予想通り 2 行 2 列です。
numpy.matmul関数も 2 つの配列間の行列乗算を行いますが、多次元配列を扱う際のルールが若干異なります。2 つの配列は、最後の 2 次元を除いて同じ形状でなければなりません。これらの最後の 2 次元は整合しなければなりません。どちらかの配列が 1 次元の場合、その形状に 1 を追加することで行列に昇格されます。
C = np.matmul(A, B)
print(C)
## 出力:
## array([[19, 22],
## [43, 50]])
この例では、numpy.dotと同じ結果が得られます。これは、配列AとBが同じ形状であるため、numpy.matmulがnumpy.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がバッチ行列乗算演算を行っています。
aとbの両方が 3 次元配列であるため、numpy.dotの出力は次元数(2,2,2,2)になります。最初の 2 次元は、aとbの2\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.dotやnumpy.matmulと同じように行列乗算を行います。Python 3.5 で導入され、numpy.matmulの省略形として使われます。
C = A @ B
print(C)
## 出力:
## array([[19, 22],
## [43, 50]])
この例では、@演算子を使って配列AとBの間で行列乗算を行っています。結果の配列Cは、numpy.dotやnumpy.matmulと同じように 2 行 2 列です。
このチュートリアルでは、NumPy で利用可能なさまざまな乗算演算を調べました。これらの演算はそれぞれ独自のルールと使用例を持っているため、特定のタスクに適したものを選ぶことが重要です。これらの演算をマスターすることで、Python で NumPy を使って効率的に配列と行列の乗算を行うことができます。