在 Python 中矢量化条件逻辑?



老派的c程序员试图与时俱进并学习Python。努力了解如何有效地使用矢量化来替换循环。我理解的基本概念是Python可以在单个语句中对整个矩阵执行数学函数,这真的很酷。但我很少研究数学关系。几乎所有我的 for 循环都应用条件逻辑。

下面是一个非常简单的示例来说明这个概念:

import numpy as np
# Initial values
default = [1,2,3,4,5,6,7,8]
# Override values should only replace initial values when not nan
override = [np.nan,np.nan,3.5,np.nan,5.6,6.7,np.nan,8.95] 
# I wish I knew how to replace this for loop with a single line of vectorized code
for i in range(len(default)):
if(np.isnan(override[i])==False): #Only override when override value is other than nan
default[i]=override[i]
default

我有一种感觉,可以通过单个python语句消除for循环,该语句仅用未np.nan的值覆盖default的值override。但我看不出该怎么做。

这只是一个简化的示例来说明该概念。我真正的问题是,矢量化对于用条件逻辑替换循环是否通常有用,或者它是否仅适用于数学关系,其中实现它们的好处和方法是显而易见的。我所有真正的代码挑战都复杂得多,条件逻辑比简单的"仅在非 nan 时才使用此值"更复杂。

我在网上找到了数百篇关于如何在 Python 中使用矢量化的文章,但它们似乎都专注于替换 for 循环中的数学计算。我所有的for循环都涉及条件逻辑。矢量化可以帮助我还是我试图在圆孔中安装方形钉子?

谢谢!

首先是矢量化版本:

override_is_not_nan = np.logical_not(np.isnan(override))
np.where(override_is_not_nan, override, default)

至于您的真正问题,矢量化对于多处理很有用。
不仅适用于多核 CPU。
考虑到今天的GPU有数千个内核,使用具有类似代码的张量可以使其运行得更快。
快多少?这取决于您的数据、实施和硬件。
显然,矢量化与GPU的结合是深度学习领域取得巨大进步的一部分。

列表推导通常是 Python 中for循环的首选单行替代方案。也可以在理解中加入条件。

在这种特定情况下,我们通过将它们压缩在一起并根据条件检查替换default的值来迭代defaultoverride的元素。

>>> [y if not(np.isnan(y)) else x for (x,y) in zip(default, override)]
[1, 2, 3.5, 4, 5.6, 6.7, 7, 8.95]

为了回答您关于矢量化和加速的更广泛问题,不幸的是,答案是这取决于。在某些情况下,简单的for循环的性能优于矢量化循环。例如,列表推导只是为了提高代码的可读性,而不是提供严重的加速。

关于这个问题的答案更详细地解决了这个问题。

首先找到非 nan 值所在的索引。
default数组中的值作为索引替换为override数组值。

import numpy as np
np_default = np.array(default).asdtype(float) # Convert np_default to numpy array with float values
non_nan_indices = np.where(~np.isnan(override)) # Get non nan indices
np_default[non_nan_indices] = np.array(override)[non_nan_indices] # Replacing the values at non-nan indices
np_default # Returns array([1.  , 2.  , 3.5 , 4.  , 5.6 , 6.7 , 7.  , 8.95])

矢量化是 numpy 为您提供帮助的地方,它利用了数组的类型化性质,从而加快了操作速度。有关详细信息,请参阅 [博客文章]。

最新更新