可以用爱因斯坦求和替代的那些矩阵运算

技术背景

在前面的几篇文章中我们分别介绍过numpy中的爱因斯坦求和函数Einsum和MindSpore框架中的爱因斯坦求和算子Einsum的基本用法。而我们需要知道,爱因斯坦求和其实还可以实现非常多的功能,甚至可以替代大部分的矩阵运算,比如常见的点乘、元素乘、求和等等这些都是可以的。那我们就逐一看一下可以用爱因斯坦求和来替代的那些函数和方法。

案例演示

在numpy、Jax框架和MindSpore框架中都是支持爱因斯坦求和算符的,那么这里为了方便演示,我们采用的是numpy来做一些参考案例:

In [1]: import numpy as np

In [2]: x = np.arange(3)

In [3]: x
Out[3]: array([0, 1, 2])

In [4]: y = np.arange(3, 6)

In [5]: y
Out[5]: array([3, 4, 5])

In [6]: P = np.arange(1, 10).reshape(3,3)

In [7]: P
Out[7]:
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

矩阵转置

矩阵转置,或者是调换矩阵的某两个维度,这个功能用爱因斯坦求和来做是非常清晰的,我们先看一下相应的公式:

[P^T=\left[ \begin{matrix} P_{00}&P_{01}&P_{02}\ P_{10}&P_{11}&P_{12}\ P_{20}&P_{21}&P_{22} \end{matrix} \right]^T= \left[ \begin{matrix} P_{00}&P_{10}&P_{20}\ P_{01}&P_{11}&P_{21}\ P_{02}&P_{12}&P_{22} \end{matrix} \right] ]

一般矩阵转置我们如果用numpy来操作的话,只需要使用 P=P.T就可以了,而这个功能用爱因斯坦求和算子也是可以实现的:

In [40]: np.allclose(P.T, np.einsum('kl->lk', P))
Out[40]: True

这里有一个比较有意思的事情是,如果不指定生成的序号,但是给定的爱因斯坦算符顺序如果前面的大于后面的,也可以实现矩阵转置的功能,比如下面的一个案例:

In [41]: np.allclose(P.T, np.einsum('ji', P))
Out[41]: True

元素乘

对应于两个矩阵(矢量、张量)之间的元素乘法,普通操作我们可以直接用(x*y)来实现(假定维度大小为3):

[xy = \left[ \begin{matrix} x_0\x_1\x_2 \end{matrix} \right] \left[ \begin{matrix} y_0\y_1\y_2 \end{matrix} \right]=\left[ \begin{matrix} x_0y_0\x_1y_1\x_2y_2 \end{matrix} \right] ]

对应于代码实现:

In [8]: np.allclose(x*y, np.einsum('k,k->k', x, y))
Out[8]: True

矩阵内求和

把矩阵中的所有元素相加:

[SUM(x)=SUM(\left[ \begin{matrix} x_0\x_1\x_2 \end{matrix} \right])=x_0+x_1+x_2 ]

对应于Python代码实现为:

In [9]: np.allclose(np.sum(x), np.einsum('k->', x))
Out[9]: True

In [12]: np.allclose(np.sum(P), np.einsum('kl->', P))
Out[12]: True

In [13]: np.allclose(np.sum(P, axis=-1), np.einsum('kl->k', P))
Out[13]: True

In [14]: np.allclose(np.sum(P, axis=0), np.einsum('kl->l', P))
Out[14]: True

那么,既然求和能算,同样的 平均值也是可以计算的,这里就不展开介绍了。

矩阵点乘

这个应用场景很多,比如当我们需要计算两个向量之间的夹角的时候,就会用到矩阵点乘。矩阵点乘的定义如下:

[x\cdot y = \left[ \begin{matrix} x_0\x_1\x_2 \end{matrix} \right]\cdot \left[ \begin{matrix} y_0\y_1\y_2 \end{matrix} \right]=x_0y_0+x_1y_1+x_2y_2 ]

对应的Python代码实现如下所示:

In [15]: np.allclose(np.dot(x, y), np.einsum('k,k->', x, y))
Out[15]: True

矩阵向量乘

这个应用场景也非常多,比如我们经常所用到的向量的伸缩、旋转等,都可以用一系列的矩阵作用在一个向量上来表示,相关的计算公式为:

[P\cdot x=\left[ \begin{matrix} P_{00}&P_{01}&P_{02}\ P_{10}&P_{11}&P_{12}\ P_{20}&P_{21}&P_{22} \end{matrix} \right]\cdot \left[ \begin{matrix} x_0\x_1\x_2 \end{matrix} \right]= \left[ \begin{matrix} P_{00}x_0+P_{01}x_1+P_{02}x_2\P_{10}x_0+P_{11}x_1+P_{12}x_2\P_{20}x_0+P_{21}x_1+P_{22}x_2 \end{matrix} \right] ]

