跳到主要内容

Vectorization

· 阅读需 7 分钟
Jiujiuwhoami
Digital nomads

从一些基础的向量化操作开始,逐步深入理解向量化计算的技巧和常见用法。向量化常见操作的重点是通过对数组、矩阵的批量操作来替代逐个元素的显式循环。以下是一些常见的向量化操作:

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 的广播、条件判断、聚合等功能,我们可以高效地处理和分析数据。掌握这些操作后,你可以将复杂的数据处理过程转化为简洁且高效的向量化代码。