numpy.dot の挙動で直感通りの動きとならない場合がありました。よくよく調べると、与える配列の次元数ごとに異なる挙動をする仕様になっていたので、ケースごとにどうなるか調べてみました。
なお、公式ドキュメントにケースごとにどのような挙動になるか書かれています。
https://docs.scipy.org/doc/numpy/reference/generated/numpy.dot.html
以下は、実際に例を出しての説明になります。
A, B が 1 次元配列の場合は、内積になる
A、B として次の例を考えます。
A = (1, 2, 3)
B = (2, 4, 6)
この場合、次の式の計算を行います。
A_{1} B_{1} + A_{2} B_{2} + A_{3} B_{3}
よって、A、B の要素数が異なるとエラーになります。
コードの例は次の通りです。
>>> A = np.array([1, 2, 3])
>>> B = np.array([2, 4, 6])
>>> np.dot(A, B)
28
A, B が 2 次元配列の場合は、行列積になる
A、B として次の例を考えます。
A =
\left(
\begin{matrix}
1 & 1 \\
2 & 2 \\
3 & 3
\end{matrix}
\right)
B =
\left(
\begin{matrix}
1 & 2 \\
3 & 4
\end{matrix}
\right)
この場合、次の式の計算を行います。
\left(
\begin{matrix}
A_{11} B_{11} + A_{12} B_{21} & A_{11} B_{12} + A_{12} B_{22} \\
A_{21} B_{11} + A_{22} B_{21} & A_{21} B_{12} + A_{22} B_{22} \\
A_{31} B_{11} + A_{32} B_{21} & A_{31} B_{12} + A_{32} B_{22}
\end{matrix}
\right)
よって、A の列数、B の行数が一致している必要があります。
コードの例は次の通りです。
>>> A = np.array([[1,1], [2,2], [3,3]])
>>> B = np.array([[1, 2], [3, 4]])
>>> np.dot(A, B)
array([[ 4, 6],
[ 8, 12],
[12, 18]])
# 次の表記でも同じことができます。
>>> A @ B
array([[ 4, 6],
[ 8, 12],
[12, 18]])
A, B のどちらかがスカラの場合は、掛け算となる
A、B として次の例を考えます。
A =
\left(
\begin{matrix}
1 & 1 \\
2 & 2 \\
3 & 3
\end{matrix}
\right)
B = 5
この場合、次の式の計算を行います。
\left(
\begin{matrix}
A_{11} B & A_{12} B \\
A_{21} B & A_{22} B \\
A_{31} B & A_{32} B
\end{matrix}
\right)
コードの例は次の通りです。
>>> A = np.array([[1,1], [2,2], [3,3]])
>>> np.dot(A, 5)
array([[ 5, 5],
[10, 10],
[15, 15]])
# 次の表記でも同じことができます。
>>> A * 5
array([[ 5, 5],
[10, 10],
[15, 15]])
A が 2 次元配列、B が 1 次元配列の場合
A、B として次の例を考えます。
A =
\left(
\begin{matrix}
1 & 1 \\
2 & 2 \\
3 & 3
\end{matrix}
\right)
B =
\left(
\begin{matrix}
7 & 8
\end{matrix}
\right)
この場合、次の式の計算を行います。
\left(
\begin{matrix}
A_{11} B_{1} + A_{12} B_{2} & A_{21} B_{1} + A_{22} B_{2} & A_{31} B_{1} + A_{32} B_{2}
\end{matrix}
\right)
よって、A の列数、B の要素数が一致している必要があります。
コードの例は次の通りです。
>>> A = np.array([[1,1], [2,2], [3,3]])
>>> B = np.array([7, 8])
>>> np.dot(A, B)
array([15, 30, 45])