我正在努力确切地了解其einsum
工作原理。我看了一下文档和一些示例,但看起来似乎并不固定.
这是我们上课的例子:
C = np.einsum("ij,jk->ki", A, B)
对于两个数组A和B
我认为可以A^T * B
,但是我不确定(它正在正确处理其中之一的移调吗?)。谁能告诉我这里的实际情况(以及使用时的一般情况einsum
)?
einsum是做什么的?
假设我们有两个多维数组,A和B。现在假设我们要…
有一个很好的机会,einsum
可以帮助我们做到这一点更快,内存更是有效的NumPy的功能组合,喜欢multiply,sum
和transpose
允许。
einsum是如何工作的?
这是一个简单(但并非完全无关紧要)的示例。取以下两个数组:
A = np.array([0, 1, 2])
B = np.array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
我们将逐个元素相乘A,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])
该签名字符串’i,ij->i’是这里的关键,需要解释的一点。你可以将其分为两半。在左侧(的左侧->),我们标记了两个输入数组。在的右侧->,我们标记了要结束的数组。
接下来是什么:
A
有一个轴;我们已经标记了它i
。并且B
有两个轴;我们将轴0
标记为i
,将轴1
标记为j
。
通过在两个输入数组中重复标签i,我们告诉我们einsum这两个轴应该相乘。换句话说,就像A数组B一样,我们将array
与array
的每一列相乘A[:, np.newaxis] * B
。
注意,j在我们期望的输出中,它没有显示为标签;我们刚刚使用过i(我们想以一维数组结尾)。通过省略标签,我们告诉einsum来总结沿着这条轴线。换句话说,我们就像对行进行求和.sum(axis=1)
。
基本上,这是你需要了解的所有信息einsum
。玩一会会有所帮助;如果我们将两个标签都留在输出中,则会'i,ij->ij'
返回2D产品数组(与相同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和B和输出数组的标签:
你会看到j重复的标签-这意味着我们会将的行A与的列相乘B。此外,j输出中不包含标签-我们对这些产品求和。标签i和k被保留用于输出,因此我们得到一个2D数组。
这一结果与其中标签阵列比较可能是更加明显j的不求和。在下面的左侧,你可以看到写入产生的3D数组np.einsum('ij,jk->ijk', A, B)
(即,我们保留了label j
):
在此处输入图片说明
求和轴j给出了预期的点积,如右图所示。
一些练习
为了获得更多的感觉einsum
,使用下标符号实现熟悉的NumPy
数组操作可能会很有用。任何涉及乘法和求和轴组合的内容都可以使用编写 einsum
。
令A和B为两个具有相同长度的一维数组。例如A = np.arange(10)和B = np.arange(5, 15)
。
np.einsum('i->', A)
np.einsum('i,i->i', A, B)
np.einsum('i,i->', A, B) # or just use 'i,i'
np.einsum('i,j->ij', A, B)
对于2D数组,C
和D
,只要轴是兼容的长度(相同长度或其中一个长度为1),下面是一些示例:
np.trace(C)
可以写成:np.einsum('ii', C)
C
和转置D,C * D.T
可以写成:np.einsum('ij,ji->ij', C, D)
C[:, :, None, None] * D
,可以写成:np.einsum('ij,kl->ijkl', C, D)
问题内容: 我是Python的新手,正在学习 TensorFlow 。在使用 notMNIST数据集 的教程中,他们提供了示例代码以将标签矩阵转换为n之一的编码数组。 目标是获取一个由标签整数0 … 9组成的数组,并返回一个矩阵,其中每个整数都已转换为n之一的编码数组,如下所示: 他们为此提供的代码是: 但是,我根本不了解这段代码是如何做到的。看起来它只是生成一个介于0到9之间的整数数组,然后将其
NumPy是一个Python包,代表'Numerical Python'。 它是一个由多维数组对象和用于处理数组的例程集合组成的库。 使用NumPy的操作 使用NumPy,开发人员可以执行以下操作 - 数组的数学和逻辑运算。 用于形状操纵的傅里叶变换和例程。 与线性代数有关的操作。 NumPy具有线性代数和随机数生成的内置函数。 NumPy - MatLab的替代品 NumPy经常与SciPy (
问题内容: 我在创建numpy数组的numpy数组时遇到问题。我将在一个循环中创建它: 所需结果: 实际结果: 可能吗?我不知道数组的最终尺寸,因此无法使用固定尺寸对其进行初始化。 问题答案: 永远不要在循环中追加数组:与基本的Python相比,这是NumPy非常不擅长的一项操作。这是因为您要对每个数据进行完整复制,这将花费您二次时间。 相反,只需将您的数组附加到Python列表中,并在最后进行转
问题内容: 我目前正在阅读Python,目前正在研究生成器。我发现很难回头。 从Java的背景出发,是否有Java的等效语言?这本书讲的是“生产者/消费者”,但是当我听说线程的时候。 什么是发电机,为什么要使用它?显然,无需引用任何书籍(除非您可以直接从书籍中找到一个体面,简单的答案)。也许举一些例子,如果您感到慷慨! 问题答案: 注意:本文采用Python 3.x语法。† 一个发电机仅仅是它返回
问题内容: 我试图了解这些之间是否存在差异,以及该差异可能是什么。 选项一: 选项二: 我知道,对于选项一,with块之后处于闭合状态。 问题答案: 我不知道为什么没有人提到这一点,因为这是工作方式的基础。与Python中的许多语言功能一样,在后台调用特殊方法,这些方法已经为内置Python对象定义,并且可以由用户定义的类覆盖。在特定情况下(和上下文管理器),方法是和。 请记住,在Python中,
问题内容: 在pandas库中多次出现改变就地等物体的方式与下面的语句一个选项… 我很好奇返回的内容以及何时传递对象与何时传递对象。 所有操作self何时都在修改?何时立即创建一个新对象,例如然后返回? 问题答案: 如果通过,该数据被重命名到位(它没有返回值),所以你会使用: 当传递(这是默认值,所以没有必要),执行操作,并返回该对象的副本,所以你会使用: