Могу я просто добавить; люди всегда предполагают, что это компьютерная проблема, но если вы считаете своими руками (база 10), вы не можете получить (1/3+1/3=2/3)=true
, если у вас нет бесконечности, чтобы добавить 0.333 ... в 0.333 ... так, как и с (1/10+2/10)!==3/10
в базе 2, вы обрезаете ее до 0,333 + 0,333 = 0,666 и, вероятно, округлите ее до 0,677, что также будет технически неточным.
Подсчитайте в тройном, а третья не проблема, может быть, какая-то гонка с 15 пальцами на каждой руке спросит, почему ваша десятичная математика была сломана ...
То, что dot-product
существенно выполняет редукцию вдоль axis=1
двух входных массивов. Размеры могут быть представлены так:
arr_in : n 3
matrices : n 3 3
. Таким образом, одним из способов его решения было бы «нажимать» размеры arr_in
вперед на один axis/dimension
, создавая таким образом одноэлементное измерение в axis=2
в версии 3D-массива. Тогда сумма, уменьшающая элементы вдоль axis = 1
, даст нам желаемый результат. Покажем это -
arr_in : n [3] 1
matrices : n [3] 3
Теперь это может быть достигнуто двумя способами.
1) С помощью np.einsum
-
np.einsum('ij,ijk->ik',arr_in,matrices)
2) С помощью NumPy broadcasting
-
(arr_in[...,None]*matrices).sum(1)
Проверка времени выполнения и проверка вывода (для версии einsum
) -
In [329]: def loop_based(arr_in,matrices):
...: arr_out = np.zeros((arr_in.shape[0], 3))
...: for i in range(arr_in.shape[0]):
...: arr_out[i] = np.dot(arr_in[i], matrices[i])
...: return arr_out
...:
...: def einsum_based(arr_in,matrices):
...: return np.einsum('ij,ijk->ik',arr_in,matrices)
...:
In [330]: # Inputs
...: N = 16935
...: arr_in = np.random.randn(N, 3)
...: matrices = np.random.randn(N, 3, 3)
...:
In [331]: np.allclose(einsum_based(arr_in,matrices),loop_based(arr_in,matrices))
Out[331]: True
In [332]: %timeit loop_based(arr_in,matrices)
10 loops, best of 3: 49.1 ms per loop
In [333]: %timeit einsum_based(arr_in,matrices)
1000 loops, best of 3: 714 µs per loop
Вы можете использовать np.einsum
. Чтобы получить v.dot(M)
для каждой пары вектор-матрица, используйте np.einsum("...i,...ij", arr_in, matrices)
. Чтобы получить M.dot(v)
, используйте np.einsum("...ij,...i", matrices, arr_in)