HOOOS

深入浅出:NMF乘法更新规则的数学推导与伪代码实现

0 47 码上行者 NMF乘法更新规则机器学习矩阵分解算法推导
Apple

你好!今天我们来深入探讨一下非负矩阵分解(NMF)中至关重要的乘法更新规则。我会用清晰的数学推导、通俗的语言和伪代码示例,带你一步步理解这个算法的核心。无论你是机器学习的初学者,还是希望深入研究NMF的算法工程师,相信这篇文章都能为你提供有价值的参考。

1. 什么是NMF?

首先,我们简单回顾一下NMF。非负矩阵分解是一种常用的降维技术,它的目标是将一个非负矩阵V分解成两个非负矩阵W和H的乘积:

V ≈ WH
  • V: 原始数据矩阵,维度为m x n,其中m代表样本数量,n代表特征数量。矩阵中的所有元素都是非负的。
  • W: 基矩阵,维度为m x k,其中k通常小于n,代表降维后的特征数量。可以理解为原始数据在低维空间中的表示。
  • H: 系数矩阵,维度为k x n,它描述了基矩阵在重构原始数据时的贡献程度。

NMF的核心思想是:通过迭代优化W和H,使得WH尽可能逼近V。由于W和H都要求非负,因此NMF能够很好地应用于图像处理、文本挖掘等领域,因为这些领域的数据通常具有非负的特性。

2. 目标函数与损失函数

为了衡量WH与V的接近程度,我们需要定义一个损失函数。常用的损失函数有:

  • 欧几里得距离 (Frobenius Norm): 这是最直观的衡量方式,计算矩阵差的平方和:

    J(W, H) = ||V - WH||^2 = Σ(Vᵢⱼ - (WH)ᵢⱼ)^2
    
  • KL散度 (Kullback-Leibler Divergence): KL散度衡量了两个概率分布之间的差异。在NMF中,我们将V和WH视为概率分布,然后计算它们的KL散度:

    J(W, H) = Σ(Vᵢⱼ * log((Vᵢⱼ) / (WH)ᵢⱼ) - Vᵢⱼ + (WH)ᵢⱼ)
    

    KL散度更适合处理数据中存在稀疏性的情况。

选择不同的损失函数,会影响最终的优化结果。本文将以欧几里得距离为例,来推导乘法更新规则。不过,KL散度的推导思路与此类似。

3. 乘法更新规则的推导(以欧几里得距离为例)

乘法更新规则是一种常用的优化方法,它通过迭代地更新W和H,来最小化损失函数。其优点是简单易实现,且在某些情况下能够保证非负性。

我们的目标是最小化损失函数J(W, H)。对于W和H的更新,我们采用梯度下降法,但为了保证W和H的非负性,我们需要对梯度下降进行一些调整。乘法更新规则正是基于这种调整得到的。

3.1 更新H的推导

首先,我们来推导H的更新规则。我们将损失函数J(W, H)对H求偏导:

∂J/∂H = ∂(||V - WH||^2) / ∂H
      = ∂(Σ(Vᵢⱼ - (WH)ᵢⱼ)^2) / ∂H
      = -2Wᵀ(V - WH)

为了得到H的更新规则,我们需要引入一个中间变量。假设H的更新规则为:

H ← H * (A / B)

其中,A和B是两个矩阵,它们的维度与H相同,且都为非负。*表示矩阵的逐元素乘法,/表示矩阵的逐元素除法。

接下来,我们需要找到合适的A和B,使得这个更新规则能够使损失函数下降。我们将H的更新规则带入损失函数,并进行一系列的推导。我们希望找到一个更新规则,使得H的更新能够使损失函数单调递减。

为了简化推导,我们引入拉格朗日乘子λᵢⱼ来约束H的非负性。我们定义拉格朗日函数:

L(W, H, λ) = ||V - WH||^2 + Σ λᵢⱼHᵢⱼ

对L(W, H, λ)关于H求偏导,并令其等于0:

∂L/∂H = -2Wᵀ(V - WH) + λ = 0

=> WᵀV - WᵀWH = λ/2

现在,我们需要选择A和B,使得H的更新规则能够满足上述条件。根据乘法更新规则的思路,我们可以选择:

A = WᵀV
B = WᵀWH

这样,H的更新规则就变成了:

Hᵢⱼ ← Hᵢⱼ * ( (WᵀV)ᵢⱼ / (WᵀWH)ᵢⱼ )

注意: 这里的除法是逐元素的除法。

3.2 更新W的推导

W的更新规则的推导过程与H类似。首先,对损失函数J(W, H)对W求偏导:

∂J/∂W = ∂(||V - WH||^2) / ∂W
      = ∂(Σ(Vᵢⱼ - (WH)ᵢⱼ)^2) / ∂W
      = -2(V - WH)Hᵀ

同样,假设W的更新规则为:

W ← W * (C / D)

其中,C和D是两个矩阵,它们的维度与W相同,且都为非负。

