NumPy 线性代数
本章目标
- 掌握向量点积与矩阵乘法(
dot/matmul/@)的区别与使用场景 - 掌握转置、行列式、逆矩阵的基本用法
- 会求方阵的特征值与特征向量
- 会用
np.linalg.solve解线性方程组 - 掌握
np.linalg.norm计算常见向量与矩阵范数
重点方法与概念速览
| 名称 | 类型 | 作用 |
|---|---|---|
np.dot(...) | 函数 | 点积 / 矩阵乘法(兼容多维) |
np.matmul(...) / @ | 函数 / 运算符 | 矩阵乘法(高维批量) |
arr.T | 属性 | 转置视图(反转所有维度) |
np.transpose(...) | 函数 | 转置,可指定轴顺序 |
np.linalg.det(...) | 函数 | 方阵行列式 |
np.linalg.inv(...) | 函数 | 方阵逆矩阵 |
np.linalg.eig(...) | 函数 | 特征值与特征向量 |
np.linalg.solve(...) | 函数 | 解线性方程组 |
np.linalg.norm(...) | 函数 | 向量 / 矩阵范数 |
np.allclose(...) | 函数 | 浮点容差比较 |
1. 点积与矩阵乘法
np.dot
作用
向量点积或矩阵乘法,行为随输入维度变化:
- 两个一维向量 → 点积
,返回标量 - 两个二维矩阵 → 矩阵乘法
- 高维数组 → 沿最后两轴做矩阵乘法
重点方法
python
np.dot(a, b, out=None)参数
| 参数名 | 类型 | 说明 | 示例取值 |
|---|---|---|---|
a | array_like | 第一个输入 | [1, 2, 3]、A(2x2) |
b | array_like | 第二个输入,形状需与 a 在相应轴上匹配 | [4, 5, 6]、B(2x2) |
out | ndarray 或 None | 写入结果的目标数组 | —— |
np.matmul / @
作用
专用的矩阵乘法,@ 是运算符写法。与 dot 的差异:
- 不支持标量乘法
- 高维时视为"批量矩阵乘法":最后两轴是矩阵维度,前轴做广播
重点方法
python
np.matmul(x1, x2, /, out=None, *, casting='same_kind', order='K', dtype=None)
# 等价运算符
A @ B参数
| 参数名 | 类型 | 说明 | 示例取值 |
|---|---|---|---|
x1 | array_like | 左矩阵 | A(2x2) |
x2 | array_like | 右矩阵,列数需与 x1 行数匹配 | B(2x2) |
out | ndarray 或 None | 目标数组 | —— |
casting | str | 类型转换策略,默认为 'same_kind' | 'safe' |
dtype | dtype 或 None | 结果类型 | —— |
综合示例
示例代码
python
import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(f"向量点积 np.dot(a, b) = {np.dot(a, b)}")
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(f"A @ B:\n{A @ B}")
print(f"np.dot(A, B):\n{np.dot(A, B)}")输出
text
向量点积 np.dot(a, b) = 32
A @ B:
[[19 22]
[43 50]]
np.dot(A, B):
[[19 22]
[43 50]]理解重点
- 现代代码优先用
@(可读性高、仅限矩阵乘法) - 需要向量点积或对标量操作时用
np.dot - 三维以上批量矩阵乘用
matmul/@,不要用dot
2. 转置
arr.T
作用
返回数组的转置视图,所有维度顺序反转。对二维数组即常规"行列交换"。
返回内容
| 类型 | 含义 |
|---|---|
ndarray | 转置视图,修改会影响原数组 |
np.transpose
作用
比 arr.T 更灵活,可通过 axes 参数指定任意的轴排列顺序。
重点方法
python
np.transpose(a, axes=None)参数
| 参数名 | 类型 | 说明 | 示例取值 |
|---|---|---|---|
a | array_like | 输入数组 | A(2x3) |
axes | tuple[int, ...] 或 None | 新轴顺序,默认为 None(反转所有维度) | (1, 0)、(1, 0, 2) |
示例代码
python
import numpy as np
A = np.array([[1, 2, 3], [4, 5, 6]])
print(f"A (2x3):\n{A}")
print(f"A.T (3x2):\n{A.T}")
print(f"np.transpose(A):\n{np.transpose(A)}")输出
text
A (2x3):
[[1 2 3]
[4 5 6]]
A.T (3x2):
[[1 4]
[2 5]
[3 6]]
np.transpose(A):
[[1 4]
[2 5]
[3 6]]3. 行列式与逆矩阵
np.linalg.det
作用
计算方阵的行列式。行列式为
重点方法
python
np.linalg.det(a)参数
| 参数名 | 类型 | 说明 | 示例取值 |
|---|---|---|---|
a | array_like | 方阵,至少二维;高维时对最后两轴批量计算 | [[4, 7], [2, 6]] |
np.linalg.inv
作用
计算方阵的逆矩阵 solve。
重点方法
python
np.linalg.inv(a)参数
| 参数名 | 类型 | 说明 | 示例取值 |
|---|---|---|---|
a | array_like | 方阵;行列式为 LinAlgError | [[4, 7], [2, 6]] |
np.allclose
作用
判断两个数组在给定容差内是否近似相等。浮点数不应直接 == 比较,应用 allclose。判断条件:
重点方法
python
np.allclose(a, b, rtol=1e-05, atol=1e-08, equal_nan=False)参数
| 参数名 | 类型 | 说明 | 示例取值 |
|---|---|---|---|
a | array_like | 待比较的数组 1 | A @ A_inv |
b | array_like | 待比较的数组 2 | np.eye(2) |
rtol | float | 相对容差,默认为 1e-05 | 1e-10 |
atol | float | 绝对容差,默认为 1e-08 | 1e-12 |
equal_nan | bool | True 时将两个 NaN 视为相等,默认为 False | True |
综合示例
示例代码
python
import numpy as np
A = np.array([[4, 7], [2, 6]])
det = np.linalg.det(A)
AInv = np.linalg.inv(A)
print(f"det(A) = {det:.4f}")
print(f"A^-1:\n{AInv}")
print(f"A @ A^-1:\n{(A @ AInv).round(10)}")
print(f"是否单位矩阵: {np.allclose(A @ AInv, np.eye(2))}")输出
text
det(A) = 10.0000
A^-1:
[[ 0.6 -0.7]
[-0.2 0.4]]
A @ A^-1:
[[ 1. 0.]
[-0. 1.]]
是否单位矩阵: True4. 特征值与特征向量
np.linalg.eig
作用
计算方阵
返回二元组 (eigenvalues, eigenvectors)。
重点方法
python
np.linalg.eig(a)参数
| 参数名 | 类型 | 说明 | 示例取值 |
|---|---|---|---|
a | array_like | 输入方阵 | [[4, 2], [1, 3]] |
返回值
| 返回值 | 类型 | 含义 |
|---|---|---|
eigenvalues | ndarray | 一维数组,长度等于方阵阶数 |
eigenvectors | ndarray | 二维数组,第 i 列是 eigenvalues[i] 对应的特征向量 |
示例代码
python
import numpy as np
A = np.array([[4, 2], [1, 3]])
eigenvalues, eigenvectors = np.linalg.eig(A)
print(f"特征值: {eigenvalues}")
print(f"特征向量:\n{eigenvectors}")
# 验证 A @ v = λ @ v
for i in range(len(eigenvalues)):
v = eigenvectors[:, i]
lam = eigenvalues[i]
print(f"λ={lam:.2f}: A@v = {A @ v}, λ*v = {lam * v}, "
f"相等={np.allclose(A @ v, lam * v)}")输出
text
特征值: [5. 2.]
特征向量:
[[ 0.89442719 -0.70710678]
[ 0.4472136 0.70710678]]
λ=5.00: A@v = [4.47213595 2.23606798], λ*v = [4.47213595 2.23606798], 相等=True
λ=2.00: A@v = [-1.41421356 1.41421356], λ*v = [-1.41421356 1.41421356], 相等=True理解重点
- 特征向量按列存放,切片用
eigvecs[:, i],不是eigvecs[i] - 特征值可能为复数(即使输入全为实数),返回类型可能为
complex128 - 对称矩阵用
np.linalg.eigh得到更稳定的实值结果
5. 解线性方程组
np.linalg.solve
作用
解线性方程组
重点方法
python
np.linalg.solve(a, b)参数
| 参数名 | 类型 | 说明 | 示例取值 |
|---|---|---|---|
a | array_like | 系数方阵,必须可逆 | [[2, 1], [1, 3]] |
b | array_like | 右端向量(或多个右端组成的矩阵) | [5, 7] |
示例代码
python
import numpy as np
# 方程组:
# 2x + y = 5
# x + 3y = 7
A = np.array([[2, 1], [1, 3]])
b = np.array([5, 7])
x = np.linalg.solve(A, b)
print(f"解 x = {x}")
print(f"验证 A @ x = {A @ x}")
print(f"是否等于 b: {np.allclose(A @ x, b)}")输出
text
解 x = [1.6 1.8]
验证 A @ x = [5. 7.]
是否等于 b: True理解重点
- 永远优先
solve,而不是inv(A) @ b——前者更快且数值更稳定 - 非方阵或超定 / 欠定系统用最小二乘
np.linalg.lstsq
6. 范数
np.linalg.norm
作用
计算向量或矩阵的范数。通过 ord 参数选择不同范数类型。
- 向量 L2 范数(欧几里得距离):
- 向量 L1 范数(曼哈顿距离):
- 矩阵 Frobenius 范数:
重点方法
python
np.linalg.norm(x, ord=None, axis=None, keepdims=False)参数
| 参数名 | 类型 | 说明 | 示例取值 |
|---|---|---|---|
x | array_like | 向量或矩阵输入 | [3, 4]、A(2x2) |
ord | int 或 str 或 None | 范数阶数,默认为 None(见下表) | 1、2、np.inf |
axis | int 或 None | 指定按轴计算范数,默认为 None(整体计算) | 0 |
keepdims | bool | 是否保留被聚合的轴,默认为 False | True |
ord 常见取值
ord | 向量含义 | 矩阵含义(二维输入) |
|---|---|---|
None(默认) | L2 范数 | Frobenius 范数 |
1 | L1 范数 | 列绝对值和的最大值 |
2 | L2 范数(同 None) | 最大奇异值(谱范数) |
np.inf | 最大绝对值 | 行绝对值和的最大值 |
-np.inf | 最小绝对值 | 行绝对值和的最小值 |
'fro' | — | Frobenius 范数 |
示例代码
python
import numpy as np
v = np.array([3, 4])
print(f"L1 范数 (曼哈顿距离): {np.linalg.norm(v, ord=1)}")
print(f"L2 范数 (欧几里得距离): {np.linalg.norm(v, ord=2)}")
print(f"无穷范数: {np.linalg.norm(v, ord=np.inf)}")
A = np.array([[1, 2], [3, 4]])
print(f"Frobenius 范数: {np.linalg.norm(A):.4f}")输出
text
L1 范数 (曼哈顿距离): 7.0
L2 范数 (欧几里得距离): 5.0
无穷范数: 4.0
Frobenius 范数: 5.4772理解重点
- 向量
的 L2 范数为 - 矩阵默认范数是 Frobenius,等于把矩阵展平为向量后的 L2 范数
常见坑
- 只有方阵才能直接
inv/det/eig——非方阵考虑 SVD 或伪逆np.linalg.pinv - 奇异或接近奇异的矩阵求逆数值不稳定,条件数大时结果误差大
- 解线性方程组永远用
np.linalg.solve,不要写np.linalg.inv(A) @ b - 比较浮点结果用
np.allclose,不要直接用== @和np.dot在高维数组上的广播语义不同:批量矩阵乘用@/matmulnp.linalg.eig的特征向量按列存放,切片写成eigvecs[i]是错误
小结
- 本章是机器学习线代工具箱的基础:
solve、eig、norm出现频率最高 - 理解维度匹配规则(
@ )是避免维度错误的关键 - 浮点比较用
allclose,求逆用solve——这两点能避开 90% 的初学者陷阱