在numpy.einsum中对省略号广播维度求和

时间:2016-02-02 22:37:47

标签: python numpy

在numpy中,我有一个可以是2-D或3-D的数组,我想在将每个元素平方时将其减少为2-D。所以我尝试了这个并且它不起作用:

A = np.random.rand(5, 3, 3)
np.einsum('...ij,...ij->ij', A, A)

它返回此错误:

ValueError: output has more dimensions than subscripts given in einstein sum, but no '...' ellipsis provided to broadcast the extra dimensions.

我认为einsum并不认为当省略号在右侧消失时,我想要省略省略号(如果它们存在)。是否有一些“优雅”的方式(即没有检查维数和使用if语句)告诉它我想为3-D做这个:

A = np.random.rand(5, 3, 3)
np.einsum('aij,aij->ij', A, A)

这是2-D?

A = np.random.rand(3, 3)
np.einsum('ij,ij->ij', A, A)

1 个答案:

答案 0 :(得分:3)

有时优雅'处理变量维度的方法是使用一组if测试,并在函数调用中隐藏它们。以np.atleast_3d为例;它有一个4路if / else子句。我在这里推荐它,除了它在最后添加额外的维度,而不是开始。使用if的{​​{1}}条款并不昂贵(时间明智),因此不要害怕使用它们。即使你发现了一些神奇的功能,看看它的代码;你可能会对隐藏的东西感到惊讶。

省略号用于“骑行”的尺寸,而不是您想要特定控制的尺寸。在这里,您希望对初始维度求和,因此需要明确地对其进行索引:

reshape

对于2D阵列:

In [161]: np.einsum('i...,i...',A,A)
Out[161]: 
array([[ 1.26942035,  1.32052776,  1.74118617],
       [ 1.59679765,  1.49331565,  2.04573002],
       [ 2.29027005,  1.48351522,  1.36679208]])
In [162]: np.einsum('aij,aij->ij',A,A)
Out[162]: 
array([[ 1.26942035,  1.32052776,  1.74118617],
       [ 1.59679765,  1.49331565,  2.04573002],
       [ 2.29027005,  1.48351522,  1.36679208]])

我认为你不能用一个表达来处理这两种情况。

获得第一笔金额的另一种方式

In [165]: np.einsum('ij,ij->ij',A[0],A[0])
Out[165]: 
array([[ 0.20497776,  0.11632197,  0.65396968],
       [ 0.0529767 ,  0.24723351,  0.27559647],
       [ 0.62806525,  0.33081124,  0.57070406]])
In [166]: A[0]*A[0]
Out[166]: 
array([[ 0.20497776,  0.11632197,  0.65396968],
       [ 0.0529767 ,  0.24723351,  0.27559647],
       [ 0.62806525,  0.33081124,  0.57070406]])
In [167]: 
In [167]: np.einsum('...,...',A[0],A[0])
Out[167]: 
array([[ 0.20497776,  0.11632197,  0.65396968],
       [ 0.0529767 ,  0.24723351,  0.27559647],
       [ 0.62806525,  0.33081124,  0.57070406]])

我提供了修复省略号处理的补丁,但那是几年前的事。所以细节在我的脑海中并不是非常新鲜。作为其中的一部分,我反向设计解析字符串表达式(原始编译),并且可以查看该代码(或引用您),如果我们需要更明确的答案。

In [168]: (A*A).sum(axis=0)
Out[168]: 
array([[ 1.26942035,  1.32052776,  1.74118617],
       [ 1.59679765,  1.49331565,  2.04573002],
       [ 2.29027005,  1.48351522,  1.36679208]])

错误消息表示它正在尝试将In [172]: np.einsum('...ij,...ij->ij',A,A) --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-172-dfe39e268402> in <module>() ----> 1 np.einsum('...ij,...ij->ij',A,A) ValueError: output has more dimensions than subscripts given in einstein sum, but no '...' ellipsis provided to broadcast the extra dimensions. In [173]: np.einsum('...ij,...ij->...ij',A,A).shape Out[173]: (5, 3, 3) 维度传递给输出,并且无法 - 因为输出缺少维度或...。换句话说,它不会在...维度上执行求和。它们不变地传递给输出(适用广播规则)。