NumPy高效数值计算指南

🎙️ 语音朗读 当前: 晓晓 (温柔女声)

NumPy高效数值计算指南

NumPy是Python科学计算的基石,几乎所有数据科学和机器学习库都建立在NumPy之上。

NumPy数组基础

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import numpy as np

# 创建数组
a = np.array([1, 2, 3, 4, 5]) # 一维数组
b = np.array([[1, 2, 3], [4, 5, 6]]) # 二维数组
c = np.zeros((3, 4)) # 全零数组
d = np.ones((2, 3)) # 全一数组
e = np.arange(0, 10, 2) # 等差数列 [0, 2, 4, 6, 8]
f = np.linspace(0, 1, 5) # 等间距 [0, 0.25, 0.5, 0.75, 1.0]
g = np.random.randn(3, 3) # 标准正态分布
h = np.eye(3) # 单位矩阵

print(f"数组形状: {b.shape}") # (2, 3)
print(f"数组维度: {b.ndim}") # 2
print(f"数据类型: {b.dtype}") # int64
print(f"元素总数: {b.size}") # 6

数组索引与切片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
arr = np.arange(24).reshape(4, 6)
print(arr)

# 基本索引
print(arr[1, 2]) # 第2行第3列元素
print(arr[1]) # 第2行
print(arr[:, 2]) # 第3列

# 切片
print(arr[1:3, 2:5]) # 第2-3行,第3-5列

# 布尔索引
mask = arr > 10
print(arr[mask]) # 所有大于10的元素

# 花式索引
print(arr[[0, 2], [1, 3]]) # (0,1)和(2,3)位置的元素

向量化运算

NumPy的核心优势是向量化运算,避免Python循环:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import time

# Python列表运算 vs NumPy向量化
size = 1000000
a_list = list(range(size))
b_list = list(range(size))
a_np = np.arange(size)
b_np = np.arange(size)

# Python列表
start = time.time()
c_list = [a + b for a, b in zip(a_list, b_list)]
print(f"Python列表: {time.time() - start:.4f}s")

# NumPy向量化
start = time.time()
c_np = a_np + b_np
print(f"NumPy向量化: {time.time() - start:.4f}s")

广播机制

广播是NumPy处理不同形状数组运算的机制:

1
2
3
4
5
6
7
8
9
# 形状 (3, 1) + 形状 (1, 4) -> 形状 (3, 4)
a = np.array([[1], [2], [3]]) # (3, 1)
b = np.array([10, 20, 30, 40]) # (1, 4)
c = a + b # (3, 4)

print(c)
# [[11 21 31 41]
# [12 22 32 42]
# [13 23 33 43]]

广播规则:

  1. 如果两个数组维度不同,较小的形状在前方补1
  2. 如果形状在某个维度上为1,则沿该维度广播
  3. 其他维度必须相等或其中一个为1

数学运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
x = np.random.randn(3, 4)

# 基本运算
print(np.sqrt(x)) # 平方根
print(np.exp(x)) # 指数
print(np.log(np.abs(x) + 1e-10)) # 对数
print(np.sin(x)) # 正弦

# 统计运算
print(np.mean(x, axis=0)) # 列均值
print(np.std(x, axis=1)) # 行标准差
print(np.max(x, axis=0)) # 列最大值
print(np.argmax(x, axis=1)) # 行最大值索引
print(np.cumsum(x, axis=0)) # 列累加和

# 矩阵运算
A = np.random.randn(3, 3)
B = np.random.randn(3, 4)

print(np.dot(A, B)) # 矩阵乘法
print(A.T) # 转置
print(np.linalg.inv(A)) # 逆矩阵
print(np.linalg.det(A)) # 行列式
print(np.linalg.eig(A)) # 特征值和特征向量

数组操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
a = np.arange(12)

# 改变形状
print(a.reshape(3, 4)) # (3, 4)
print(a.reshape(2, -1)) # -1表示自动计算

# 拼接
b = np.arange(12, 24).reshape(3, 4)
print(np.vstack([a.reshape(3, 4), b])) # 垂直拼接
print(np.hstack([a.reshape(3, 4), b])) # 水平拼接

# 分割
c = np.arange(24).reshape(4, 6)
print(np.hsplit(c, 3)) # 水平3等分
print(np.vsplit(c, 2)) # 垂直2等分

# 排序
d = np.random.randn(5, 3)
print(np.sort(d, axis=0)) # 按列排序
print(np.argsort(d[:, 0])) # 第1列排序的索引

性能优化技巧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 1. 预分配数组
result = np.empty(1000)
for i in range(1000):
result[i] = i ** 2

# 2. 使用视图而非拷贝
a = np.arange(12).reshape(3, 4)
b = a.reshape(4, 3) # 视图,不复制数据
c = a.copy() # 显式拷贝

# 3. 使用np.where代替条件循环
x = np.random.randn(1000)
y = np.where(x > 0, x, 0) # ReLU操作

# 4. 使用einsum高效矩阵运算
A = np.random.randn(3, 4)
B = np.random.randn(4, 5)
C = np.einsum('ij,jk->ik', A, B) # 等价于 np.dot(A, B)

线性代数应用

1
2
3
4
5
6
7
8
9
10
11
12
13
# 解线性方程组 Ax = b
A = np.array([[3, 1], [1, 2]])
b = np.array([9, 8])
x = np.linalg.solve(A, b)
print(f"解: {x}") # [2. 3.]

# 最小二乘法
A = np.random.randn(100, 3)
b = np.random.randn(100)
x, residuals, rank, sv = np.linalg.lstsq(A, b, rcond=None)

# SVD分解
U, S, Vt = np.linalg.svd(A, full_matrices=False)

总结

NumPy是Python科学计算的核心库,其向量化运算和广播机制使得数值计算既高效又简洁。掌握数组操作、数学运算、广播规则和性能优化技巧,是进行数据科学和机器学习工作的基础。在实际项目中,应尽量使用NumPy的向量化操作替代Python循环,以获得最佳性能。

© 2019-2026 ovo$^{mc^2}$ All Rights Reserved. | 站点总访问 28969 次 | 访客 19045
Theme by hiero