1. 矩阵的本质:从数字表格到多维数据桥梁
矩阵这个看似简单的数学概念,实际上构成了现代人工智能和数据分析的基石。我第一次真正理解矩阵的重要性是在研究生时期,当时尝试用Python处理一个包含10万用户行为数据的数据集。当我意识到这些海量数据可以优雅地压缩成一个矩阵时,那种顿悟感至今难忘。
矩阵本质上是一种特殊的二维数组结构,但它远不止是数字的简单排列。想象你面前有一张Excel表格:每一行代表一个客户,每一列记录客户的不同属性(年龄、消费金额、浏览时长等)。这种行列分明的结构就是矩阵在现实中最直观的体现。
与标量(单个数字)和向量(一列数字)相比,矩阵的强大之处在于它能同时表达两种维度的信息。比如在图像处理中,一个28×28的矩阵可以完美表示MNIST手写数字图片——每个元素对应一个像素点的灰度值。这种表达能力使得矩阵成为连接现实世界复杂性和计算机处理的理想媒介。
关键认知:矩阵不是数学家发明的抽象概念,而是对现实世界数据关系的自然建模。当一个问题同时涉及"多个对象"和"多个特征"时,矩阵就是最自然的表达方式。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 矩阵的数学结构与表示方法
2.1 矩阵的规范定义
数学上,一个m×n的矩阵A可以严格定义为:
A = [aᵢⱼ], 其中 i = 1,...,m; j = 1,...,n
这个定义中有三个关键要素:
- 行数m:表示数据对象的数量或空间的第一维度
- 列数n:表示特征维度或空间的第二维度
- 元素aᵢⱼ:位于第i行第j列的具体数值
例如,在神经网络中,一个包含100个样本、每个样本有784个特征的批次数据,就可以表示为100×784的矩阵。这种表示不是随意的,而是为了适配GPU的并行计算特性。
2.2 矩阵的特殊形态
在实际应用中,我们会遇到几种特殊矩阵形态:
- 方阵:行数列数相等(m=n),常见于线性变换和特征值计算
- 对角矩阵:非零元素只出现在主对角线上,常用于权重初始化
- 对称矩阵:aᵢⱼ = aⱼᵢ,常见于协方差矩阵
- 稀疏矩阵:大部分元素为零,如推荐系统中的用户-物品交互矩阵
python复制# Python中创建特殊矩阵的示例
import numpy as np
# 创建3×3对角矩阵
diag_matrix = np.diag([1, 2, 3])
# 创建5×5零矩阵
zero_matrix = np.zeros((5,5))
# 创建随机对称矩阵
random_matrix = np.random.rand(4,4)
sym_matrix = (random_matrix + random_matrix.T)/2
2.3 矩阵的内存表示
在计算机中,矩阵主要有两种存储方式:
- 行优先存储(C风格):元素按行顺序连续存储
- 列优先存储(Fortran风格):元素按列顺序连续存储
这种差异会影响程序性能。例如,在Python的NumPy中,默认是行优先存储,所以按行遍历通常更快:
python复制# 性能对比示例
matrix = np.random.rand(1000,1000)
# 按行访问更快
%timeit [matrix[i,j] for i in range(1000) for j in range(1000)]
# 按列访问较慢
%timeit [matrix[i,j] for j in range(1000) for i in range(1000)]
3. 矩阵在AI中的核心应用
3.1 数据表示:从表格到图像
矩阵最直观的应用就是结构化数据的表示。以经典的鸢尾花数据集为例:
| 样本 | 花萼长度 | 花萼宽度 | 花瓣长度 | 花瓣宽度 | 种类 |
|---|---|---|---|---|---|
| 1 | 5.1 | 3.5 | 1.4 | 0.2 | 0 |
| 2 | 4.9 | 3.0 | 1.4 | 0.2 | 0 |
| ... | ... | ... | ... | ... | ... |
这样的表格可以直接转换为矩阵,其中前四列是特征矩阵X,最后一列是标签向量y。
在图像处理中,矩阵的应用更加直观。一张RGB图片本质上是三个矩阵的叠加(红、绿、蓝三个通道),每个矩阵元素对应像素的强度值。例如在OpenCV中:
python复制import cv2
# 读取图像为矩阵
img = cv2.imread('image.jpg') # 返回的是H×W×C的三维数组
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转换为灰度矩阵
3.2 矩阵运算:AI计算的引擎
矩阵乘法是深度学习中的核心运算。一个全连接层的前向传播本质上就是矩阵乘法:
Y = XW + b
其中:
- X是输入矩阵(batch_size×input_dim)
- W是权重矩阵(input_dim×output_dim)
- b是偏置向量
- Y是输出矩阵
这种表示方式使得我们可以用单行代码处理整个批次的样本:
python复制# 神经网络层的前向传播示例
batch_size = 64
input_dim = 784
output_dim = 256
X = np.random.randn(batch_size, input_dim) # 输入矩阵
W = np.random.randn(input_dim, output_dim) # 权重矩阵
b = np.random.randn(output_dim) # 偏置向量
Y = np.dot(X, W) + b # 前向传播
3.3 矩阵分解:降维与特征提取
矩阵分解技术如SVD(奇异值分解)和PCA(主成分分析)是特征提取的利器。以推荐系统为例,用户-物品评分矩阵R可以通过矩阵分解近似为:
R ≈ UΣVᵀ
其中U矩阵包含用户潜在特征,V矩阵包含物品潜在特征。这种分解可以将原始的高维稀疏数据转换为低维稠密表示。
python复制# SVD分解示例
from scipy.linalg import svd
# 用户-物品评分矩阵 (5用户×4物品)
R = np.array([
[5, 3, 0, 1],
[4, 0, 0, 1],
[1, 1, 0, 5],
[1, 0, 0, 4],
[0, 1, 5, 4]
])
U, s, Vh = svd(R)
print("用户特征矩阵形状:", U.shape)
print("奇异值:", s)
print("物品特征矩阵形状:", Vh.shape)
4. 矩阵运算的陷阱与优化技巧
4.1 常见错误与避免方法
-
形状不匹配错误:这是初学者最常犯的错误。矩阵乘法要求第一个矩阵的列数等于第二个矩阵的行数。
python复制A = np.random.rand(3,4) B = np.random.rand(5,6) # 会报错:形状不匹配 # C = np.dot(A, B) # 正确的做法 B = np.random.rand(4,6) # 确保A的列数等于B的行数 C = np.dot(A, B) -
广播机制误解:NumPy的广播机制虽然方便,但也容易导致意外结果。
python复制A = np.array([[1,2],[3,4]]) v = np.array([1,2]) # 这可能不是你想要的 print(A * v) # 广播乘法 # 矩阵向量乘法应该用 print(np.dot(A, v)) -
内存共享问题:NumPy的视图(view)和副本(copy)机制可能导致意外的数据修改。
python复制A = np.array([[1,2],[3,4]]) B = A[:1,:] # 创建视图 B[0,0] = 99 # 这会同时修改A print(A) # [[99 2] [3 4]] # 安全的做法 B = A[:1,:].copy()
4.2 性能优化技巧
-
向量化计算:避免Python循环,使用矩阵运算。
python复制# 不好的做法 result = np.zeros((100,100)) for i in range(100): for j in range(100): result[i,j] = i + j # 好的做法 i = np.arange(100)[:,None] j = np.arange(100) result = i + j -
使用高效函数:如
np.einsum进行复杂张量运算。python复制# 计算矩阵点乘的迹 A = np.random.rand(3,3) B = np.random.rand(3,3) # 低效做法 trace = np.sum(A * B.T) # 高效做法 trace = np.einsum('ij,ji->', A, B) -
内存布局优化:对于大矩阵,注意内存连续性。
python复制# 创建非连续数组 A = np.random.rand(1000,1000)[::2,:] # 转换为连续数组 A_cont = np.ascontiguousarray(A) # 连续数组运算更快 %timeit np.dot(A, A.T) %timeit np.dot(A_cont, A_cont.T)
5. 从矩阵到张量:AI中的高维数据
虽然矩阵处理二维数据已经非常强大,但现代AI经常需要处理更高维的数据。例如:
- 彩色图像:高度×宽度×通道(3D)
- 视频序列:帧数×高度×宽度×通道(4D)
- 图结构数据:节点×节点×特征(3D)
这就是张量(Tensor)的概念应运而生的原因。在PyTorch和TensorFlow等框架中,张量是核心数据结构。理解矩阵是掌握张量的关键基础。
python复制# 3D张量示例 (批次×高度×宽度)
batch_size = 32
height = 28
width = 28
# MNIST图像批次
images = np.random.rand(batch_size, height, width)
# 卷积核 (输出通道×输入通道×高度×宽度)
filters = np.random.rand(16, 1, 5, 5)
# 2D卷积运算 (实际中应使用专门的卷积函数)
output = np.zeros((batch_size, 16, height-4, width-4))
for b in range(batch_size):
for o in range(16):
for i in range(1):
for h in range(height-4):
for w in range(width-4):
output[b,o,h,w] = np.sum(
images[b,i,h:h+5,w:w+5] * filters[o,i,:,:]
)
这个例子展示了矩阵运算如何自然扩展到高维张量。虽然实际中我们会使用优化过的卷积函数,但理解其矩阵本质非常重要。
6. 矩阵视角下的经典AI算法
6.1 线性回归的矩阵表示
线性回归模型可以优雅地表示为:
y = Xβ + ε
其中:
- X是设计矩阵(n×p)
- β是参数向量(p×1)
- y是响应向量(n×1)
- ε是误差项
参数的最小二乘估计解为:
β̂ = (XᵀX)⁻¹Xᵀy
这种矩阵表示不仅简洁,而且可以直接转换为NumPy代码:
python复制# 生成模拟数据
n = 100 # 样本数
p = 5 # 特征数
X = np.random.randn(n, p)
true_beta = np.array([1, 2, 3, 4, 5])
y = X @ true_beta + np.random.randn(n)*0.1
# 计算最小二乘估计
beta_hat = np.linalg.inv(X.T @ X) @ X.T @ y
print("真实参数:", true_beta)
print("估计参数:", beta_hat)
6.2 主成分分析(PCA)的矩阵解释
PCA本质上是对数据协方差矩阵的特征分解。给定中心化的数据矩阵X(n×p),其协方差矩阵为:
Σ = (XᵀX)/(n-1)
对Σ进行特征分解:
Σ = VΛVᵀ
其中V的列就是主成分方向。在NumPy中实现:
python复制# 数据标准化
X_centered = X - X.mean(axis=0)
# 计算协方差矩阵
cov = X_centered.T @ X_centered / (n-1)
# 特征分解
eigenvalues, eigenvectors = np.linalg.eig(cov)
# 按特征值降序排列
idx = eigenvalues.argsort()[::-1]
components = eigenvectors[:,idx]
# 投影到前两个主成分
X_pca = X_centered @ components[:,:2]
6.3 神经网络中的矩阵运算
神经网络的前向传播本质上是矩阵运算的堆叠。以一个简单的两层网络为例:
Z₁ = XW₁ + b₁
A₁ = σ(Z₁)
Z₂ = A₁W₂ + b₂
ŷ = softmax(Z₂)
其中每个运算都是矩阵运算:
python复制# 两层神经网络实现
def relu(x):
return np.maximum(0, x)
def softmax(x):
e_x = np.exp(x - np.max(x, axis=1, keepdims=True))
return e_x / e_x.sum(axis=1, keepdims=True)
# 参数初始化
W1 = np.random.randn(input_dim, hidden_dim) * 0.01
b1 = np.zeros(hidden_dim)
W2 = np.random.randn(hidden_dim, output_dim) * 0.01
b2 = np.zeros(output_dim)
# 前向传播
Z1 = X @ W1 + b1
A1 = relu(Z1)
Z2 = A1 @ W2 + b2
y_hat = softmax(Z2)
7. 矩阵计算的硬件加速
现代AI严重依赖矩阵运算的硬件加速。理解这一点对算法优化至关重要。
7.1 GPU并行计算
GPU的架构特别适合并行矩阵运算。以矩阵乘法为例:
- CPU:顺序计算每个元素
- GPU:同时计算多个元素
python复制# PyTorch GPU加速示例
import torch
# 创建大矩阵
size = 4096
A_cpu = torch.rand(size, size)
B_cpu = torch.rand(size, size)
# CPU计算
%timeit torch.mm(A_cpu, B_cpu)
# GPU计算
A_gpu = A_cpu.cuda()
B_gpu = B_cpu.cuda()
%timeit torch.mm(A_gpu, B_gpu); torch.cuda.synchronize()
7.2 BLAS库优化
基础线性代数子程序(BLAS)是矩阵运算的底层优化库。NumPy等库底层都调用BLAS:
- Level 1 BLAS:向量运算
- Level 2 BLAS:矩阵-向量运算
- Level 3 BLAS:矩阵-矩阵运算
使用优化的BLAS库(如Intel MKL、OpenBLAS)可以显著提升性能。
7.3 内存访问优化
矩阵运算性能常受内存带宽限制。一些优化技巧:
- 分块计算:将大矩阵分成小块,提高缓存命中率
- 循环展开:减少循环开销
- 数据对齐:确保内存地址对齐
python复制# 分块矩阵乘法示例
def block_matmul(A, B, block_size=32):
m, n = A.shape
n, p = B.shape
C = np.zeros((m, p))
for i in range(0, m, block_size):
for j in range(0, p, block_size):
for k in range(0, n, block_size):
# 分块计算
C[i:i+block_size, j:j+block_size] += \
A[i:i+block_size, k:k+block_size] @ \
B[k:k+block_size, j:j+block_size]
return C
8. 矩阵在深度学习框架中的应用
8.1 TensorFlow中的矩阵运算
TensorFlow使用张量作为核心数据结构,但矩阵运算仍然是基础:
python复制import tensorflow as tf
# 创建矩阵常量
A = tf.constant([[1,2],[3,4]])
B = tf.constant([[5,6],[7,8]])
# 矩阵乘法
C = tf.matmul(A, B)
# 执行计算
with tf.Session() as sess:
result = sess.run(C)
print(result)
8.2 PyTorch的自动微分
PyTorch的自动微分功能依赖于矩阵运算的梯度计算:
python复制import torch
# 创建需要梯度的矩阵
x = torch.randn(3,4, requires_grad=True)
w = torch.randn(4,2, requires_grad=True)
b = torch.randn(2, requires_grad=True)
# 前向计算
y = torch.matmul(x, w) + b
# 计算梯度
loss = y.sum()
loss.backward()
print("x的梯度:", x.grad)
print("w的梯度:", w.grad)
print("b的梯度:", b.grad)
8.3 稀疏矩阵处理
在推荐系统等场景中,稀疏矩阵处理非常重要:
python复制from scipy.sparse import csr_matrix
# 创建稀疏矩阵
data = np.array([1, 2, 3, 4])
row_ind = np.array([0, 1, 2, 3])
col_ind = np.array([1, 3, 2, 0])
sparse_mat = csr_matrix((data, (row_ind, col_ind)), shape=(4,4))
# 稀疏矩阵与稠密矩阵相乘
dense_vec = np.array([1,2,3,4])
result = sparse_mat.dot(dense_vec)
9. 矩阵可视化的实用技巧
9.1 热力图展示矩阵结构
python复制import matplotlib.pyplot as plt
import seaborn as sns
# 创建相关矩阵
data = np.random.randn(100, 10)
corr = np.corrcoef(data, rowvar=False)
# 绘制热力图
plt.figure(figsize=(8,6))
sns.heatmap(corr, annot=True, cmap='coolwarm', center=0)
plt.title("特征相关矩阵")
plt.show()
9.2 矩阵分解可视化
python复制# PCA投影可视化
from sklearn.datasets import load_iris
iris = load_iris()
X = iris.data
y = iris.target
# 标准化
X_std = (X - X.mean(axis=0)) / X.std(axis=0)
# SVD分解
U, s, Vt = np.linalg.svd(X_std)
X_pca = U[:,:2] * s[:2]
# 绘制
plt.scatter(X_pca[:,0], X_pca[:,1], c=y)
plt.xlabel("PC1")
plt.ylabel("PC2")
plt.title("鸢尾花数据集PCA投影")
plt.show()
9.3 神经网络权重可视化
python复制# 加载预训练模型
from tensorflow.keras.datasets import mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
(X_train, y_train), _ = mnist.load_data()
X_train = X_train.reshape(-1, 784)/255.0
# 简单模型
model = Sequential([
Dense(128, activation='relu', input_shape=(784,)),
Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')
model.fit(X_train, y_train, epochs=1)
# 可视化第一层权重
weights = model.layers[0].get_weights()[0]
plt.figure(figsize=(12,6))
for i in range(32): # 显示前32个神经元
plt.subplot(4,8,i+1)
plt.imshow(weights[:,i].reshape(28,28), cmap='viridis')
plt.axis('off')
plt.suptitle("神经网络第一层权重可视化")
plt.show()
10. 矩阵运算的数学基础深入
10.1 矩阵微积分基础
理解矩阵求导对深度学习中的反向传播至关重要。一些基本规则:
- 对于向量x,有∂(aᵀx)/∂x = a
- 对于矩阵X,有∂(aᵀXb)/∂X = abᵀ
- 链式法则同样适用
例如,在线性回归中,损失函数L = (y - Xβ)ᵀ(y - Xβ)对β的导数为:
∂L/∂β = -2Xᵀ(y - Xβ)
10.2 特征值与特征向量的意义
矩阵A的特征向量v满足Av = λv,其中λ是特征值。这在数据分析中有重要应用:
- 主成分分析:主成分是协方差矩阵的特征向量
- PageRank算法:网页重要性得分是链接矩阵的主特征向量
- 谱聚类:利用拉普拉斯矩阵的特征向量进行聚类
python复制# 特征分解应用:矩阵幂计算
A = np.array([[2,1],[1,2]])
eigvals, eigvecs = np.linalg.eig(A)
# 计算A的100次方
A_100 = eigvecs @ np.diag(eigvals**100) @ np.linalg.inv(eigvecs)
10.3 矩阵范数与正则化
矩阵范数在机器学习正则化中很常见:
- Frobenius范数:||A||_F = √(ΣΣ|aᵢⱼ|²)
- 谱范数:最大的奇异值
- 核范数:奇异值之和
python复制# 各种范数计算
A = np.random.randn(4,4)
# Frobenius范数
fro_norm = np.linalg.norm(A, 'fro')
# 谱范数
spec_norm = np.linalg.norm(A, 2)
# 核范数
nuc_norm = np.sum(np.linalg.svd(A)[1])
11. 高级矩阵分解技术
11.1 奇异值分解(SVD)的深入应用
SVD将一个矩阵分解为:
A = UΣVᵀ
其中U和V是正交矩阵,Σ是对角矩阵。SVD在推荐系统、自然语言处理中广泛应用。
python复制# 使用SVD进行图像压缩
from skimage import data
# 加载示例图像
image = data.camera().astype(float)
# 进行SVD分解
U, s, Vt = np.linalg.svd(image)
# 保留前k个奇异值
k = 50
compressed = U[:,:k] @ np.diag(s[:k]) @ Vt[:k,:]
# 显示结果
plt.figure(figsize=(10,5))
plt.subplot(121)
plt.imshow(image, cmap='gray')
plt.title("原始图像")
plt.subplot(122)
plt.imshow(compressed, cmap='gray')
plt.title(f"压缩图像(k={k})")
plt.show()
11.2 QR分解与最小二乘
QR分解将矩阵分解为正交矩阵Q和上三角矩阵R:
A = QR
这在求解线性方程组时更稳定:
python复制# 使用QR分解求解线性方程组
A = np.random.randn(100,50)
b = np.random.randn(100)
# 传统方法 (数值不稳定)
x1 = np.linalg.inv(A.T @ A) @ A.T @ b
# QR分解方法
Q, R = np.linalg.qr(A)
x2 = np.linalg.solve(R, Q.T @ b)
# 比较误差
print("传统方法误差:", np.linalg.norm(A @ x1 - b))
print("QR方法误差:", np.linalg.norm(A @ x2 - b))
11.3 Cholesky分解与正定矩阵
对于对称正定矩阵A,可以分解为:
A = LLᵀ
其中L是下三角矩阵。这在多元正态分布采样中很有用:
python复制# 使用Cholesky分解生成相关随机变量
cov = np.array([[1, 0.8], [0.8, 1]])
L = np.linalg.cholesky(cov)
# 生成独立正态随机变量
n_samples = 1000
Z = np.random.randn(n_samples, 2)
# 转换为相关随机变量
X = Z @ L.T
# 绘制结果
plt.scatter(X[:,0], X[:,1], alpha=0.5)
plt.title("使用Cholesky分解生成的相关随机变量")
plt.show()
12. 矩阵在自然语言处理中的应用
12.1 词袋模型与文档-词矩阵
在NLP中,文档集合常表示为文档-词矩阵:
python复制from sklearn.feature_extraction.text import CountVectorizer
corpus = [
'这是第一个文档',
'这个文档是第二个文档',
'而这是第三个文档',
'这是第一个文档吗'
]
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(corpus)
print("词汇表:", vectorizer.get_feature_names_out())
print("文档-词矩阵:")
print(X.toarray())
12.2 TF-IDF矩阵
TF-IDF是文档-词矩阵的改进版本,考虑词频和逆文档频率:
python复制from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer()
X_tfidf = tfidf.fit_transform(corpus)
print("TF-IDF矩阵:")
print(X_tfidf.toarray())
12.3 词嵌入与矩阵分解
词嵌入如Word2Vec可以看作是对共现矩阵的分解:
python复制from gensim.models import Word2Vec
sentences = [
['this', 'is', 'the', 'first', 'sentence'],
['this', 'is', 'the', 'second', 'sentence'],
['the', 'third', 'sentence', 'is', 'here']
]
model = Word2Vec(sentences, vector_size=50, window=5, min_count=1, workers=4)
# 获取词向量矩阵
word_vectors = model.wv
print("'sentence'的向量:", word_vectors['sentence'])
13. 矩阵在计算机视觉中的核心作用
13.1 图像卷积的矩阵表示
图像滤波本质上是矩阵运算:
python复制from scipy.signal import convolve2d
# 读取图像
image = data.camera()
# 定义Sobel算子
sobel_x = np.array([[-1,0,1], [-2,0,2], [-1,0,1]])
sobel_y = np.array([[-1,-2,-1], [0,0,0], [1,2,1]])
# 应用卷积
grad_x = convolve2d(image, sobel_x, mode='same')
grad_y = convolve2d(image, sobel_y, mode='same')
grad = np.sqrt(grad_x**2 + grad_y**2)
# 显示结果
plt.imshow(grad, cmap='gray')
plt.title("Sobel边缘检测结果")
plt.show()
13.2 图像变形中的变换矩阵
仿射变换可以用矩阵表示:
python复制from skimage import transform
# 定义变换矩阵
matrix = np.array([[1, -0.5, 50],
[0.3, 0.8, -20],
[0, 0, 1]])
# 应用变换
tform = transform.AffineTransform(matrix=matrix)
warped = transform.warp(image, tform.inverse)
# 显示结果
plt.imshow(warped, cmap='gray')
plt.title("仿射变换后的图像")
plt.show()
13.3 相机标定中的矩阵运算
相机模型可以用投影矩阵表示:
python复制# 相机内参矩阵
K = np.array([[1000, 0, 320],
[0, 1000, 240],
[0, 0, 1]])
# 世界坐标到相机坐标的变换
R = np.eye(3)
t = np.array([0,0,1])
P = K @ np.hstack([R, t[:,None]])
# 3D点到2D的投影
X = np.array([1,1,5,1]) # 齐次坐标
x = P @ X
x = x[:2]/x[2]
print("投影后的2D坐标:", x)
14. 矩阵在推荐系统中的关键应用
14.1 协同过滤的矩阵分解
协同过滤通过分解用户-物品评分矩阵来预测缺失值:
python复制# 创建用户-物品评分矩阵
ratings = np.array([
[5, 3, 0, 1],
[4, 0, 0, 1],
[1, 1, 0, 5],
[1, 0, 0, 4],
[0, 1, 5, 4]
])
# 使用SVD进行矩阵补全
U, s, Vt = np.linalg.svd(ratings, full_matrices=False)
k = 2 # 潜在因子维度
pred = U[:,:k] @ np.diag(s[:k]) @ Vt[:k,:]
print("原始矩阵:")
print(ratings)
print("预测矩阵:")
print(pred)
14.2 交替最小二乘(ALS)算法
ALS是推荐系统中常用的矩阵分解算法:
python复制def als(R, k, steps=10, reg=0.1):
m, n = R.shape
U = np.random.rand(m, k)
V = np.random.rand(n, k)
for step in range(steps):
# 固定V,更新U
for i in range(m):
V_i = V[R[i,:]>0]
R_i = R[i,R[i,:]>0]
U[i,:] = np.linalg.solve(V_i.T @ V_i + reg*np.eye(k), V_i.T @ R_i)
# 固定U,更新V
for j in range(n):
U_j = U[R[:,j]>0]
R_j = R[R[:,j]>0,j]
V[j,:] = np.linalg.solve(U_j.T @ U_j + reg*np.eye(k), U_j.T @ R_j)
return U @ V.T
# 应用ALS
R_pred = als(ratings, k=2)
print("ALS预测矩阵:")
print(R_pred)
14.3 矩阵分解的评估指标
评估推荐系统质量的常用指标:
python复制def mse(true, pred):
mask = true > 0
return np.mean((true[mask] - pred[mask])**2)
def precision_at_k(true, pred, k=3):
top_k = np.argsort(-pred, axis=1)[:,:k]
hits = np.sum(true[np.arange(len(true))[:,None], top_k] > 0)
return hits / (len(true)*k)
print("MSE:", mse(ratings, R_pred))
print("Precision@3:", precision_at_k(ratings, R_pred))
15. 矩阵运算的数值稳定性问题
15.1 病态矩阵与条件数
矩阵的条件数cond(A) = ||A||·||A⁻¹||衡量数值稳定性:
python复制# 病态矩阵示例
A = np.array([[1, 1],
[1, 1.0001]])
b = np.array([2, 2.0001])
# 解应该是[1,1]
x = np.linalg.solve(A, b)
print("解:", x)
# 计算条件数
cond = np.linalg.cond(A)
print("条件数:", cond)
15.2 正则化技术
解决病态问题的常用方法:
- Tikhonov正则化:(AᵀA + αI)x = Aᵀb
- 截断SVD:丢弃小的奇异值
python复制# 正则化求解
alpha = 1e-5
x_reg = np.linalg.solve(A.T @ A + alpha*np.eye(2), A.T @ b)
print("正则化解:", x_reg)
# 截断SVD
U, s, Vt = np.linalg.svd(A)
s_trunc = s.copy()
s_trunc[s < 1e-5] = 0
A_trunc = U @ np.diag(s_trunc) @ Vt
x_svd = np.linalg.pinv(A_trunc) @ b
print("SVD解:", x_svd)
15.3 数值误差传播
矩阵运算中的误差会累积:
python复制# 矩阵求逆的数值误差
A = np.random.randn(100,100)
A_inv = np.linalg.inv(A)
I = A @ A_inv
print("单位矩阵误差:", np.linalg.norm(I - np.eye(100)))
# 更稳定的解法是直接解线性系统
b = np.random.randn(100)
x1 = np.linalg.solve(A, b) # 更精确
x2 = A_inv @ b # 误差更大
print("解误差:", np.linalg.norm(x1 - x2))
16. 矩阵在概率统计中的应用
16.1 协方差矩阵与多元正态分布
协方差矩阵Σ描述变量间的相关性:
python复制# 生成多元正态随机变量
mean = [0, 0]
cov = [[1, 0.8], [0.8, 1]]
X = np.random.multivariate_normal(mean, cov, 500)
# 计算样本协方差矩阵
cov_est = np.cov(X.T)
print("真实协方差矩阵:")
print(cov)
print("估计协方差矩阵:")
print(cov_est)
# 绘制散点图
plt.scatter(X[:,0], X[:,1], alpha=0.5)
plt.title("相关随机变量")
plt.show()
16.2 马氏距离
考虑协方差的距离度量:
python复制# 计算马氏距离
X_centered = X - X.mean(axis=0)
cov_inv = np.linalg.inv(cov_est)
# 计算每个点到中心的马氏距离
mahalanobis = np.sqrt(np.sum(X_centered @ cov_inv * X_centered, axis=1))
# 检测异常值
outliers = X[mahalanobis > 2.5]
print("检测到的异常值数量:", len(outliers))
