【问题标题】:(Surprisingly challenging?) Numpy Vectorization(令人惊讶的挑战?)Numpy Vectorization
【发布时间】:2020-04-17 08:44:29
【问题描述】:

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

换句话说:一个索引列表被解析为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' 索引在输出范围内随机分布。有什么想法吗?

【问题讨论】:

    标签: python numpy vectorization


    【解决方案1】:

    这是一个基于 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()
    

    同样,我们可以利用 multi-coresnumexpr -

    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]
    

    【讨论】:

    • 谢谢!这已经是一个很好的解决方案。尽管如此,我还是希望找到一种方法来避免不必要的计算再次被取消,因为我需要多次重复应用此功能,因此需要它尽可能高效。我应该在我的问题中指出这一点。
    • @fabriz-io 查看编辑。它只对相关/有效元素进行那些数学繁重的计算。
    猜你喜欢
    • 1970-01-01
    • 2019-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-09
    • 2011-04-29
    • 2022-06-11
    • 2021-08-20
    相关资源
    最近更新 更多