EnsekiTT Blog

EnsekiTTが書くブログです。

Python(Numpy)の@(アット)演算子を使って見る話

つまりなにしたの?

Python3.5以降ではNumpyのmatmulに相当する@演算子が使えるようになったみたいなので使ってみた。

f:id:ensekitt:20180908173406j:plain

@演算子とは

行列の乗算のための中置演算子(値と値の間置く演算子)。
何が嬉しいかと言うと、今まではmatmulとか、dot関数で記述していたものが式の見た目のとおりに打てること。

PEP465から抜粋すると、
 S = (H \beta - r)^T (HVH^T)^{-1}  (H  \beta - r)

こんな式を今までは

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で行列演算するならこれでやることにした。

クリエイティブ・コモンズ・ライセンス
この 作品 は クリエイティブ・コモンズ 表示 4.0 国際 ライセンスの下に提供されています。