np.einsum(爱因斯坦求和约定)

欢迎关注我的微信公号:小张Python

einsum 全称 Einstein summation convention(爱因斯坦求和约定),用简单的方式来代表多维数组运算;

矩阵求各元素之和
A = ∑ i = 0 n ∑ j = 0 n a i a j A = \sum_{i=0}^n\sum_{j=0}^na_ia_j A=i=0nj=0naiaj
如果用 einsum函数可表示为

A = np.einsum('i',a)

多矩阵相乘
C i k = ∑ j = 1 n A i j B j k C_{ik} = \sum_{j=1}^nA_{ij}B_{jk} Cik=j=1nAijBjk
表示为

C_i = np.einsum('ij,jk',a,b)

求矩阵的迹
t r a c e = ∑ i = 1 n A i i trace = \sum_{i=1}^nA_{ii} trace=i=1nAii
用 einsum函数可表示为

trace = np.einsum('ii',a)

对于数组间运算例如矩阵乘积和、沿某一轴点积和;enisum 为多维数组运算提供另外一种表示方式,指定的下标标签列表,用逗号隔开;enisum 函数在 numpy ,Pytorch,Tensorflow 都有实现,使用方式如下

np.einsum(subscripts:str,operands:list of array_like)

函数中参数 subscripts 为字符串类型,表示运算命令,例如 "ii","ij,jk" 参数 operands 代表需要计算的数组或数组列表;

enisum 中 subscrpts 参数的字符串形式有两种方式:

1,implicit(隐式模式) 不包含-> 标识符和输出标签;输出数组会根据选择的下标顺序进行排序,例如 np.einsum('ij',a) 得到的二维数组无变化,但 np.einsum('ji',a) 需要对输出数组进行转置 (i ,j 轴互换)操作

2,explicit(显式模式) 包含 标识符->及输出标签,能够增加函数的灵活性,例如调用 np.einsum('i->',a) 效果类似于 np.sum(a,axis = -1) ;而 np.einsum('ii->i',a) 等同于 np.diag(a) ;另外在显式模式中,会直接指定输出数组下标顺序,例如 np.einsum('ij,jh->ih',a,b) 表示矩阵相乘;目前下面运算都可用 enisum 函数表示;

  • 求一个数组的迹,numpy.trace;
  • 返回对角线,numpy.diag
  • 对数组沿某个轴求和,numpy.sum
  • 数组转置,numpy.transpose
  • 矩阵相乘或点积,numpy.matmul,numpy.dot
  • 向量内积外积,numpy.inner,numpy.outer
  • 广播,逐像素相乘,或标量相乘,numpy.multiply
  • 张量收缩,numpy.tensorbot

关于 np.enisum() 函数举几个栗子:

>>> a = np.arange(25).reshape(5,5)
>>> b = np.arange(5)
>>> c = np.arange(6).reshape(2,3)

1,计算矩阵的迹

>>> np.einsum('ii...->...i',a)
array([-0.796318  ,  0.08363816, -0.79171551,  0.36235911])
>>> np.einsum('i...i',a)
-1.1420362461348776
>>> a
array([[-0.796318  ,  1.54759498, -0.744291  ,  0.02107445],
       [ 0.03826498,  0.08363816,  0.92709203,  0.04769788],
       [ 0.39088153, -0.85566069, -0.79171551, -1.50750047],
       [-1.16165527,  0.77327936,  0.44133708,  0.36235911]])
>>> np.trace(a)
-1.1420362461348776

2,矩阵相乘

>>> b =np.random.rand(4,5)
>>> np.einsum('ij...,jk...->ik...',a,b)
array([[-0.207485  ,  0.37929742, -1.14191507, -0.30398675, -0.59431733],
       [ 0.03389816,  0.10101184,  0.78917293,  0.41502013,  0.37634113],
       [-0.3499671 , -0.45043889, -1.67700784, -0.68798725, -0.49966522],
       [-0.2186732 , -0.30529867, -0.21863002,  0.02300085, -0.50540297]])
>>> np.matmul(a,b)
array([[-0.207485  ,  0.37929742, -1.14191507, -0.30398675, -0.59431733],
       [ 0.03389816,  0.10101184,  0.78917293,  0.41502013,  0.37634113],
       [-0.3499671 , -0.45043889, -1.67700784, -0.68798725, -0.49966522],
       [-0.2186732 , -0.30529867, -0.21863002,  0.02300085, -0.50540297]])

3,对角线 diag

>>> np.einsum('ii->i',a)
array([ 0,  6, 12, 18, 24])
>>> np.diag(a)
array([ 0,  6, 12, 18, 24])

