在朴素贝叶斯(Python、scikit)中使用稀疏矩阵/在线学习

Posted

技术标签:

【中文标题】在朴素贝叶斯(Python、scikit)中使用稀疏矩阵/在线学习【英文标题】:Using sparse matrices/online learning in Naive Bayes (Python, scikit) 【发布时间】:2012-08-26 16:21:27 【问题描述】:

我正在尝试对具有超过 6,000,000 个条目且每个条目具有 150k 个特征的数据集执行朴素贝叶斯。我试图从以下链接实现代码: Implementing Bag-of-Words Naive-Bayes classifier in NLTK

问题是(据我了解),当我尝试使用 dok_matrix 作为参数运行训练方法时,它找不到 iterkeys(我已将行与 OrderedDict 作为标签配对):

Traceback (most recent call last):
  File "skitest.py", line 96, in <module>
    classif.train(add_label(matr, labels))
  File "/usr/lib/pymodules/python2.6/nltk/classify/scikitlearn.py", line 92, in train
    for f in fs.iterkeys():
  File "/usr/lib/python2.6/dist-packages/scipy/sparse/csr.py", line 88, in __getattr__
    return _cs_matrix.__getattr__(self, attr)
  File "/usr/lib/python2.6/dist-packages/scipy/sparse/base.py", line 429, in __getattr__
    raise AttributeError, attr + " not found"
AttributeError: iterkeys not found

我的问题是,有没有办法通过逐项(在线)教授分类器条目来避免使用稀疏矩阵,或者在这种情况下我可以有效地使用稀疏矩阵格式而不是 dok_matrix?还是我遗漏了一些明显的东西?

感谢任何人的时间。 :)

编辑,9 月 6 日:

找到了iterkeys,所以至少代码可以运行。它仍然太慢,因为它花了几个小时处理一个 32k 大小的数据集,但仍未完成。这是我目前得到的:

matr = dok_matrix((6000000, 150000), dtype=float32)
labels = OrderedDict()

#collect the data into the matrix

pipeline = Pipeline([('nb', MultinomialNB())])
classif = SklearnClassifier(pipeline)

add_label = lambda lst, lab: [(lst.getrow(x).todok(), lab[x])
                              for x in xrange(lentweets-foldsize)] 

classif.train(add_label(matr[:(lentweets-foldsize),0], labels))
readrow = [matr.getrow(x + foldsize).todok() for x in xrange(lentweets-foldsize)]
data = np.array(classif.batch_classify(readrow))

问题可能是所取的每一行都没有利用向量的稀疏性,而是遍历了 150k 条目中的每一个。作为这个问题的延续,有谁知道如何使用这个带有稀疏矩阵的朴素贝叶斯,或者有没有其他方法来优化上面的代码?

【问题讨论】:

也许您可以更有效地对特征进行编码,或者减小它们的大小? 是的,但不管有多少功能,恐怕我仍然需要管理矩阵的大小。数据集由推文的单词组成。 至少找到了iterkeys,现在问题是代码太慢了。 你需要用 Python 做吗?看看 MALLET:mallet.cs.umass.edu,它的速度非常快。 本身不需要python,但我们在这里得到了熟悉的窥视。谢谢,我会检查一下。不过,我想为大型数据集找到一个明确的解决方案会很好,这样任何在谷歌上搜索这个问题的人都会在这里找到答案。 【参考方案1】:

查看 scikit-learn 中的 document classification example。诀窍是让库为您处理特征提取。跳过 NLTK 包装器,因为它不适用于如此大的数据集。(*)

如果您有文本文件中的文档,那么您只需将这些文本文件交给TfidfVectorizer,它会根据它们创建一个稀疏矩阵:

from sklearn.feature_extraction.text import TfidfVectorizer
vect = TfidfVectorizer(input='filename')
X = vect.fit_transform(list_of_filenames)

您现在有一个 CSR 稀疏矩阵格式的训练集 X,如果您还有一个标签列表 y(可能源自文件名,如果您对类):

from sklearn.naive_bayes import MultinomialNB
nb = MultinomialNB()
nb.fit(X, y)

如果事实证明这不起作用,因为文档集太大(不太可能因为 TfidfVectorizer 仅针对此数量的文档进行了优化),请查看 out-of-core document classification 示例,该示例演示了 @987654329 @ 和 partial_fit API 用于小批量学习。您需要 scikit-learn 0.14 才能正常工作。

(*) 我知道,因为我写了那个包装器。与 NLTK 的其余部分一样,它用于教育目的。我还致力于 scikit-learn 的性能改进,我宣传的一些代码是我自己的。

【讨论】:

第一个链接失效了

以上是关于在朴素贝叶斯(Python、scikit)中使用稀疏矩阵/在线学习的主要内容,如果未能解决你的问题,请参考以下文章

scikit-learn 朴素贝叶斯类库使用小结

如何为 scikit-learn 的朴素贝叶斯指定先验概率

如何从 CSV 在 Scikit 中执行朴素贝叶斯分类

使用 python 的朴素贝叶斯分类器

处理 scikit learn 的朴素贝叶斯看不见的特征

Scikit-Learn 朴素贝叶斯分类丨数析学院