skip to content
s7ev3n'space

Einsum

/ 5 min read

einsum,又称为爱因斯坦求和约定,是爱因斯坦在张量运算中引入的一种简化符号规则,用于省略求和符号(\sum)。对于操作高维张量的深度学习系统来说,einsum非常的有用,可以简化很多的操作,例如转置,增加维度等。看到求和标记,经常会一脸懵逼不知道在做什么。

einsum规则

先看一个例子:np.einsum('ij,jk->ik', A, B),其中的'ij,jk->ik'就是所谓的求和约定,ij就是A的维度,jk就是B的维度,A和B在j这个维度上长度是一致的的,->ik就是输出的维度,并且观察到j这个维度被省略了,这就是einsum的求和规则,从输入中消失的标记,表示在这个维度上进行了求和操作。对于维度较低的矩阵操作,比较好想象,下面也有速查表

我们再来一个稍微复杂一些例子:einsum('abc,cd->abd', A, B),这里的求和标记到底意味着什么呢?发生了哪些的操作呢?

最简单的理解方式是从多层的for loop的角度来看,参考这里1

for a in range(A.shape[0]):
for b in range(A.shape[1]):
for d in range(B.shape[1]):
total = 0
for c in range(A.shape[2]):
total += A[a, b, c] * B[c, d]
C[a, b, d] = total

可以观察到,从输出的维度的a,b,d作为外层循环,并且观察输出的维度中相比输入的维度少了c,那就是在这个维度上求和,体现在上面的代码中,然后在c这个维度上进行遍历求和!

另外一种理解方式是从广播的角度来看的,还是以上面的求和标记为例:

  • 首先,观察输出是abcd,并在c的维度求和
  • abcd对比A的abc,在最后一个维度上缺失了,于是补1,变成(a, b, c, 1)
  • abcd对比B的cd,在前面两个维度上缺失了,于是补1,变成(1, 1, c, d)
  • 根据广播规则复制A和B,使得A和B的维度一致,进行逐元素相乘,得到(a, b, c, d)
  • 然后再对c这个维度求和,得到(a, b, d)

einsum的速查表

向量

AB是一维向量:

标记符号Numpy等价形式描述
('i', A)A向量A本身
('i->', A)sum(A)向量A所有元素求和
('i,i->i', A, B)A * B向量A和向量B逐元素相乘
('i,i', A, B)inner(A, B)向量A和向量B的内积
('i,j->ij', A, B)outer(A, B)向量A和向量B的外积

二维矩阵

AB是二维向量:

标记符号Numpy等价形式描述
('ij', A)A矩阵 A 本身
('ji', A)A.T矩阵 A 转置
('ii->i', A)diag(A)矩阵 A 对角元素
('ii', A)trace(A)矩阵 A 的 迹(主对角线之和)
('ij->', A)sum(A)矩阵 A 所有元素求和
('ij->j', A)sum(A, axis=0)矩阵 A 列求和
('ij->i', A)sum(A, axis=1)矩阵 A 行求和
('ij,ij->ij', A, B)A * BA 和 B 哈达玛积(逐元素相乘)
('ij,ji->ij', A, B)A * B.TA 和 B 的转置逐元素相乘
('ij,jk', A, B)dot(A, B)A 和 B 的矩阵乘法
('ij,kj->ik', A, B)inner(A, B)矩阵 A 和 矩阵 B 的内积
('ij,kj->ikj', A, B)A[:, None, :] * B[None, ...]
('ij,kl->ijkl', A, B)A[:, :, None, None] * B[None, None, :, :]

Footnotes

  1. Einstein Summation in Numpy

  2. Einsum Notation Practice