我是靠谱客的博主 舒心音响,最近开发中收集的这篇文章主要介绍einsum:深度学习中的爱因斯坦求和约定1.爱因斯坦求和约定2.以Tf为例,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1.爱因斯坦求和约定

PyTorch/TensorFlow中那些计算点积、外积、转置、矩阵-向量乘法、矩阵-矩阵乘法的函数名字和签名很费劲,那么einsum记法就是我们的救星。einsum记法是一个表达以上这些运算,包括复杂张量运算在内的优雅方式,基本上,可以把einsum看成一种领域特定语言。一旦你理解并能利用einsum,除了不用记忆和频繁查找特定库函数这个好处以外,你还能够更迅速地编写更加紧凑、高效的代码。而不使用einsum的时候,容易出现引入不必要的张量变形或转置运算,以及可以省略的中间张量的现象。此外,einsum这样的领域特定语言有时可以编译到高性能代码,事实上,PyTorch最近引入的能够自动生成GPU代码并为特定输入尺寸自动调整代码的张量理解(Tensor Comprehensions)就基于类似einsum的领域特定语言。此外,可以使用opt einsum和tf einsum opt这样的项目优化einsum表达式的构造顺序。

比方说,我们想要将两个矩阵A in R^{I times K}B in R^{Ktimes J}相乘,接着计算每列的和,最终得到向量C in R^J。使用爱因斯坦求和约定,这可以表达为:

矩阵相乘求和

这一表达式指明了c中的每个元素c_i是如何计算的,列向量A_{i:}乘以行向量B_{:j},然后求和。注意,在爱因斯坦求和约定中,我们省略了求和符号Sigma,因为我们隐式地累加重复的下标(这里是k)和输出中未指明的下标(这里是i)。当然,einsum也能表达更基本的运算。比如,计算两个向量aa,b  in R^J的点积可以表达为:

向量点积

在深度学习中,我经常碰到的一个问题是,变换高阶张量到向量。例如,我可能有一个张量,其中包含一个batch中的N个训练样本,每个样本是一个长度为T的K维词向量序列,我想把词向量投影到一个不同的维度Q。如果将这个张量记作T in R^{N times T times K},将投影矩阵记作W in R^{K times Q},那么所需计算可以用einsum表达为:

投影词向量

最后一个例子,比方说有一个四阶张量T in R^{N times T times K times M},我们想要使用之前的投影矩阵将第三维投影至Q维,并累加第二维,然后转置结果中的第一维和最后一维,最终得到张量C in R^{M times Q times N}。einsum可以非常简洁地表达这一切:

复杂张量计算

注意,我们通过交换下标nmC_{mqn}而不是C_{nqm}),转置了张量构造结果。

2.以Tf为例

tf.einsum
einsum( equation, *inputs) 
一般来说, 方程是从较熟悉的元素方程得到:

删除变量名称、括号和逗号; 
用 “*” 替换 “,”; 
删除总和标志; 
将输出移到右侧,并将 “=” 替换为 “->>”。 
许多常见操作可以用这种方式来表示。例如:

# Matrix multiplication
>>> einsum('ij,jk->ik', m0, m1)  # output[i,k] = sum_j m0[i,j] * m1[j, k]

# Dot product
>>> einsum('i,i->', u, v)  # output = sum_i u[i]*v[i]

# Outer product
>>> einsum('i,j->ij', u, v)  # output[i,j] = u[i]*v[j]

# Transpose
>>> einsum('ij->ji', m)  # output[j,i] = m[i,j]

# Batch matrix multiplication
>>> einsum('aij,ajk->aik', s, t)  # out[a,i,k] = sum_j s[a,i,j] * t[a, j, k]


例子

# 初始化矩阵
x = tf.constant([[1., 2., 3.],
                 [1., 2., 3.]])
y = tf.constant([[2., 3., 4.],
                 [2., 3., 4.]])
z = tf.constant([[3., 4.],
                 [3., 4.],
                 [3., 4.]])
# 外积
out = tf.multiply(x, y)
out1 = tf.einsum('ij,ij->ij', x, y)
# 点积
dot = tf.matmul(x, z)
dot1 = tf.einsum('ij,jk->ik', x, z)
# 转置
trans = tf.transpose(x, [1, 0])
trans1 = tf.einsum('ij->ji', x)
with tf.Session() as sess:
    print('外积')
    print('outn{}'.format(sess.run(out)))
    print('out1n{}'.format(sess.run(out1)))
    print('点积')
    print('dotn{}'.format(sess.run(dot)))
    print('dot1n{}'.format(sess.run(dot1)))
    print('转置')
    print('transn{}'.format(sess.run(trans)))
    print('trans1n{}'.format(sess.run(trans1)))


输出
 

# 初始化矩阵
x = tf.constant([[1., 2., 3.],
                 [1., 2., 3.]])
y = tf.constant([[2., 3., 4.],
                 [2., 3., 4.]])
z = tf.constant([[3., 4.],
                 [3., 4.],
                 [3., 4.]])
# 外积
out = tf.multiply(x, y)
out1 = tf.einsum('ij,ij->ij', x, y)
# 点积
dot = tf.matmul(x, z)
dot1 = tf.einsum('ij,jk->ik', x, z)
# 转置
trans = tf.transpose(x, [1, 0])
trans1 = tf.einsum('ij->ji', x)
with tf.Session() as sess:
    print('外积')
    print('outn{}'.format(sess.run(out)))
    print('out1n{}'.format(sess.run(out1)))
    print('点积')
    print('dotn{}'.format(sess.run(dot)))
    print('dot1n{}'.format(sess.run(dot1)))
    print('转置')
    print('transn{}'.format(sess.run(trans)))
    print('trans1n{}'.format(sess.run(trans1)))

 

最后

以上就是舒心音响为你收集整理的einsum:深度学习中的爱因斯坦求和约定1.爱因斯坦求和约定2.以Tf为例的全部内容,希望文章能够帮你解决einsum:深度学习中的爱因斯坦求和约定1.爱因斯坦求和约定2.以Tf为例所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部