对应的Python代码如下所示:

In [16]: np.allclose(np.dot(P, x), np.einsum('kl,l->k', P, x))
Out[16]: True

In [25]: np.allclose(np.dot(P, x[:, None]), np.einsum('kl,lm->km', P, x[:, None]))
Out[25]: True

In [31]: np.allclose(np.dot(P, P.T), np.einsum('kl,lm->km', P, P.T))
Out[31]: True

在上述案例中我们还包含了矩阵跟矩阵之间的乘法,这些基本运算都是可以通用的。

克罗内克积

克罗内克积,又叫张量积,比如两个矢量或者矩阵之间没有耦合关系,那么可以用一个克罗内克积来总体表示这两个矢量或者矩阵组成的矢量或者矩阵,该运算被定义为:

[x\otimes y^{T}=\left[ \begin{matrix} x_0\x_1\x_2 \end{matrix} \right]\otimes \left[y_0, y_1, y_2\right]=\left[ \begin{matrix} x_0y_0&x_0y_1&x_0y_2\ x_1y_0&x_1y_1&x_1y_2\ x_2y_0&x_2y_1&x_2y_2 \end{matrix} \right] ]

对应Python代码实现如下所示:

In [36]: np.allclose(np.kron(x[:, None], y), np.einsum('kl,l->kl', x[:, None], y))
Out[36]: True

In [37]: np.allclose(np.kron(x, y), np.einsum('kl,l->kl', x[:, None], y).reshape(9))
Out[37]: True

需要注意的是,爱因斯坦求和运算只能减少总的维度数量,但是不可改变维度大小,因此有时候会需要用到reshape的功能配合使用。

取对角元

这个应用也好理解,就是把矩阵的每一个对角元素取出来,用公式描述就是:

[diag(P)=diag(\left[ \begin{matrix} P_{00}&P_{01}&P_{02}\ P_{10}&P_{11}&P_{12}\ P_{20}&P_{21}&P_{22} \end{matrix} \right])=\left[P_{00}, P_{11}, P_{22}\right] ]

相关的Python代码实现如下所示:

In [46]: np.allclose(np.diag(P), np.einsum('ii->i', P))
Out[46]: True

求矩阵迹

矩阵的迹(Trace),就是对所有的对角元进行求和,那么有了上一步使用爱因斯坦求和函数提取所有的对角元之后,其实我们可以稍微调整一下,就能得到求矩阵迹的方法。首先看下矩阵迹的公式定义:

[Tr(P) = Tr(\left[ \begin{matrix} P_{00}&P_{01}&P_{02}\ P_{10}&P_{11}&P_{12}\ P_{20}&P_{21}&P_{22} \end{matrix} \right])=P_{00}+P_{11}+P_{22} ]

相关的Python代码实现如下所示:

In [47]: np.allclose(np.trace(P), np.einsum('ii->', P))
Out[47]: True

多重运算

有时候会涉及到一系列的矩阵按照顺序作用在一个向量上,如果从张量的角度来考虑的话,其中的维度还可以非常灵活的变化,不一定全都是方阵。应该说,这也是爱因斯坦求和算子的重大意义所在。如果不使用爱因斯坦求和算子,那么要计算(A\cdot B\cdot C\cdot x)这样的一个过程,可以多次嵌套使用numpy的dot点乘函数。但是这样比较麻烦,一般推荐可以使用numpy中的另外一个函数: multi_dot,相关的Python代码实现如下所示:

In [39]: np.allclose(np.linalg.multi_dot((P, P, P, x)), np.einsum('ij,jk,kl,l->i', P, P, P, x))
Out[39]: True

在这种多重运算的过程中,可以使用einsum_path去找到一条更好的归并路径,以达到提升算法性能的效果。

总结概要

本文主要基于Python的Numpy库,介绍一些爱因斯坦求和算子Einsum的应用场景,包括求和、求内外积、求转置等等。我们需要明确的是,爱因斯坦求和算子的意义主要在于矩阵的多重运算时,可以通过爱因斯坦求和约定将这种复杂问题定义成一个张量网络,通过图模型去找到一个更好的缩并路径,以得到更好的算法复杂度。而如果只是普通的点乘求和之类的运算,其实并不是Einsum的主要功能。但是这些功能也可以用爱因斯坦求和的形式来实现,也说明了这个约定的先进性。当然,也有众多的矩阵运算功能是无法直接通过爱因斯坦求和算子来实现的,比如矩阵求逆、求本征值、矩阵扩维、矩阵重构还有向量叉乘等等。只有在合适的地方使用Einsum,才能体现它的真正价值。

版权声明

版权声明
本文首发链接为:https://www.cnblogs.com/dechinphy/p/einsum-examples.html

作者ID:DechinPhy

更多原著文章请参考:https://www.cnblogs.com/dechinphy/

