NumPy完全教程:多维数组操作+矩阵运算(AI数值计算核心)

2 阅读9分钟

NumPy(Numerical Python)是Python数据科学、人工智能领域的基础核心库——它以C语言级别的效率实现了多维数组(ndarray)操作和矩阵运算,解决了原生Python列表数值计算慢、维度操作繁琐的问题。无论是深度学习中的张量计算、数据分析中的数值处理,还是机器学习中的矩阵运算,NumPy都是绕不开的核心工具。本文从实操角度出发,手把手教你掌握NumPy多维数组的创建、变形、索引,以及矩阵的加减乘除、逆矩阵、特征值等核心操作,代码可直接复制运行,新手也能快速上手。

一、前置准备:安装与环境配置

NumPy是Python的第三方库,先完成安装(推荐搭配Anaconda,避免版本冲突):

# 方式1:pip安装(通用)
pip install numpy

# 方式2:Anaconda安装(推荐AI/数据科学开发)
conda install numpy

安装完成后,在Python环境中验证:

import numpy as np  # 约定俗成的简写,所有教程均采用此方式
print(np.__version__)  # 输出版本号,如1.26.0,验证安装成功

二、核心基础:NumPy多维数组(ndarray)

NumPy的核心是ndarray(N-dimensional array),即多维数组,它是同类型数据的集合,相比Python原生列表,具备“固定维度、统一类型、向量化运算”三大优势。

1. 数组创建:从基础到常用场景

(1)基础创建:列表/元组转数组

最常用的方式是通过np.array()将Python列表/元组转为多维数组:

# 一维数组(向量)
arr1d = np.array([1, 2, 3, 4, 5])
print("一维数组:", arr1d)
print("维度:", arr1d.ndim)  # 输出1
print("形状:", arr1d.shape)  # 输出(5,) → 5个元素的一维数组

# 二维数组(矩阵)
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
print("\n二维数组:\n", arr2d)
print("维度:", arr2d.ndim)  # 输出2
print("形状:", arr2d.shape)  # 输出(2, 3) → 2行3列
print("元素类型:", arr2d.dtype)  # 输出int64(默认整数类型)

# 三维数组(张量,AI中常用)
arr3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print("\n三维数组:\n", arr3d)
print("形状:", arr3d.shape)  # 输出(2, 2, 2) → 2个2行2列的矩阵

(2)快速创建:常用特殊数组

实际开发中,很少手动输入元素,更多用NumPy内置函数快速创建:

# 全0数组(AI中初始化权重常用)
zeros_arr = np.zeros((3, 4))  # 3行4列全0数组
print("全0数组:\n", zeros_arr)

# 全1数组
ones_arr = np.ones((2, 2), dtype=np.float32)  # 指定类型为float32
print("\n全1数组:\n", ones_arr)

# 单位矩阵(对角线为1,其余为0,线性代数核心)
eye_arr = np.eye(3)  # 3×3单位矩阵
print("\n单位矩阵:\n", eye_arr)

# 随机数组(AI中初始化参数常用)
np.random.seed(42)  # 设置随机种子,保证结果可复现
rand_arr = np.random.rand(2, 3)  # 0~1之间的随机数,2行3列
rand_int_arr = np.random.randint(0, 10, (2, 3))  # 0~9的随机整数,2行3列
print("\n0~1随机数组:\n", rand_arr)
print("\n0~9随机整数数组:\n", rand_int_arr)

# 等差数列(数值范围)
linspace_arr = np.linspace(0, 10, 5)  # 0到10之间取5个等距数
arange_arr = np.arange(0, 10, 2)  # 0到10(不含),步长2
print("\n等差数列:", linspace_arr)
print("步长数组:", arange_arr)

2. 数组操作:变形、拼接、分割

(1)数组变形(reshape):调整维度

AI中常需将一维数据转为二维/三维,或反之,核心用reshape()

# 基础变形:一维转二维
arr = np.arange(12)  # [0,1,2,...,11]
reshape_arr = arr.reshape(3, 4)  # 转为3行4列
print("一维转3×4数组:\n", reshape_arr)

# 自动计算维度:用-1表示“自动推导”
reshape_auto = arr.reshape(2, -1)  # 2行,列数自动计算(12/2=6)
print("\n2行自动推导列数:\n", reshape_auto)

# 展平数组:多维转一维(AI中输出层常用)
flatten_arr = reshape_arr.flatten()
print("\n多维数组展平:", flatten_arr)

(2)数组拼接:合并多个数组

