AI 高手之路 5:NumPy 教程——高效处理 AI 数据

目录

  1. 引言:为什么 NumPy 在 AI 中如此重要?
  2. NumPy 数组 (ndarray)
    • 2.1 创建数组
      • 从列表或元组创建
      • 使用 arangelinspacelogspace
      • 使用 zerosonesemptyfull
      • 使用 eyediag
      • 从文件读取 (loadtxt, genfromtxt)
    • 2.2 数组属性
      • ndim (维度)
      • shape (形状)
      • size (元素个数)
      • dtype (数据类型)
      • itemsize (每个元素的字节大小)
      • nbytes (总字节大小)
    • 2.3 数据类型
      • 整数 (int8, int16, int32, int64)
      • 无符号整数 (uint8, uint16, uint32, uint64)
      • 浮点数 (float16, float32, float64)
      • 复数 (complex64, complex128)
      • 布尔值 (bool)
      • 对象 (object)
      • 字符串 (string_, unicode_)
    • 2.4 数组操作
      • 索引 (indexing)
      • 切片 (slicing)
      • 变形 (reshaping)
      • 拼接 (concatenation, stacking)
      • 拆分 (splitting)
      • 转置 (transposing)
      • 广播 (broadcasting)
  3. NumPy 通用函数 (ufunc)
    • 3.1 数学运算 (+, -, *, /, **, %, abs, sqrt, exp, log, sin, cos, tan, …)
    • 3.2 比较运算 (==, !=, >, <, >=, <=)
    • 3.3 逻辑运算 (np.logical_and, np.logical_or, np.logical_not)
    • 3.4 位运算 (&, |, ^, ~)
  4. NumPy 线性代数 (linalg)
    • 4.1 矩阵乘法 (dot, matmul)
    • 4.2 矩阵转置 (transpose)
    • 4.3 矩阵求逆 (inv)
    • 4.4 矩阵行列式 (det)
    • 4.5 矩阵的秩 (matrix_rank)
    • 4.6 求解线性方程组 (solve)
    • 4.7 特征值和特征向量 (eig)
    • 4.8 奇异值分解 (svd)
    • 4.9 最小二乘法 (lstsq)
  5. NumPy 随机数 (random)
    • 5.1 随机数种子 (seed)
    • 5.2 简单随机数 (rand, randn, randint)
    • 5.3 各种分布的随机数 (uniform, normal, binomial, poisson, exponential, …)
    • 5.4 随机排列 (shuffle, permutation)
  6. NumPy 实用技巧
    • 6.1 条件筛选 (boolean indexing)
    • 6.2 数组排序 (sort)
    • 6.3 数组去重 (unique)
    • 6.4 查找最大/最小值 (max, min, argmax, argmin)
    • 6.5 数组求和、平均值、标准差 (sum, mean, std)
    • 6.6 数组累积和 (cumsum)
    • 6.7 数组舍入 (round, floor, ceil)
    • 6.8 将 NumPy 数组保存到文件 (save, savez, savetxt)
  7. NumPy 在 AI 中的应用
  8. 总结与下一步
  9. 挑战任务

今天,我想和大家聊聊一个看似基础,却又至关重要的工具——NumPy。如果你正在AI的道路上探索,或者已经身处其中,那么NumPy绝对是你不可或缺的伙伴。

1. 引言:为什么 NumPy 在 AI 中如此重要?

想象一下,AI模型就像精密的机器,而数据就是驱动它的燃料。在AI的世界里,数据往往以多维数组的形式存在。无论是图像、文本、音频,还是复杂的表格数据,最终都会被转化成计算机能够理解和处理的数字阵列。

NumPy,正是为高效处理这些多维数组而生的Python库。它就像AI世界的地基,为各种高级的AI框架(如TensorFlow、PyTorch、Scikit-learn)提供了坚实的数据运算基础。

为什么NumPy如此重要?原因很简单:高效、简洁、方便、且无处不在

  • 高效性:NumPy底层使用C语言编写,对数组运算进行了极致优化,速度远超Python原生列表。这对于动辄处理海量数据的AI应用至关重要。
  • 简洁性:NumPy提供了丰富的函数库,几行代码就能完成复杂的矩阵运算、统计分析等任务,让你的代码更易读、易维护。
  • 方便性:NumPy的广播机制、切片索引等特性,使得数组操作如同行云流水般顺畅,极大地提升了开发效率。
  • 广泛应用:毫不夸张地说,只要你接触AI,就绕不开NumPy。它是数据科学、机器学习、深度学习生态系统中不可或缺的核心组件。

