Python numpy.einsum中的省略号广播

Python numpy.einsum中的省略号广播,python,numpy,ellipsis,array-broadcasting,numpy-einsum,Python,Numpy,Ellipsis,Array Broadcasting,Numpy Einsum,我无法理解为什么以下各项不起作用: 我有一个数组前置因子,可以是三维的,也可以是六维的。 我有一个四维的阵列偶极子。偶极子的前三个维度与前因子的后三个维度相匹配 由于我不知道前置因子的形状,我使用省略号来解释前置因子中的三个可选维度: (在这里的示例中,prefactor.shape是(1,1,1,160,160,128),dipoles.shape是(160,160,128,3)。执行时,我得到错误: 操作数1没有足够的维数来匹配广播,并且无法扩展,因为在开始和结束时都指定了einstein和

我无法理解为什么以下各项不起作用:

我有一个数组前置因子,可以是三维的,也可以是六维的。 我有一个四维的阵列偶极子。偶极子的前三个维度与前因子的后三个维度相匹配

由于我不知道前置因子的形状,我使用省略号来解释前置因子中的三个可选维度:

(在这里的示例中,prefactor.shape是(1,1,1,160,160,128),dipoles.shape是(160,160,128,3)。执行时,我得到错误:

操作数1没有足够的维数来匹配广播,并且无法扩展,因为在开始和结束时都指定了einstein和下标

但是,当我在第二个术语中添加省略号时,它也会起作用:

numpy.einsum('...lmn,...lmno->...o', prefactor, dipoles)
只是我不明白为什么,因为这里不需要省略号。有人知道这里发生了什么吗


在上提出了相同的问题,但还没有令人满意的答案。

此问题存在github问题:

einsum(Trac#1862)索引表示法的改进

错误案例:

einsum('ij...,j->ij...',A,B)
当前解决方案需要(空)省略号:

einsum('ij…,j…->ij…',A,B)

它看起来像是
einsum
多次遍历字符串参数和ops,识别索引和广播类型(右、左、中、无),和op维度。使用此函数,它将构造一个
numpy.nditer
。在为nditer构造
op\u轴时,
einsum
会引发此错误。我不知道测试标准是否过紧(
ibroadcast>=ndim
),或者如果需要采取额外步骤来构造此参数的右
op_轴

显示如何使用
nditer
复制
einsum
行为。通过此操作,我可以复制您的计算,因此:

prefactor = np.random.random((1, 1, 1, 160, 160, 128))
dipoles = np.random.random((160, 160, 128, 3))
x = numpy.einsum('...lmn,...lmno->...o', prefactor, dipoles)
#numpy.einsum('...lmn,lmno->...o', prefactor, dipoles)  # not work

op_axes = [[0,1,2,3,4,5,-1], [-1,-1,-1,0,1,2,3], [0,1,2,-1,-1,-1,3]]
flags = ['reduce_ok','buffered', 'external_loop', 'delay_bufalloc', 'grow_inner']
op_flags = [['readonly']]*nops + [['allocate','readwrite']]
it = np.nditer([prefactor,dipoles,None], flags, op_flags, op_axes=op_axes)
it.operands[nops][...] = 0
it.reset()
#it.debug_print()
for (x,y,w) in it:
    w[...] += x*y
print "\nnditer usage:"
print it.operands[nops] # == x
print it.operands[nops].shape # (1, 1, 1, 3)
op\u轴
线表示
einsum
“…lmn,…lmno->…o”
推断出的内容


我正在网上探讨这个问题

在那里我有一个
einsum\u py.py
,它用Python代码模拟
np.einsum
。与这个问题相关的部分是
parse_subscripts()
,特别是
prepare_op_axes()
。似乎只有
正确地广播了
迭代(从末尾开始)需要正确创建
op_轴
,而不管椭圆在下标中的位置。它还删除了此问题的核心错误消息

该存储库中的
einsum.c.src
文件有此更改,并使用当前主发行版正确编译(只需替换文件并生成)。它可以根据
test_einsum.py
以及本期中的示例进行良好测试

我已提交此更改的请求

prefactor = np.random.random((1, 1, 1, 160, 160, 128))
dipoles = np.random.random((160, 160, 128, 3))
x = numpy.einsum('...lmn,...lmno->...o', prefactor, dipoles)
#numpy.einsum('...lmn,lmno->...o', prefactor, dipoles)  # not work

op_axes = [[0,1,2,3,4,5,-1], [-1,-1,-1,0,1,2,3], [0,1,2,-1,-1,-1,3]]
flags = ['reduce_ok','buffered', 'external_loop', 'delay_bufalloc', 'grow_inner']
op_flags = [['readonly']]*nops + [['allocate','readwrite']]
it = np.nditer([prefactor,dipoles,None], flags, op_flags, op_axes=op_axes)
it.operands[nops][...] = 0
it.reset()
#it.debug_print()
for (x,y,w) in it:
    w[...] += x*y
print "\nnditer usage:"
print it.operands[nops] # == x
print it.operands[nops].shape # (1, 1, 1, 3)