使用 sklearn 对大型稀疏矩阵执行 PCA
Posted
技术标签:
【中文标题】使用 sklearn 对大型稀疏矩阵执行 PCA【英文标题】:Performing PCA on large sparse matrix by using sklearn 【发布时间】:2016-02-09 18:48:42 【问题描述】:我正在尝试将 PCA 应用于巨大的稀疏矩阵,在下面的链接中它说 sklearn 的随机 PCA 可以处理 scipy 稀疏格式的稀疏矩阵。 Apply PCA on very large sparse matrix
但是,我总是出错。有人可以指出我做错了什么。
输入矩阵 'X_train' 包含 float64 中的数字:
>>>type(X_train)
<class 'scipy.sparse.csr.csr_matrix'>
>>>X_train.shape
(2365436, 1617899)
>>>X_train.ndim
2
>>>X_train[0]
<1x1617899 sparse matrix of type '<type 'numpy.float64'>'
with 81 stored elements in Compressed Sparse Row format>
我正在努力:
>>>from sklearn.decomposition import RandomizedPCA
>>>pca = RandomizedPCA()
>>>pca.fit(X_train)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/RT11/.pyenv/versions/2.7.9/lib/python2.7/site-packages/sklearn/decomposition/pca.py", line 567, in fit
self._fit(check_array(X))
File "/home/RT11/.pyenv/versions/2.7.9/lib/python2.7/site-packages/sklearn/utils/validation.py", line 334, in check_array
copy, force_all_finite)
File "/home/RT11/.pyenv/versions/2.7.9/lib/python2.7/site-packages/sklearn/utils/validation.py", line 239, in _ensure_sparse_format
raise TypeError('A sparse matrix was passed, but dense '
TypeError: A sparse matrix was passed, but dense data is required. Use X.toarray() to convert to a dense numpy array.
如果我尝试转换为密集矩阵,我想我内存不足。
>>> pca.fit(X_train.toarray())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/RT11/.pyenv/versions/2.7.9/lib/python2.7/site-packages/scipy/sparse/compressed.py", line 949, in toarray
return self.tocoo(copy=False).toarray(order=order, out=out)
File "/home/RT11/.pyenv/versions/2.7.9/lib/python2.7/site-packages/scipy/sparse/coo.py", line 274, in toarray
B = self._process_toarray_args(order, out)
File "/home/RT11/.pyenv/versions/2.7.9/lib/python2.7/site-packages/scipy/sparse/base.py", line 800, in _process_toarray_args
return np.zeros(self.shape, dtype=self.dtype, order=order)
MemoryError
【问题讨论】:
您在链接的问题中看到这个答案了吗? ***.com/a/10721425/2272172 是的,但我想知道是否有办法将 PCA 应用于巨大的稀疏矩阵(如果可能的话,使用 python 和 sklearn) 所以你已经使用了TruncatedSVD
,但它不起作用?如果是这样,请在您的问题中也记录下来。
TruncatedSVD 如果我设置小的 n_components,例如 100,则可以工作,但如果我将其设置为 1,000,000,则会失败。
事实上,即使为 TruncatedSVD 设置 n_components = 3000 也会产生 MemoryError。
【参考方案1】:
由于 PCA 的性质,即使输入是稀疏矩阵,输出也不是。你可以用一个简单的例子来检查它:
>>> from sklearn.decomposition import TruncatedSVD
>>> from scipy import sparse as sp
创建一个随机稀疏矩阵,其中 0.01% 的数据为非零。
>>> X = sp.rand(1000, 1000, density=0.0001)
对其应用 PCA:
>>> clf = TruncatedSVD(100)
>>> Xpca = clf.fit_transform(X)
现在,检查结果:
>>> type(X)
scipy.sparse.coo.coo_matrix
>>> type(Xpca)
numpy.ndarray
>>> print np.count_nonzero(Xpca), Xpca.size
95000, 100000
这表明有 95000 个条目是非零的,但是,
>>> np.isclose(Xpca, 0, atol=1e-15).sum(), Xpca.size
99481, 100000
99481 个元素接近0
(<1e-15
),但不接近0
。
简而言之,这意味着对于 PCA,即使输入是稀疏矩阵,输出也不是。因此,如果您尝试从矩阵中提取 100,000,000 (1e8
) 个分量,您最终将得到一个 1e8 x n_features
(在您的示例中为 1e8 x 1617899
)密集矩阵,当然,它不能保存在内存中。
我不是专业的统计学家,但我相信目前没有使用 scikit-learn 解决此问题的方法,因为这不是 scikit-learn 实现的问题,只是他们的 Sparse PCA 的数学定义(通过sparse SVD) 这使得结果密集。
唯一可能对您有用的解决方法是,您从少量组件开始,然后增加它,直到您在可以保留在内存中的数据与解释的数据百分比之间取得平衡(你可以计算如下):
>>> clf.explained_variance_ratio_.sum()
【讨论】:
我明白了,我能够将特征数量从 1.6M 减少到 500 个(刚好足以容纳在内存中)。除非您有非常大的 RAM,否则似乎不可能在巨大的矩阵之上执行 SVD。【参考方案2】:PCA(X) 是 SVD(X-mean(X))。 即使 X 是稀疏矩阵,X-mean(X) 也始终是密集矩阵。 因此,随机 SVD(TruncatedSVD)不像稀疏矩阵的随机 SVD 那样有效。 但是,延迟评估
延迟(X-mean(X))
可以避免将稀疏矩阵X扩展为密集矩阵X-mean(X)。 延迟评估可以使用随机 SVD 对稀疏矩阵进行有效的 PCA。
这个机制在我的包里实现了:https://github.com/niitsuma/delayedsparse/
您可以使用这种机制查看 PCA 的代码: https://github.com/niitsuma/delayedsparse/blob/master/delayedsparse/pca.py
与现有方法的性能比较表明,这种机制大大减少了所需的内存大小: https://github.com/niitsuma/delayedsparse/blob/master/demo-pca.sh
可以在我的专利中找到有关此技术的更多详细说明: https://patentscope2.wipo.int/search/ja/detail.jsf?docId=JP225380312
【讨论】:
以上是关于使用 sklearn 对大型稀疏矩阵执行 PCA的主要内容,如果未能解决你的问题,请参考以下文章