einsum
功能描述
评估操作数的爱因斯坦求和约定。
- 在隐式模式下,einsum使用爱因斯坦求和约定,许多常见的多维线性代数矩阵运算可以用简单的方式表示。
- 在显式模式下,einsum通过禁用或在指定的下标标签上强制求和,为计算其他可能不被视为经典爱因斯坦求和操作的数组操作提供了进一步的灵活性。
必选输入参数
参数名 |
类型 |
说明 |
|---|---|---|
subscript |
str |
将求和的下标指定为逗号分隔的下标标签列表。除非包含显式指标“->”以及精确输出形式的下标标签,否则将执行隐式(经典爱因斯坦求和)计算。 |
operands |
list |
操作数列表。 |
不允许输入标量,否则抛出异常。
可选输入参数
参数名 |
类型 |
默认值 |
说明 |
|---|---|---|---|
out |
ndarray |
None |
如果提供,将计算结果存储到这个数组中。 |
dtype |
{data-type, None} |
None |
如果提供,则强制使用指定的数据类型计算。请注意,您可能还必须给出一个更自由的casting参数。 |
order |
{‘C’, ‘F’, ‘A’, ‘K’} |
‘K’ |
控制输出的内存布局。
|
casting |
{‘no’, ‘equiv’, ‘safe’, ‘same_kind’, ‘unsafe’} |
‘safe’ |
控制可能发生哪种数据转换。不建议将其设置为“unsafe”,可能会出现未定义的结果。
|
optimize |
{False, True, ‘greedy’, ‘optimal’} |
False |
控制是否应该进行中间优化。如果False和True默认为“贪婪”算法,则不会发生优化。还接受np.einsum_path函数的显式收缩列表。 |
返回数据
类型 |
说明 |
|---|---|
ndarray |
基于爱因斯坦求和约定的计算结果。 |
示例
>>> import numpy as np
>>> a = np.arange(25).reshape((5,5))
>>> a
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]])
>>> b = np.arange(5)
>>> b
array([0, 1, 2, 3, 4])
>>> c = np.arange(6).reshape(2,3)
>>> c
array([[0, 1, 2],
[3, 4, 5]])
>>>
>>> # 矩阵的迹(对角线之和)
>>> np.einsum('ii', a)
60
>>> np.einsum(a, [0,0])
60
>>> np.trace(a)
60
>>>
>>> # 矩阵对角线元素
>>> np.einsum('ii->i', a)
array([ 0, 6, 12, 18, 24])
>>> np.einsum(a, [0,0], [0])
array([ 0, 6, 12, 18, 24])
>>> np.diag(a)
array([ 0, 6, 12, 18, 24])
>>>
>>> # 矩阵按行求和
>>> np.einsum('ij->i', a)
array([ 10, 35, 60, 85, 110])
>>> np.einsum(a, [0,1], [0])
array([ 10, 35, 60, 85, 110])
>>> np.sum(a, axis = 1)
array([ 10, 35, 60, 85, 110])
>>> np.einsum(a, [Ellipsis,1], [Ellipsis])
array([ 10, 35, 60, 85, 110])
>>> np.einsum('...j->...', a)
array([ 10, 35, 60, 85, 110])
>>>
>>> c # 矩阵转置
array([[0, 1, 2],
[3, 4, 5]])
>>> np.einsum('ji', c)
array([[0, 3],
[1, 4],
[2, 5]])
>>> np.einsum('ij->ji', c)
array([[0, 3],
[1, 4],
[2, 5]])
>>> np.einsum(c, [1,0])
array([[0, 3],
[1, 4],
[2, 5]])
>>>
>>> # 向量内积
>>> b
array([0, 1, 2, 3, 4])
>>> np.einsum('i,i', b, b)
30
>>> np.einsum(b, [0], b, [0])
30
>>> np.inner(b, b)
30
>>>
>>> # 向量和矩阵的乘积
>>> np.einsum('ij,j', a, b)
array([ 30, 80, 130, 180, 230])
>>> np.einsum(a, [0,1], b, [1])
array([ 30, 80, 130, 180, 230])
>>> np.dot(a, b)
array([ 30, 80, 130, 180, 230])
>>> np.einsum('...j,j', a, b)
array([ 30, 80, 130, 180, 230])
>>>
>>> # 广播和标量乘法
>>> c
array([[0, 1, 2],
[3, 4, 5]])
>>> np.einsum('...,...', 3, c)
array([[ 0, 3, 6],
[ 9, 12, 15]])
>>> np.einsum(',ij', 3, c)
array([[ 0, 3, 6],
[ 9, 12, 15]])
>>> np.einsum(3, [Ellipsis], c, [Ellipsis])
array([[ 0, 3, 6],
[ 9, 12, 15]])
>>> np.multiply(3, c)
array([[ 0, 3, 6],
[ 9, 12, 15]])
>>>
>>> # 向量外积
>>> t = np.arange(2) + 1
>>> t
array([1, 2])
>>> b
array([0, 1, 2, 3, 4])
>>>
>>> np.einsum('i,j', t, b)
array([[0, 1, 2, 3, 4],
[0, 2, 4, 6, 8]])
>>> np.einsum(t, [0], b, [1])
array([[0, 1, 2, 3, 4],
[0, 2, 4, 6, 8]])
>>> np.outer(t, b)
array([[0, 1, 2, 3, 4],
[0, 2, 4, 6, 8]])
>>>
>>> # tensordot
>>> a = np.arange(60).reshape(3,4,5)
>>> b = np.arange(24).reshape(4,3,2)
>>> np.einsum('ijk,jil->kl', a, b)
array([[4400, 4730],
[4532, 4874],
[4664, 5018],
[4796, 5162],
[4928, 5306]])
>>> np.einsum(a, [0,1,2], b, [1,0,3], [2,3])
array([[4400, 4730],
[4532, 4874],
[4664, 5018],
[4796, 5162],
[4928, 5306]])
>>> np.tensordot(a, b, axes=([1,0],[0,1]))
array([[4400, 4730],
[4532, 4874],
[4664, 5018],
[4796, 5162],
[4928, 5306]])
>>>
父主题: 统计基础函数