矩阵分解:从基础到进阶的全面解析

一、什么是矩阵分解?

矩阵分解(Matrix Factorization)是将一个复杂的矩阵分解为多个简单矩阵乘积的过程。这种技术在机器学习、推荐系统、信号处理等领域有着广泛应用,其核心思想是用低维表示高维数据,发现数据中的潜在结构。

基本形式

给定矩阵 A ∈ R^{m×n},矩阵分解可表示为:
A ≈ B × C
其中 B ∈ R^{m×k},C ∈ R^{k×n},且 k ≪ min(m,n)

二、为什么需要矩阵分解?

  1. 数据压缩:原始矩阵可能非常大,分解后只需存储小矩阵
  2. 降维去噪:保留主要特征,过滤噪声
  3. 发现潜在特征:揭示数据背后的隐含模式
  4. 解决稀疏性问题:特别适用于稀疏矩阵的补全

三、经典矩阵分解方法

1. 特征值分解(EVD)

适用条件:方阵,且可对角化

A=QΛQ−1 A = QΛQ^{-1} A=QΛQ−1

其中Q是特征向量矩阵,Λ是对角特征值矩阵

import numpy as np

# 特征值分解示例
def eigen_decomposition(A):
    eigenvalues, eigenvectors = np.linalg.eig(A)
    return eigenvectors, np.diag(eigenvalues), np.linalg.inv(eigenvectors)

# 验证分解
A = np.array([[4, 2], [1, 3]])
Q, Lambda, Q_inv = eigen_decomposition(A)
A_reconstructed = Q @ Lambda @ Q_inv
print("原始矩阵:\n", A)
print("重构矩阵:\n", A_reconstructed)
2. 奇异值分解(SVD)

最通用的分解方法,适用于任意矩阵

A=UΣVT A = UΣV^T A=UΣVT

  • U:左奇异向量矩阵,U^T U = I
  • Σ:奇异值对角矩阵
  • V:右奇异向量矩阵,V^T V = I

截断SVD(Truncated SVD):
保留前k个最大的奇异值,用于降维

A≈UkΣkVkT A ≈ U_k Σ_k V_k^T A≈Uk​Σk​VkT​

import numpy as np
from scipy.sparse.linalg import svds

def svd_decomposition(A, k=None):
    if k is None:
        # 完全SVD
        U, s, Vt = np.linalg.svd(A, full_matrices=False)
        Sigma = np.diag(s)
    else:
        # 截断SVD
        U, s, Vt = svds(A, k=k)
        Sigma = np.diag(s)
    return U, Sigma, Vt

# 示例:图像压缩
def compress_image(matrix, k):
    U, Sigma, Vt = svd_decomposition(matrix, k)
    compressed = U @ Sigma @ Vt
    compression_ratio = (U.size + Sigma.size + Vt.size) / matrix.size
    return compressed, compression_ratio
3. 非负矩阵分解(NMF)

特点:所有矩阵元素非负,适合文本、图像等非负数据

A≈WHs.t.W≥0,H≥0 A ≈ WH \quad \text{s.t.} \quad W ≥ 0, H ≥ 0 A≈WHs.t.W≥0,H≥0

from sklearn.decomposition import NMF
import numpy as np

def nmf_decomposition(A, n_components):
    model = NMF(n_components=n_components, init='random', random_state=42)
    W = model.fit_transform(A)  # 基矩阵
    H = model.components_       # 系数矩阵
    
    # 重构误差
    reconstruction_error = model.reconstruction_err_
    return W, H, reconstruction_error

# 示例:文档主题提取
doc_term_matrix = np.array([[2, 1, 0, 0],
                           [0, 1, 3, 2],
                           [1, 0, 1, 0]])
W, H, error = nmf_decomposition(doc_term_matrix, n_components=2)
print("主题-词矩阵 H:\n", H)
print("文档-主题矩阵 W:\n", W)
4. 矩阵分解在推荐系统中的应用

用户-物品评分矩阵分解:
R≈PQT R ≈ P Q^T R≈PQT
其中 R ∈ R^{m×n}(评分矩阵),P ∈ R^{m×k}(用户特征),Q ∈ R^{n×k}(物品特征)

损失函数(加入正则化):
L=∑(i,j)∈Ω(rij−piTqj)2+λ(∣∣P∣∣F2+∣∣Q∣∣F2) L = \sum_{(i,j)∈Ω}(r_{ij} - p_i^T q_j)^2 + λ(||P||_F^2 + ||Q||_F^2) L=(i,j)∈Ω∑​(rij​−piT​qj​)2+λ(∣∣P∣∣F2​+∣∣Q∣∣F2​)

