爱因斯坦求和约定 含代码

目录

一、简介

1.自由标

2.哑标

二、torch实现

1.计算迹

2.取矩阵对角线

3.计算外积

4.batch矩阵乘法

5.带有子列表和省略号

6.变换维度

7.双线性变换,类似于torch.nn.functional.bilinear


一、简介

        爱因斯坦求和约定(Einstein summation convention)是一种标记的约定, 又称为爱因斯坦标记法(Einstein notation), 可以基于一些约定简写格式表示多维线性代数数组操作,让表达式更加简洁明了,比如通过省略求和符号\sum

        我们先来看两个概念,自由标和哑标:

1.自由标

        自由标是在表达式的两边都出现,并且不遵循求和约定的指标。自由标用于指示表达式结果中保留的维度。在爱因斯坦求和约定中,自由标的顺序决定了结果张量的维度顺序。下图中i是自由标、j是哑标。

y_{1}=a_{11}x_{1}+a_{12}x_{2}+a_{13}x_{3}

y_{2}=a_{21}x_{1}+a_{22}x_{2}+a_{23}x_{3}

y_{3}=a_{31}x_{1}+a_{32}x_{2}+a_{33}x_{3}

        爱因斯坦和表示为

y_{i}=a_{ij}x_{j}

2.哑标

        哑标是在表达式的同一边出现两次的指标,遵循求和约定,即对这个指标进行求和。它在张量运算中仅仅是起到一个辅助的作用,并不影响最终结果的形状,相同的哑标表示对应位置进行求和。下图中的i和j都是哑标。

\sum_{i=1}^{3}a_{i}b_{i}=a_{i}b_{i}

\sum_{i=1}^{3}\sum_{j=1}^{3}a_{ij}x_{i}y_{j}=a_{ij}x_{i}y_{j}

        总的来说,自由标用于表示张量运算的结果的维度,而哑标则是进行求和操作时的辅助指标

二、torch实现

        Einsum在torch、tf和numpy中都有实现,而且用方式差不多,这里我们以torch为例,使用torch.einsum方法。

    总体思想是用一些下标标记输入的每个维度,并定义哪些下标是输出的一部分。然后,通过将操作中下标不属于输出的维度的元素先乘积再求和来计算输出。下面是一些例子,还是很好理解的。

    值得注意的是torch.einsum会自动调整张量的乘法顺序以匹配所需的乘法操作,并且会自动处理张量的维度匹配。因此,无论参数的顺序如何,都会得到相同的结果

1.计算迹

torch.einsum('ii', torch.randn(4, 4))
# tensor(-1.2104)

        ii表示对第一个维度和第二个维度取相同的索引值,并对所有这些索引值的元素进行求和。在一个方阵中,就是对其对角线上的元素求和。没有显式的输出就是先求和再输出。 

2.取矩阵对角线

torch.einsum('ii->i', torch.randn(4, 4))
# tensor([-0.1034,  0.7952, -0.2433,  0.4545])

        ii表示对张量的第一个维度和第二个维度取相同的索引值,并对所有这些索引值的元素进行操作。而 ->i 表示我们希望得到的输出张量的形状是一个一维张量,其中包含对每个索引值进行操作后的结果。

3.计算外积

x = torch.randn(5)
y = torch.randn(4)
torch.einsum('i,j->ij', x, y)
# tensor([[ 0.1156, -0.2897, -0.3918,  0.4963],
#         [-0.3744,  0.9381,  1.2685, -1.6070],
#         [ 0.7208, -1.8058, -2.4419,  3.0936],
#         [ 0.1713, -0.4291, -0.5802,  0.7350],
#         [ 0.5704, -1.4290, -1.9323,  2.4480]])

        i 和 j 表示两个张量 x 和 y 的维度。标记中的箭头 ->ij 表示我们希望得到的输出张量的形状是一个二维张量,其中第一个维度的大小与 x 张量的大小相同,第二个维度的大小与 y 张量的大小相同。

        i,j->ij表示对两个张量 x 和 y 进行乘法操作,并返回一个形状为 (len(x), len(y)) 的二维张量,其中的每个元素是两个输入张量对应位置元素的乘积,即外积。

4.batch矩阵乘法

As = torch.randn(3,2,5)
Bs = torch.randn(3,5,4)
torch.einsum('bij,bjk->bik', As, Bs)
# tensor([[[-1.0564, -1.5904,  3.2023,  3.1271],
#          [-1.6706, -0.8097, -0.8025, -2.1183]],
# 
#         [[ 4.2239,  0.3107, -0.5756, -0.2354],
#          [-1.4558, -0.3460,  1.5087, -0.8530]],
# 
#         [[ 2.8153,  1.8787, -4.3839, -1.2112],
#          [ 0.3728, -2.1131,  0.0921,  0.8305]]])

        bij 和 bjk 分别代表两个输入张量 As 和 Bs 的维度。bik 表示我们希望得到的输出张量的形状。

        bij,bjk->bik表示对两个张量 As 和 Bs 进行乘法操作,并返回一个形状为 (b, i, k) 的张量,其中 b 是批量大小,i 是 As 张量的第二个维度大小,k 是 Bs 张量的第三个维度大小。

    一行代码,将转置和乘法放在一起,确实很方便。

