【问题标题】:Vectorized Evaluation of a Function, Broadcasting and Element Wise Operations函数、广播和元素操作的矢量化评估
【发布时间】:2016-09-20 06:06:22
【问题描述】:

鉴于此...

我必须解释这段代码的作用,知道它使用广播和元素明智的操作概念执行 F 的矢量化评估...

def F(x_pos, alpha):
    D = x_pos.reshape(1,-1) - x_pos.reshape(-1,1)
    return (1./alpha) * (alpha.reshape(1,-1) * R(D)).sum(axis=1)

我的解释是:

函数F的第一行接收x_pos和alpha作为参数(都是numpy数组),第二行矩阵D是通过广播的方式计算的(数组numpy中的加法等基本操作是按元素执行的,即, 逐个元素,但是如果 numpy 可以将它们转换为相同大小的其他数组,则也可以使用不同大小的数组,这种转换称为广播),用另一个 Nx1 阶的数组减去 1xN 阶的数组,得到矩阵NxN 阶 D 包含 x_j - x_1、x_j - x_2 等作为元素,最后,在最后一行计算 alpha 的倒数(这显然是一种排列),其中每个元素乘以 R 评估的总和矩阵 D 的每个单元格水平乘以 alpha_j(由于参数中的轴 = 1)

问题:

  1. 考虑到我是 Python 新手,我的解释可以吗?
  2. 代码是否有错误?因为我没有看到代码中考虑了每个总和中的“j必须不同于1、2、...、n”...如果它实际上是错误的...我该如何解决代码,所以它做的事情与图片中的完全一样?

【问题讨论】:

    标签: python numpy vectorization elementwise-operations


    【解决方案1】:

    这里可以建议一些 cmets/改进/修复。

    1] 第一步也可以通过引入一个新轴并减去自身来完成,就像这样 -

    D = x_pos[:,None] - x_pos
    

    在我看来,这是一个更干净的选择。性能优势可能只是微不足道的。

    2] 在第二行中,我认为它需要修复,因为我们需要避免计算 R(D) 的对角线元素。所以,如果我理解正确,更正后的代码将是 -

    vals = R(D)
    np.fill_diagonal(vals,0)
    out = (1./alpha) * (alpha.reshape(1,-1) * vals).sum(axis=1)
    

    现在,让我们让代码更惯用/更简洁。

    在那一行,我们可以写:(alpha * vals) 而不是alpha.reshape(1,-1) * vals。这是因为形状已经为broadcasting 对齐,如下图所示 -

    alpha :      n
    vals  :  n x n
    

    因此,alpha 将自动扩展到2D,其元素沿第一个轴广播vals 的长度,然后生成元素乘法。同样,这意味着代码更简洁。

    (alpha.reshape(1,-1) * vals).sum(axis=1) 可以用matrix-multiplicatiion 替换,使用np.dot 作为alpha.dot(vals) 可以进一步提高性能。这一步对性能的好处应该很明显。

    所以,第二步简化为 -

    out = (1./alpha) * alpha.dot(vals)
    

    【讨论】:

    • x_pos[:,None] - x_pos 几乎肯定会更慢,因为它必须解析切片,但只有一个可以忽略不计的常数,而且肯定更惯用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多