大型稀疏矩阵的快速非负矩阵分解



使用Scikit-learn (v 0.15.2)在一个大型稀疏矩阵(小于1%的值> 0)上进行非负矩阵分解。我想通过最小化矩阵的非零值的错误来找到因子(即,不计算条目为零的错误),并支持稀疏性。我不确定我所做的是否有问题。scikit-learn包的NMF和ProjectedGradientNMF以前对我很有效。但似乎当矩阵大小增加时,分解速度非常慢。

我说的是有> 10^10个单元格的矩阵。对于有~10^7个单元的矩阵,我发现执行时间是好的。

我使用的参数如下:nmf_model = NMF(n_components = 100, init='nndsvd', random_state=0, tol = 0.01, sparseness='data') .

当我尝试稍微不同的参数(更改为init=random)时,我得到以下警告。发出警告后,脚本停止执行。

/lib/python2.7/site-packages/sklearn/decomposition/nmf.py:252: UserWarning: Iteration limit reached in nls subproblem.
  warnings.warn("Iteration limit reached in nls subproblem.")

是否有一种方法可以使这个更快并解决上述问题?我尝试过使用numpy稀疏矩阵(列和行稀疏),但令人惊讶的是-它在我使用较小的矩阵(~10^7个单元格)进行的测试中速度较慢。

考虑到必须对这种分解进行多次迭代(以选择理想数量的因子和k-fold交叉验证),因此非常需要一种更快的方法来解决这个问题。

我也愿意接受非基于sklearn或python的包/工具的建议。我知道关于包/工具选择的问题是不被鼓励的,但是对于这样一个特定的用例,了解该领域中其他人使用的技术将非常有帮助。

也许对最初问题的解释能使我们给出更好的答案。

由于问题的性质,对一个非常大的矩阵进行分解总是很慢的。

建议:将n_components还原为<20美元会加快速度。然而,唯一真正提高速度的方法是限制矩阵的大小。对于你所描述的矩阵,人们可能会认为你在尝试分解一个项频率矩阵。如果是这样,您可以尝试使用scikit-learn中的矢量化函数来限制矩阵的大小。它们大多数都有一个max_features参数。例子:

vectorizer = TfidfVectorizer(
    max_features=10000,
    ngram_range=(1,2))
tfidf = vectorizer.fit_transform(data)

这将大大加快问题的解决。

如果我完全错了,这不是一个项频率问题,我仍然会寻找方法来限制你试图分解的初始矩阵

您可能想看看这篇讨论NMF最新技术的文章:http://www.cc.gatech.edu/~hpark/papers/nmf_blockpivot.pdf

我们的想法是只处理分解的非零项,这样可以减少计算时间,特别是当涉及的矩阵/矩阵非常稀疏时。

同样,同一篇文章的一位作者在github上创建了NMF实现,包括他们文章中提到的那些。链接:https://github.com/kimjingu/nonnegfac-python

希望对你有帮助。

老问题,新答案

OP请求"zero-mask "NMF,其中零被视为缺失值。这永远不会比正常的NMF更快。通过交替最小二乘来考虑NMF,这里方程系统的左侧通常是常数(它只是WHtcrossprod),但在零屏蔽NMF中,它需要为每个样本或特征重新计算。

我已经在RcppML R包中实现了零屏蔽NMF。您可以从CRAN安装它,并使用nmf函数将mask_zeros参数设置为TRUE:

install.packages("RcppML")
A <- rsparsematrix(1000, 1000, 0.1) # simulate random matrix
model <- RcppML::nmf(A, k = 10, mask_zeros = TRUE)

我的NMF实现比没有屏蔽零的scikit-learn更快,并且对于99%的稀疏矩阵来说不应该是不可能的慢。