Вот один из тех же методов, что и для @Bi Rico's post
, но с einsum
для вычислений norm
-
den = np.sqrt(np.einsum('ij,ij->i',arr,arr)*np.einsum('j,j',vec,vec))
out = arr.dot(vec) / den
Кроме того, мы можем использовать vec.dot(vec)
вместо np.einsum('j,j',vec,vec)
для некоторого незначительного улучшения.
Сроки -
In [45]: vec = np.random.randn(300,)
...: arr = np.random.randn(400, 300)
# @Bi Rico's soln with norm
In [46]: %timeit (np.linalg.norm(arr, axis=1) * np.linalg.norm(vec))
10000 loops, best of 3: 100 µs per loop
In [47]: %timeit np.sqrt(np.einsum('ij,ij->i',arr,arr)*np.einsum('j,j',vec,vec))
10000 loops, best of 3: 77.4 µs per loop
На больших массивах -
In [48]: vec = np.random.randn(3000,)
...: arr = np.random.randn(4000, 3000)
In [49]: %timeit (np.linalg.norm(arr, axis=1) * np.linalg.norm(vec))
10 loops, best of 3: 22.2 ms per loop
In [50]: %timeit np.sqrt(np.einsum('ij,ij->i',arr,arr)*np.einsum('j,j',vec,vec))
100 loops, best of 3: 8.18 ms per loop