目 录CONTENT

文章目录

提升代码效率:7个Numpy向量化技巧,让你的Python代码运行飞快!

青云TOP
2025-10-10 / 0 评论 / 0 点赞 / 0 阅读 / 0 字

📢 转载信息

原文链接:https://machinelearningmastery.com/7-numpy-tricks-to-vectorize-your-code/

原文作者:Jason Brownlee


🚀 7个Numpy技巧,助你彻底向量化代码,大幅提升性能!

在数据科学和机器学习领域,Numpy无疑是Python中最核心的库之一。然而,许多初学者仍然习惯于使用Python的循环(loops)来处理数组,这在处理大型数据集时效率极低。

向量化(Vectorization)是Numpy的精髓,它利用底层C语言的优化,使数组操作比逐个元素处理快得多。本文将介绍7个强大的Numpy技巧,帮助你摆脱低效的循环,让你的代码运行速度得到质的飞跃。

7个Numpy技巧,助你彻底向量化代码,大幅提升性能!

1. 避免循环:使用 `np.where()` 代替条件判断

当你在处理数组时需要根据条件进行赋值,比如“如果满足条件A,则取值X;否则取值Y”,很多人会想到使用Python的if/else语句放在循环中。Numpy提供了更简洁高效的np.where()函数来完成这项任务。

低效示例(使用循环):

# 假设我们有一个数组a
a = np.array([1, 5, -3, 10, -2, 8])

b = np.zeros_like(a)
for i in range(len(a)):
    if a[i] > 0:
        b[i] = a[i] * 2
    else:
        b[i] = a[i] / 2

高效向量化示例(使用 `np.where()`):

a = np.array([1, 5, -3, 10, -2, 8])

b = np.where(a > 0, a * 2, a / 2)
print(b) 
# 输出: [ 2.  10.  -1.5  20.  -1.  16. ]

np.where(condition, x, y)会根据条件返回x或y的对应元素,完全避免了Python级别的循环开销。

2. 使用布尔索引进行高效筛选

如果你想根据条件从数组中提取元素,避免使用循环或列表推导式。布尔索引(Boolean Indexing)是实现这一目标的原生Numpy方式。

低效示例:

a = np.array([1, 5, -3, 10, -2, 8])

positive_numbers = []
for x in a:
    if x > 0:
        positive_numbers.append(x)

高效向量化示例:

a = np.array([1, 5, -3, 10, -2, 8])

positive_mask = a > 0  # 生成布尔数组
positive_numbers = a[positive_mask]
# 或者直接:
positive_numbers = a[a > 0]

print(positive_numbers)
# 输出: [ 1  5 10  8]

3. 广播(Broadcasting)的力量

广播是Numpy最强大、最难以理解但却至关重要的特性之一。它允许不同形状的数组进行算术运算,而无需显式地复制数据。

例如,将一个标量(单个数字)加到一个Numpy数组的所有元素上,或者将一个1D数组与一个2D数组的每一行相加,Numpy都会自动“广播”该操作。

A = np.array([[1, 2, 3], 
              [4, 5, 6]])

# 广播一个标量
B = A + 10
print(B)
# 输出:
# [[11 12 13]
#  [14 15 16]]

# 广播一个一维数组到矩阵的每一行
C = np.array([100, 200, 300])
D = A + C
print(D)
# 输出:
# [[101 202 303]
#  [104 205 306]]

4. 避免不必要的内存拷贝:使用视图

在Numpy中,切片(slicing)通常不会创建数据的副本,而是返回原始数组的一个“视图”(View)。修改视图会直接修改原始数组,这极大地节省了内存和时间。

你需要知道什么时候操作返回的是视图,什么时候返回的是副本。例如,简单的切片返回视图,但使用布尔索引或整数索引返回副本。

# 返回视图的例子
original = np.arange(10)
view = original[2:5]  # 视图

view[:] = 999  # 修改视图
print(original) 
# 输出: [  0   1 999 999 999   5   6   7   8   9]

# 返回副本的例子
copy_slice = original[original > 5] # 副本
copy_slice[:] = 111 
print(original) # 原始数组未变
# 输出: [  0   1 999 999 999   5   6   7   8   9]

5. 矩阵乘法:使用 `@` 运算符

如果你需要进行矩阵乘法(线性代数中的点积),请避免使用嵌套循环。在Python 3.5及更高版本中,推荐使用简洁的@运算符,它对应于np.matmul()

A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])

# 向量化操作
C = A @ B
print(C)
# 输出:
# [[19 22]
#  [43 50]]

6. 使用 `np.ufunc` 进行元素级操作

通用函数(Universal Functions,ufuncs)是Numpy处理数组的标准方式,比如np.add(), np.sqrt(), np.sin()等。它们都经过高度优化,并且支持广播。

永远不要在Numpy数组上循环来计算这些基本数学函数。

a = np.array([1.0, 4.0, 9.0])

# 向量化平方根
result = np.sqrt(a) 
print(result)
# 输出: [1. 2. 3.]

7. 利用 `np.meshgrid` 创建坐标网格

在需要对二维空间中的每个点进行计算时(例如在绘图或物理模拟中),np.meshgrid是一个强大的工具,它可以生成坐标矩阵,避免了嵌套循环。

# 假设我们要计算 x^2 + y^2 在 x=[-2, -1, 0, 1, 2] 和 y=[-2, -1, 0, 1, 2] 上的值

x = np.array([-2, -1, 0, 1, 2])
y = np.array([-2, -1, 0, 1, 2])

# 创建网格坐标矩阵
X, Y = np.meshgrid(x, y)

# 直接在矩阵上进行向量化计算
Z = X**2 + Y**2

print("X 矩阵:\n", X)
print("Y 矩阵:\n", Y)
print("Z 结果:\n", Z)

通过使用XY这两个矩阵,我们一次性完成了5x5=25个点的计算,效率远高于使用两个嵌套for循环。

总结

掌握Numpy的向量化编程是成为高效数据科学家的必经之路。当你看到自己写下for i in range(len(array)):时,请立即停下来思考:Numpy是否有内置函数或广播机制可以替代这段代码? 坚持使用这些技巧,你的代码性能将会显著提升!




🚀 想要体验更好更全面的AI调用?

欢迎使用青云聚合API,约为官网价格的十分之一,支持300+全球最新模型,以及全球各种生图生视频模型,无需翻墙高速稳定,小白也可以简单操作。

青云聚合API官网https://api.qingyuntop.top

支持全球最新300+模型:https://api.qingyuntop.top/pricing

详细的调用教程及文档:https://api.qingyuntop.top/about

0

评论区