Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在秩N张量(ndarray)中选择收缩2个索引_Python_Numpy - Fatal编程技术网

Python 如何在秩N张量(ndarray)中选择收缩2个索引

Python 如何在秩N张量(ndarray)中选择收缩2个索引,python,numpy,Python,Numpy,我有一个2^L x 2^L矩阵,然后通过每个轴有2个元素的重塑命令将其转换为秩为2L的张量。例如,对于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指数求和。但这会打乱指数的顺序,因此进一步收缩将非常困难,因此我真的很想知道如何执行这种收缩。在一个或多个轴上求和 关于你所说的“收缩”——

我有一个2^L x 2^L矩阵,然后通过每个轴有2个元素的重塑命令将其转换为秩为2L的张量。例如,对于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指数求和。但这会打乱指数的顺序,因此进一步收缩将非常困难,因此我真的很想知道如何执行这种收缩。

在一个或多个轴上求和 关于你所说的“收缩”——沿着一个或两个轴的总和,这里有一个粗略的猜测

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的
跟踪答案,可以使用
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
的工作原理,
重塑
路线更容易:

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)上跟踪跟踪

两条记录道都可以在一个
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

我假设你指的是“广义轨迹”意义上的张量收缩,那么让我们看看
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]]]])
最后,您可以
挤压
多余的轴

>>> np.squeeze(_)
array([[ 9, 13],
       [17, 21]])

你想要的具体操作是什么?您能为
L=1
显示吗<代码>[[1,2],[3,4]]->?你所说的收缩是什么意思?它不是
numpy
中的常用术语。你想沿着其中一个轴做加法吗?收缩意味着在数据列中求两个轴的和。np.trace可以像保罗在下面说的那样做汉克斯!多余轴上的注释对于(0,3)跟踪,
np.einsum('[ijki',a)
np.einsum(a[0,1,2,0])非常有用
works@hpaulj我真的应该学习一下einsum magic!它比现有的专用函数有什么优势吗?我想我读到过einsum过去比numpy内置函数更快的地方。仍然是这样吗?同样,有什么理由不使用
expand\u dims
和其他类似
moveaxis
的便利吗当轴和尺寸不固定时,它们会使生活变得更加轻松。
>>> np.squeeze(_)
array([[ 9, 13],
       [17, 21]])