打赏专用链接:https://www.cnblogs.com/dechinphy/gallery/image/379634.html

腾讯云专栏同步:https://cloud.tencent.com/developer/column/91958

CSDN同步链接:https://blog.csdn.net/baidu_37157624?spm=1008.2028.3001.5343

51CTO同步链接:https://blog.51cto.com/u_15561675

Original: https://www.cnblogs.com/dechinphy/p/einsum-examples.html
Author: DECHIN
Title: 可以用爱因斯坦求和替代的那些矩阵运算

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/714756/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • es通过时间聚合查询一周中每天的数据平均值

    场景回顾:设备上传的数据保存在es中,大屏模块要统计本周的数据折线图(一个设备三分总上传一次,所以拟定每天聚合求个平均值) kibana查询请求 GET xxxx_2022-10/…

    技术杂谈 2023年7月24日
    073
  • Windows下安装SDKMAN

    Windows下安装SDKMAN SDKMAN(软件开发包管理器)可以对各种各样的二进制SDK包进行版本管理,包括Groovy和JDK等。 目前MacOS和Linux支持比较好,安…

    技术杂谈 2023年5月31日
    092
  • 我是一个垃圾

    哒哒哒…… 回收者的脚步声越来越清晰,我竭力锁紧身体让自己别那么引人注目,尽管气喘吁吁,但我仍然压抑住自己的呼吸。 终归是藏不住的,但是多活个几毫秒也是好的…

    技术杂谈 2023年7月23日
    078
  • 海报轮播常用面板设置

    内容模式,决定海报展示方式,图片轮播则在指定高度内进行图片切换,单列图片,则往下输出图片。 轮播方式,可设置手动或者自动 圆点显示隐藏,轮播模式底部圆点显示隐藏 单图间距,单列图片…

    技术杂谈 2023年6月1日
    085
  • C# File API

    【 C# File API】 1、System.IO.File Provides static methods for the creation, copying, deletio…

    技术杂谈 2023年5月31日
    094
  • Oracle Client没有正确安装

    lnitialization errorOracle Client没有正确安装OracleHomeKey:OracleHomeDir: Original: https://www….

    技术杂谈 2023年5月30日
    0106
  • 背题!

    博客园 :当前访问的博文已被密码保护 请输入阅读密码: Original: https://www.cnblogs.com/0x3e-time/p/16344648.htmlAut…

    技术杂谈 2023年6月21日
    083
  • 年年出妖事,一例由JSON解析导致的”薛定谔BUG”排查过程记录

    前言 做开发这么多年,也碰到无数的bug了。不过再复杂的bug,只要仔细去研读代码,加上debug,总能找到原因。 但是最近公司内碰到的这一个bug,这个bug初看很简单,但是非常…

    技术杂谈 2023年7月11日
    083
  • linux开机自动挂载(/etc/fstab)

    fatab 介绍 通常情况,Linux 的 /etc/fstab 文件可能有如下内容: # /etc/fstab Created by anaconda on Fri Aug 18…

    技术杂谈 2023年7月24日
    0102
  • linux全新机器环境搭建流程梳理

    软件解压后安装基础指令(复制用):./configure && make && make install ./configure –pr…

    技术杂谈 2023年7月11日
    085
  • [极客大挑战 2019]Secret File

    0x01 寻找做题信息 打开环境,查看源代码,发现可疑链接,/Archive_room.php,action.php打开action.php会发生302跳转,查找302跳转无果,百…

    技术杂谈 2023年7月10日
    084
  • 使用Java刷评论为平台引流的经历

    场景:需要在一网站中批量评论留言。分析接口:列表接口获取idList,返回的是json数据直接用FastJson转就可以,如果返回的是HTML片段,则需要使用Jsoup进行提取,值…

    技术杂谈 2023年7月11日
    0100
  • 正则表达式规则与语法

    正则表达式(regular expression)就是用一个”字符串”来描述一个特征,然后去验证另一个”字符串”是否符合这个特征。比…

    技术杂谈 2023年5月31日
    0121
  • 使用Supervisor监控mysql

    监控文件配置: [program:mysql] ; 管理的子程序名字,要和项目有关联,不能乱写command=/usr/local/mysql/bin/mysqld_safe &#…

    技术杂谈 2023年7月11日
    070
  • Shopify Atlantic主题模板配置修改

    Shopify Atlantic主题是一个经受住了时间考验的经典 Shopify 主题,引人注目、可扩展且专为提高转化率而打造‎。使用经过验证的灵活主题建立您的业务,以帮助商店发展…

    技术杂谈 2023年5月31日
    095
  • 深入浅出全面解析RDMA

    RDMA(RemoteDirect Memory Access)技术全称远程直接内存访问,就是为了解决网络传输中客户端与服务器端数据处理的延迟而产生的。它将数据直接从一台计算机的内…

    技术杂谈 2023年5月31日
    098
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球