【问题标题】:How to do a scalar product along the right axes with numpy and vectorize the process如何使用 numpy 沿右轴进行标量积并将过程矢量化
【发布时间】:2019-08-07 10:08:24
【问题描述】:

我有尺寸为 (100, 100, 16, 16) 的 numpy 数组“测试”,它为 100x100 网格上的点提供了一个不同的 16x16 数组。 我还有一些特征值和向量,其中 vals 具有维度 (100, 100, 16) 和 vecs (100, 100, 16, 16),其中 vecs[x, y, :, i] 将是矩阵的第 i 个特征向量第 i 个特征值 vals[x, y, i] 对应的点 (x, y)。

现在我想在网格上的所有点上取数组的第一个特征向量,与测试矩阵做一个矩阵乘积,然后在所有点上与数组的所有其他特征向量做一个结果向量的标量乘积在网格上并将它们相加。 结果数组的维度应为 (100, 100)。在此之后,我想取数组的第二个特征向量,矩阵将它与 test 相乘,然后将结果与不是第二个的所有特征向量相乘,依此类推,最后我有 16(100 , 100) 或更确切地说是 (100, 100, 16) 数组。到目前为止,我只成功了很多我想避免的 for 循环,但是使用 tensordot 给了我错误的维度,我不知道如何选择 np.dot 函数沿矢量化的轴。 我听说 einsum 可能适合这项任务,但是不依赖 python 循环的一切对我来说都很好。

import numpy as np
from numpy import linalg as la

test = np.arange(16*16*100*100).reshape((100, 100, 16, 16))
vals, vecs = la.eig(test + 1)

np.tensordot(vecs, test, axes=[2, 3]).shape
>>> (10, 10, 16, 10, 10, 16)

编辑:好的,所以我使用 np.einsum 来获得正确的中间结果。

np.einsum('ijkl, ijkm -> ijlm', vecs, test)

但在下一步中,我只想对 vec 的所有其他条目进行标量积。我可以在这个 einsum 形式中实现一些逆 Kronecker delta 吗?或者我现在应该切换回通常的 numpy 吗?

【问题讨论】:

  • 使用np.einsum('ijkl,ijkl->ij',vecs,test)获取矩阵乘积。

标签: python python-3.x numpy linear-algebra


【解决方案1】:

好的,我玩过 np.einsum 并找到了一种方法来执行上述操作。 einsum 的一个很好的特性是,如果您在“输出”中重复出现两次的索引(在“->”-事物的右侧),您可以沿着某些轴进行元素乘法并沿着其他一些轴进行收缩(您没有'没有手写张量代数符号)。

result =  np.einsum('ijkl, ijlm -> ijkm', np.einsum('ijkl, ijkm -> ijlm', vecs, test), vecs)

这几乎可以解决问题。现在只需要去掉对角线项。我们可以通过减去这样的对角项来做到这一点:

result = result - result * np.eye(np.shape(test)[-1])[None, None, ...]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-07
    • 1970-01-01
    • 2018-06-05
    • 2023-04-11
    • 2017-05-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多