如果你想在AI领域更进一步,那么深入理解NumPy,绝对是你的必修课。

2. NumPy 数组 (ndarray)

NumPy的核心是ndarray(N-dimensional array),即N维数组对象。它可以存储同类型的数据,并支持快速的数学运算。

2.1 创建数组

NumPy 提供了多种便捷的方法来创建数组:

从列表或元组创建

这是最直接的方式:

import numpy as np

# 从列表创建
a = np.array([1, 2, 3])
print(a) # 输出: [1 2 3]

# 从嵌套列表创建二维数组
b = np.array([[1, 2], [3, 4]])
print(b)
# 输出:
# [[1 2]
#  [3 4]]

# 从元组创建
c = np.array((1, 2, 3))
print(c) # 输出: [1 2 3]
使用 arangelinspacelogspace

这些函数可以快速生成有规律的数组:

# arange: 类似于 Python 的 range,但返回数组
c = np.arange(10)  # 生成 0 到 9 的整数数组
print(c) # 输出: [0 1 2 3 4 5 6 7 8 9]

d = np.arange(0, 10, 2) # 生成 0 到 10 (不包含) 步长为 2 的数组
print(d) # 输出: [0 2 4 6 8]

# linspace: 生成指定范围内,指定数量的等差数列
e = np.linspace(0, 1, 11)  # 生成 0 到 1 之间,包含 11 个元素的等差数组
print(e) # 输出: [0.  0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ]

# logspace: 生成指定范围内,指定数量的等比数列 (对数刻度)
f = np.logspace(0, 2, 5)  # 生成 10^0 到 10^2 之间,包含 5 个元素的等比数组
print(f) # 输出: [  1.           3.16227766  10.          31.6227766  100.        ]
使用 zerosonesemptyfull

这些函数可以创建特定形状和初始值的数组:

# zeros: 创建指定形状的全 0 数组
g = np.zeros((2, 3))  # 2 行 3 列的全 0 数组
print(g)
# 输出:
# [[0. 0. 0.]
#  [0. 0. 0.]]

# ones: 创建指定形状的全 1 数组
h = np.ones((3, 2))   # 3 行 2 列的全 1 数组
print(h)
# 输出:
# [[1. 1.]
#  [1. 1.]
#  [1. 1.]]

# empty: 创建指定形状的未初始化数组 (速度快,但值不确定)
i = np.empty((2, 2))  # 2 行 2 列的未初始化数组
print(i)
# 输出 (值不确定,每次运行可能不同):
# [[6.23042e-307 1.60222e-322]
#  [0.00000e+000 0.00000e+000]]

# full: 创建指定形状,并用指定值填充的数组
j = np.full((3, 3), 7) # 3 行 3 列,所有元素为 7 的数组
print(j)
# 输出:
# [[7 7 7]
#  [7 7 7]
#  [7 7 7]]
使用 eyediag

用于创建特殊矩阵:

# eye: 创建单位矩阵 (对角线为 1,其余为 0)
k = np.eye(3)    # 3x3 单位矩阵
print(k)
# 输出:
# [[1. 0. 0.]
#  [0. 1. 0.]
#  [0. 0. 1.]]

# diag: 创建对角矩阵,或提取对角线元素
l = np.diag([1, 2, 3])  # 以 [1, 2, 3] 为对角线元素的对角矩阵
print(l)
# 输出:
# [[1 0 0]
#  [0 2 0]
#  [0 0 3]]
从文件读取 (loadtxt, genfromtxt)

在实际AI项目中,数据通常存储在文件中。NumPy 提供了方便的函数来读取文件中的数据并创建数组:

# 假设有一个名为 'data.txt' 的文本文件,内容如下 (逗号分隔):
# 1,2,3
# 4,5,6

# 使用 loadtxt 读取文本文件 (适用于数据类型一致的文件)
# data = np.loadtxt('data.txt', delimiter=',')
# print(data)
# 输出:
# [[1. 2. 3.]
#  [4. 5. 6.]]

# genfromtxt 更通用,可以处理缺失值等更复杂的情况
# data_gen = np.genfromtxt('data.txt', delimiter=',')
# print(data_gen)
# 输出:
# [[1. 2. 3.]
#  [4. 5. 6.]]

# 注意:请先自行创建 'data.txt' 文件进行测试

2.2 数组属性

理解数组的属性对于操作和管理数据至关重要:

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

