鉴于此......
我必须解释这段代码的作用,知道它使用广播和元素操作概念执行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可以将它们转换为相同大小的其他大小,也可以使用不同大小的arranys,这种转换称为广播),用另一个Nx1的顺序减去1xN的数组,从而得到矩阵包含x_j - x_1,x_j - x_2等的阶NxN的D作为元素,最后,在最后一行中计算α的倒数(这显然是一种排列),其中每个元素乘以R评估的总和矩阵D的每个单元格水平乘以alpha_j(由于参数中的轴= 1)
问题:
答案 0 :(得分:0)
这里可以提出很少的意见/改进/修正。
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)
。通过此步骤,性能的好处应该是显而易见的。
因此,第二步减少到 -
border-color:green;