矩阵上的 Python PCA 太大而无法放入内存

Posted

技术标签:

【中文标题】矩阵上的 Python PCA 太大而无法放入内存【英文标题】:Python PCA on Matrix too large to fit into memory 【发布时间】:2015-11-18 09:40:25 【问题描述】:

我有一个 100,000 行 x 27,000 列的 csv,我正在尝试对其进行 PCA 以生成 100,000 行 X 300 列矩阵。 csv 为 9GB 大。这是我目前正在做的事情:

from sklearn.decomposition import PCA as RandomizedPCA
import csv
import sys
import numpy as np
import pandas as pd

dataset = sys.argv[1]
X = pd.DataFrame.from_csv(dataset)
Y = X.pop("Y_Level")
X = (X - X.mean()) / (X.max() - X.min())
Y = list(Y)
dimensions = 300
sklearn_pca = RandomizedPCA(n_components=dimensions)
X_final = sklearn_pca.fit_transform(X)

当我运行上述代码时,我的程序在步骤中执行 .from_csv 时被杀死。我已经能够通过将 csv 分成 10,000 组来解决这个问题;逐一读取它们,然后调用 pd.concat。这使我可以在被杀死之前进入标准化步骤 (X - X.mean())....我的数据对于我的 macbook air 来说是否太大?或者有没有更好的方法来做到这一点。我真的很想将我拥有的所有数据用于我的机器学习应用程序。


如果我想按照以下答案的建议使用增量 PCA,我会这样做吗?:

from sklearn.decomposition import IncrementalPCA
import csv
import sys
import numpy as np
import pandas as pd

dataset = sys.argv[1]
chunksize_ = 10000
#total_size is 100000
dimensions = 300

reader = pd.read_csv(dataset, sep = ',', chunksize = chunksize_)
sklearn_pca = IncrementalPCA(n_components=dimensions)
Y = []
for chunk in reader:
    y = chunk.pop("virginica")
    Y = Y + list(y)
    sklearn_pca.partial_fit(chunk)
X = ???
#This is were i'm stuck, how do i take my final pca and output it to X,
#the normal transform method takes in an X, which I don't have because I
#couldn't fit it into memory.

我在网上找不到任何好的例子。

【问题讨论】:

能否使用稀疏矩阵表示来减少原始数据的内存占用? 【参考方案1】:

尝试将您的数据分批或将其分批加载到脚本中,并在每个批次上使用它的 partial_fit 方法将您的 PCA 与 Incremetal PCA 匹配。

from sklearn.decomposition import IncrementalPCA
import csv
import sys
import numpy as np
import pandas as pd

dataset = sys.argv[1]
chunksize_ = 5 * 25000
dimensions = 300

reader = pd.read_csv(dataset, sep = ',', chunksize = chunksize_)
sklearn_pca = IncrementalPCA(n_components=dimensions)
for chunk in reader:
    y = chunk.pop("Y")
    sklearn_pca.partial_fit(chunk)

# Computed mean per feature
mean = sklearn_pca.mean_
# and stddev
stddev = np.sqrt(sklearn_pca.var_)

Xtransformed = None
for chunk in pd.read_csv(dataset, sep = ',', chunksize = chunksize_):
    y = chunk.pop("Y")
    Xchunk = sklearn_pca.transform(chunk)
    if Xtransformed == None:
        Xtransformed = Xchunk
    else:
        Xtransformed = np.vstack((Xtransformed, Xchunk))

Useful link

【讨论】:

感谢您的回复!你介意快速看看我上面的实现吗?我在网上找不到好的例子;您发送的链接上的那个是将整个数据加载到内存中。 感谢您的帮助。循环完成后我需要调用转换或其他函数吗?最终,我需要一个 100,000 x 300,000 尺寸的二维浮点矩阵。只是调用 fit 会给我这个还是我需要以某种方式调用 transform?当我的数据很小时,我不得不使用 fit_trasnformed。 我的脚本刚刚完成,它看起来不像返回 X 矩阵。 更清楚地说明了我在问题中遇到的问题。 @mt88,在所有数据块上使用 partial_fit 完成 pca 拟合后,如果您想转换数据(降低维度),可能会再次按块(在单独的 for 循环中,装好后)。转换后你将得到 100k * 300 矩阵。您必须在拟合后调用转换,因为模型必须从可用数据集中学习所有示例,否则将无法正确转换数据。这就是为什么您不能将 fit_transform 与 IncrementalPCA 一起使用,只能使用 partial_fit、fit 和 transform。【参考方案2】:

PCA 需要计算一个相关矩阵,即 100,000x100,000。如果数据以双精度存储,则为 80 GB。我敢打赌你的 Macbook 没有 80 GB RAM。

对于合理大小的随机子集,PCA 变换矩阵可能几乎相同。

【讨论】:

感谢您的回复!有没有办法告诉 RandomizedPCA 使用数据子集而不是所有 X?另外,有没有办法判断合理的尺寸是多少? 10,000 行是否足够好? 27k * 27k,他只有27k个特征,相关矩阵表示特征到特征的相关性。

以上是关于矩阵上的 Python PCA 太大而无法放入内存的主要内容,如果未能解决你的问题,请参考以下文章

如何有效地读取和写入太大而无法放入内存的文件?

C & MinGW:Hello World 给我错误“程序太大而无法放入内存”

大数据的增量 PCA

SQLiteBlobTooBigException:写入数据库时​​行太大而无法放入 CursorWindow

字体太大而无法放入缓存

Android - 视图太大而无法放入绘图缓存