4,沿数组某一轴求和(需要在 explicit 模式下运行)

>>> # 沿着某一轴求和,显示模式运行
>>> np.einsum('ij->i',a)
array([ 10,  35,  60,  85, 110])
d
>>> np.sum(a,axis = 1)
array([ 10,  35,  60,  85, 110])

5,数组转置,改变轴顺序

>>> # 计算数组转置,对某些轴重新排序
>>> c
array([[0, 1, 2],
       [3, 4, 5]])
>>> np.einsum('ji',c)
array([[0, 3],
       [1, 4],
       [2, 5]])
>>> np.transpose(c)
array([[0, 3],
       [1, 4],
       [2, 5]])

6,inner(计算内积)

>>> np.einsum('i,i',b,b)
30
>>> b
array([0, 1, 2, 3, 4])
>>> np.inner(b,b)# 一维数组,逐像素乘积和
30

7,矩阵点乘

>>> np.einsum('ij,j',a,b)
array([ 30,  80, 130, 180, 230])
>>> np.dot(a,b)
array([ 30,  80, 130, 180, 230])
>>> 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
array([0, 1, 2, 3, 4])
>>> np.dot(a[-1],b)# Test
230

8,张量数组相乘

>>> np.einsum(',ij',3,c)
array([[ 0,  3,  6],
       [ 9, 12, 15]])
>>> np.multiply(3,c)
array([[ 0,  3,  6],
       [ 9, 12, 15]])
>>> # 向量外积

8,广播机制,outer

>>> b
array([0, 1, 2, 3, 4])
>>> np.einsum('i,j',np.arange(2)+1,b)
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]])

9,Tensor contraction,数组收缩沿着某一轴相乘

>>> 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.tensordot(a,b,axes = [[1,0],[0,1]])
array([[4400, 4730],
       [4532, 4874],
       [4664, 5018],
       [4796, 5162],
       [4928, 5306]])

:在 numpy 版本 1.12.0 之后,einsum加入了 optimize 参数,用来优化 contraction 操作,对于 contraction 运算部分,操作的数组包含三个或三个以上,optimize 参数设置能提高计算效率,减小内存占比;


Reference:

1,https://zhuanlan.zhihu.com/p/71639781

2,https://numpy.org/doc/stable/reference/generated/numpy.einsum.html

  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 可以使用以下代码来使用np.einsum求立方: import numpy as np # 创建一个3 x 3的数组 a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 使用np.einsum求立方 a_cubed = np.einsum('ijk, ijk -> ijk', a, a, a) print(a_cubed) 输出结果: [[ 1 8 27] [ 64 125 216] [343 512 729]] ### 回答2: np.einsum函数是NumPy中的一个强大的多维数组计算工具,可以灵活地进行各种矩阵运算。使用np.einsum函数可以实现求立方的操作。 具体实现方法如下: 首先,我们需要创建一个三维的多维数组,可以使用np.arange函数创建一个一维数组,然后使用np.reshape函数将其转换为三维数组。 例如,创建一个形状为(3,3,3)的三维数组: arr = np.arange(27).reshape((3,3,3)) 然后,我们可以使用np.einsum函数对数组进行立方运算。具体实现可以使用完全指定的字符串表示,例如"ijk,ijk->ijk"表示对三维数组arr的每个元素进行立方运算。 例如,对arr进行立方运算: result = np.einsum("ijk,ijk->ijk", arr, arr, arr) 最后,我们可以打印出结果查看: print(result) 这样,我们就可以使用np.einsum函数实现对多维数组进行立方的操作了。 ### 回答3: np.einsum是一个用于执行张量操作的函数。在求立方方面,可以使用np.einsum来实现。假设有一个输入张量A,它是一个形状为(N, N, N)的三维张量,表示一个立方体。现在我们想要计算立方体中每个元素的立方。我们可以使用np.einsum来实现这个操作。 具体实现如下: ```python import numpy as np # 创建一个形状为(N, N, N)的三维张量A N = 10 A = np.random.rand(N, N, N) # 使用np.einsum对A中的每个元素进行立方操作 result = np.einsum('ijk,ijk,ijk->ijk', A, A, A) print(result) ``` 在上面的代码中,我们使用了np.einsum函数,并通过字符串参数来定义了实际的张量操作。在字符串参数中,'ijk'表示A的三个维度,相当于遍历了每个维度的元素,并将其立方。最后,我们将结果存储在名为result的新张量中,并输出结果。 通过使用np.einsum函数,我们可以方便地对三维立方体中的每个元素进行立方操作,实现了立方的计算。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员大飞1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值