深度学习--爱因斯坦求和einsum--85

目录
  • 1. 爱因斯坦求和的来源
  • 2. 求和表达式的规范
  • 3. 规则1:外部重复做乘积
  • 4. 规则2 内部重复把数取
  • 5. 规则3 从有到无要求和
  • 6. 规则4 重复默认要丢弃
  • 7. 把这个实现一下 加深理解

1. 爱因斯坦求和的来源

https://zhuanlan.zhihu.com/p/672346603
爱因斯坦在研究相对论时,曾经对冗余的求和公式做了一个简化版的约定,并且发表在了一些关于相对论的书籍, 比如《The Meaning of Relativity》中。
看完后你就与爱因斯坦有过碰撞了!!
原始的约定其实很简单:

省略求和符号,简化书写。。。

意思就是下标出现两次的求和公式可以将求和符号省略:

对于这个求和约定,爱因斯坦曾经这么评价:
这是数学史上的一大发现,若不信的话,可以试着返回那不使用这方法的古板日子。
这就是爱因斯坦求和约定最原始的出处,简称为 einsum。

后来各个领域比如数学,物理,AI 等领域都对求和约定进行了一些规范化。
最近很多代码实现都基于einsum, 用一种最好理解的方式讲一下爱因斯坦求和约定。

注意:
下面讲的主要是针对 AI 领域的,也就是 np.einsum 或者 torch.einsum,tf.sinsum,物理等其他领域的可能有其他的约定。

einsum,4句口诀:
外部重复做乘积,
内部重复把数取,
从有到无要求和,
重复默认要丢弃.

2. 求和表达式的规范

首先理解一下求和标记。np.einsum 或者 torch.einsum 的第一个参数是求和标记,它表明了 einsum 的输入下标和输出下标,我们举个例子。

np.einsum('ij,jk->ijk', A, B)  # 得到的是一个新的矩阵 维度是(i,j,k)

看下图更直观:

解释:
-> 符号左边是输入下标,右侧是输出下标
, 对输入的下标进行分割,分割后第n段代表第n个输入
下标用'a-z'的小写字母表示,代表了输入的第几维。
比如上例中逗号左侧的i是输入A的第1维, j是输入A的第2维。
逗号右侧的j是输入B的第1维, k是输入B的第二维。

内部重复与外部重复
求和标记的下标有时候会重复,比如 ij,jk->ijk 中,输入坐标j就重复了。
注意:
重复只针对输入下标,输出下标是没有重复的。
重复的下标做对应输入维度的长度肯定是相同的。

举例:
比如 A.shape 为 (2,3,2),B.shape 为 (2,3,4), 此时 'iji,ijk' 是合法的。
但是:
'iii,ijk' 非法,因为 A 的第一维长度为2,第二维长度为3,不匹配。
'iji,iji' 非法,因为 B 的最后一维长度为4,i 所在维度都是2,不匹配。
'ija,ijk' 合法,长度相同的可以不重复,但是重复的一定长度相同。

对于例子 'ij,jk->ijk'来说,可以看到重复的 j 分别属于两个输入,中间用逗号隔开,我们称这种为外部重复。
如果重复的下标出现在了同一个输入中,则称为内部重复。比如 iji,jk->ijk, 此时 i 为内部重复, j 为外部重复。
下标可以同时为内部重复和外部重复,比如 iji,ijk->ijk。此时 i 在第一个输入中内部重复,同时在第一个和第二个输入中外部重复。

先把上面的约定理解了

3. 规则1:外部重复做乘积

在 np.einsum('ij,jk->ijk', A, B) 这个例子中,j 属于外部重复
einsum 会对外部重复的下标进行相乘操作,一个方便理解但是并不高效的实现方法如下:

for i in range(A.shape[0]):for j in range(A.shape[1]):for k in range(B.shape[1]):C[i, j, k] = A[i, j] * B[j, k]

高维没法画图:

A4D = np.random.randint(20, size=(3, 4, 5, 2))
B3D = np.random.randint(20, size=(2, 4, 5))
x = np.einsum('ipqk,jpq->ijkpq', A4D, B3D)
# x的shape (3,2,2,4,5)y = np.zeros((3,2,2,4,5))
# equals below
for i in range(A4D.shape[0]):for j in range(B3D.shape[0]):for k in range(A4D.shape[3]):for p in range(A4D.shape[1]):for q in range(A4D.shape[2]):y[i,j,k,p,q] = A4D[i,p,q,k] * B3D[j,p,q]
y

4. 规则2 内部重复把数取

对于前一个例子来说,可以看到输入对每个维度都遍历了一遍,那可以思考一下,如果一个下标内部重复了,在遍历时是个什么情况?
A 是一个 3x3 的矩阵,求和标记为 'ii->i', 如果仿照上面类似的方法进行运算

C = np.einsum('ii->i', A)for i in range(A.shape[0]):for i in range(A.shape[1]):C[i] = A[i, i]

如果这么写,你会发现 C[i] 的值会被改写,这在 einsum 中是不允许的,所以同一下标只能迭代一次才能保证输出的稳定性。
正确的写法:

for i in range(A.shape[0]):C[i] = A[i, i]


可以看到,输入中只有部分参与了运算,所以对于内部重复的下标,其实是一个取数的操作。
上面的例子就是取数,而且正好是取了矩阵的对角线,相当于 diag 操作。

5. 规则3 从有到无要求和

上面的例子有个特点,那就是输入的下标全部都在输出中都出现了。那假设输出中某些下标没有了,对于这些消失的下标要进行求和操作。
还是以第一个举例,假设求和标记从 ij,jk->ijk 变成了 ij,jk->ik。也就是下标 j 消失了,这个时候要对 j 维进行求和,相当于 np.sum(y, axis=j)


