Vectorization
从一些基础的向量化操作开始,逐步深入理解向量化计算的技巧和常见用法。向量化常见操作的重点是通过对数组、矩阵的批量操作来替代逐个元素的显式循环。以下是一些常见的向量化操作:
1. 数组和矩阵创建
在学习向量化计算之前,我们首先需要了解如何创建和操作数组或矩阵。
创建数组
我们可以使用 NumPy
来创建一维、二维或更高维度的数组(或矩阵)。
import numpy as np
# 创建一维数组
a = np.array([1, 2, 3, 4, 5])
# 创建二维数组(矩阵)
b = np.array([[1, 2], [3, 4], [5, 6]])
print(a)
print(b)
2. 基本算术运算
最简单的向量化操作之一是执行元素级别的数学运算。对于两个相同大小的数组,可以直接进行加减乘除等操作,而无需显式循环。
例子:
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
# 向量化加法
result_add = a + b
print(result_add) # 输出: [5 7 9]
# 向量化减法
result_sub = a - b
print(result_sub) # 输出: [-3 -3 -3]
# 向量化乘法
result_mul = a * b
print(result_mul) # 输出: [4 10 18]
# 向量化除法
result_div = a / b
print(result_div) # 输出: [0.25 0.4 0.5]
在这些例子中,a + b
等操作就是向量化,它们不会逐个元素地计算,而是直接对整个数组进行操作,底层通常会使用更高效的 C 实现来加速。
3. 广播机制 (Broadcasting)
广播是 NumPy 的一个非常强大的功能,它允许不同形状的数组之间进行数学运算。其核心思想是自动地“扩展”较小的数组,使得它们与较大的数组形状匹配,从而执行元素级操作。
例子:
假设我们有一个 1D 数组和一个 2D 数组,我们可以通过广播将 1D 数组加到 2D 数组的每一行:
a = np.array([1, 2, 3]) # 形状:(3,)
b = np.array([[4, 5, 6], [7, 8, 9]]) # 形状:(2, 3)
# 向量化加法,广播a到b的形状
result = a + b
print(result)
输出:
[[5 7 9]
[8 10 12]]
这里,a
的形状是 (3,)
,而 b
的形状是 (2, 3)
。NumPy 会自动将 a
扩展为 (2, 3)
,使得加法操作能够顺利执行。
4. 条件操作
你可以在向量化中使用条件语句来处理数据。例如,使用 np.where()
函数可以根据条件对数组元素进行修改。
例子:
a = np.array([1, 2, 3, 4, 5])
# 将数组中的偶数替换为 0,奇数保留原值
result = np.where(a % 2 == 0, 0, a)
print(result) # 输出: [1 0 3 0 5]
5. 聚合操作
NumPy 提供了许多用于聚合操作的函数,如求和、均值、最大值、最小值等。
例子:
a = np.array([1, 2, 3, 4, 5])
# 求和
sum_a = np.sum(a)
print(sum_a) # 输出: 15
# 求均值
mean_a = np.mean(a)
print(mean_a) # 输出: 3.0
# 求最大值和最小值
max_a = np.max(a)
min_a = np.min(a)
print(max_a, min_a) # 输出: 5 1
这些聚合操作通常是向量化的,直接对整个数组进行计算,避免了显式的循环。
6. 矩阵乘法与点积
矩阵的乘法或向量的点积在机器学习、深度学习等领域是非常常见的操作,NumPy 提供了直接支持这些操作的函数。
例子:
# 向量点积
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
dot_product = np.dot(a, b)
print(dot_product) # 输出: 32(1*4 + 2*5 + 3*6)
# 矩阵乘法
m1 = np.array([[1, 2], [3, 4]])
m2 = np.array([[5, 6], [7, 8]])
matrix_product = np.dot(m1, m2)
print(matrix_product)
输出:
[[19 22]
[43 50]]
7. 矩阵转置与逆
矩阵转置和逆是常见的线性代数操作,NumPy 也提供了相关的向量化操作。
例子:
# 矩阵转置
m = np.array([[1, 2], [3, 4]])
transpose_m = m.T
print(transpose_m)
输出:
[[1 3]
[2 4]]
8. 矢量化的常见函数
除了基本的运算,NumPy 还提供了很多常用的矢量化函数,例如 np.sin()
、np.exp()
、np.log()
等。
例子:
a = np.array([0, np.pi / 2, np.pi])
# 使用向量化的 sin 函数
result_sin = np.sin(a)
print(result_sin) # 输出: [0. 1. 0.]
9. 高级向量化操作
- 矩阵的特征值和特征向量:
np.linalg.eig()
,用于计算矩阵的特征值和特征向量。 - 奇异值分解:
np.linalg.svd()
,用于奇异值分解。
10. 总结
向量化计算的关键思想是避免显式循环,通过对数组或矩阵的批量运算来提升效率。NumPy 提供的数组和矩阵操作支持大量常见的数学和线性代数运算。通过合理利用 NumPy 的广播、条件判断、聚合等功能,我们可以高效地处理和分析数据。掌握这些操作后,你可以将复杂的数据处理过程转化为简洁且高效的向量化代码。