らんだむな記憶

blogというものを体験してみようか!的なー

einsum (2)

>>> a = np.arange(1,5).reshape(2,2)
>>> a
array([[1, 2],
       [3, 4]])
>>> b = np.arange(-5,-1).reshape(2,2)
>>> b
array([[-5, -4],
       [-3, -2]])

を使ったすこぶる分かりにくい挙動を見てみよう。

>>> np.einsum('ij,ij->ij', a, b)
array([[-5, -8],
       [-9, -8]])
>>> np.einsum('ij,ij->ji', a, b)
array([[-5, -9],
       [-8, -8]])

を考えてみたい。最初の例はいわゆるアダマール積であり、次の例はその転置行列である。
最初の例は数式で書くと

\begin{align*}
(c_{ij}) = (a_{ij} b_{ij}) = \begin{pmatrix} 1 \times (-5) & 2 \times (-4) \\ 3 \times (-3) & 4 \times (-2) \end{pmatrix} = \begin{pmatrix} -5 & -8 \\ -9 & -8 \end{pmatrix}
\end{align*}

であり、次の例は添字を逆にして、${c_{ij}^\prime} = (c_{ji})$ を考えたものである。

どちらの例でも和はとらないので、これもまた分かりにくい部分がある。「アインシュタインの規約」という響きに惑わされずに、そういう API なのだと理解するしかないだろう。