取高维numpy数组的点积
Taking dot products of high dimensional numpy arrays
我正在尝试计算三个 numpy 数组之间的点积。但是,我正在努力解决这个问题。
问题如下:
我有两个 (4,) 形状的 numpy 数组,分别为 a
和 b
,以及一个形状为 (4, 4, 3),c
的 numpy 数组。
import numpy as np
a = np.array([0, 1, 2, 3])
b = np.array([[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]],
[[2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2]],
[[3, 3, 3], [3, 3, 3], [3, 3, 3], [3, 3, 3]],
[[4, 4, 4], [4, 4, 4], [4, 4, 4], [4, 4, 4]]])
c = np.array([4, 5, 6, 7])
我想以我的结果是一个三元组的方式计算点积。也就是说,先用 b
点 a
,然后用 c
点,必要时进行转置。换句话说,我想计算 a
、b
和 c
之间的点积,就好像 c
的形状是 (4, 4)
,但我想要 3 -结果为元组。
我试过:
重塑 a
和 c
,然后计算点积:
a = np.reshape(a, (4, 1))
c = np.reshape(c, (4, 1))
tmp = np.dot(a.T, b) # now has shape (1, 4, 3)
result = np.dot(tmp, c)
理想情况下,我现在应该有:
print(result.shape)
>> (1, 1, 3)
但我收到错误
ValueError: shapes (1,4,3) and (4,1) not aligned: 3 (dim 2) != 4 (dim 0)
我也尝试过使用 numpy 的 tensordot 函数,但没有成功。
不是自动的,但可以完成工作:
np.einsum('i,ijk,j->k',a,b,c)
# array([440, 440, 440])
计算形状 (3,) 的 d
使得 d_k = sum_{ij} a_i b_{ijk} c_j
.
基本的dot(A,B)
规则是:A的最后一个轴与B的第二个到最后一个
In [965]: a.shape
Out[965]: (4,)
In [966]: b.shape
Out[966]: (4, 4, 3)
a
(和 c
)是 1d。它的 (4,) 可以与 b
的第二个 (4) 点在一起:
In [967]: np.dot(a,b).shape
Out[967]: (4, 3)
在输出中使用 c
产生一个 (3,) 数组
In [968]: np.dot(c, np.dot(a,b))
Out[968]: array([360, 360, 360])
这个组合可能更清楚等同于 einsum
:
In [971]: np.einsum('i,jik,j->k',a,b,c)
Out[971]: array([360, 360, 360])
但是如果我们想让a
作用在b
的第一个轴上呢?使用 einsum
这很容易做到:
In [972]: np.einsum('i,ijk,j->k',a,b,c)
Out[972]: array([440, 440, 440])
要对 dot
做同样的事情,我们可以切换 a
和 c
:
In [973]: np.dot(a, np.dot(c,b))
Out[973]: array([440, 440, 440])
或转置 b
的轴:
In [974]: np.dot(c, np.dot(a,b.transpose(1,0,2)))
Out[974]: array([440, 440, 440])
如果a
和c
的长度不同,这道换位题会更清楚。例如A (2,) 和 (4,) 与 (2,4,3) 或 (4,2,3)。
在
tmp = np.dot(a.T, b) # now has shape (1, 4, 3)
你有一个 (1,4a) 点缀着 (4,4a,3)。结果是 (1,4,3)。我添加了 a
来标识轴何时组合。
要应用 (4,1) c
,我们必须进行相同的转置:
In [977]: np.dot(c[:,None].T, np.dot(a[:,None].T, b))
Out[977]: array([[[360, 360, 360]]])
In [978]: _.shape
Out[978]: (1, 1, 3)
np.dot(c[None,:], np.dot(a[None,:], b))
在没有转置的情况下也会做同样的事情。
I was hoping numpy would automagically distribute over the last axis. That is, that the dot product would run over the two first axes, if that makes sense.
鉴于我在开头引用的 dot
规则,这没有意义。但是如果我们转置 b
所以 (3) 轴是第一个,它可以 'carry that along',使用最后一个和第二个到最后一个。
In [986]: b.transpose(2,0,1).shape
Out[986]: (3, 4, 4)
In [987]: np.dot(a, b.transpose(2,0,1)).shape
Out[987]: (3, 4)
In [988]: np.dot(np.dot(a, b.transpose(2,0,1)),c)
Out[988]: array([440, 440, 440])
(4a).(3, 4a, 4c) -> (3, 4c)
(3, 4c). (4c) -> 3
您正在将 (1,4,3) 矩阵乘以 (4,1) 矩阵,所以这是不可能的,因为您在 b 中有 3 页的 (1,4) 矩阵。如果您想将矩阵 b 的每一页乘以 c,只需分别将每一页相乘即可。
a = np.array([0, 1, 2, 3])
b = np.array([[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]],
[[2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2]],
[[3, 3, 3], [3, 3, 3], [3, 3, 3], [3, 3, 3]],
[[4, 4, 4], [4, 4, 4], [4, 4, 4], [4, 4, 4]]])
c = np.array([4, 5, 6, 7])
a = np.reshape(a, (4, 1))
c = np.reshape(c, (4, 1))
tmp = np.dot(a.T, b) # now has shape (1, 4, 3)
result = np.dot(tmp[:,:,0], c)
for i in range(1,3):
result = np.dstack((result, np.dot(tmp[:,:,i], c)))
print np.shape(result)
所以你得到大小为 (1,1,3) 的结果
我正在尝试计算三个 numpy 数组之间的点积。但是,我正在努力解决这个问题。
问题如下:
我有两个 (4,) 形状的 numpy 数组,分别为 a
和 b
,以及一个形状为 (4, 4, 3),c
的 numpy 数组。
import numpy as np
a = np.array([0, 1, 2, 3])
b = np.array([[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]],
[[2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2]],
[[3, 3, 3], [3, 3, 3], [3, 3, 3], [3, 3, 3]],
[[4, 4, 4], [4, 4, 4], [4, 4, 4], [4, 4, 4]]])
c = np.array([4, 5, 6, 7])
我想以我的结果是一个三元组的方式计算点积。也就是说,先用 b
点 a
,然后用 c
点,必要时进行转置。换句话说,我想计算 a
、b
和 c
之间的点积,就好像 c
的形状是 (4, 4)
,但我想要 3 -结果为元组。
我试过:
重塑 a
和 c
,然后计算点积:
a = np.reshape(a, (4, 1))
c = np.reshape(c, (4, 1))
tmp = np.dot(a.T, b) # now has shape (1, 4, 3)
result = np.dot(tmp, c)
理想情况下,我现在应该有:
print(result.shape)
>> (1, 1, 3)
但我收到错误
ValueError: shapes (1,4,3) and (4,1) not aligned: 3 (dim 2) != 4 (dim 0)
我也尝试过使用 numpy 的 tensordot 函数,但没有成功。
不是自动的,但可以完成工作:
np.einsum('i,ijk,j->k',a,b,c)
# array([440, 440, 440])
计算形状 (3,) 的 d
使得 d_k = sum_{ij} a_i b_{ijk} c_j
.
基本的dot(A,B)
规则是:A的最后一个轴与B的第二个到最后一个
In [965]: a.shape
Out[965]: (4,)
In [966]: b.shape
Out[966]: (4, 4, 3)
a
(和 c
)是 1d。它的 (4,) 可以与 b
的第二个 (4) 点在一起:
In [967]: np.dot(a,b).shape
Out[967]: (4, 3)
在输出中使用 c
产生一个 (3,) 数组
In [968]: np.dot(c, np.dot(a,b))
Out[968]: array([360, 360, 360])
这个组合可能更清楚等同于 einsum
:
In [971]: np.einsum('i,jik,j->k',a,b,c)
Out[971]: array([360, 360, 360])
但是如果我们想让a
作用在b
的第一个轴上呢?使用 einsum
这很容易做到:
In [972]: np.einsum('i,ijk,j->k',a,b,c)
Out[972]: array([440, 440, 440])
要对 dot
做同样的事情,我们可以切换 a
和 c
:
In [973]: np.dot(a, np.dot(c,b))
Out[973]: array([440, 440, 440])
或转置 b
的轴:
In [974]: np.dot(c, np.dot(a,b.transpose(1,0,2)))
Out[974]: array([440, 440, 440])
如果a
和c
的长度不同,这道换位题会更清楚。例如A (2,) 和 (4,) 与 (2,4,3) 或 (4,2,3)。
在
tmp = np.dot(a.T, b) # now has shape (1, 4, 3)
你有一个 (1,4a) 点缀着 (4,4a,3)。结果是 (1,4,3)。我添加了 a
来标识轴何时组合。
要应用 (4,1) c
,我们必须进行相同的转置:
In [977]: np.dot(c[:,None].T, np.dot(a[:,None].T, b))
Out[977]: array([[[360, 360, 360]]])
In [978]: _.shape
Out[978]: (1, 1, 3)
np.dot(c[None,:], np.dot(a[None,:], b))
在没有转置的情况下也会做同样的事情。
I was hoping numpy would automagically distribute over the last axis. That is, that the dot product would run over the two first axes, if that makes sense.
鉴于我在开头引用的 dot
规则,这没有意义。但是如果我们转置 b
所以 (3) 轴是第一个,它可以 'carry that along',使用最后一个和第二个到最后一个。
In [986]: b.transpose(2,0,1).shape
Out[986]: (3, 4, 4)
In [987]: np.dot(a, b.transpose(2,0,1)).shape
Out[987]: (3, 4)
In [988]: np.dot(np.dot(a, b.transpose(2,0,1)),c)
Out[988]: array([440, 440, 440])
(4a).(3, 4a, 4c) -> (3, 4c)
(3, 4c). (4c) -> 3
您正在将 (1,4,3) 矩阵乘以 (4,1) 矩阵,所以这是不可能的,因为您在 b 中有 3 页的 (1,4) 矩阵。如果您想将矩阵 b 的每一页乘以 c,只需分别将每一页相乘即可。
a = np.array([0, 1, 2, 3])
b = np.array([[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]],
[[2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2]],
[[3, 3, 3], [3, 3, 3], [3, 3, 3], [3, 3, 3]],
[[4, 4, 4], [4, 4, 4], [4, 4, 4], [4, 4, 4]]])
c = np.array([4, 5, 6, 7])
a = np.reshape(a, (4, 1))
c = np.reshape(c, (4, 1))
tmp = np.dot(a.T, b) # now has shape (1, 4, 3)
result = np.dot(tmp[:,:,0], c)
for i in range(1,3):
result = np.dstack((result, np.dot(tmp[:,:,i], c)))
print np.shape(result)
所以你得到大小为 (1,1,3) 的结果