首页 > 解决方案 > 向量化双重求和的 Pythonic 方法

问题描述

我正在尝试将双重求和公式转换为代码,但无法弄清楚它的正确矩阵/向量表示。

第一个求和是 i 到 n,第二个求和超过 j > i 到 n。

我猜有一种更有效和 Pythonic 的方式来写这个?

我求助于嵌套的 for 循环来让它工作,但正如预期的那样,它在大型数据集下运行非常缓慢:

def wapc_denom(weights, vols):
    x = []
    y = []

    for i, wi in enumerate(weights):
        for j, wj in enumerate(weights):
            if j > i:
                x.append(wi * wj * vols[i] * vols[j])
        y.append(np.sum(x))

    return np.sum(y)

编辑:

使用 smci's answer 的指导,我认为我有一个潜在的解决方案:

def wapc_denom2(weights, vols):
    return np.sum(np.tril(np.outer(weights, vols.T)**2, k=-1))

标签: pythonnumpymatrixvectorization

解决方案


假设您只想计算每个术语一次(为此您必须将其x = []移到外循环中)计算总和的一种廉价方法是

创建模拟数据

weights = np.random.random(10)
vols = np.random.random(10)

进行计算

wv = weights * vols
result = (wv.sum()**2 - wv@wv) / 2

检查是否相同

def wapc_denom(weights, vols):
    y = []

    for i, wi in enumerate(weights):
        x = []
        for j, wj in enumerate(weights):
            if j > i:
                x.append(wi * wj * vols[i] * vols[j])
        y.append(np.sum(x))

    return np.sum(y)

assert np.allclose(result, wapc_denom(weights, vols))

为什么它有效?

我们正在做的是计算整个矩阵的总和,减去对角线并除以二。这很便宜,因为很容易验证外部产品的总和只是总和因子的乘积。


推荐阅读