# 横向拼接(列扩展):要求行数相同
arr1 = np.array([[1,2], [3,4]])
arr2 = np.array([[5,6], [7,8]])
h_stack = np.hstack((arr1, arr2))
print("横向拼接:\n", h_stack)

# 纵向拼接(行扩展):要求列数相同
v_stack = np.vstack((arr1, arr2))
print("\n纵向拼接:\n", v_stack)

# 按指定轴拼接(通用方式)
concatenate_h = np.concatenate((arr1, arr2), axis=1)  # axis=1横向,axis=0纵向
print("\naxis=1拼接:\n", concatenate_h)

(3)数组分割:拆分一个数组

arr = np.arange(12).reshape(3,4)
# 横向分割:拆分为2个部分
h_split = np.hsplit(arr, 2)  # 将4列拆分为2列×2
print("横向分割结果:")
print(h_split[0], "\n", h_split[1])

# 纵向分割:拆分为3个部分
v_split = np.vsplit(arr, 3)  # 将3行拆分为1行×3
print("\n纵向分割结果:")
print(v_split[0], "\n", v_split[1], "\n", v_split[2])

3. 数组索引与切片:提取目标数据

NumPy的索引/切片比Python列表更灵活,支持多维索引,是AI中提取样本/特征的核心操作:

arr = np.arange(12).reshape(3,4)
print("原始数组:\n", arr)

# 二维数组索引:行索引, 列索引
print("\n取第1行第2列元素:", arr[0, 1])  # 索引从0开始,输出1
print("取第2行所有列:", arr[1, :])  # 输出[4 5 6 7]
print("取所有行的第3列:", arr[:, 2])  # 输出[2 6 10]

# 切片:左闭右开
print("\n取前2行前3列:\n", arr[:2, :3])  # 行0-1,列0-2
print("取奇数行(行1、3):\n", arr[1::2, :])  # 步长2

# 布尔索引:按条件筛选(AI中数据过滤常用)
bool_idx = arr > 5
print("\n大于5的元素:", arr[bool_idx])  # 输出[6 7 8 9 10 11]
print("大于5的元素位置:\n", bool_idx)

# 花式索引:按列表指定索引
fancy_idx = arr[[0, 2], [1, 3]]  # 取(0,1)和(2,3)位置的元素
print("\n花式索引结果:", fancy_idx)  # 输出[1 11]

三、核心进阶:矩阵运算(AI数值计算核心)

NumPy的矩阵运算完全对标线性代数规则,是深度学习(如神经网络反向传播)的底层基础,重点掌握“元素级运算、矩阵乘法、线性代数专用操作”。

1. 元素级运算:逐元素计算

NumPy数组支持直接加减乘除,无需循环,效率远超Python列表:

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

# 元素级加法
add = arr1 + arr2  # 等价于np.add(arr1, arr2)
print("元素级加法:\n", add)

# 元素级乘法(注意:不是矩阵乘法!)
mul = arr1 * arr2  # 等价于np.multiply(arr1, arr2)
print("\n元素级乘法:\n", mul)

# 元素级除法/减法
div = arr1 / arr2
sub = arr1 - arr2
print("\n元素级除法:\n", div)

# 广播运算:不同维度数组运算(AI中权重偏置相加常用)
# 例:2×2矩阵 + 1×2向量 → 自动广播向量为2×2
arr3 = np.array([1, 2])
broadcast_add = arr1 + arr3
print("\n广播加法:\n", broadcast_add)

2. 矩阵乘法:线性代数核心

矩阵乘法是AI的核心运算(如神经网络中输入×权重),NumPy中有两种实现方式:

arr1 = np.array([[1,2], [3,4]])  # 2×2矩阵
arr2 = np.array([[5,6], [7,8]])  # 2×2矩阵
arr3 = np.array([[1,2,3], [4,5,6]])  # 2×3矩阵

# 方式1:np.matmul()(推荐,通用矩阵乘法)
matmul1 = np.matmul(arr1, arr2)  # 2×2 × 2×2 = 2×2
matmul2 = np.matmul(arr1, arr3)  # 2×2 × 2×3 = 2×3
print("2×2矩阵乘法:\n", matmul1)
print("\n2×2 × 2×3矩阵乘法:\n", matmul2)

# 方式2:@运算符(Python 3.5+支持,更简洁)
matmul3 = arr1 @ arr2
print("\n@运算符矩阵乘法:\n", matmul3)

# 注意:矩阵乘法要求“前一个的列数=后一个的行数”,否则报错
# 错误示例:np.matmul(arr3, arr1) → 2×3 × 2×2,列数3≠行数2,报错

