2014-10-26 90 views
0

我试图做一个函数,如numpy.inner,但总结了第一个两个数组的轴而不是最后一个轴。目前我使用tensordotrollaxis计算numpy.inner()在第一个(而不是最后一个)轴

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

但我想知道:有没有更好的办法?也许一个不需要我滚动轴?

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

(注:我上午知道有到求和第一轴,而不是最后的性能影响,但我在这里忽略它们)

回答

2

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

+0

您确定这种方式有效吗?这失败了:'einsum('i ...,i ...-> ...',((1,2)),((1,3)))' – Mehrdad 2014-10-26 23:18:19

+0

这一切都取决于你想要什么去做。在这种情况下,我认为你想,'einsum('ij ...,ik ...-> jk ...',((1,2)),((1,3)))''。 – farenorth 2014-10-26 23:21:57

+0

我想你可能错过了这个问题的要点?我无法控制输入形状。据我所知,他们可能是“(1,2,3,4)”和“(1,5,6,7)';重点是除了第一个维度之外的所有维度都应该是不相关的,所以当我不知道字符串应该是什么时,我将如何使用'einsum'? – Mehrdad 2014-10-26 23:23:19

1

这不是为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]) 

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

在编写messier时,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:]) 
+0

我其实自己试过这个,结果在我的情况下变慢了 - 但是让我更加困扰的问题是,在一般情况下,字母表中没有足够的字母来完成这项工作。 :P – Mehrdad 2014-10-27 23:10:36

+0

我喜欢使用轴列表;我以前从未见过。很高兴知道。谢谢! – farenorth 2014-10-28 00:58:32

+0

我添加了一个使用重塑的方法。 – hpaulj 2014-10-28 16:48:56

相关问题