[代码学习]einsum详解

2023-10-11 12:01
文章标签 代码 学习 详解 einsum

本文主要是介绍[代码学习]einsum详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

einsum详解

该函数用于对一组输入 Tensor 进行 Einstein 求和,该函数目前仅适用于paddle的动态图。

Einstein 求和是一种采用 Einstein 标记法描述的 Tensor 求和,输入单个或多个 Tensor,输出单个 Tensor。

在这里插入图片描述

paddle.einsum(equation, *operands)

参数

  • equation (str):求和标记
  • operands (Tensor, [Tensor, …]):输入 Tensor

返回

  • Tensor:输出 Tensor

求和特例

  • 单操作数

    • 迹:trace

    • 对角元:diagonal

    • 转置:transpose

    • 求和:sum

  • 双操作数

    • 内积:dot

    • 外积:outer

    • 广播乘积:mul,*

    • 矩阵乘:matmul

    • 批量矩阵乘:bmm

  • 多操作数

    • 广播乘积:mul,*

    • 多矩阵乘:A.matmul(B).matmul(C)

关于求和标记的约定

  • 维度分量下标:Tensor 的维度分量下标使用英文字母表示,不区分大小写,如’ijk’表示 Tensor 维度分量为 i,j,k

  • 下标对应输入操作数:维度下标以`,`分段,按顺序 1-1 对应输入操作数

  • 广播维度:省略号`…`表示维度的广播分量,例如,'i…j’表示首末分量除外的维度需进行广播对齐

  • 自由标和哑标:输入标记中仅出现一次的下标为自由标,重复出现的下标为哑标,哑标对应的维度分量将被规约消去

  • 输出:输出 Tensor 的维度分量既可由输入标记自动推导,也可以用输出标记定制化

  • 自动推导输出

    • 广播维度分量位于维度向量高维位置,自由标维度分量按字母顺序排序,位于维度向量低纬位置,哑标维度分量不输出
  • 定制化输出

    • 维度标记中`->`右侧为输出标记

    • 若输出包含广播维度,则输出标记需包含`…`

    • 输出标记为空时,对输出进行全量求和,返回该标量

    • 输出不能包含输入标记中未出现的下标

    • 输出下标不可以重复出现

    • 哑标出现在输出标记中则自动提升为自由标

    • 输出标记中未出现的自由标被降为哑标

例子

  • ‘…ij, …jk’,该标记中 i,k 为自由标,j 为哑标,输出维度’…ik’

  • ‘ij -> i’,i 为自由标,j 为哑标

  • ‘…ij, …jk -> …ijk’,i,j,k 均为自由标

  • ‘…ij, …jk -> ij’,若输入 Tensor 中的广播维度不为空,则该标记为无效标记

求和规则

Einsum 求和过程理论上等价于如下四步,但实现中实际执行的步骤会有差异。

  • 第一步,维度对齐:将所有标记按字母序排序,按照标记顺序将输入 Tensor 逐一转置、补齐维度,使得处理后的所有 Tensor 其维度标记保持一致

  • 第二步,广播乘积:以维度下标为索引进行广播点乘

  • 第三步,维度规约:将哑标对应的维度分量求和消除

  • 第四步,转置输出:若存在输出标记,则按标记进行转置,否则按广播维度+字母序自由标的顺序转置,返回转之后的 Tensor 作为输出

关于 trace 和 diagonal 的标记约定(待实现功能)

  • 在单个输入 Tensor 的标记中重复出现的下标称为对角标,对角标对应的坐标轴需进行对角化操作,如’i…i’表示需对首尾坐标轴进行对角化

  • 若无输出标记或输出标记中不包含对角标,则对角标对应维度规约为标量,相应维度取消,等价于 trace 操作

  • 若输出标记中包含对角标,则保留对角标维度,等价于 diagonal 操作

实例实践

首先,看一下一维度简单实验:

