是否可以在Python中向量化if-else语句的循环?

问题描述 投票:0回答:1

我想知道是否有可能将带有多个 if-else 语句的 for 循环转换为 Python 中的向量化版本。假设我有几个 numpy 数组

a,b,c,d
,其中
a,b,c,d
具有相同的长度。我需要编写以下 for 循环来计算
c
和 'd'

的值
    for i in range(2, len(a)):
        if (
            a[i - 2] < b[i - 2]
            and a[i - 1] > b[i - 1]
            and c[i - 1] == 0
        ):
            d[i] = -1
            c[i] = c[i - 1] - 1
        elif (
            a[i - 2] > b[i - 2]
            and a[i - 1] < b[i - 1]
            and c[i - 1] == 0
        ):
            d[i] = 1
            c[i] = c[i - 1] + 1
        else: 
            d[i] = 0  
            c[i] = c[i - 1]

问题是数组的大小是

10^5
,我必须为
10^3' times, the time complexity is 
O(10^8)` 执行这个 for 循环,使用带有 if-else 语句的 for 循环非常慢且计算量大。我想知道是否有矢量化或更快的方法在 Python 中执行这些操作?

我已经向 ChatGPT 寻求帮助,它建议将

if
,
elif
条件改为

condition1 = (
    (a[:-2] < b[:-2]) &
    (a[1:-1] > b[1:-1]) &
    (d 1:-1] == 0)
)

condition2 = (
    (a[:-2] > b[:-2]) &
    (a[1:-1] < b[1:-1]) &
    (d 1:-1] == 0)
)
分别是

。然后,它使用

np.where
来执行条件

c[2:] = np.where(condition1, -1,0)
d[2:] = np.where(condition1, d[1:-1] - 1, d[1:-1])

c[2:] = np.where(condition2, 1, 0)
d[2:] = np.where(condition2, d1:-1] + 1, d[1:-1])

但是,与 for 循环结果相比,这些结果并不正确。另外,我不知道

else
语句的条件在哪里。

python numpy for-loop optimization vectorization
1个回答
0
投票

首先,你(或chatgpt)混合c和d(原始代码测试a,b和c,以决定影响-1,0,1到d。尝试的答案测试a,b,d以决定影响 -1,0,1 到 c)

其次,您的 chatgpt 答案没有正确链接

if/then/else
来创建
if cond1 thenCase1 else (if cond2 thenCase2 elseCase3)

但是如果您了解

np.where
的作用 (
np.where(arrayOfBoolConds, thenArray, elseArray)
),您就可以自己完成。

例如

d[2:] = np.where(condition1, -1, np.where(condition2, 1, 0))

第三,你的问题不能直接矢量化。至少如果您一般性地考虑它的话(也许,在更仔细地思考您的问题的具体情况时,我们可能会将其转换为矢量化函数和累积函数的组合)。 ChatGPT 没有看到这一点。 您不能执行

c[2:] = vectorizedFunctionOf(c[1:-1])
并期望它正确迭代。无论如何,“向量化”和“迭代”是两个矛盾的词。向量化是同时处理情况的事实(这个词与 numpy 一起使用是说,从 python 的角度来看,它是在一个 numpy 的调用中完成的,即使在该调用内部,可能会发生迭代。但严格来说,矢量化是在 Cray 的超级计算机或英特尔 MMX 和下一个指令中发生的事情 - 当然,还有新的矢量化处理器:在不同的数据上同时执行多个相同的指令)

话虽这么说,有一些函数,如

cumsum
cumprod
在 numpy 的世界中被称为“向量化”,同时执行一些迭代过程(但同样,在单个 numpy 的调用中)。也许他们可以帮忙。

如果

c
不是条件的一部分,我会建议
c[2:]
c[1]+d[2:].cumsum()
。但是你需要一个完全计算的
c
来执行
np.where
,并且你需要那些
np.where
来计算
c
。因此,不可矢量化,除非您设法以不同的方式编写算法。

一般来说(除了一些可以通过

cumsum
的巧妙组合来完成的特定情况之外),你不能矢量化迭代过程。

© www.soinside.com 2019 - 2024. All rights reserved.