numpy.einsum

原文:https://docs.scipy.org/doc/numpy/reference/generated/numpy.einsum.html

译者:飞龙 UsyiyiCN

校对:(虚位以待)

numpy.einsum(subscripts, *operands, out=None, dtype=None, order='K', casting='safe')

评估操作数上的爱因斯坦求和约定。

使用爱因斯坦求和约定,许多常见的多维数组操作可以以简单的方式表示。该函数提供了一种计算这种求和的方法。理解此函数的最佳方法是尝试下面的示例,它们显示了可以实现多少常见NumPy函数作为对einsum的调用。

参数:

下标:str

指定求和的下标。

操作数:array_like的列表

这些是操作的数组。

out:ndarray,可选

如果提供,计算将在此数组中完成。

dtype:数据类型,可选

如果提供,强制计算使用指定的数据类型。请注意,您可能还必须提供更宽松的投射参数,以允许转换。

订单:{'C','F','A','K'},可选

控制输出的内存布局。'C'意味着它应该是C连续的。'F'意味着它应该是Fortran连续,'A'意味着如果输入全部是'F',则它应该是'F',否则'C'。'K'意味着它应该尽可能接近输入的布局,包括任意排列的轴。默认值为“K”。

投射:{'no','equiv','safe','same_kind','unsafe'},可选

控制可能发生的数据转换类型。不建议将此设置为“不安全”,因为它会对累积产生不利影响。

  • 'no'意味着不应该转换数据类型。
  • 'equiv'意味着只允许字节顺序改变。
  • “安全”意味着只允许保留值的转换。
  • 'same_kind'表示只允许一种类型中的安全类型转换,例如float64到float32。
  • “不安全”表示可以进行任何数据转换。
返回:

输出:ndarray

基于爱因斯坦求和约定的计算。

也可以看看

dotinneroutertensordot

笔记

版本1.6.0中的新功能。

下标字符串是逗号分隔的下标标签列表,其中每个标签引用相应操作数的维。一个操作数中的重复下标标签采用对角线。例如,np.einsum('ii', a)等效于np.trace(a)

每当重复标签时,它被求和,因此np.einsum('i,i', a, b) / t0>等效于np.inner(a,b)If a label appears only once, it is not summed, so np.einsum('i', a) produces a view of a with no changes.

输出中的标签顺序默认为字母顺序。这意味着np.einsum('ij', a)不影响2D数组,而.einsum('ji', a)接受其转置。

输出也可以通过指定输出下标标签来控制。这指定标签顺序,并且允许在需要时禁止或强制求和。调用np.einsum('i->', a)就像np.sum axis = -1)np.einsum('ii-> i', / t8>就像np.diag(a)区别在于einsum默认不允许广播。

要启用和控制广播,请使用省略号。通过在每个项的左侧添加省略号来完成默认NumPy风格广播,例如np.einsum('... ii-> ... i', a)要沿着第一个和最后一个轴进行跟踪,你可以做np.einsum('i ... i', a) 或者用最左边的索引而不是最右边的索引来做矩阵矩阵乘积,你可以做np.einsum('ij ...,jk ...-> ik ...' a, b)

当只有一个操作数,没有轴被求和,并且没有提供输出参数时,将返回操作数中的视图,而不是返回一个新的数组。因此,将对角线视为np.einsum('ii-> i', a)产生视图。

提供下标和操作数的替代方式是einsum(op0, sublist0, op1, sublist1, t4> ..., [sublistout])以下示例使用两个参数方法进行相应的einsum调用。

版本1.10.0中的新功能。

从输入数组可写时,从einsum返回的视图现在可写。例如,np.einsum('ijk ...-> kji ...', a)现在将具有相同的效果作为np.wapaxes(a, 0, 2)np.einsum 'i', a)将返回2D数组的对角线的可写视图。

例子

>>> a = np.arange(25).reshape(5,5)
>>> b = np.arange(5)
>>> c = np.arange(6).reshape(2,3)
>>> 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,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])
>>> np.einsum('ji', c)
array([[0, 3],
       [1, 4],
       [2, 5]])
>>> np.einsum(c, [1,0])
array([[0, 3],
       [1, 4],
       [2, 5]])
>>> c.T
array([[0, 3],
       [1, 4],
       [2, 5]])
>>> np.einsum('..., ...', 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]])
>>> np.einsum('i,i', b, b)
30
>>> np.einsum(b, [0], b, [0])
30
>>> np.inner(b,b)
30
>>> np.einsum('i,j', np.arange(2)+1, b)
array([[0, 1, 2, 3, 4],
       [0, 2, 4, 6, 8]])
>>> np.einsum(np.arange(2)+1, [0], b, [1])
array([[0, 1, 2, 3, 4],
       [0, 2, 4, 6, 8]])
>>> np.outer(np.arange(2)+1, b)
array([[0, 1, 2, 3, 4],
       [0, 2, 4, 6, 8]])
>>> np.einsum('i...->...', a)
array([50, 55, 60, 65, 70])
>>> np.einsum(a, [0,Ellipsis], [Ellipsis])
array([50, 55, 60, 65, 70])
>>> np.sum(a, axis=0)
array([50, 55, 60, 65, 70])
>>> 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.]])
>>> a = np.arange(6).reshape((3,2))
>>> b = np.arange(12).reshape((4,3))
>>> np.einsum('ki,jk->ij', a, b)
array([[10, 28, 46, 64],
       [13, 40, 67, 94]])
>>> np.einsum('ki,...k->i...', a, b)
array([[10, 28, 46, 64],
       [13, 40, 67, 94]])
>>> np.einsum('k...,jk', a, b)
array([[10, 28, 46, 64],
       [13, 40, 67, 94]])
>>> # since version 1.10.0
>>> a = np.zeros((3, 3))
>>> np.einsum('ii->i', a)[:] = 1
>>> a
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])