PythonのNumPyで、*
と np.dot()
(または @
)を使ったときに「同じ掛け算のように見えるのに、結果が全然違う」ことに混乱したので、学習の記録として整理しておきます。
✅ 要素ごとの積(element-wise multiplication)
*
は「同じ位置の要素をそのまま掛ける」演算です。配列の形が同じか、ブロードキャストで整えられる必要があります。
import numpy as np
A = np.array([[1, 2],
[3, 4]])
B = np.array([[10, 20],
[30, 40]])
print(A * B)
[[ 10 40]
[ 90 160]]
このように、それぞれの位置の値をそのまま掛けた結果になります。
✅ ドット積(内積・行列積)
np.dot()
や @
は、行と列を掛けて足し合わせる「内積(ドット積)」を行います。数学の線形代数で使われるものです。
import numpy as np
A = np.array([[1, 2],
[3, 4]])
B = np.array([[10],
[20]])
print(np.dot(A, B)) # または A @ B
[[ 50]
[110]]
計算内容:
- 1×10 + 2×20 = 50
- 3×10 + 4×20 = 110
配列の形(shape)に注意が必要で、Aの列数とBの行数が一致している必要があります。
✅ 1次元配列での「*」と np.dot() の違い
NumPyでは np.array([1, 2, 3])
のような 1次元配列 を「ベクトルのようなもの」として扱うことがあります。このとき *
と np.dot()
の結果が全然違うことに注意が必要です。
import numpy as np
A = np.array([1, 2, 3])
B = np.array([4, 5, 6])
print(A * B) # 要素ごとの積
print(np.dot(A, B)) # ドット積
[ 4 10 18]
32
-
A * B
は位置ごとに掛けただけ([1×4, 2×5, 3×6]) -
np.dot(A, B)
は掛けてから合計(1×4 + 2×5 + 3×6 = 32)
このように、1次元配列でも演算の意味が全く異なるので注意が必要です。
✅ 用語補足:「ベクトル」って何?
数学では「ベクトル」とは向きと大きさを持った矢印のようなものを意味します。
NumPyでよく使う np.array([1, 2, 3])
は、そうしたベクトルのような配列を1次元で表したものです。
ただし、数学でいう「行ベクトル」や「列ベクトル」は2次元配列(shapeが (1, 3)
や (3, 1)
)で表されるので、厳密には区別があります。
NumPyでは簡単のために shape = (3,)
の1次元配列も「ベクトル」と呼ぶことがあります。
✅ まとめ
種類 | 記号 | 内容 | 結果の形 |
---|---|---|---|
要素ごとの積 | * |
同じ位置の要素をそのまま掛ける | 配列そのもの |
ドット積(内積) |
np.dot() / @
|
掛けて足す | スカラーまたは行列 |
ドット積と要素ごとの積は似た見た目ですが、まったく違う動作をします。特に1次元配列(ベクトルっぽい形)では混乱しやすいので、自分で実行しながら理解するのがよさそうです。
間違いや補足があればコメントいただけると嬉しいです。