5.带有子列表和省略号

As = torch.randn(3,2,5)
Bs = torch.randn(3,5,4)
torch.einsum(As, [..., 0, 1], Bs, [..., 1, 2], [..., 0, 2])
# tensor([[[-1.0564, -1.5904,  3.2023,  3.1271],
#          [-1.6706, -0.8097, -0.8025, -2.1183]],
# 
#         [[ 4.2239,  0.3107, -0.5756, -0.2354],
#          [-1.4558, -0.3460,  1.5087, -0.8530]],
# 
#         [[ 2.8153,  1.8787, -4.3839, -1.2112],
#          [ 0.3728, -2.1131,  0.0921,  0.8305]]])

        [..., 0, 1] 表示对 As 进行切片操作。省略号 ... 表示我们不关心其他的维度,而 [0, 1] 表示我们选择 As 张量的最后两个维度。

        [..., 1, 2] 表示对 Bs 进行切片操作。同样,省略号 ... 表示其他的维度不变,而 [1, 2] 表示我们选择 Bs 张量的最后两个维度。

        [..., 0, 2] 表示我们希望得到的输出张量的形状。同样,省略号 ... 表示其他的维度不变,而 [0, 2] 表示我们选择输出张量的倒数第二个维度和最后一个维度。

        所以下面的代码表示对输入张量 As 和 Bs 进行一系列切片操作,并对结果进行乘法和求和,最后返回一个输出张量,其形状与输入张量的形状相同,但最后两个维度的顺序交换了位置。

6.变换维度

A = torch.randn(2, 3, 4, 5)
torch.einsum('...ij->...ji', A).shape
# torch.Size([2, 3, 5, 4])

        ...ij表示输入张量 A 的维度。省略号 ... 表示可以匹配任意数量的维度,而 'ij' 表示张量中的最后两个维度。

        ->...ji表示我们希望得到的输出张量的形状,其维度与输入张量的维度相同,但是最后两个维度交换了位置。

        ...ij->...ji 表示对输入张量 A 进行转置操作。

7.双线性变换,类似于torch.nn.functional.bilinear

l = torch.randn(2,5)
A = torch.randn(3,5,4)
r = torch.randn(2,4)
torch.einsum('bn,anm,bm->ba', l, A, r)
# tensor([[-0.3430, -5.2405,  0.4494],
#         [ 0.3311,  5.5201, -3.0356]])

        这个比较复杂,计算步骤如下:

        a.bn和bm中的b表示l和r在这个维度上是相同的,所以会对这个维度进行广播操作,得到中间值:维度(2,5,4),即(b,n,m)

        b.A维度(a,n,m)中的n和m与中间值的n和m相对应,表示在这两个维度上进行乘法操作。

        c.对n和m维度上的结果进行求和,得到最终的输出张量,其形状由->ba指定,即(2, 3)。

        这个例子有点绕,在实际工作中也不会经常遇到,还是建议大家把逻辑写的可读性强一点,这样以后的你会感激现在的自己。

        爱因斯坦求和约定就介绍到这里,点个关注不迷路(#^.^#)!

 关注订阅号了解更多精品文章

 交流探讨、商务合作请加微信

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Execute-Assembly(1)

原理 在《Cobalt Strike 原理分析》一文中,介绍了内存加载程序集(Assembly)的主要有四步: 1 加载CLR环境 2 获取程序域 3 装载程序集 4 执行程序集 在odzhan的Shellcode: Loading .NET Assemblies From Memory所描述的那样,.Net Framework随着…

MySQL 嵌套查询

嵌套查询 是指在一个完整的查询语句之中,包含若干个不同功能的小查询;从而一起完成复杂查询的一种编写形式。包含的查询放在()里 , 包含的查询出现的位置: 位置含义SELECT之后把查询结果作为表头使用FROM…

【InternLM】茴香豆:搭建你的RAG智能助理

茴香豆是 InternLM开源的基于 LLM的群聊知识助手,其提供了一整套前后端 web、android、算法源码,支持工业级商用。其最低运行运行成本低至 1.5G 显存,无需训练适用各行业。 1. 技术报告 参照技术报告HuixiangDou: Overcoming Group Chat Sc…

【DM8】外部表

外部表是指不存在于数据库中的表。 通过向达梦数据库定义描述外部表的元数据,可以把一个操作系统文件当成一个只读的数据库表,对外部表将像普通定义的表一样访问。 外部表的数据存储在操作系统文件中,建立外部表的时候,不会产生…

百度驾驶证C++离线SDK V1.1 C#接入

百度驾驶证C离线SDK V1.1 C#接入 目录 说明 效果 项目 代码 下载 说明 自己根据SDK封装了动态库,然后C#调用。 SDK包结构 效果 项目 代码 using Newtonsoft.Json; using OpenCvSharp; using System; using System.Collections.Generic; using System.D…

Taro打包生成不同目录

使用taro init创建taro项目时,taro默认打包目录是: /config/index.js outputRoot:dist默认的目录,编译不同平台代码时就会覆盖掉,为了达到多端同步调试的目的,这时需要修改默认生成目录了,通过查看官方文…

大语言模型如何工作?

此为观看视频How Large Language Model works的笔记。 GPT(Generative Pre-trained Transformer)是一个大语言模型(LLM),可以生成类似人类的文本。本文阐述: 什么是LLMLLM如何工作LLM的应用场景 什么是…

一些 MaxCompute 日常优化案例分享

作者:开七 一、前言 MaxCompute 优化是一个多样而又重要的过程,优化过程中若能够深入理解 ODPS 的工作原理和内部机制,才能够更明确的发现运行过程中存在的问题,这样才能更有针对性地进行优化,优化需要不断思考和尝试…

Vue.js组件精讲 基础:Vue.js组件的三个API:prop、event、slot

如果您已经对 Vue.js 组件的基础用法了如指掌,可以跳过本小节,不过当做复习稍读一下也无妨。 组件的构成 一个再复杂的组件,都是由三部分组成的:prop、event、slot,它们构成了 Vue.js 组件的 API。如果你开发的是一个…

w1r3s 靶机学习

w1r3s 靶机学习 0x01 IP C for command kali ip 10.10.10.128victim ip 10.10.10.1290x02 开扫 C sudo nmap -sn 10.10.10.0/24-sn 多一步入侵和轻量级侦察 发送四项请求 -sL 列表扫描,多用于探测可用ip,广播扫描 –send-ip 时间戳请求&#xff0…

YOLOv7全网独家改进: 卷积魔改 | 变形条状卷积,魔改DCNv3二次创新

💡💡💡本文独家改进: 变形条状卷积,DCNv3改进版本,不降低精度的前提下相比较DCNv3大幅度运算速度 💡💡💡强烈推荐:先到先得,paper级创新,直接使用; 💡💡💡创新点:1)去掉DCNv3中的Mask;2)空间域上的双线性插值转改为轴上的线性插值; 💡💡💡…