print("维度 (ndim):", a.ndim)    # 输出: 维度 (ndim): 2 (二维数组)
print("形状 (shape):", a.shape)   # 输出: 形状 (shape): (2, 3) (2 行 3 列)
print("元素个数 (size):", a.size)  # 输出: 元素个数 (size): 6 (总共 6 个元素)
print("数据类型 (dtype):", a.dtype) # 输出: 数据类型 (dtype): int64 (整数类型,根据系统可能不同)
print("每个元素的字节大小 (itemsize):", a.itemsize) # 输出: 每个元素的字节大小 (itemsize): 8 (int64 占 8 字节)
print("总字节大小 (nbytes):", a.nbytes)  # 输出: 总字节大小 (nbytes): 48 (6 个元素 * 每个元素 8 字节)

2.3 数据类型

NumPy 提供了丰富的数据类型,可以灵活地存储各种数据:

  • 整数: int8, int16, int32, int64 (不同位数的整数)
  • 无符号整数: uint8, uint16, uint32, uint64 (非负整数)
  • 浮点数: float16, float32, float64 (单精度、双精度浮点数)
  • 复数: complex64, complex128 (复数)
  • 布尔值: bool (True 或 False)
  • 对象: object (可以存储任意 Python 对象,效率较低)
  • 字符串: string_, unicode_ (固定长度字符串)

你可以在创建数组时使用 dtype 参数显式指定数据类型:

a = np.array([1, 2, 3], dtype=np.float32) # 创建 float32 类型的数组
print(a.dtype) # 输出: float32

选择合适的数据类型可以有效节省内存空间,并提升运算效率。

2.4 数组操作

NumPy 提供了强大的数组操作功能,让数据处理更加高效便捷。

索引 (indexing)

访问数组中的单个元素:

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

print(a[0, 0])  # 输出: 1 (第一行第一列,索引从 0 开始)
print(a[1, 2])  # 输出: 6 (第二行第三列)
切片 (slicing)

访问数组的子区域:

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

print(a[0, :])   # 输出: [1 2 3] (第一行,":" 表示所有列)
print(a[:, 1])   # 输出: [2 5 8] (第二列,":" 表示所有行)
print(a[0:2, 1:3]) # 输出: [[2 3] [5 6]] (第 1-2 行,第 2-3 列)
变形 (reshaping)

改变数组的形状,但不改变元素数量:

a = np.arange(6) # 创建 [0 1 2 3 4 5]
print(a) # 输出: [0 1 2 3 4 5]

b = a.reshape(2, 3) # 变形为 2 行 3 列的矩阵
print(b)
# 输出:
# [[0 1 2]
#  [3 4 5]]

c = b.ravel()  # 将多维数组展开为一维数组
print(c)  # 输出: [0 1 2 3 4 5]
拼接 (concatenation, stacking)

将多个数组合并成一个数组:

a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[7, 8, 9], [10, 11, 12]])

# concatenate: 沿指定轴拼接数组
c = np.concatenate((a, b), axis=0)  # 沿行 (axis=0) 拼接
print(c)
# 输出:
# [[ 1  2  3]
#  [ 4  5  6]
#  [ 7  8  9]
#  [10 11 12]]

d = np.concatenate((a, b), axis=1)  # 沿列 (axis=1) 拼接
print(d)
# 输出:
# [[ 1  2  3  7  8  9]
#  [ 4  5  6 10 11 12]]

# hstack (horizontal stack): 水平拼接 (相当于 axis=1 的 concatenate)
e = np.hstack((a, b))
print(e)
# 输出 (与 d 相同):
# [[ 1  2  3  7  8  9]
#  [ 4  5  6 10 11 12]]

# vstack (vertical stack): 垂直拼接 (相当于 axis=0 的 concatenate)
f = np.vstack((a,b))
print(f)
# 输出 (与 c 相同):
# [[ 1  2  3]
#  [ 4  5  6]
#  [ 7  8  9]
#  [10 11 12]]
拆分 (splitting)

将一个数组拆分成多个子数组:

a = np.arange(9).reshape(3, 3) # 创建 3x3 数组
print(a)
# 输出:
# [[0 1 2]
#  [3 4 5]
#  [6 7 8]]

# split: 沿指定轴拆分数组
g = np.split(a, 3, axis=0)  # 沿行 (axis=0) 拆分成 3 份
print(g)
# 输出 (列表,每个元素都是一个子数组):
# [array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]

h = np.split(a, 3, axis=1)  # 沿列 (axis=1) 拆分成 3 份
print(h)
# 输出 (列表,每个元素都是一个子数组):
# [array([[0], [3], [6]]), array([[1], [4], [7]]), array([[2], [5], [8]])]
转置 (transposing)

