Como faço o seguinte produto escalar em 3 dimensões com numpy?
Tentei:
x = np.array([[[-1, 2, -4]], [[-1, 2, -4]]])
W = np.array([[[2, -4, 3], [-3, -4, 3]],
[[2, -4, 3], [-3, -4, 3]]])
y = np.dot(W, x.transpose())
mas recebi esta mensagem de erro:
y = np.dot(W, x)
ValueError: shapes (2,2,3) and (2,1,3) not aligned: 3 (dim 2) != 1 (dim 1)
Seu equivalente em 2 dimensões é:
x = np.array([-1, 2, -4])
W = np.array([[2, -4, 3],
[-3, -4, 3]])
y = np.dot(W,x)
print(f'{y=}')
que retornará:
y=array([-22, -17])
Além disso, y = np.dot(W,x.transpose())
retornará a mesma resposta.
O problema vem da transposição 3D que não transpõe os eixos que você quer por padrão. Você precisa especificar os eixos corretos durante esta chamada:
Você também pode usar
einsum
, isso torna as dimensões correspondentes mais explícitas:Saída:
Primeiro, acho que @Jérôme Richard e @mozway forneceram as soluções mais concisas e eficientes. Não consigo imaginar respostas melhores do que essas.
Minha abordagem é apenas por diversão, se você quiser brincar com
zip
+map
dá
Outra solução possível:
Ao multiplicar
W
(shape(2, 2, 3)
) porx
(shape(2, 1, 3)
), o numpy transmite automaticamentex
para corresponderW
ao shape de , resultando em um produto elemento a elemento de shape(2, 2, 3)
. Somando esse produto ao longo do último eixo (axis=2
) comkeepdims=True
produz o shape de saída desejado(2, 2, 1)
.Saída: