理解 NumPy 的 einsum

2023-11-24

如何np.einsum work?

给定数组A and B,它们的矩阵乘法和转置计算使用(A @ B).T,或等效地,使用:

np.einsum("ij, jk -> ki", A, B)

(注:这个答案是基于一个简短的博客文章 about einsum我不久前写过。)

什么是einsum do?

想象一下我们有两个多维数组,A and B。现在假设我们想要...

  • multiply A with B以特定的方式创造新的产品系列;然后也许
  • sum这个沿着特定轴的新数组;然后也许
  • 转置新数组的轴按特定顺序排列。

有一个很好的机会einsum与 NumPy 函数的组合(如multiply, sum and transpose会允许。

如何einsum work?

这是一个简单(但并非完全微不足道)的示例。取以下两个数组:

A = np.array([0, 1, 2])

B = np.array([[ 0,  1,  2,  3],
              [ 4,  5,  6,  7],
              [ 8,  9, 10, 11]])

我们将倍增A and B按元素排序,然后沿新数组的行求和。在“正常”NumPy 中我们会这样写:

>>> (A[:, np.newaxis] * B).sum(axis=1)
array([ 0, 22, 76])

所以这里的索引操作A将两个数组的第一个轴对齐,以便可以广播乘法。然后对产品数组的行进行求和以返回答案。

现在如果我们想使用einsum相反,我们可以写:

>>> np.einsum('i,ij->i', A, B)
array([ 0, 22, 76])

The 签名 string 'i,ij->i'是这里的关键,需要一些解释。你可以把它想象成两半。在左侧(->)我们已经标记了两个输入数组。在 - 的右边->,我们已经标记了我们想要最终得到的数组。

接下来会发生以下情况:

  • A有一个轴;我们已经给它贴上了标签i. And B有两个轴;我们将轴 0 标记为i轴 1 为j.

  • By 重复标签i在两个输入数组中,我们都告诉einsum这两个轴应该是乘以一起。换句话说,我们将数组相乘A数组的每一列B, 就像A[:, np.newaxis] * B does.

  • 请注意j没有作为标签出现在我们想要的输出中;我们刚刚使用过i(我们希望最终得到一个一维数组)。经过omitting标签,我们告诉einsum to sum沿着这个轴。换句话说,我们对产品的行进行求和,就像.sum(axis=1) does.

这基本上就是您使用时需要知道的全部内容einsum。玩一点是有帮助的;如果我们在输出中保留两个标签,'i,ij->ij',我们得到一个二维产品数组(与A[:, np.newaxis] * B)。如果我们说没有输出标签,'i,ij->,我们返回一个数字(与执行相同(A[:, np.newaxis] * B).sum()).

伟大的事情是einsum然而,它并没有首先构建临时的产品系列;它只是将结果相加。这可以大大节省内存使用。

一个稍微大一点的例子

为了解释点积,这里有两个新数组:

A = array([[1, 1, 1],
           [2, 2, 2],
           [5, 5, 5]])

B = array([[0, 1, 0],
           [1, 1, 0],
           [1, 1, 1]])

我们将使用以下方法计算点积np.einsum('ij,jk->ik', A, B)。这是一张显示标签的图片A and B以及我们从函数中获得的输出数组:

enter image description here

你可以看到这个标签j被重复 - 这意味着我们将行相乘A与列B。此外,标签j不包含在输出中 - 我们正在对这些乘积求和。标签i and k保留用于输出,因此我们返回一个二维数组。

将此结果与标签所在的数组进行比较可能会更清楚j is not总结。下面,在左侧您可以看到由写入产生的 3D 数组np.einsum('ij,jk->ijk', A, B)(即我们保留了标签j):

enter image description here

求和轴j给出预期的点积,如右图所示。

一些练习

为了更多地感受einsum,使用下标表示法实现熟悉的 NumPy 数组操作非常有用。任何涉及乘法轴和求和轴组合的东西都可以使用以下方式编写einsum.

设 A 和 B 是两个长度相同的一维数组。例如,A = np.arange(10) and B = np.arange(5, 15).

  • 总数是A可以写成:

    np.einsum('i->', A)
    
  • 逐元素乘法,A * B,可以写成:

    np.einsum('i,i->i', A, B)
    
  • 内积或点积,np.inner(A, B) or np.dot(A, B),可以写成:

    np.einsum('i,i->', A, B) # or just use 'i,i'
    
  • 外层产品,np.outer(A, B),可以写成:

    np.einsum('i,j->ij', A, B)
    

对于二维数组,C and D,前提是轴的长度兼容(两者长度相同或其中之一的长度为 1),以下是一些示例:

  • 的踪迹C(主对角线之和),np.trace(C),可以写成:

    np.einsum('ii', C)
    
  • 逐元素乘法C和转置D, C * D.T,可以写成:

    np.einsum('ij,ji->ij', C, D)
    
  • 将每个元素相乘C通过数组D(制作 4D 数组),C[:, :, None, None] * D,可以写成:

    np.einsum('ij,kl->ijkl', C, D)    
    
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

理解 NumPy 的 einsum 的相关文章

随机推荐

  • Horner 小数部分递归算法 - Java

    我正在尝试创建一个递归方法 使用 Horner 算法将以 n 为基数的小数转换为以 10 为基数的小数 我在这里和各处进行了搜索 但找不到任何详细处理小数部分的地方 需要注意的是 我在递归方面非常薄弱 因为我还没有在编程课程中正式学习它 但
  • 我需要一个 MSI 自定义操作来从 MSI 源目录复制文件

    我正在使用 VS 2008 为 c windows 项目创建一个安装程序 我正在尝试编写一个自定义操作 该操作从存储在文件服务器上的 MSI 文件的源目录复制设置文件 例如 server fileshare myappinstaller m
  • Spring REST 服务:如何配置以删除 json 响应中的空对象

    我有一个返回 json 响应的 Spring Web 服务 我使用此处给出的示例来创建服务 http www mkyong com spring mvc spring 3 mvc and json example 返回的json格式为 na
  • 配置 Tomcat 以使用 Windows 证书存储进行 SSL

    我已经部署了许多 SSL 配置 包括 Tomcat cacerts keytool 和 IIS Windows 证书存储 netsh http sslcert 因此我熟悉这些过程 有没有人想出一种方法将 Tomcat 的 SSL 连接器指向
  • 可以允许来自 HTTPS 网站的 HTTP 请求吗?

    我已经安装了 非通配符 SSL 证书 以便我的网站可以使用 HTTPS 当我尝试从 HTTP url 请求资源时 我收到如下错误消息 混合内容 页面位于 https example com 已加载完毕 HTTPS 但请求不安全的样式表 ht
  • JsonSchema:根据另一个属性的值验证类型

    我正在使用以下架构来验证我的 json schema http json schema org schema title Rules description Describes a set of rules type object prop
  • 无法从 Microsoft Graph Explorer 更新 Sharepoint 托管元数据字段

    我正在尝试通过 Graph Explorer 更新与列表项关联的字段 https developer microsoft com en us graph graph explorer 或 REST API 调用 对于其中一个字段 其值可以是
  • Apache Camel Http 和 SSL

    我一直在尝试获得与 Camel 一起使用的 2 路 ssl https 代理 我已经能够使用 2 路 ssl 设置 Jetty 组件 现在尝试让它与 Http4 组件一起工作以完成代理的客户端 当我将码头流量路由到日志组件时 一切都很好 并
  • Weka GUI - 内存不足,无法加载?

    我过去也曾加载过同样的 Weka 安装 我只是尝试加载 Weka GUI 双击图标 但出现以下错误 我该如何修复它 OutOfMemory Not enough memory Please load a smaller dataset or
  • 无法在当前目录中获取脚本源

    显然 我不能source脚本 如果该脚本位于当前目录中 例如 source some dir script sh Ok 工作正常 但如果我与脚本位于同一目录中 则会出错 cd some dir source script sh sh sou
  • Java显示当前时间

    我有一个代码 可以显示运行应用程序时的当前日期和时间 DateFormat dateFormat new SimpleDateFormat yyyy MM dd HH mm ss Calendar cal Calendar getInsta
  • VIM:按函数名称排序

    我的 menu vim 文件中有很多函数 是否可以 由我 选择它们并按函数名称对它们进行排序 p e 从乐趣中找到台词 或函数 到线endfun 查找函数名称并根据函数名称对整个块进行排序 从 a z 有时我会在函数名称上方添加一行注释 可
  • CloudKit 通知

    我可能在这里遗漏了一些明显的东西 如何创建一个 CloudKit 通知 其中包含有关您收到通知的 CKRecord 的详细信息 即不仅仅是通用的 已创建新项目 而是带有记录标题的通知 例如 吉尔和杰西卡的生日派对 为每个新记录更改创建一个带
  • 如何配置 BIRT 报告引擎直接从类路径加载字体?

    我正在编写一个使用 BIRT 生成报告的 Java 应用程序 我想将自定义字体打包在 jar 文件中 并能够将它们嵌入到 PDF 报告中 我可以先将字体提取到文件系统 然后将 BIRT 指向文件系统位置 但我想知道是否可以将 BIRT 配置
  • 树枝模板内的变量 jquery

    我正在尝试使用 twig 模板内的 jquery 变量通过 ajax 发送 但我无法访问 twig 内的 jquery 变量 我的代码是
  • JPA 实体 - 指定持久性单元?

    我有一个使用多个持久性单元的 JavaEE 项目 有没有办法指定特定 JPA 实体属于哪个持久单元 一些实体位于一个数据源中 而其他实体位于我的第二个数据源中 有没有办法使用注释来区分两者 指定哪个持久单元Entity属于 使用persis
  • 为商店构建通用应用程序时出错:“清单引用文件‘MyAppName.dll’,该文件不是有效负载的一部分。”

    当尝试为 Windows 通用应用程序的商店创建应用程序包时 我在 Visual Studio 2015 中遇到此错误 清单引用文件 MyAppName dll 该文件不是有效负载的一部分 错误是在 MyAppSourcePath Pack
  • 使用 .NET(控制台应用程序)发布多个文件和表单值

    我想将多个文件和表单变量发布到 CGI 脚本 全部在oneHTTP 请求 我相信这需要一个 HTTP postmultipart form data编码 以下是发送所需信息的 HTML 表单示例 我需要通过应用程序发送相同的信息
  • ASP.NET 捆绑/缩小:包括动态生成的 Javascript

    我有一个动态生成 Javascript 的网站 生成的代码描述了类型元数据和一些服务器端常量 以便客户端可以轻松使用服务器的服务 因此它非常可缓存 生成的 Javascript 由 ASP NET MVC 控制器提供服务 所以它有一个 Ur
  • 理解 NumPy 的 einsum

    如何np einsum work 给定数组A and B 它们的矩阵乘法和转置计算使用 A B T 或等效地 使用 np einsum ij jk gt ki A B 注 这个答案是基于一个简短的博客文章 about einsum我不久前写