交换数组的维度,对于二维数组来说就是行列互换:

a = np.array([[1, 2, 3], [4, 5, 6]])
print(a)
# 输出:
# [[1 2 3]
#  [4 5 6]]

print(a.T) # 转置
# 输出:
# [[1 4]
#  [2 5]
#  [3 6]]
广播 (broadcasting)

NumPy 最强大的特性之一,允许不同形状的数组进行运算。NumPy 会自动扩展维度较小的数组,使其与维度较大的数组兼容,再进行逐元素运算。

x = np.array([[1, 2, 3], [4, 5, 6]]) # 2x3 数组
y = np.array([1, 0, 1]) # 1x3 数组 (或 shape 为 (3,) 的一维数组)
print(y.shape) # 输出:(3,)

print(x + y)  # 广播机制:y 会自动扩展为 [[1, 0, 1], [1, 0, 1]],再与 x 相加
# 输出:
# [[2 2 4]
#  [5 5 7]]

系统架构图:NumPy 在 AI 生态中的位置

AI Ecosystem
Data Processing Analysis
Deep Learning Frameworks
NumPy
TensorFlow
PyTorch
Pandas
Scikit-learn
Matplotlib
Data Sources
AI
Deep

图示:NumPy 作为 AI 生态系统的基础,为数据处理、分析以及深度学习框架提供核心支持。数据首先进入 NumPy 进行高效处理,之后才能被其他库和框架有效地利用。

3. NumPy 通用函数 (ufunc)

NumPy 提供了大量的通用函数 (ufunc),可以对数组进行逐元素操作,极大地提升了运算效率。

3.1 数学运算

NumPy 提供了丰富的数学运算 ufunc,涵盖了基础的算术运算到复杂的数学函数:

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

print("加法 (+):", a + b)  # 输出: 加法 (+): [5 7 9]
print("减法 (-):", a - b)  # 输出: 减法 (-): [-3 -3 -3]
print("乘法 (*):", a * b)  # 输出: 乘法 (*): [ 4 10 18]
print("除法 (/):", a / b)  # 输出: 除法 (/): [0.25 0.4  0.5 ]
print("幂运算 (**):", a ** b) # 输出: 幂运算 (**): [  1  32 729]
print("取模 (%):", a % b)  # 输出: 取模 (%): [1 2 3]

print("绝对值 (abs):", np.abs([-1, -2, 3]))  # 输出: 绝对值 (abs): [1 2 3]
print("平方根 (sqrt):", np.sqrt(a))           # 输出: 平方根 (sqrt): [1.         1.41421356 1.73205081]
print("指数 (exp):", np.exp(a))            # 输出: 指数 (exp): [ 2.71828183  7.3890561  20.08553692]
print("对数 (log):", np.log(a))            # 输出: 对数 (log): [0.         0.69314718 1.09861229]
print("正弦 (sin):", np.sin(a))            # 输出: 正弦 (sin): [0.84147098 0.90929743 0.14112001]
print("余弦 (cos):", np.cos(a))            # 输出: 余弦 (cos): [ 0.54030231 -0.41614684 -0.9899925 ]
print("正切 (tan):", np.tan(a))            # 输出: 正切 (tan): [ 1.55740772 -2.18503986 -0.14254654]

3.2 比较运算

比较运算 ufunc 返回布尔值数组,用于条件判断和数据筛选:

a = np.array([1, 2, 3])
b = np.array([3, 2, 1])

print("等于 (==):", a == b)  # 输出: 等于 (==): [False  True False]
print("不等于 (!=):", a != b)  # 输出: 不等于 (!=): [ True False  True]
print("大于 (>):", a > b)   # 输出: 大于 (>): [False False  True]
print("小于 (<):", a < b)   # 输出: 小于 (<): [ True False False]
print("大于等于 (>=):", a >= b)  # 输出: 大于等于 (>=): [False  True  True]
print("小于等于 (<=):", a <= b)  # 输出: 小于等于 (<=): [ True  True False]

3.3 逻辑运算

逻辑运算 ufunc 用于进行布尔数组的逻辑操作:

a = np.array([True, True, False, False])
b = np.array([True, False, True, False])

print("逻辑与 (logical_and):", np.logical_and(a, b))  # 输出: 逻辑与 (logical_and): [ True False False False]
print("逻辑或 (logical_or):", np.logical_or(a, b))   # 输出: 逻辑或 (logical_or): [ True  True  True False]
print("逻辑非 (logical_not):", np.logical_not(a))     # 输出: 逻辑非 (logical_not): [False False  True  True]

3.4 位运算

位运算 ufunc 直接操作整数的二进制位:

a = np.array([1, 2, 3], dtype=np.uint8)  # 二进制: 00000001, 00000010, 00000011
b = np.array([3, 2, 1], dtype=np.uint8)  # 二进制: 00000011, 00000010, 00000001

print("按位与 (&):", a & b)   # 输出: 按位与 (&): [1 2 1] (二进制: 00000001, 00000010, 00000001)
print("按位或 (|):", a | b)   # 输出: 按位或 (|): [3 2 3] (二进制: 00000011, 00000010, 00000011)
print("按位异或 (^):", a ^ b)   # 输出: 按位异或 (^): [2 0 2] (二进制: 00000010, 00000000, 00000010)
print("按位取反 (~):", ~a)      # 输出: 按位取反 (~): [254 253 252] (二进制: 11111110, 11111101, 11111100 - 注意 uint8 的溢出)

4. NumPy 线性代数 (linalg)

numpy.linalg 模块提供了强大的线性代数运算功能,这在机器学习和深度学习中应用极其广泛。

4.1 矩阵乘法

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

print("矩阵乘法 (dot):")
print(np.dot(A, B))
# 输出:
# [[19 22]
#  [43 50]]

print("矩阵乘法 (@ 运算符):")
print(A @ B)  # 另一种更简洁的写法
# 输出 (与 dot 相同):
# [[19 22]
#  [43 50]]

4.2 矩阵转置

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

print("矩阵转置 (A.T):")
print(A.T)
# 输出:
# [[1 3]
#  [2 4]]

print("矩阵转置 (transpose):")
print(np.transpose(A))
# 输出 (与 A.T 相同):
# [[1 3]
#  [2 4]]

4.3 矩阵求逆

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

A_inv = np.linalg.inv(A) # 计算矩阵 A 的逆矩阵
print("矩阵求逆 (inv):")
print(A_inv)
# 输出:
# [[-2.   1. ]
#  [ 1.5 -0.5]]

print("验证逆矩阵 (A @ A_inv):")
print(A @ A_inv)  # 矩阵 A 乘以其逆矩阵,应该接近单位矩阵
# 输出 (接近单位矩阵):
# [[1.0000000e+00 0.0000000e+00]
#  [8.8817842e-16 1.0000000e+00]]

4.4 矩阵行列式

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

det_A = np.linalg.det(A) # 计算矩阵 A 的行列式
print("矩阵行列式 (det):", det_A)  # 输出: 矩阵行列式 (det): -2.0

4.5 矩阵的秩

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

rank_A = np.linalg.matrix_rank(A) # 计算矩阵 A 的秩
print("矩阵的秩 (matrix_rank):", rank_A)  # 输出: 矩阵的秩 (matrix_rank): 2

4.6 求解线性方程组

# 求解线性方程组 Ax = b
# 例如: x + 2y = 5, 3x + 4y = 11

A = np.array([[1, 2], [3, 4]]) # 系数矩阵 A
b = np.array([5, 11]) # 常数向量 b

x = np.linalg.solve(A, b) # 求解 Ax = b
print("求解线性方程组 (solve):", x)  # 输出: 求解线性方程组 (solve): [1. 2.] (即 x=1, y=2)

4.7 特征值和特征向量

A = np.array([[1, 2], [2, 1]])

eigenvalues, eigenvectors = np.linalg.eig(A) # 计算矩阵 A 的特征值和特征向量
print("特征值 (eig values):", eigenvalues)    # 输出: 特征值 (eig values): [ 3. -1.]
print("特征向量 (eig vectors):\n", eigenvectors)
# 输出:
# 特征向量 (eig vectors):
# [[ 0.70710678 -0.70710678]
#  [ 0.70710678  0.70710678]]

4.8 奇异值分解 (SVD)

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

U, S, V = np.linalg.svd(A) # 对矩阵 A 进行奇异值分解
print("U (SVD U):\n", U)
print("S (SVD Singular Values):", S)  # 奇异值 (对角线元素)
print("V (SVD V):\n", V)

4.9 最小二乘法

# 求解 Ax = b 的最小二乘解 (当 A 不是方阵或方程组无解时)
# 例如:拟合直线 y = mx + c,已知若干个 (x, y) 数据点

A = np.array([[1, 1], [1, 2], [1, 3]]) # 设计矩阵 A (假设 y = c + mx)
b = np.array([2, 3, 5]) # 观测值向量 b (y 值)

