Python中如何使用numpy取消循环操作?

有如下代码,请问该如何去掉两重 for 循环,使用 numpy 的数组操作来实现呢?谢谢各位了

import numpy as np

a = np.zeros((100, 100)) b = np.zeros((100, 100)) ds = [] for i in range(5, 95): for j in range(5, 95): pa = a[i-5:i+5, j-5:j+5] pb = b[i-5:i+5, j-5:j+5] d = pa - pb ds.append(d)

return ds


Python中如何使用numpy取消循环操作?

6 回复

from skimage.util.shape import view_as_windows

a = np.random.random((100,100))
b = np.random.random((100,100))

ret = view_as_windows(a-b, (10,10))

In [1]: np.allclose(ret[:-1,:-1,:], ds.reshape(90,90,10,10))
Out[1]: True

顺带一提,view_as_windows 有 step 函数,你这个情况 step=1,是默认参数。


在Python里用NumPy取消循环,核心就是利用它的向量化操作。NumPy的底层是C实现的,对数组进行整体计算比Python的for循环快几个数量级。

核心方法:

  1. 直接使用NumPy的通用函数(ufunc):比如要对一个数组每个元素做数学运算(np.sin(), np.exp(), +, -, *, / 等),直接用数组操作,别用循环。
  2. 使用广播(Broadcasting):让不同形状的数组进行算术运算,NumPy会自动扩展维度。
  3. 使用聚合函数:比如 np.sum(), np.mean(), np.max() 等,直接对整个数组或某个轴进行计算。

举个例子,把数组里每个元素加1:

import numpy as np

# 低效的循环方式
arr = np.array([1, 2, 3, 4, 5])
result_loop = np.empty_like(arr)
for i in range(len(arr)):
    result_loop[i] = arr[i] + 1

# 高效的向量化方式
result_vectorized = arr + 1  # 或者 np.add(arr, 1)

print("循环结果:", result_loop)
print("向量化结果:", result_vectorized)

再比如,计算两个数组对应元素的乘积和(点积):

# 低效的循环方式
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
dot_loop = 0
for i in range(len(a)):
    dot_loop += a[i] * b[i]

# 高效的向量化方式
dot_vectorized = np.dot(a, b)  # 或者 (a * b).sum()

print("循环点积:", dot_loop)
print("向量化点积:", dot_vectorized)

关键就一句话:看到循环,先想想能不能直接用数组整体算。

step=10 在你的例子里应该相当于刚好无重叠,可以用 view_as_blocks 函数。

这个函数基本上是在用 np.lib.stride_tricks.as_strided,所以如果你没有 skimage,去 skimage 找到那个函数拷过来就行。麻烦的地方只在怎么根据 window_size 和 step 算 stride

感谢帮助,我去试试~

这种直接改 numba

回到顶部