【问题标题】:Numpy vectorization with calculation depending on previous value(s)Numpy 向量化,计算取决于先前的值
【发布时间】:2022-01-14 17:27:35
【问题描述】:

是否有一种矢量化方法可以将第一个1offset 内的所有并发1 更改为0s(将A 转换为B)?我目前正在尝试在一个包含超过 100 万个项目的 numpy 数组上执行此操作,其中速度至关重要。

1s 表示信号触发,0s 表示无触发。例如:给定偏移量5,只要有1,以下5项必须是0(以去除信号并发)。

示例 1:

offset = 3
A = np.array([1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0])
B = np.array([1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0])

示例 2:

offset = 2
A = np.array([1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0])
B = np.array([1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0])

【问题讨论】:

  • 很抱歉,我不明白您从 A 到 B 的具体路线
  • 刚刚更新了问题。 Lmk 如果这样可以解决问题。
  • 0 之后的第一个1 的位置是np.argwhere(np.diff(np.pad(A,1)) == 1).squeeze()。但这对手头的问题并没有真正的帮助,因为您还想在新创建的0s 之后计算1s。
  • “矢量化”在动作是“并行”时最简单——无论顺序如何,对所有元素都执行相同的动作。 numpy 方法不实现顺序操作,除了有限的情况,如 cumsum 和类似的 ufunc.accumulate。不是不能对顺序操作进行编码,而是更难创建可以一个接一个地应用的构建块。在某些时候,您可能需要使用像 numba 这样的编译工具。
  • 我将从基于列表的解决方案开始。随着对任务的更好理解,您可能会看到允许您以“多维”方式表达的模式。但是对于长度和间距不同的序列,这可能会很困难。使用numba 加速可能比尝试挤出某种全阵列numpy 解决方案更容易。

标签: python arrays numpy vectorization


【解决方案1】:

从 cmets 看来,问题不仅仅与使用 NumPy 和……有关,主要目标是加快代码速度。由于您使用的是 JohanC 提到的部分解决方案(对于这个问题需要更多考虑),我建议使用以下方法:

def com_():
    n = 1
    for i in range(1, len(A)+1):
        if A[n-1] == 1:
            A[n:n+offset] = 0
            n += offset + 1
        else:
            n += 1
        if n > len(A):
            break


@nb.jit(forceobj=True)
def com_fast(): 
    B = A.tolist()
    n = 1
    while n < len(B):
        if B[n-1] == 1:
            for i in range(offset):
                if n+i < len(B):
                    B[n+i] = 0
            n += offset + 1
        else:
            n += 1

第一种方法是使用NumPy数组形式的A和循环。第二个使用 list 形式的输入并循环,并由numba 加速,正如 hpaulj 在 cmets 中提到的那样。
对方法使用相同的输入 (1,000,000 in length),并在 Google Colab TPU 上运行:

1000 loops, best of 5: 153 ms per loop         # for com_()
1000 loops, best of 5: 10.2 ms per loop        # for com_fast()

我认为,对于这么大的数据,这将显示可接受的性能时间。 我觉得,这个问题光靠NumPy是解决不了的,不然的话,会很困难,需要好好想一想(我试过了,效果不错,最后还是需要循环)。我的猜测是,使用 numba 和类似的库可能会产生类似的结果(在运行时),因此它不需要只使用 NumPy。

【讨论】:

    猜你喜欢
    • 2011-11-01
    • 2019-03-13
    • 1970-01-01
    • 1970-01-01
    • 2016-04-01
    • 1970-01-01
    • 2020-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多