class MatrixFactorization:
    def __init__(self, n_factors=10, lr=0.01, reg=0.1, n_epochs=100):
        self.n_factors = n_factors
        self.lr = lr
        self.reg = reg
        self.n_epochs = n_epochs
        
    def fit(self, R):
        n_users, n_items = R.shape
        # 初始化用户和物品矩阵
        self.P = np.random.normal(scale=1./self.n_factors, 
                                 size=(n_users, self.n_factors))
        self.Q = np.random.normal(scale=1./self.n_factors,
                                 size=(n_items, self.n_factors))
        
        # 训练过程
        for epoch in range(self.n_epochs):
            for i in range(n_users):
                for j in range(n_items):
                    if R[i, j] > 0:  # 只使用已知评分
                        error = R[i, j] - np.dot(self.P[i], self.Q[j])
                        
                        # 梯度更新
                        self.P[i] += self.lr * (error * self.Q[j] - self.reg * self.P[i])
                        self.Q[j] += self.lr * (error * self.P[i] - self.reg * self.Q[j])
            
            if epoch % 20 == 0:
                loss = self.calculate_loss(R)
                print(f"Epoch {epoch}, Loss: {loss:.4f}")
    
    def calculate_loss(self, R):
        predictions = np.dot(self.P, self.Q.T)
        mask = R > 0
        mse = np.mean((predictions[mask] - R[mask]) ** 2)
        reg_term = self.reg * (np.sum(self.P**2) + np.sum(self.Q**2))
        return mse + reg_term
    
    def predict(self, user_id, item_id):
        return np.dot(self.P[user_id], self.Q[item_id])

# 使用示例
R = np.array([[5, 3, 0, 1],
              [4, 0, 0, 1],
              [1, 1, 0, 5],
              [1, 0, 0, 4],
              [0, 1, 5, 4]])

mf = MatrixFactorization(n_factors=2, lr=0.001, reg=0.01, n_epochs=200)
mf.fit(R)
print("预测评分:", mf.predict(0, 2))

四、进阶矩阵分解方法

1. 带偏置的矩阵分解

r^ui=μ+bu+bi+puTqi \hat{r}_{ui} = μ + b_u + b_i + p_u^T q_i r^ui​=μ+bu​+bi​+puT​qi​

  • μ:全局平均评分
  • b_u:用户偏置
  • b_i:物品偏置
2. 概率矩阵分解(PMF)

从概率角度建模,假设评分服从正态分布:
p(R∣P,Q,σ2)=∏i=1N∏j=1M[N(rij∣piTqj,σ2)]Iij p(R|P,Q,σ^2) = ∏_{i=1}^N ∏_{j=1}^M [N(r_{ij}|p_i^T q_j, σ^2)]^{I_{ij}} p(R∣P,Q,σ2)=i=1∏N​j=1∏M​[N(rij​∣piT​qj​,σ2)]Iij​

3. 张量分解

处理多维数据的扩展,如用户-物品-时间三维数据:
X≈Σr=1Rar∘br∘cr \mathcal{X} ≈ Σ_{r=1}^R a_r ∘ b_r ∘ c_r X≈Σr=1R​ar​∘br​∘cr​

五、矩阵分解的优化算法

  1. 梯度下降法:最基础的优化方法
  2. 交替最小二乘法(ALS):固定一个矩阵,优化另一个
  3. 随机梯度下降(SGD):适合大规模数据
  4. 坐标下降法:每次优化一个变量
def als_optimize(R, k, steps=10, reg=0.1):
    m, n = R.shape
    P = np.random.rand(m, k)
    Q = np.random.rand(n, k)
    
    for step in range(steps):
        # 固定Q,优化P
        for i in range(m):
            mask = R[i] > 0
            if np.sum(mask) > 0:
                Q_masked = Q[mask]
                R_masked = R[i, mask]
                P[i] = np.linalg.solve(
                    Q_masked.T @ Q_masked + reg * np.eye(k),
                    Q_masked.T @ R_masked
                )
        
        # 固定P,优化Q
        for j in range(n):
            mask = R[:, j] > 0
            if np.sum(mask) > 0:
                P_masked = P[mask]
                R_masked = R[mask, j]
                Q[j] = np.linalg.solve(
                    P_masked.T @ P_masked + reg * np.eye(k),
                    P_masked.T @ R_masked
                )
    
    return P, Q

六、性能评估指标

def evaluate_predictions(R_true, R_pred, test_indices):
    """评估矩阵分解性能"""
    mae = 0
    rmse = 0
    n = len(test_indices)
    
    for i, j in test_indices:
        pred = R_pred[i, j]
        true = R_true[i, j]
        mae += abs(pred - true)
        rmse += (pred - true) ** 2
    
    return mae/n, np.sqrt(rmse/n)

七、实际应用注意事项

  1. 数据预处理:标准化、归一化
  2. 冷启动问题:新用户/物品的处理策略
  3. 隐式反馈:点击、浏览时长等数据的利用
  4. 实时更新:增量学习策略
  5. 可扩展性:分布式实现(Spark MLlib)

八、总结

矩阵分解作为数据科学的核心技术,提供了强大的数据降维和特征提取能力。从传统的SVD到现代的深度矩阵分解,其不断发展为解决现实世界问题提供了有力工具。选择哪种分解方法取决于具体问题、数据特性和应用需求。

附名片福利 | 免费技术选型、选题建议、毕设指导、随时答疑~

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