x, residuals, rank, s = np.linalg.lstsq(A, b, rcond=None) # 求解最小二乘解
print("最小二乘解 (lstsq):", x)  # 输出: 最小二乘解 (lstsq): [0.5 1.5] (即 c=0.5, m=1.5)
print("残差平方和 (residuals):", residuals) # 输出: 残差平方和 (residuals): [0.5]

5. NumPy 随机数 (random)

numpy.random 模块提供了强大的随机数生成功能,用于模拟数据、初始化模型参数、以及各种随机算法。

5.1 随机数种子

np.random.seed(42)  # 设置随机数种子,保证每次运行程序生成的随机数序列相同,便于结果复现

5.2 简单随机数

print("0-1 均匀分布随机数 (rand):\n", np.random.rand(2, 3))  # 生成 2x3 数组,元素为 [0, 1) 之间的均匀分布随机数
# 输出 (每次运行可能不同,但种子固定后会相同):
# [[0.37454012 0.95071431 0.73199394]
#  [0.59865848 0.15601864 0.15599452]]

print("标准正态分布随机数 (randn):\n", np.random.randn(2, 3)) # 生成 2x3 数组,元素为标准正态分布 (均值为 0,标准差为 1) 随机数
# 输出 (每次运行可能不同,但种子固定后会相同):
# [[ 0.70807258 -0.12289023  0.2088636 ]
#  [-1.95967015 -0.43333143  1.21791614]]

print("指定范围整数随机数 (randint):\n", np.random.randint(1, 10, (2, 3)))  # 生成 2x3 数组,元素为 [1, 10) 之间的随机整数
# 输出 (每次运行可能不同,但种子固定后会相同):
# [[4 4 8]
#  [5 7 3]]

5.3 各种分布的随机数

NumPy 提供了各种常见概率分布的随机数生成函数:

print("均匀分布 (uniform):\n", np.random.uniform(1, 10, (2, 3)))  # 生成 2x3 数组,元素为 [1, 10) 之间的均匀分布随机数
print("正态分布 (normal):\n", np.random.normal(0, 1, (2, 3)))    # 生成 2x3 数组,元素为正态分布随机数 (均值为 0,标准差为 1)
print("二项分布 (binomial):\n", np.random.binomial(10, 0.5, (2, 3))) # 生成 2x3 数组,元素为二项分布随机数 (n=10, p=0.5)
print("泊松分布 (poisson):\n", np.random.poisson(5, (2, 3)))      # 生成 2x3 数组,元素为泊松分布随机数 (lambda=5)
print("指数分布 (exponential):\n", np.random.exponential(2, (2, 3)))  # 生成 2x3 数组,元素为指数分布随机数 (scale=2,即均值为 2)
# ... 还有更多分布,例如 gamma, beta, chi2 等

5.4 随机排列

a = np.arange(10) # 创建 [0 1 2 3 4 5 6 7 8 9]
print("原始数组:", a) # 输出: 原始数组: [0 1 2 3 4 5 6 7 8 9]

np.random.shuffle(a)  # 就地打乱数组 a 的顺序 (改变原数组)
print("shuffle 打乱后:", a)
# 输出 (每次运行可能不同,但种子固定后会相同):
# shuffle 打乱后: [9 1 6 7 3 0 8 4 2 5]

b = np.arange(10) # 重新创建 [0 1 2 3 4 5 6 7 8 9]
c = np.random.permutation(b)  # 返回打乱后的新数组,不改变原数组 b
print("permutation 打乱后:", c)
# 输出 (每次运行可能不同,但种子固定后会相同):
# permutation 打乱后: [1 7 4 6 9 2 8 0 3 5]
print("原始数组 b (未改变):", b) # 输出: 原始数组 b (未改变): [0 1 2 3 4 5 6 7 8 9]

流程图:NumPy 数组创建流程

列表/元组
范围/序列
等差序列
等比序列
特定值填充
全零
全一
指定值
未初始化
特殊矩阵
单位矩阵
对角矩阵
文件读取
文本文件
B
使用np.array()
选择序列生成函数
np.arange()/np.linspace()
np.logspace()
选择填充函数
np.zeros()
np.ones()
np.full()
np.empty()
选择特殊矩阵函数
np.eye()
np.diag()
选择文件读取函数
np.loadtxt()/np.genfromtxt()
创建ndarray

流程图:展示了 NumPy 数组创建的主要流程,根据不同的数据来源和需求,选择不同的 NumPy 函数来创建 ndarray 对象。

6. NumPy 实用技巧

掌握一些 NumPy 的实用技巧,可以让你在数据处理中更加得心应手。

