爱因斯坦求和约定
在数学里,特别是将 线性代数套用到物理时,爱因斯坦求和约定(Einstein summation convention)是一种标记的约定,又称为爱因斯坦标记法(Einstein notation),在处理关于 坐标的方程式 时非常有用
采用爱因斯坦求和约定,可以使 数学表达式 显得 简洁明快
约定
在同一项中,如果同一指标(如上式中的i)成对出现,就表示遍历其取值范围求和。这时求和符号可以省略。
上述成对出现的指标可以用另一对小写字母替换,只要其取值范围不变。
当两个求和式 相乘 时,两个求和式的指标 不能 使用相同的小写字母。
以上内容源自百度百科(缩减):
https://baike.baidu.com/item/%E7%88%B1%E5%9B%A0%E6%96%AF%E5%9D%A6%E6%B1%82%E5%92%8C%E7%BA%A6%E5%AE%9A/2477100?fr=aladdin
tf.einsum()
在tensorflow中,通过tf.einsum()实现爱因斯坦求和,计算 点积、外积、转置、矩阵-向量乘法时,更加简练
- ein:Einstein缩写
- sun:summation缩写
用法与np.einsum()类似
官方api文档:
https://www.tensorflow.org/api_docs/python/tf/einsum?version=nightly
语法
tf.einsum(
equation,
*inputs,
**kwargs
)
参数
- equation:str类型,描述运算格式。详见下面用法
- *inputs:a Tensor
- **kwargs:-优化:用于通过opt_einsum查找收缩路径的优化策略。必须为’greedy’, ‘optimal’, ‘branch-2’, ‘branch-all’ or ‘auto’.。(可选,默认为:“ greedy”)。
name:操作名称(可选)
返回值
a Tensor
一般用法
- ◻是占位符,表示张量维度。
删掉变量名、括号、总和符号
将*替换成,
将输出移到右侧,用->表示 - arg1、arg2、arg3是矩阵,可变数量的输入。
例子中指定了三个参数之上的操作,但可以用在 一个参数、两个参数、三个以上参数 的操作上。
矩阵转置
a = tf.constant(np.arange(6).reshape(2, 3))
print(a.numpy())
a2=tf.einsum('ij->ji', a)
print(a2.numpy())
执行结果:
[[0 1 2]
[3 4 5]]
[[0 3]
[1 4]
[2 5]]
对矩阵求和
对一个矩阵的所有元素求和
a = tf.constant(np.arange(6).reshape(2, 3))
print(a.numpy())
sum=tf.einsum('ij->', a)
print(sum.numpy())
执行结果:
[[0 1 2]
[3 4 5]]
15
对矩阵的 列求和
对一个矩阵的列求和
a = tf.constant(np.arange(6).reshape(2, 3))
print(a.numpy())
res=tf.einsum('ij->j', a)
print(res.numpy())
执行结果:
[[0 1 2]
[3 4 5]]
[3 5 7]
对矩阵的 行求和
对一个矩阵的行求和
a = tf.constant(np.arange(6).reshape(2, 3))
print(a.numpy())
res=tf.einsum('ij->i', a)
print(res.numpy())
执行结果:
[[0 1 2]
[3 4 5]]
[ 3 12]
2个一维数组按照矩阵相乘
一个长度是i的一维数组,一个长度是j的一维数组,按照矩阵相乘,这里先将第一个数组转成二维(i行1列),然后再按照矩阵相乘
# 转置后运算
a=tf.constant(np.arange(3))
b=tf.constant(np.arange(3,7))
print("a:",a.numpy(),sep="\n")
print("b:",b.numpy(),sep="\n")
res=tf.einsum('i,j->ij',a,b)
print("res:",res.numpy(),sep="\n")
print("相当于","-"*50)
a2=tf.reshape(a,(-1,1))
print("a2:",a2.numpy(),sep="\n")
print(a2*b)
执行结果:
a:
[0 1 2]
b:
[3 4 5 6]
res:
[[ 0 0 0 0]
[ 3 4 5 6]
[ 6 8 10 12]]
相当于 --------------------------------------------------
a2:
[[0]
[1]
[2]]
tf.Tensor(
[[ 0 0 0 0]
[ 3 4 5 6]
[ 6 8 10 12]], shape=(3, 4), dtype=int32)
矩阵-向量 相乘
# 矩阵-向量相乘
a = tf.constant(np.arange(6).reshape(2, 3))
b = tf.constant(np.arange(3))
print("a:",a.numpy(),sep="\n")
print("b:",b.numpy(),sep="\n")
res=tf.einsum('ij,j->i', a, b)
print("res:",res.numpy(),sep="\n")
执行结果:
a:
[[0 1 2]
[3 4 5]]
b:
[0 1 2]
res:
[ 5 14]
m行j列矩阵-j行n列矩阵相乘
# 矩阵-矩阵相乘
a = tf.constant(np.arange(6).reshape(2, 3))
b=tf.constant(np.arange(6).reshape(3,2))
print("a:",a.numpy(),sep="\n")
print("b:",b.numpy(),sep="\n")
res=tf.einsum('ij,jk->ik',a,b)
print("res:",res.numpy(),sep="\n")
# 等同tf.matmul(a,b)
res2=tf.matmul(a,b)
print("res2:",res.numpy(),sep="\n")
执行结果:
a:
[[0 1 2]
[3 4 5]]
b:
[[0 1]
[2 3]
[4 5]]
res:
[[10 13]
[28 40]]
res2:
[[10 13]
[28 40]]
形状相同的矩阵 相乘
2个形状相同的矩阵 相乘
# 矩阵-矩阵相乘
a=tf.constant(np.arange(6).reshape(2, 3))
a=tf.transpose(a,(1,0))
b=tf.constant(np.arange(6).reshape(3,2))
print("a:",a.numpy(),sep="\n")
print("b:",b.numpy(),sep="\n")
res=tf.einsum('ij,ik->jk',a,b)
print("res:",res.numpy(),sep="\n")
#等同下面的代码
res2=tf.matmul(a,b,transpose_a=True)
print("res2:",res.numpy(),sep="\n")
哈达玛积
# 哈达玛积,即矩阵同位置元素相乘
a = tf.constant(np.arange(6).reshape(2,3))
c = tf.constant(np.arange(6).reshape(2,3))
print("a:",a.numpy(),sep="\n")
print("b:",b.numpy(),sep="\n")
res=tf.einsum('ij,ij->ij',a,c)
print("res:",res.numpy(),sep="\n")
# 相当于
res2=tf.multiply(a,c)
print("res2:",res2.numpy(),sep="\n")
重点用法
一维向量 点积
# 点积
a=tf.constant(np.arange(3))
b=tf.constant(np.arange(3,6))
print("a:",a.numpy(),sep="\n")
print("b:",b.numpy(),sep="\n")
res=tf.einsum('i,i->',a,b)
print("res:",res.numpy(),sep="\n")
执行结果:
a:
[0 1 2]
b:
[3 4 5]
res:
14
矩阵 点积
# 矩阵-矩阵点积
a=tf.constant(np.arange(6).reshape(2, 3))
b=tf.constant(np.arange(6,0,-1).reshape(2,3))
print("a:",a.numpy(),sep="\n")
print("b:",b.numpy(),sep="\n")
res=tf.einsum('ij,ij->',a,b)
print("res:",res.numpy(),sep="\n")
执行结果:
a:
[[0 1 2]
[3 4 5]]
b:
[[6 5 4]
[3 2 1]]
res:
35
可以理解为阿达姆积,然后求和
i行j列矩阵-j行k列矩阵点积(废弃)
# 矩阵-矩阵点积
a=tf.constant(np.arange(6).reshape(2, 3))
b=tf.constant(np.arange(6).reshape(3,2))
print("a:",a.numpy(),sep="\n")
print("b:",b.numpy(),sep="\n")
res=tf.einsum('ij,jk->',a,b)
print("res:",res.numpy(),sep="\n")
执行结果:
a:
[[0 1 2]
[3 4 5]]
b:
[[0 1]
[2 3]
[4 5]]
res:
91
感谢:
https://blog.csdn.net/zzq060143/article/details/89107567
https://cloud.tencent.com/developer/article/1369762

