numpy einsum 折叠除第一维之外的所有内容

问题描述

我有一个维度为 (5,...) 的数组(... 可以是任何东西),我想在 5 之后形成所有维度的点积,以便生成的数组具有形状(5,)。我以为是einsum

i...,i...->i

看起来很有希望,可惜

import numpy as np

a = np.random.rand(5)
b = np.einsum("i...,i...->i",a,a)
assert b.shape == (5,)  # okay


a = np.random.rand(5,2)
b = np.einsum("i...,a)  # fail
assert b.shape == (5,)


a = np.random.rand(5,2,3)
b = np.einsum("i...,)
in einsum
    return c_einsum(*operands,**kwargs)
ValueError: output has more dimensions than subscripts given in einstein sum,but no '...' ellipsis provided to broadcast the extra dimensions.

我或许可以将 a 改造成

b = np.einsum("ij,ij->i",a.reshape(a.shape[0],-1),-1))

但这看起来太乱了。有什么更好的建议吗?

解决方法

根据文档,省略号“启用和控制广播”。您想对这些维度进行点积求和。这些维度需要明确的整体。因此,对于减少最后 2 个维度的 4d,'...ij->...'

In [15]: arr = np.arange(24).reshape(2,3,4)

最后或最后两个维度的减少:

In [17]: np.einsum('...i->...',arr).shape
Out[17]: (2,3)
In [18]: np.einsum('...ij->...',arr).shape
Out[18]: (2,)

sum 等价物:

In [20]: arr.sum(axis=(-1))
Out[20]: 
array([[ 6,22,38],[54,70,86]])
In [21]: arr.sum(axis=(-1)).shape
Out[21]: (2,3)
In [22]: arr.sum(axis=(-2,-1)).shape
Out[22]: (2,)
In [23]: arr.sum(axis=(-2,-1))
Out[23]: array([ 66,210])
In [24]: np.einsum('...ij->...',arr)
Out[24]: array([ 66,210])

来自sympy的这个表达式可能有助于形象化einsum

In [37]: f = Function('f')
    ...: Sum(f(x,y,z),(y,3),(z,2))
Out[37]: 
  2     3             
 ___   ___            
 ╲     ╲              
  ╲     ╲             
  ╱     ╱   f(x,z)
 ╱     ╱              
 ‾‾‾   ‾‾‾            
z = 0 y = 0 

f 是 3 个变量 (3d) 的函数。 einsum 表示法模拟爱因斯坦表示法,其中明确列出了应该求和的维度。那些没有总结的,从某种意义上说,只是随身携带,不需要(如)明确。

,

为了说明,假设张量 A 是一个 2×2 矩阵。你需要的点积可以写成

C_i = A_{kj} A_{ij} D_{ki},

其中 D 是单位矩阵。

使用np.einsum,可以写成

D= np.identity(2)
X= np.einsum("k...,i...,ki->i...",A,D)
C= np.sum(X.reshape(X.shape[0],-1),axis=-1)

我们需要上面的 np.sum 对所有 j 个索引求和。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...