【问题标题】:Translating np.einsum() to MATLAB将 np.einsum() 转换为 MATLAB
【发布时间】:2020-06-04 15:19:14
【问题描述】:

我无法理解documentation of np.einsum()subscripts 是如何解释的?

我正在尝试编写np.einsum('a...c,b...c', Y, conj(Y)),其中Y 是原始python 上形状为C, F, T 的矩阵。此外,由于之前的实现差异,我的 MATLAB Y 的大小为 [F, T, C]

'a...c,b...c' 在每个组件中的索引是什么?我很困惑。

如何在 MATLAB 中编写相同的指令?

【问题讨论】:

  • 您是否在 SO 上寻找有关此主题的问题?一个例子 - Element-wise matrix multiplication for multi-dimensional array
  • 我做了,但我错过了你的链接。我现在正在阅读它。
  • 这对我没有帮助。例如,我不明白为什么'mki'是5,3,1。这些字母代表什么?这些是“A”的指数吗?如果是这样,他们应该是2,2,2000吗?
  • 如果你错过了,那一定是你没用过“按标签搜索”功能,here's an example搜索matlab+numpy-einsum(返回5个问题,包括这个和那个我链接)。 5,3,1 是维度的顺序。因此,如果一个矩阵的大小为[20,3,500,100,4,2],它指的是大小为 2 的维度,然后是大小为 100 的矩阵,最后是大小为 3 的矩阵(考虑到 python 的基于 0 的索引)。
  • YY.conj() 都是相同形状的 3d 数组,所以 a...c 是隐含的 aicb...c 是隐含的 bic,而缺少的 @987654344 @ 使其等同于 aic, bic -> iab。这又与(Y.transpose(1, 2, 0)[..., None] * Y.conj().transpose(1, 2, 0)[:, :, None, :]).sum(1) 相同:将第一个数组的[F, T, C] 形状变成[T, C, F, 1],第二个变成[T, C, 1, F],广播到[T, C, F, F],最后将第二个维度相加得到[T, F, F],即希望正是你得到的。我会在 einsum 调用中明确说明以使其可读。

标签: matlab permutation ellipsis code-translation numpy-einsum


【解决方案1】:

引用einsum 文档页面:

要启用和控制广播,请使用省略号。默认 NumPy 样式的广播是通过在每个术语的左侧添加一个省略号来完成的,例如 np.einsum('...ii->...i', a)。要沿第一个和最后一个轴进行跟踪,您可以使用np.einsum('i...i', a),或者使用最左边的索引而不是最右边的索引进行矩阵-矩阵乘积,可以使用np.einsum('ij...,jk...->ik...', a, b)

后面给出一个例子:

>>> a = np.arange(25).reshape(5,5)
>>> np.einsum('...j->...', a)
array([ 10,  35,  60,  85, 110])

此示例的等效 MATLAB 代码为:

>> a = reshape(0:24, [5,5]).';
>> sum(a,2).'
ans =
    10    35    60    85   110

注意几点:

  1. 省略号运算符 (...) 不应理解为“范围”,而应理解为“任何需要存在的内容”。
  2. Broadcasting”是指沿相关维度自动复制数组,以便定义数学运算。这是自 R2016b 以来 MATLAB 中存在的一项功能(称为“隐式扩展”)。
  3. 您可能会注意到 MATLAB 等效项中有几个转置操作 (.')。这是因为 numpy 数组是行优先的,而 MATLAB 数组是列优先的。实际上,虽然基础数据具有相同的顺序,但与 MATLAB 相比,numpy 数组出现转置。已完成转置,以便阵列在中间阶段看起来相同。

这些文档的另一个例子是:

>>> a = np.arange(6).reshape((3,2))
>>> b = np.arange(12).reshape((4,3))
>>> np.einsum('ki,jk->ij', a, b)
array([[10, 28, 46, 64],
       [13, 40, 67, 94]])
>>> np.einsum('ki,...k->i...', a, b)
array([[10, 28, 46, 64],
       [13, 40, 67, 94]])
>>> np.einsum('k...,jk', a, b)
array([[10, 28, 46, 64],
       [13, 40, 67, 94]])

在MATLAB中可以写成如下:

A = reshape(0:5, [2 3]).';
B = reshape(0:11, [3 4]).';

A.' * B.'
permute(sum( permute(A, [3 1 2]) .* B,2), [3 1 2])
shiftdim(sum( shiftdim(A, -1) .* B, 2), 2)

注意几点:

  1. np.einsum('ki,jk->ij', a, b)np.einsum('ki,...k->i...', a, b) 时,您可以看到j-th 维度被... 替换。事实上,这两个示例中都有一个->,这意味着它处于显式模式
  2. 当从np.einsum('ki,jk->ij', a, b)np.einsum('k...,jk', a, b) 时,您可以看到现在i-th 维度已替换为...->...j 的省略只是演示了隐式模式(输出维度按字母顺序排列)。

【讨论】:

    猜你喜欢
    • 2011-12-05
    • 2020-02-15
    • 1970-01-01
    • 1970-01-01
    • 2015-01-18
    • 1970-01-01
    • 1970-01-01
    • 2011-11-02
    • 2011-08-09
    相关资源
    最近更新 更多