import paddle# 定义两个输入矩阵
# paddle.seed(102)
# x = paddle.rand([4])
# y = paddle.rand([5])
x = paddle.to_tensor([1,2,], dtype='float32')
y = paddle.to_tensor([3,4,5], dtype='float32')# sum
sum_x = paddle.einsum('i->', x).numpy()# dot
dox_x = paddle.einsum('i,i->', x, x).numpy()# outer
outer_xy = paddle.einsum("i,j->ij", x, y).numpy()print(f"x: {x.numpy()}, shape: {x.shape}")
print(f"y: {y.numpy()}, shape: {y.shape}")
print(f"sum_x: {sum_x}, shape: {sum_x.shape}")
print(f"dox_x: {dox_x}, shape: {dox_x.shape}")
print(f"outer_xy: {outer_xy}, shape: {outer_xy.shape}")

结果输出为:

x: [1. 2.], shape: [2]
y: [3. 4. 5.], shape: [3]
sum_x: 3.0, shape: ()
dox_x: 5.0, shape: ()
outer_xy: [[ 3.  4.  5.][ 6.  8. 10.]], shape: (2, 3)

然后,看一下高纬度的实验:

import paddle# A = paddle.rand([2, 3, 2])
# B = paddle.rand([2, 2, 3])
A = paddle.to_tensor([[[1,2],[1,2],[1,2]], [[1,2],[1,2],[1,2]]], dtype='float32')
B = paddle.to_tensor([[[3,4,5],[3,4,5]], [[3,4,5],[3,4,5]]], dtype='float32')# transpose
transpose_A = paddle.einsum('ijk->kji', A)# batch matrix multiplication
BMM_AB = paddle.einsum('ijk, ikl->ijl', A,B)# Ellipsis transpose
ET_A = paddle.einsum('...jk->...kj', A)# Ellipsis batch matrix multiplication
EBMM_AB = paddle.einsum('...jk, ...kl->...jl', A,B)print(f"A: {A.numpy()}, shape: {A.shape}")
print(f"B: {B.numpy()}, shape: {B.shape}")
print(f"transpose_A: {transpose_A.numpy()}, shape: {transpose_A.shape}")
print(f"BMM_AB: {BMM_AB.numpy()}, shape: {BMM_AB.shape}")
print(f"ET_A: {ET_A.numpy()}, shape: {ET_A.shape}")
print(f"EBMM_AB: {EBMM_AB.numpy()}, shape: {EBMM_AB.shape}")

结果输出为:

A: [[[1. 2.][1. 2.][1. 2.]][[1. 2.][1. 2.][1. 2.]]], shape: [2, 3, 2]
B: [[[3. 4. 5.][3. 4. 5.]][[3. 4. 5.][3. 4. 5.]]], shape: [2, 2, 3]
transpose_A: [[[1. 1.][1. 1.][1. 1.]][[2. 2.][2. 2.][2. 2.]]], shape: [2, 3, 2]
BMM_AB: [[[ 9. 12. 15.][ 9. 12. 15.][ 9. 12. 15.]][[ 9. 12. 15.][ 9. 12. 15.][ 9. 12. 15.]]], shape: [2, 3, 3]
ET_A: [[[1. 1. 1.][2. 2. 2.]][[1. 1. 1.][2. 2. 2.]]], shape: [2, 2, 3]
EBMM_AB: [[[ 9. 12. 15.][ 9. 12. 15.][ 9. 12. 15.]][[ 9. 12. 15.][ 9. 12. 15.][ 9. 12. 15.]]], shape: [2, 3, 3]

reference

关于matmul可以查看:https://blog.csdn.net/orDream/article/details/133744368
官方链接:
@misc{BibEntry2023Oct,
title = {{einsum-API文档-PaddlePaddle深度学习平台}},
year = {2023},
month = oct,
urldate = {2023-10-10},
language = {chinese},
note = {[Online; accessed 10. Oct. 2023]},
url = {https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/einsum_cn.html}
}

这篇关于[代码学习]einsum详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/187911

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss