引言
非负矩阵分解 (NMF, Non-negative Matrix Factorization) 是一种常用的降维和特征提取技术。 你可以将它想象成一种“积木搭建”的过程:给定一堆“积木”(原始数据),NMF试图找出一些“基础积木”(基矩阵),通过组合这些“基础积木”来尽可能地还原出原始的“积木堆”。NMF 的核心在于“非负”约束,即所有“积木”和“基础积木”的元素都必须是正数或零。这使得NMF在很多领域,如图像处理、文本挖掘、推荐系统等,都有广泛的应用,因为它能得到具有可解释性的分解结果。
在NMF中,我们通常需要一个“尺子”来衡量“搭建”的结果与原始“积木堆”之间的差异,这就是损失函数。KL散度 (Kullback-Leibler Divergence) 就是一种常用的损失函数,它衡量的是两个概率分布之间的差异。当我们将KL散度应用到NMF中时,我们实际上是在假设数据服从泊松分布,这在很多场景下(如计数数据)是合理的。
本文将深入探讨KL散度在NMF中的应用,详细推导基于KL散度的乘法更新规则,并提供相应的伪代码实现。相信我,这绝对不是一篇“水文”,我会尽可能地把每一个细节都讲清楚,让你真正理解KL-NMF的内在逻辑。
NMF基础
首先,我们来回顾一下NMF的基本概念。给定一个非负矩阵 (V \in \mathbb{R}{+}^{m \times n}) (例如,(V) 可以是图像的像素矩阵,文本的词频矩阵等),NMF的目标是找到两个非负矩阵 (W \in \mathbb{R}{+}^{m \times r}) 和 (H \in \mathbb{R}_{+}^{r \times n}),使得:
[
V \approx WH
]
其中,(r) 是一个小于 (m) 和 (n) 的正整数,称为分解的秩。(W) 被称为基矩阵,(H) 被称为系数矩阵。你可以把 (W) 的每一列看作是“基础积木”,(H) 的每一行则表示如何用这些“基础积木”来组合出 (V) 的每一列。
KL散度
KL散度,也称为相对熵,是衡量两个概率分布 (P) 和 (Q) 之间差异的一种方式。对于离散概率分布,KL散度的定义如下:
[
D_{KL}(P||Q) = \sum_{i} P(i) \log \frac{P(i)}{Q(i)}
]
需要注意的是,KL散度是不对称的,即 (D_{KL}(P||Q) \neq D_{KL}(Q||P))。KL散度总是非负的,且 (D_{KL}(P||Q) = 0) 当且仅当 (P = Q)。
在NMF中,我们可以将 (V) 和 (WH) 看作是两个概率分布(经过归一化后),然后用KL散度来衡量它们之间的差异。因此,基于KL散度的NMF的损失函数可以定义为:
[
L(W, H) = D_{KL}(V||WH) = \sum_{ij} \left( V_{ij} \log \frac{V_{ij}}{(WH){ij}} - V{ij} + (WH)_{ij} \right)
]
乘法更新规则推导
为了最小化损失函数 (L(W, H)),我们可以使用梯度下降法。但是,直接使用梯度下降法并不能保证 (W) 和 (H) 的非负性。因此,Lee和Seung提出了一种乘法更新规则,它能够保证在迭代过程中 (W) 和 (H) 始终保持非负。
下面,我们来详细推导基于KL散度的乘法更新规则。
首先,我们计算损失函数 (L(W, H)) 对 (W) 和 (H) 的梯度:
[
\frac{\partial L}{\partial W_{ik}} = \sum_{j} \left( -\frac{V_{ij}}{(WH){ij}} H{kj} + H_{kj} \right) = \sum_j H_{kj} \left( 1 - \frac{V_{ij}}{(WH){ij}} \right) ]
[
\frac{\partial L}{\partial H{kj}} = \sum_{i} \left( -\frac{V_{ij}}{(WH){ij}} W{ik} + W_{ik} \right) = \sum_i W_{ik} \left( 1 - \frac{V_{ij}}{(WH)_{ij}} \right)
]
接下来,我们使用梯度下降法的更新规则:
[
W_{ik} \leftarrow W_{ik} - \eta_{ik} \frac{\partial L}{\partial W_{ik}}
]
[
H_{kj} \leftarrow H_{kj} - \gamma_{kj} \frac{\partial L}{\partial H_{kj}}
]
其中,(\eta_{ik}) 和 (\gamma_{kj}) 是学习率。
为了得到乘法更新规则,我们巧妙地选择学习率:
[
\eta_{ik} = \frac{W_{ik}}{\sum_j H_{kj}}
]
[
\gamma_{kj} = \frac{H_{kj}}{\sum_i W_{ik}}
]
将学习率代入梯度下降法的更新规则,我们得到:
[
W_{ik} \leftarrow W_{ik} \frac{\sum_j H_{kj} \frac{V_{ij}}{(WH){ij}}}{\sum_j H{kj}}
]
[
H_{kj} \leftarrow H_{kj} \frac{\sum_i W_{ik} \frac{V_{ij}}{(WH){ij}}}{\sum_i W{ik}}
]
这就是基于KL散度的NMF的乘法更新规则。可以看出,只要初始的 (W) 和 (H) 是非负的,那么在迭代过程中,(W) 和 (H) 始终会保持非负。
伪代码实现
下面是基于KL散度的NMF的伪代码实现:
输入:非负矩阵 V,分解秩 r,最大迭代次数 max_iter
输出:基矩阵 W,系数矩阵 H
1. 初始化 W 和 H 为非负随机矩阵
2. for iter = 1 to max_iter do
3. 更新 H:
H = H .* (W' * (V ./ (W * H + 1e-9))) ./ (W' * ones(size(V)) + 1e-9)
4. 更新 W:
W = W .* ((V ./ (W * H + 1e-9)) * H') ./ (ones(size(V)) * H' + 1e-9)
5. end for
其中,.*
表示逐元素乘法,./
表示逐元素除法,1e-9
是一个很小的正数,用于防止除零错误。ones(size(V))
生成一个与V大小相同的全1矩阵。
这段伪代码非常简洁,但它却蕴含着深刻的数学原理。你可能觉得它有些“神奇”,但只要你理解了上面的推导过程,就会发现它其实是很自然的。
总结
本文详细介绍了KL散度在NMF中的应用,推导了基于KL散度的乘法更新规则,并提供了伪代码实现。KL-NMF是一种常用的NMF算法,它在很多领域都有广泛的应用。希望本文能帮助你深入理解KL-NMF的原理和实现。
当然,NMF还有很多其他的变种和扩展,例如,基于不同损失函数的NMF,稀疏NMF,正交NMF等等。如果你对这些内容感兴趣,可以进一步查阅相关文献。学习NMF就像探索一个“积木世界”,你会发现很多有趣的东西。 相信你一定可以在这个“积木世界”中找到属于自己的乐趣!