@演算子とは
行列の乗算のための中置演算子(値と値の間置く演算子)。
何が嬉しいかと言うと、今まではmatmulとか、dot関数で記述していたものが式の見た目のとおりに打てること。
PEP465から抜粋すると、
こんな式を今までは
S = np.dot((np.dot(H, beta) - r).T,np.dot(np.linalg.inv(np.dot(np.dot(H, V), H.T)), np.dot(H, beta) - r))
こうだったのが、
S = (H @ beta - r).T @ np.linalg.inv(H @ V @ H.T) @ (H @ beta - r)
こうなる。
実際にやってみる
ベクトル同士の場合
>>> a array([[1, 2, 3]]) >>> b array([[1], [2], [3]]) >>> a @ b array([[14]]) >>> b @ a array([[1, 2, 3], [2, 4, 6], [3, 6, 9]])
行列の場合
>>> SS array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) >>> SS @ SS array([[ 30, 36, 42], [ 66, 81, 96], [102, 126, 150]])
一応時間も図ってみた
In [5]: import numpy as np In [6]: X = np.random.rand(1000, 1000) In [7]: Y = np.random.rand(1000, 1000) In [8]: np.dot(X,Y) Out[8]: array([[253.53511137, 256.8615953 , 246.46819357, ..., 243.49153546, 244.02637281, 246.62408715], [250.61435394, 249.05804577, 247.37355866, ..., 247.52512226, 250.95392689, 243.85349119], [253.65065532, 250.48256653, 246.86987208, ..., 243.97691732, 252.23674308, 245.52656707], ..., [256.99955016, 256.68289898, 248.29087992, ..., 249.41390784, 247.45459195, 251.30253342], [245.52760553, 238.21189944, 240.93692084, ..., 243.90156923, 239.60112492, 240.96903498], [257.19063359, 249.52967264, 246.68525264, ..., 249.57146663, 245.5789229 , 248.81562363]]) In [9]: %timeit np.dot(X,Y) 31.6 ms ± 1.65 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) In [10]: %timeit X @ Y 31.6 ms ± 1.37 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
そのへんは変わらんですね。
やってみた結果
Numpyで行列演算するならこれでやることにした。