Разница между numpy dot() и Python 3.5 + матричное умножение @
Я недавно перешел на Python 3.5 и заметил новый оператор умножения матрицы (@) иногда ведет себя иначе, чем numpy dot оператора. Например, для 3d массивов:
import numpy as np
a = np.random.rand(8,13,13)
b = np.random.rand(8,13,13)
c = a @ b # Python 3.5+
d = np.dot(a, b)
The @
оператор возвращает массив форма:
c.shape
(8, 13, 13)
С np.dot()
функция возвращает:
d.shape
(8, 13, 8, 13)
как я могу воспроизвести тот же результат с numpy dot? Есть ли другие существенные отличия?
3 ответа:
The
@
оператор вызывает массив__matmul__
метод, а неdot
. Этот метод также присутствует в API как функцияnp.matmul
.>>> a = np.random.rand(8,13,13) >>> b = np.random.rand(8,13,13) >>> np.matmul(a, b).shape (8, 13, 13)
из документации:
matmul
отличается отdot
двумя важными способами.
- умножение на скаляры не допускается.
- стеки матриц транслируются вместе, как если бы матрицы были элементами.
последний пункт дает понять, что
dot
иmatmul
методы ведут себя по-разному при передаче трехмерных (или многомерных) массивов. Цитируя из документации еще несколько:на
matmul
:если любой из аргументов N-D, N > 2, он обрабатывается как стек матриц, находящихся в последних двух индексах, и транслируется соответственно.
на
np.dot
:Для 2-D массивы эквивалентны умножению матрицы, а для 1-D массивов-внутреннему произведению векторов (без комплексного сопряжения). для n измерений это произведение суммы по последней оси a и предпоследней из b
ответ @ajcr объясняет, как
dot
иmatmul
(вызывается командой@
символ) отличаются. Глядя на простой пример, ясно видно, как эти два ведут себя по-разному при работе с "стеками матриц" или тензорами.чтобы уточнить различия, возьмите массив 4x4 и верните
dot
продукта иmatmul
продукт с 2x4x3 'стек матриц' или тензор.import numpy as np fourbyfour = np.array([ [1,2,3,4], [3,2,1,4], [5,4,6,7], [11,12,13,14] ]) twobyfourbythree = np.array([ [[2,3],[11,9],[32,21],[28,17]], [[2,3],[1,9],[3,21],[28,7]], [[2,3],[1,9],[3,21],[28,7]], ]) print('4x4*4x2x3 dot:\n {}\n'.format(np.dot(fourbyfour,twobyfourbythree))) print('4x4*4x2x3 matmul:\n {}\n'.format(np.matmul(fourbyfour,twobyfourbythree)))
продукты каждой операции приведены ниже. Обратите внимание, как точка продукт есть,
...произведение суммы по последней оси a и предпоследней из b
и как матричный продукт формируется путем трансляции матрицы вместе.
4x4*4x2x3 dot: [[[232 152] [125 112] [125 112]] [[172 116] [123 76] [123 76]] [[442 296] [228 226] [228 226]] [[962 652] [465 512] [465 512]]] 4x4*4x2x3 matmul: [[[232 152] [172 116] [442 296] [962 652]] [[125 112] [123 76] [228 226] [465 512]] [[125 112] [123 76] [228 226] [465 512]]]
в математике, я думаю точка в numpy имеет больше смысла
точка(А,Б)_sum_m Ох{Я,J,к,м}, что{А,Б,М,с}
так как он дает точечное произведение, когда A и b являются векторами, или умножение Матрицы, когда A и b являются матрицами
Как matmul операция в numpy, она состоит из частей точка результат, и его можно определить как
matmul(a,b)_{i,j,k,c} = \sum_m a_{i,j,k,m}b_{i,j,m,c}
Итак, вы можете видеть, что matmul (a,b) возвращает массив с небольшую форму, который имеет меньшее потребление памяти и имеет больше смысла в приложениях. В частности, в сочетании с вещания вы можете узнать
matmul(a,b)_{i,j,k,l} = \sum_m a_{i,j,k,m}b_{j,m,l}
для образец.
из приведенных выше двух определений вы можете увидеть требования к использованию этих двух операций. Предположим a. shape=(s1,s2,s3,s4) и b. shape=(t1,t2,t3,t4)
использовать точка (a,b) вам нужно
1. **t3=s4**;
использовать matmul (a,b) вам нужно
- t3=s4
- t2=s2, или один из t2 и s2 является 1
- t1=s1, или один из t1 и s1 равен 1
использовать следующий фрагмент кода, чтобы убедить себя.
пример кода
import numpy as np for it in xrange(10000): a = np.random.rand(5,6,2,4) b = np.random.rand(6,4,3) c = np.matmul(a,b) d = np.dot(a,b) #print 'c shape: ', c.shape,'d shape:', d.shape for i in range(5): for j in range(6): for k in range(2): for l in range(3): if not c[i,j,k,l] == d[i,j,k,j,l]: print it,i,j,k,l,c[i,j,k,l]==d[i,j,k,j,l] #you will not see them