引入拉格朗日乘子μᵢⱼ来约束W的非负性。我们定义拉格朗日函数:

L(W, H, μ) = ||V - WH||^2 + Σ μᵢⱼWᵢⱼ

对L(W, H, μ)关于W求偏导,并令其等于0:

∂L/∂W = -2(V - WH)Hᵀ + μ = 0

=> VHᵀ - WHHᵀ = μ/2

选择:

C = VHᵀ
D = WHHᵀ

这样,W的更新规则就变成了:

Wᵢⱼ ← Wᵢⱼ * ( (VHᵀ)ᵢⱼ / (WHHᵀ)ᵢⱼ )

注意: 这里的除法是逐元素的除法。

4. 乘法更新规则的伪代码

现在,我们将上述推导结果总结成伪代码,方便你理解和实现:

# 输入:
# V: 原始数据矩阵 (m x n)
# k: 潜在特征的数量
# max_iter: 最大迭代次数
# tol: 收敛容忍度

# 初始化W和H,可以使用随机初始化,也可以使用其他方法
# W: 基矩阵 (m x k)
# H: 系数矩阵 (k x n)

def nmf_multiplicative_update(V, k, max_iter=100, tol=1e-4):
    m, n = V.shape
    W = np.random.rand(m, k)  # 随机初始化
    H = np.random.rand(k, n)  # 随机初始化

    for iter in range(max_iter):
        # 1. 更新H
        H = H * (W.T @ V) / (W.T @ W @ H + 1e-9)  # 加上一个小的常数,避免除以0

        # 2. 更新W
        W = W * (V @ H.T) / (W @ H @ H.T + 1e-9)  # 加上一个小的常数,避免除以0

        # 3. 计算损失函数(可选,用于判断收敛)
        loss = np.sum((V - W @ H)**2)

        # 4. 检查收敛
        if iter > 0 and (prev_loss - loss) / prev_loss < tol:
            print(f"收敛于迭代 {iter} 次")
            break

        prev_loss = loss

    return W, H

代码说明:

  • 初始化: W和H通常使用随机初始化。你也可以使用其他初始化方法,例如,使用SVD分解的结果来初始化。
  • 迭代更新: 在每次迭代中,我们先更新H,再更新W。更新的顺序并不影响算法的收敛性。
  • 避免除零: 在实际的编程实现中,为了避免出现除以0的情况,我们通常会在分母上加上一个小的常数,例如1e-9
  • 收敛判断: 我们可以通过计算损失函数,来判断算法是否收敛。如果损失函数的变化小于某个阈值(tol),则认为算法收敛。

5. 算法的优缺点与注意事项

优点:

  • 简单易实现: 乘法更新规则的计算过程非常简单,易于理解和实现。
  • 非负性保证: 由于乘法更新规则的特性,W和H的元素在每次更新后都会保持非负性,这使得NMF特别适合处理非负数据。
  • 局部最优解: 乘法更新规则能够找到局部最优解。虽然不能保证找到全局最优解,但在实际应用中,局部最优解通常也具有很好的效果。

缺点:

  • 收敛速度慢: 乘法更新规则的收敛速度相对较慢,需要进行多次迭代才能达到收敛。
  • 对初始化敏感: W和H的初始化会影响最终的结果。不同的初始化可能导致算法收敛到不同的局部最优解。
  • 参数选择: k值的选择(即潜在特征的数量)对结果有很大影响。需要根据实际数据和应用场景来选择合适的k值。

注意事项:

  • 初始化: 尝试不同的初始化方法,找到最适合你数据的初始化方式。
  • 迭代次数: 设置合适的max_iter值,避免算法过早停止或过度迭代。
  • 收敛判断: 仔细调整tol值,确保算法能够收敛到满意的结果。
  • 正则化: 为了防止过拟合,可以考虑在损失函数中加入正则化项,例如L1正则化或L2正则化。
  • 损失函数: 可以尝试使用不同的损失函数,例如KL散度,以获得更好的效果。

6. 扩展与变种

NMF有很多扩展和变种,可以根据不同的应用场景进行选择和调整。例如:

  • 稀疏NMF: 通过在损失函数中加入稀疏性约束,来提高W和H的稀疏性。这有助于提取更具解释性的特征。
  • 半NMF: 允许W或H为负值,放宽了非负性的限制,可以处理更广泛的数据类型。
  • 协同NMF: 将NMF应用于协同过滤,用于推荐系统。
  • 正则化NMF: 通过在损失函数中加入正则化项,来控制模型的复杂度,防止过拟合。

7. 总结

通过这篇文章,我们详细地推导了NMF乘法更新规则的数学公式,并提供了伪代码示例。希望你能够深入理解NMF算法的核心,并能够将其应用于实际项目中。记住,实践是检验真理的唯一标准。尝试用不同的数据集和参数来实验,你会发现更多有趣的现象。

希望这篇文章对你有所帮助!

点评评价

captcha
健康