6.1 条件筛选 (boolean indexing)

使用布尔数组作为索引,可以高效地筛选数组中满足特定条件的元素:

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

print("大于 2 的元素:", a[a > 2])  # 输出: 大于 2 的元素: [3 4 5]
print("大于 1 且小于 5 的元素:", a[(a > 1) & (a < 5)])  # 输出: 大于 1 且小于 5 的元素: [2 3 4]

6.2 数组排序

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

print("排序后的数组 (sort):", np.sort(a))   # 输出: 排序后的数组 (sort): [1 2 3 4 5] (返回排序后的副本,原数组不变)
print("原始数组 a (未改变):", a) # 输出: 原始数组 a (未改变): [3 1 4 2 5]

a.sort()          # 就地排序,直接修改原数组 a
print("就地排序后的数组 (a.sort()):", a)          # 输出: 就地排序后的数组 (a.sort()): [1 2 3 4 5]

6.3 数组去重

a = np.array([1, 2, 2, 3, 3, 3, 4, 4, 4, 4])

print("去重后的数组 (unique):", np.unique(a))  # 输出: 去重后的数组 (unique): [1 2 3 4]

6.4 查找最大/最小值

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

print("最大值 (max):", np.max(a))     # 输出: 最大值 (max): 5
print("最小值 (min):", np.min(a))     # 输出: 最小值 (min): 1
print("最大值索引 (argmax):", np.argmax(a))  # 输出: 最大值索引 (argmax): 4 (最大值 5 的索引)
print("最小值索引 (argmin):", np.argmin(a))  # 输出: 最小值索引 (argmin): 1 (最小值 1 的索引)

6.5 数组求和、平均值、标准差

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

print("求和 (sum):", np.sum(a))   # 输出: 求和 (sum): 15
print("平均值 (mean):", np.mean(a))  # 输出: 平均值 (mean): 3.0
print("标准差 (std):", np.std(a))   # 输出: 标准差 (std): 1.4142135623730951

6.6 数组累积和

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

print("累积和 (cumsum):", np.cumsum(a))  # 输出: 累积和 (cumsum): [ 1  3  6 10 15]
# 累积和的计算过程: [1, 1+2, 1+2+3, 1+2+3+4, 1+2+3+4+5]

6.7 数组舍入

a = np.array([1.2, 2.5, 3.7])

print("四舍五入 (round):", np.round(a))  # 输出: 四舍五入 (round): [1. 2. 4.]
print("向下取整 (floor):", np.floor(a))  # 输出: 向下取整 (floor): [1. 2. 3.]
print("向上取整 (ceil):", np.ceil(a))   # 输出: 向上取整 (ceil): [2. 3. 4.]

6.8 将 NumPy 数组保存到文件

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

np.save("my_array.npy", a)   # 保存为 .npy 文件 (NumPy 专用的二进制格式,高效)
print("数组已保存到 my_array.npy")

b = np.load("my_array.npy")   # 加载 .npy 文件
print("从 my_array.npy 加载的数组:\n", b)
# 输出:
# 从 my_array.npy 加载的数组:
# [[1 2 3]
#  [4 5 6]]

np.savetxt("my_array.txt", a, delimiter=",")  # 保存为文本文件 (例如 CSV 格式,通用性好)
print("数组已保存到 my_array.txt")

c = np.loadtxt("my_array.txt", delimiter=",")  # 加载文本文件
print("从 my_array.txt 加载的数组:\n", c)
# 输出:
# 从 my_array.txt 加载的数组:
# [[1. 2. 3.]
#  [4. 5. 6.]]

# np.savez("my_arrays.npz", array_a=a, array_b=b) # 保存多个数组到一个 .npz 文件中 (压缩格式)
# arrays = np.load("my_arrays.npz") # 加载 .npz 文件
# print(arrays['array_a']) # 访问保存的数组

7. NumPy 在 AI 中的应用

