我有一个2 ^ L x 2 ^ L矩阵,然后通过重塑命令将其转换为等级2L的张量,每个轴具有2个元素。例如,对于L = 2,它将是:
Z = np.asarray([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
X = np.reshape(Z,[2,2,2,2])
我试图通过交换轴来使用np.einsum
求和,例如L和2L索引。但它会使指数秩序陷入混乱,因此进一步的收缩将非常困难,所以我真的在努力应对如何实现这种收缩。
答案 0 :(得分:2)
这是一个疯狂的猜测,你的意思是'收缩' - sum
沿一个或两个轴。
In [239]: X.sum(1)
Out[239]:
array([[[ 6, 8],
[10, 12]],
[[22, 24],
[26, 28]]])
In [240]: np.einsum('ijkl->ikl',X)
Out[240]:
array([[[ 6, 8],
[10, 12]],
[[22, 24],
[26, 28]]])
In [241]: np.einsum('ijkl->il',X)
Out[241]:
array([[16, 20],
[48, 52]])
In [242]: X.sum((1,2))
Out[242]:
array([[16, 20],
[48, 52]])
In [243]: X.sum(2).sum(1)
Out[243]:
array([[16, 20],
[48, 52]])
要更多地探索@Paul Panzer's
跟踪答案,可以使用einsum
计算(0,3)跟踪:
In [314]: a1=np.einsum('ijki', a) # repeated indicies
In [315]: a1
Out[315]:
array([[ 9, 13],
[17, 21]])
In [316]: a1[None,:,:,None] # restore the dimensions
Out[316]:
array([[[[ 9],
[13]],
[[17],
[21]]]])
从i,j=0,3
以编程方式执行此操作需要更多工作。构建替代einsum
语法
a1=np.einsum(a, [0,1,2,0])
In [321]: dex=np.arange(a.ndim)
In [322]: dex[j]=dex[i]
In [323]: dex
Out[323]: array([0, 1, 2, 0])
In [324]: a1=np.einsum(a, dex.tolist())
In [325]: a1
Out[325]:
array([[ 9, 13],
[17, 21]])
newaxis
扩展可以从切片和None
:
In [326]: dex=np.zeros(a.ndim, object)
In [327]: dex[...]=slice(None)
In [328]: dex[[i,j]] = None
In [329]: dex
Out[329]: array([None, slice(None, None, None), slice(None, None, None), None], dtype=object)
In [330]: a1[tuple(dex)]
Out[330]:
array([[[[ 9],
[13]],
[[17],
[21]]]])
但是看看expand_dims
如何运作,reshape
路线更容易:
In [334]: dex = np.array(a.shape)
In [335]: dex[[i,j]]=1
In [336]: dex
Out[336]: array([1, 2, 2, 1])
In [337]: a1.reshape(dex)
您提到了进一步的收缩操作。在这4d情况下,我假设这意味着跟踪轴(1,2)
上的跟踪In [426]: a2 = a1.reshape(dex)
In [427]: a2.shape
Out[427]: (1, 2, 2, 1)
In [429]: np.einsum('ijjk',a2)
Out[429]: array([[30]])
两条痕迹都可以在一个einsum
中进行:
In [430]: np.einsum('ijji',a)
Out[430]: 30
In [431]: np.trace(a1)
Out[431]: 30
einsum
往往与dot
一样好,但是当数组变得非常大并且其迭代空间增长时它会消失。但在这里,它始终比双重追踪更好:
In [464]: N=100;abig=np.arange(N*N*N*N).reshape(N,N,N,N)
In [465]: abig.shape
Out[465]: (100, 100, 100, 100)
In [466]: timeit np.trace(np.trace(abig,0,0,3))
100 loops, best of 3: 12.4 ms per loop
In [467]: timeit np.einsum('ijji',abig)
The slowest run took 7.51 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 30.2 µs per loop
答案 1 :(得分:2)
我假设你指的是"广义跟踪"意义上的张量收缩,所以让我们看看numpy.trace
能为我们做些什么:
>>> import numpy as np
>>> a = np.arange(16).reshape(2, 2, 2, 2)
>>> L, i, j = 2, 0, 1
>>> np.trace(a, axis1=i, axis2=L+j)
array([[ 9, 13],
[17, 21]])
如果你必须多次这样做并且不想让轴移动,只需插入新轴来替换合同的轴。
>>> np.expand_dims(np.expand_dims(_, i), L+j)
array([[[[ 9],
[13]],
[[17],
[21]]]])
最后,你可以squeeze
多余的轴。
>>> np.squeeze(_)
array([[ 9, 13],
[17, 21]])