JavaSE:预定义类,访问修饰符,Java面向对象的特征

预定义类 JDK提供的类就是预定义类 Date类,LocalDate类等 访问修饰符 Java提供了四种访问修饰符,访问范围从大到小是:public > protected > 缺省 > private public:不同包的不相关子类 protected:不同包…

一例Foxmail的发件错误问题及解决方案

问题 Foxmail发件时,提示“连接失败” 点击左上角“收取”也连接失败 解决方法 点击右上角三个横线: 再点击“设置”在“网络”中,看看默认代理是不是“不使用代理” 如果不是,选成第一个 再在“账号”里选择自己用的账号&a…

NLP在搜索召回领域中的应用场景

自然语言处理(NLP)在搜索召回领域中的应用场景非常广泛,它通过理解和分析人类语言,提高了信息检索的准确性和效率。以下是一些具体的应用场景: 1. 搜索引擎优化 NLP技术可以用于优化搜索引擎的查询处理,通…

Centos 下载地址

下载镜像地址: 1、官网地址:The CentOS Project 2、阿里镜像站:centos安装包下载_开源镜像站-阿里云 3、清华镜像源:Index of /centos/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 3.、CentOS搜狐镜像&#xff1…

针对于OB_GINS的CMakeList文件的深入学习

Project()——配置项目信息 project(CMakeTemplate VERSION 1.0.0 LANGUAGES C CXX DESCRIPTION "A cmake template project") //通过project命令配置项目信息project(项目名称 VERSION major.minor.patch.tweak )CMake会将对应的值分别赋值给以下变量: PROJECT_VE…

家庭网络防御系统搭建-将NDR系统的zeek日志集成到securit yonion

在前面的文章中安装了zeek,这里,安装了securityonion,这里,本文讲述如何将zeek生成的日志发送到siem security onion之中。 所有日志集成的步骤分为如下几步: 日志收集配置日志发送接收日志解析配置日志展示配置 ZEEK日志收集配…

购买国外虚拟主机应该怎么支付

国外虚拟主机支付,大多接受visa信用卡支付方式,如果用一张visa信用卡相对会方便很多,此外像Skrill、PayPal、比特币等,部分虚拟主机服务商也接受,另外还有小部分服务商接受支付宝、微信形式。 美国虚拟主机&#xff0…

大厂高频面试题复习JAVA学习笔记-学习路线

对于应届生,要找到一份java工作,你得大概学会: java基础:javase、jvm、juc、gc、mysql、jdbc,计网计组 Java微服务基础Maven→Gradle→Spring6→SpringMVC→MyBatis→MyBatisPlus→SSM->Redis7->SpringBoot2-&…

matlab:有限差分求解纳维尔(Navier)边界的双调和(Biharmonic)方程,边值为零

我们考虑如下形式的双调和方程的数值解 其中,Ω是欧氏空间中的多边形或多面体域,在其中,d为维度,具有分段利普希茨边界,满足内部锥条件,f(x) ∈ L2(Ω)是给定的函数,∆是标准的拉普拉斯算子。算…