NumPy 在 AI 的各个环节都扮演着重要的角色:

  • 数据预处理:数据清洗、缺失值处理、数据转换(例如归一化、标准化)、特征缩放等,都离不开 NumPy 的高效数组运算。
  • 特征工程:从原始数据中提取、构造有意义的特征,例如图像像素特征、文本词向量特征、音频频谱特征等,NumPy 提供了强大的数组操作和数学运算支持。
  • 模型构建:无论是传统的机器学习模型(如线性回归、逻辑回归、支持向量机),还是现代的深度学习模型(神经网络),其底层运算都基于 NumPy 数组。模型参数、权重、偏置项等都以 NumPy 数组的形式存储和计算。
  • 图像处理:图像本质上是像素矩阵,NumPy 可以方便地进行图像的读取、显示、裁剪、缩放、旋转、滤波、特征提取等操作。很多图像处理库(如 OpenCV, Pillow)都与 NumPy 紧密结合。
  • 自然语言处理 (NLP):文本数据可以转换为词袋模型、TF-IDF 向量、词嵌入向量(如 Word2Vec, GloVe, FastText),这些向量表示都以 NumPy 数组的形式存储。NumPy 也用于文本数据的预处理、特征提取、模型构建等环节。
  • 音频处理:音频信号可以表示为波形数据(一维数组)或频谱图数据(二维数组),NumPy 可以用于音频数据的读取、分析、特征提取(如 MFCCs, Mel 频谱)、音频合成等操作。

NumPy 在 AI 应用流程中的角色

机器学习模型
深度学习模型
NumPy
NumPy
NumPy 数组
NumPy 数组
原始数据
数据预处理
特征工程
模型选择
Scikit-learn 等
TensorFlow/PyTorch
模型训练
模型评估
模型部署/应用

图示:NumPy 在 AI 应用流程中的核心地位。数据预处理、特征工程阶段,NumPy 用于高效的数据操作和特征提取。模型训练阶段,各种 AI 框架(Scikit-learn, TensorFlow, PyTorch)都依赖 NumPy 数组作为数据输入和模型参数的载体。

8. 总结与下一步

NumPy 是 AI 世界的基石,掌握 NumPy 的核心概念和常用功能,是成为一名合格的 AI 从业者的必要条件。本文深入浅出地介绍了 NumPy 的方方面面,从数组创建、属性、操作,到通用函数、线性代数、随机数生成,再到实用技巧和在 AI 中的应用,希望能够帮助你系统地学习 NumPy。

下一步,建议你:

  • 实践练习:动手敲代码,完成文中的代码示例,并尝试解决文末的挑战任务。
  • 查阅文档:深入阅读 NumPy 官方文档,了解更多高级功能和细节。
  • 结合应用:尝试将 NumPy 应用到实际的 AI 项目中,例如数据分析、图像处理、简单的机器学习模型等。
  • 学习相关库:继续学习基于 NumPy 的其他库,例如 Pandas (数据分析)、Matplotlib (数据可视化)、Scikit-learn (机器学习)、TensorFlow/PyTorch (深度学习),构建更完整的 AI 技术栈。

9. 挑战任务

  1. 复习:回顾本文所有概念和代码示例,确保理解 NumPy 的核心知识点。
  2. 练习:完成以下 NumPy 操作:
    • 创建一个 3x4 的全 0 数组。
    • 创建一个 5x5 的单位矩阵。
    • 创建一个从 10 到 100 (不包括 100) 的等差数列,步长为 5。
    • 创建一个 2x3x4 的三维数组,元素为随机整数 (范围自定)。
    • 给定数组 a = np.array([1, 2, 3, 4, 5, 6]),将其变形为 2x3 的矩阵。
    • 给定数组 a = np.array([1, 2, 3])b = np.array([4, 5, 6]),计算它们的点积 (矩阵乘法)。
    • 给定矩阵 A = np.array([[1, 2], [3, 4]]),计算它的逆矩阵。
    • 给定矩阵 A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]),计算它的特征值和特征向量。
    • 生成 100 个服从标准正态分布的随机数,并计算它们的平均值和标准差。
    • 生成 10 个服从二项分布 (n=10, p=0.5) 的随机数。
    • 给定数组 a = np.array([5, 2, 8, 1, 9, 4]),对其进行升序和降序排序。
    • 给定数组 a = np.array([1, 2, 2, 3, 3, 3, 4, 4, 4, 4]),找出其中的唯一值,并统计每个唯一值出现的次数。
    • 给定数组 a = np.array([1, 2, 3, 4, 5]),找出大于 2 且小于 5 的元素,并将它们替换为 0。
    • 将一个 NumPy 数组保存到文件 (文本和二进制两种格式),然后从文件中加载。
  3. 探索:尝试使用 NumPy 实现一个简单的线性回归模型,例如使用最小二乘法拟合一组数据点。
  4. 阅读:深入阅读 NumPy 官方文档,特别是关于广播机制、ufunc 高级用法、以及性能优化的部分。

希望这篇博客能成为你 NumPy 学习的良好起点。AI 的世界广阔而精彩,NumPy 将是你手中最可靠的工具之一。让我们一起在 AI 的道路上不断前行!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海棠AI实验室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值