Recentemente, mudei para Python 3.5 e notei que o novo operador de multiplicação de matriz (@) às vezes se comporta de maneira diferente do operador numpy dot . Por exemplo, para matrizes 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)
O @
operador retorna uma matriz de forma:
c.shape
(8, 13, 13)
enquanto a np.dot()
função retorna:
d.shape
(8, 13, 8, 13)
Como posso reproduzir o mesmo resultado com ponto numpy? Existem outras diferenças significativas?
matmul
função anos atrás?@
como um operador infixo é novo, mas a função funciona tão bem sem ele.Respostas:
O
@
operador chama o__matmul__
método da matriz , nãodot
. Este método também está presente na API como a funçãonp.matmul
.Da documentação:
O último ponto deixa claro que os métodos
dot
ematmul
se comportam de maneira diferente quando passados para matrizes 3D (ou dimensões superiores). Citando um pouco mais da documentação:Para
matmul
:Para
np.dot
:fonte
A resposta de @ajcr explica como o
dot
ematmul
(invocado pelo@
símbolo) diferem. Olhando para um exemplo simples, pode-se ver claramente como os dois se comportam de maneira diferente quando operam em 'pilhas de matrizes' ou tensores.Para esclarecer as diferenças, pegue uma matriz 4x4 e retorne o
dot
produto e omatmul
produto com uma 'pilha de matrizes' ou tensor 3x4x2.Os produtos de cada operação aparecem abaixo. Observe como o produto escalar é,
e como o produto da matriz é formado pela difusão da matriz em conjunto.
fonte
a = np.arange(24).reshape(3, 4, 2)
seria criar um array com as dimensões 3x4x2.Apenas para sua informação,
@
e seus equivalentes numpydot
ematmul
são todos igualmente rápidos. (Plot criado com perfplot , um projeto meu.)Código para reproduzir o gráfico:
fonte
Em matemática, acho que o ponto em numpy faz mais sentido
uma vez que dá o produto escalar quando a e b são vetores, ou a multiplicação da matriz quando a e b são matrizes
Quanto à operação matmul em numpy, consiste em partes do resultado de ponto , e pode ser definido como
> matmul (a, b) _ {i, j, k, c} =
Portanto, você pode ver que matmul (a, b) retorna um array com um formato pequeno, que tem menor consumo de memória e faz mais sentido nos aplicativos. Em particular, combinando com a transmissão , você pode obter
por exemplo.
A partir das duas definições acima, você pode ver os requisitos para usar essas duas operações. Assuma a.shape = (s1, s2, s3, s4) e b.shape = (t1, t2, t3, t4)
Para usar o ponto (a, b) você precisa
Para usar matmul (a, b) você precisa
Use o código a seguir para se convencer.
Amostra de código
fonte
np.matmul
também fornece o produto escalar em vetores e o produto matricial em matrizes.Aqui está uma comparação com
np.einsum
para mostrar como os índices são projetadosfonte
Minha experiência com MATMUL e DOT
Eu recebia constantemente "ValueError: A forma dos valores passados é (200, 1), os índices implicam (200, 3)" ao tentar usar o MATMUL. Eu queria uma solução alternativa rápida e descobri que o DOT oferece a mesma funcionalidade. Não recebo nenhum erro ao usar o DOT. Eu recebo a resposta correta
com MATMUL
com DOT
fonte