3. 线性代数专用操作(linalg模块)

NumPy的np.linalg模块封装了线性代数的核心操作,如逆矩阵、行列式、特征值等,是AI中求解线性方程组、降维(PCA)的基础:

# 1. 逆矩阵(仅方阵且行列式非0时有逆)
arr = np.array([[1,2], [3,4]])
inv_arr = np.linalg.inv(arr)
print("原矩阵:\n", arr)
print("\n逆矩阵:\n", inv_arr)
# 验证:原矩阵×逆矩阵=单位矩阵
print("\n原矩阵×逆矩阵:\n", arr @ inv_arr)  # 近似单位矩阵(浮点误差)

# 2. 行列式
det = np.linalg.det(arr)
print("\n行列式值:", det)

# 3. 特征值和特征向量(PCA、特征分解核心)
eigenvalues, eigenvectors = np.linalg.eig(arr)
print("\n特征值:", eigenvalues)
print("特征向量:\n", eigenvectors)

# 4. 求解线性方程组 Ax = b
# 例:求解 1x + 2y = 5;3x + 4y = 11
A = np.array([[1,2], [3,4]])
b = np.array([5, 11])
x = np.linalg.solve(A, b)
print("\n线性方程组解:x={}, y={}".format(x[0], x[1]))  # x=1, y=2

4. 统计运算:AI中评估模型常用

NumPy提供了丰富的统计函数,用于计算均值、方差、最大值等,是数据预处理、模型评估的基础:

arr = np.random.randint(0, 10, (3,4))
print("原始数组:\n", arr)

# 全局统计
print("\n最大值:", np.max(arr))
print("最小值:", np.min(arr))
print("均值:", np.mean(arr))
print("方差:", np.var(arr))
print("标准差:", np.std(arr))
print("求和:", np.sum(arr))

# 按轴统计(AI中按样本/特征统计)
print("\n按行求和(axis=1):", np.sum(arr, axis=1))  # 每行求和
print("按列求均值(axis=0):", np.mean(arr, axis=0))  # 每列求均值

# 其他常用统计
print("\n中位数:", np.median(arr))
print("最大值位置:", np.argmax(arr))  # 全局最大值的索引
print("按列最大值位置:", np.argmax(arr, axis=0))  # 每列最大值的行索引

四、实战案例:AI中NumPy的典型应用

案例1:数据标准化(机器学习预处理核心)

数据标准化(Z-score):将数据转为均值0、方差1的分布,公式:x=(xμ)/σx' = (x - μ) / σ

# 模拟特征数据(3个样本,2个特征)
features = np.array([[10, 20], [15, 25], [20, 30]])
print("原始特征:\n", features)

# 计算每个特征的均值和标准差(按列)
mean = np.mean(features, axis=0)
std = np.std(features, axis=0)

# 标准化
standardized = (features - mean) / std
print("\n标准化后特征:\n", standardized)
print("标准化后均值:", np.mean(standardized, axis=0))  # 近似0
print("标准化后方差:", np.var(standardized, axis=0))  # 近似1

案例2:神经网络前向传播(简化版)

模拟神经网络的一层计算:output = relu(X @ W + b)

# 激活函数:ReLU
def relu(x):
    return np.maximum(0, x)  # 元素级取最大值,小于0的置为0

# 输入:4个样本,3个特征
X = np.random.rand(4, 3)
# 权重:3个输入特征 → 2个输出神经元
W = np.random.rand(3, 2)
# 偏置:2个神经元的偏置
b = np.random.rand(2)

# 前向传播计算
z = X @ W + b  # 线性变换:4×3 × 3×2 + 2 → 4×2
a = relu(z)  # 激活函数

print("输入X:\n", X)
print("\n线性变换结果z:\n", z)
print("\nReLU激活后a:\n", a)

五、避坑指南:NumPy常见错误与解决方案

  1. 维度不匹配报错:矩阵乘法时“前列≠后行”,检查shape
    # 调试方法:打印数组形状
    print(arr1.shape, arr2.shape)
    
  2. 数据类型错误:整数数组除法结果为整数(Python 2),建议指定dtype=np.float64
  3. 广播失败:不同维度数组运算时,确保低维数组可扩展为高维形状;
  4. 随机数不可复现:忘记设置np.random.seed(),AI实验中务必设置种子;
  5. 内存占用过高:超大数组(如100万×1000)建议分块处理,或用np.memmap内存映射。