这不就是矩阵的乘法

A = np.random.randint(20, size=(2,3))
B = np.random.randint(20, size=(3,4))
print(A)
print(B)
C = np.zeros((2,4))
for i in range(A.shape[0]):for k in range(B.shape[1]):for j in range(A.shape[1]):C[i, k] += A[i, j] * B[j, k]
print(C)            C = np.ones((2,4))
for i in range(A.shape[0]):for k in range(B.shape[1]):C[i, k] = (A[i, :] * B[:, k]).sum()  # 取A的第i行 与B的k列相乘相加结果放入C[i,k]
print(C)

6. 规则4 重复默认要丢弃

在使用中,有时候你会看到只有输入下标。没有 -> 和输出下标。
这个时候就触发了默认求和标记,此时输出默认为:重复下标都去掉,不重复的下标按字母序保留。

A = np.random.randint(0, 20, size=(2, 3, 2))
B = np.random.randint(0, 20, (3, 4))
print(A) # (2,3, 2)
print(B) # (3,4)

A = np.random.randint(20, size=(2,3))
B = np.random.randint(20, size=(3,4))
print(A)
print(B)np.einsum('ij,jk', A, B)
np.einsum('ij,jk->ik', A, B)
# 这两等价

7. 把这个实现一下 加深理解

https://blog.csdn.net/weixin_42014622/article/details/104829672

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/721184.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python 使用 pyinstaller打包可执行文件

首先要pip install pyinstaller 命令 安装库,下面这图显示我已经安装成功了。主要是看在哪里输入命令。 然后打开设置,点击加号点完加号之后,就是这样的。name 自己设置,主要是Tool Settings 里面的三个选项。 第一个是刚才下载好的pyinstaller.exe文件地址,点击浏览文件…

WebLogic T3反序列化漏洞

在Weblogic中RMI通信的实现是使用T3协议,并且在T3的传输过程中同样会进行序列化和反序列化的操作。目录前言T3协议概述T3反序列漏洞分析漏洞复现修复措施 前言 WebLogic的反序列化漏洞是一个经典的漏洞系列,原因就在于WebLogic在通信过程中使用T3协议传输数据,涉及到了序列化…

自定义监控项

采集TCP连接状态(实战项目) 精确分析tcp连接状态,可以精准得知服务器的链接情况,确保web服务器的健康1. 命令获取tcp的状态[root@web-7 ~]# # -a 显示所有socket、-t显示tcp协议连接 -n 只显示ip [root@web-7 ~]#netstat -ant Active Internet connections (servers and e…

Android Media Framework(二)OpenMAX 类型阅读与分析

OMX IL Spec将API划分为Control API、Data API、Extension API,所谓Control API指的是IL Client用于控制组件的接口,包含调用OMX Core和OMX Component要用的接口与相关结构体,这一篇我们将重点阅读与Control API相关的宏、结构体与枚举。1、OMX IL目录结构 OMX IL API由一组…

zabbix企业微信报警

1.微信报警原理流程注册微信企业号,通过企业号提供的信息ID、以及获取微信的API接口,就可以将服务器的报警数据,发给API,发给微信,发给关注这个公众号的所有用户、2.注册企业微信https://work.weixin.qq.com/wework_admin/frame3.修改通讯录组名4.创建自定义zabbix应用5.查…

Win 开机自启动顺序

所有 Windows 系列都没有提供调整开机自启动优先级的功能,但 Windows 可以间接延迟启动顺序。1:自启动方式 开机自启动一般有以下三种方式,启动顺序根据设置方式决定。 系统启动时执行的顺序大于用户登录时执行的顺序。方式 解释计划任务 用户登录时执行 和 系统启动时执行 …

zabbix钉钉报警

1.钉钉报警原理流程和微信报警类似,发送指定的数据到钉钉官方提供的API接口,钉钉会将报警信息,发送到指定的钉钉群聊,提醒所有的群成员查看,实现告警通知。具体操作流程 创建钉钉群聊 创建自定义机器人 创建报警关键词 生成webhook认证信息 开发报警脚本 填写zabbix-UI界面…

如何在Windows系统下配置最新的MinGW(GCC14)环境,同时应用到Dev-C++中

本文手把手地介绍了如何配置安装好最新的MinGW环境,然后进一步教了如何给Dev-C++加新的GCC编译器。如何在Windows系统下配置最新的MinGW(GCC14)环境,同时应用到Dev-C++中 前言 本教程只面向小白,目的是配置出一个Windows能用的新GCC环境,未深入涉及细节配置。 在访问文中…

Github Discussions使用指南(建议收藏)

序言 之所以想着翻译这篇文章,是因为我看到国内不管是开源爱好者,还是开发者都不怎么了解 Github Discussions,以致于在 Github 仓库中提问时,总是忘记使用这个好东西,或者问错地方。 翻译自:What is GitHub Discussions? A complete guide引言 GitHub Discussions 可将…

BUUCTF-Misc(111-120)

[UTCTF2020]File Carving 010editor打开发现了一个压缩包解压出来一个ELF文件我们拖到虚拟机去运行一下吧得到flag flag{2fbe9adc2ad89c71da48cabe90a121c0}二维码 参考: BUUCTF:二维码 - B0mbax - 博客园 (cnblogs.com) ps修复一下,我也不会,用的大佬的flag{7bf116c8ec2545…

spring security 指定了 failureForwardUrl 的请求接口 但是没有效果

springboot版本:3.3.0 spring security版本:3.3.0代码如下: spring security 配置类import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.buil…