在第一个(而不是最后一个)轴上计算numpy.inner()



我正在尝试制作一个类似numpy.inner的函数,但它在两个数组的第一个轴上求和,而不是在最后一个轴上求总和。目前我正在使用tensordotrollaxis:

def inner1(a, b):
    return numpy.tensordot(numpy.rollaxis(a, 0, len(a.shape)), b, 1)

但我想知道:有更好的方法吗?也许是一个不需要我转动斧头的?

我觉得einsum应该使这成为可能,但我不确定如何在这里使用它
当我指定下标字符串时,似乎需要我对ab的维度进行硬编码,但我在这里不能真正做到这一点,因为对输入维度没有特别的要求。

(注意:我知道在第一个轴而不是最后一个轴上求和会对性能产生影响,但我在这里忽略了它们。)

我想您想要的是np.tensordot(a, b, (0, 0))

这不如tensordot解决方案漂亮,但您可以从输入的ndim构造einsum字符串:

ll = 'abcdefghijklmnopqrstuvw'
astr = ll[0]+ll[1:a.ndim]+','+ll[0]+ll[a.ndim:a.ndim+b.ndim-1]
np.einsum(astr,a,b)

np.einsum允许您将轴指定为列表,而不是字符串

np.einsum(a, [0]+range(1,a.ndim), b, [0]+range(a.ndim,a.ndim+b.ndim-1))

对于一对3d和2d阵列,它们产生:

 np.einsum('abc,ad', a, b)
 np.einsum(a, [0,1,2], b, [0,3])

'...'在这里不起作用,因为这意味着重复的轴(在可能的范围内),其中你想要唯一的轴(除了第一个)。

虽然写起来更混乱,但einsum解决方案比tensordot解决方案快(小型测试阵列快3倍)。


einsum的另一个选项是重塑阵列,将"剩余"维度减少到一。这给计算增加了一点时间,但不是很多:

np.einsum('ij,ik',a.reshape(a.shape[0],-1), b.reshape(a.shape[0],-1)).reshape(a.shape[1:]+b.shape[1:])

相关内容

  • 没有找到相关文章

最新更新