python - (出人意料地具有挑战性?)Numpy 向量化

标签 python numpy vectorization

我想找到一种方法在我的代码中避免循环。我需要实现以下公式,一开始很简单:

formula

简而言之:索引列表被解析为I。对于 I 中指定的每个索引,需要减去数组 x 中所有后续索引的值。对减去的值进行一些计算。总结一切。完成。

我当前的代码:

def loss(x, indices):
    """ 
    Args:
        x: array_like, dtype=float
        indices: array_like, dtype=int

    Example:
        >>> x = np.array([0.3, 0.5, 0.2, 0.1, 1.2, 2.4, 2.8, 1.5, 3.2])
        >>> indices = np.array([0, 2, 3, 6])
        >>> print(loss(x, indices))
        21.81621815885847
    """

    total = 0.0
    for index in indices:
        # Broadcasting here, as all values from all following indices have
        # to be subtracted from the value at the given i index.
        difference = x[index] - x[index + 1:]

        # Sum all up
        log_addition = 1.0 + np.log(np.abs(difference))
        total += np.sum(log_addition)

    return total

具有挑战性的部分是 'i' 索引随机分布在输出范围内。有什么想法吗?

最佳答案

这是一个基于 NumPy 的矢量化 -

mask = indices[:,None] < np.arange(len(x))
v = x[indices,None] - x
vmasked = v[mask]
log_addition = np.log(np.abs(vmasked))
out = log_addition.sum() + mask.sum()

或者,使用对数定律,我们可以将最后两步替换为 -

out = np.log(np.prod(np.abs(vmasked))).sum() + mask.sum()

abs 推出,以便它在标量上运行,它将是 -

out = np.log(np.abs(np.prod(vmasked))).sum() + mask.sum()

同样,我们可以利用 多核numexpr -

import numexpr as ne
out = np.log(np.abs(ne.evaluate('prod(vmasked)'))) + mask.sum()

如果你发现即使v也有太多不需要的元素,我们可以直接去vmasked -

xi = x[indices]
x2D = np.broadcast_to(x, (len(indices),len(x)))
vmasked = np.repeat(xi,mask.sum(1))-x2D[mask]

关于python - (出人意料地具有挑战性?)Numpy 向量化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61267484/

相关文章:

Python Decimal 模块 - 不需要的类似 float 的输出?

python - VMWare pyvmomi 6.0.0 : Operation not supported

使用 Numpy 仅出现在浮雕图像上的 Python 错误

python - 查找多边形点的二维数组中最近的点

python - 有没有好方法在 numpy 数组上进行 "moving"计算?

python - BeautifulSoup 如何在运行时创建对象名称?

python - 各时段活跃ID数

python - Tensorflow:如何实现累积最大值?

matlab - 在 MATLAB 中向量化矩阵的加权和

r - 对具有后向依赖性的 R 循环进行向量化