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

爱因斯坦求和约定

在数学里,特别是将 线性代数套用到物理时,爱因斯坦求和约定(Einstein summation convention)是一种标记的约定,又称为爱因斯坦标记法(Einstein notation),在处理关于 坐标的方程式 时非常有用

采用爱因斯坦求和约定,可以使 数学表达式 显得 简洁明快

约定

  1. 在同一项中,如果同一指标(如上式中的i)成对出现,就表示遍历其取值范围求和。这时求和符号可以省略。

  2. 上述成对出现的指标可以用另一对小写字母替换,只要其取值范围不变。

  3. 当两个求和式 相乘 时,两个求和式的指标 不能 使用相同的小写字母。

以上内容源自百度百科(缩减):
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


原文出处:/show_1EF4iknVnZK4.html