使用Scikit Learn的DictVectorizer时出现MemoryError错误

5 投票
7 回答
10202 浏览
提问于 2025-04-18 10:00

我正在尝试在我的数据上实现SelectKBest算法,以便找出最好的特征。为此,我首先使用DictVectorizer对数据进行预处理。我的数据有1061427行,包含15个特征。每个特征都有很多不同的值,我觉得我遇到内存错误是因为特征的种类太多了。

我遇到了以下错误:

File "FeatureExtraction.py", line 30, in <module>
    quote_data = DV.fit_transform(quote_data).toarray()
File "/usr/lib64/python2.6/site-packages/scipy/sparse/compressed.py", line 563, in toarray
    return self.tocoo(copy=False).toarray()
File "/usr/lib64/python2.6/site-packages/scipy/sparse/coo.py", line 233, in toarray
    B = np.zeros(self.shape, dtype=self.dtype)
MemoryError

有没有其他方法可以做到这一点?为什么我在一台有256GB内存的机器上处理时会出现内存错误呢?

任何帮助都非常感谢!

7 个回答

1

我在使用DictVectorizer把分类数据库里的数据转换成独热编码(one hot vectors)时,老是遇到内存错误。我犯了一个致命的错误:d = DictVectorizer(sparse=False)。当我对一些有2000个以上类别的字段调用d.transform()时,Python就崩溃了。解决这个问题的办法是把DictVectorizer的sparse参数设置为True,实际上这也是默认的设置。如果你在处理有很多类别的项目的独热编码时,使用稠密数组(dense arrays)并不是最有效的选择。在这种情况下调用.toArray()会非常低效。

独热编码在矩阵乘法中的作用是从某个矩阵中选择一行或一列。其实可以更高效地通过查找向量中1出现的索引来完成。这是一种隐式的乘法方式,所需的操作次数比显式乘法少得多。

2

如果你的数据包含很多不同的文本内容,导致数据种类非常多(我们称之为高基数),你可以试试使用一种更节省资源的工具,叫做 HashingVectorizer

4

问题出在 toarray() 这个方法上。DictVectorizer 是 sklearn 里的一个工具,主要用来处理类别特征(也就是分类数据),特别是那些种类很多的特征。默认情况下,它输出的是稀疏矩阵,也就是只存储非零值的矩阵,这样可以节省内存。

你之所以内存不够,是因为你调用了 fit_transform().toarray(),这会要求用更占内存的方式来表示数据。

你只需要使用:

quote_data = DV.fit_transform(quote_data)
6

我找到了问题所在。

当我删除了一个包含非常多不同值的列后,DictVectorizer就正常工作了。那个列有好几百万个独特的值,所以DictVectorizer才出现了内存错误。

1

在进行 fit_transform 操作时,不要把整个字典都传给它,而是先创建一个只包含唯一值的字典。这样做可以节省很多空间。

下面是一个例子:

转换前的字典:

[ {A:1,B:22.1,C:Red,D:AB12},
      {A:2,B:23.3,C:Blue,D:AB12},
  {A:3,B:20.2,C:Green,D:AB65},
    ]

转换后的字典:

    [ {A:1,B:22.1,C:Red,D:AB12},
      {C:Blue},
  {C:Green,D:AB65},
    ]

这样做可以节省很多存储空间。

撰写回答