不那么慢的numpy 等价物是g(x,y.T),利用广播,然后是f(..., axis=1)。
In [136]: general_inner(np.sum, np.multiply, x, y)
Out[136]:
array([[ 1.1],
[ 3.1]])
In [137]: np.multiply(x,y.T)
Out[137]:
array([[ 0.9, 0.2],
[ 2.7, 0.4]])
In [138]: np.sum(np.multiply(x,y.T),axis=1)
Out[138]: array([ 1.1, 3.1])
类似地求和的最大值:
In [145]: general_inner(np.max, np.add, x, y)
Out[145]:
array([[ 2.1],
[ 4.1]])
In [146]: np.max(np.add(x,y.T), axis=1)
Out[146]: array([ 2.1, 4.1])
np.add、np.multiply、np.maximum 是 ufunc,而 np.sum、np.prod、np.max 不是,但使用 axis 参数和 @987654334 @。 (编辑:np.add.reduce 是 ufunc 等价于 np.sum。)
In [152]: np.max(np.add(x,y.T), axis=1, keepdims=True)
Out[152]:
array([[ 2.1],
[ 4.1]])
在np.einsum 中有一个旧的增强请求来实现这种事情。这实现了sum of products 计算,并对索引进行了高度控制。所以从概念上讲,它可以使用相同的索引控制执行max of sums。但据我所知,没有人尝试过实现它。
广义内积是 APL 的一个可爱特性(几十年前它是我的主要语言)。但显然它没有那么有用,以至于它从那个语言家族中迁移出来了。 MATLAB 没有类似的东西。
APL & J 可以用这个结构做些什么,而 numpy 不能用我们展示的那种广播来做?
对于更一般的x 和y 形状,我需要添加其他答案中给出的newaxis
In [176]: x = np.arange(3*4).reshape(4,3)
In [177]: y = np.arange(3*2).reshape(3,2)
In [178]: np.sum(np.multiply(x[...,None],y[None,...]),axis=1)
Out[178]:
array([[10, 13],
[28, 40],
[46, 67],
[64, 94]])
In [179]: np.max(np.add(x[...,None],y[None,...]),axis=1)
Out[179]:
array([[ 6, 7],
[ 9, 10],
[12, 13],
[15, 16]])
推广到 3d,同时使用 matmul 的最后一个暗淡/第二个最后一个 matmul 的想法:
In [195]: x = np.arange(2*4*5).reshape(2,4,5)
In [196]: y = np.arange(2*5*3).reshape(2,5,3)
In [197]: np.einsum('ijk,ikm->ijm', x, y).shape
Out[197]: (2, 4, 3)
In [203]: np.add.reduce(np.multiply(x[...,None], y[...,None,:,:]), axis=-2).shape
Out[203]: (2, 4, 3)
# shapes broadcast: (2,4,5,n) * (2,n,5,3) => (2,4,5,3); sum on the 5
因此,虽然 numpy(和 MATLAB)没有像 APL 这样的特殊语法,但扩展(外部)操作后跟缩减的想法很常见。
测试其他ufunc:
In [205]: np.maximum.reduce(np.add(x[...,None], y[...,None,:,:]), axis=-2).shape
Out[205]: (2, 4, 3)
In [208]: np.logical_or.reduce(np.greater(x[...,None], y[...,None,:,:]), axis=-2).shape
Out[208]: (2, 4, 3)