我需要一个整洁的数据结构建议来存储一个非常大的数据集(用Python训练Naive Bayes)

时间:2011-09-17 06:22:58

标签: python data-structures machine-learning spam-prevention

我将使用Python实现Naive Bayes分类器,并将电子邮件归类为垃圾邮件或非垃圾邮件。我有一个非常稀疏和长的数据集,有很多条目。每个条目如下:

1 9:3 94:1 109:1 163:1 405:1 406:1 415:2 416:1 435:3 436:3 437:4 ...

其中1是标签(垃圾邮件,不是垃圾邮件),每对都对应一个单词及其频率。例如。 9:3对应于单词9,它在此电子邮件样本中出现3次。

我需要读取此数据集并将其存储在结构中。由于它是一个非常大且稀疏的数据集,我正在寻找一个整洁的数据结构来存储以下变量:

  • 每封电子邮件的索引
  • 标签(1或-1)
  • 单词及每封电子邮件的频率
  • 我还需要使用标签信息
  • 创建所有单词及其频率的语料库

对此类数据结构有何建议?

4 个答案:

答案 0 :(得分:0)

如果您认为自己并不关心电子邮件中每个单词的多次出现,那么您真正需要知道的是(即您的功能是布尔值):

对于每个特征,积极关联和消极关联的数量是多少?

您可以一次性在线轻松完成此操作,并跟踪每个功能的这两个数字。

非布尔功能意味着你必须将这些功能离散化,但你并不是真的在询问如何做到这一点。

答案 1 :(得分:0)

https://github.com/Yelp/sqlite3dbm
http://packages.python.org/sqlite3dbm/

这就像一个python字典,除了它存储你在磁盘上提供的所有东西,因此,是持久的!这不会使大量的内存膨胀,因为它将内容写入磁盘。您可以让一个程序设置这些文件,另一个程序使用它们进行分类,而不必担心序列化问题。

您可以将第一个问题干净地建模为

doc_to_info[doc_id] = {'label': 'label_0', 'word_freqs': {'this': 3, 'is': 4, ...}}

您可以将第二个问题建模为

word_to_freq[word] = {'label_0': 42, 'label_1': 314}

答案 2 :(得分:0)

我会从一些关系数据库开始(SQLite很容易设置),并使用下面的表结构:

Word
-----
Number    INT   -- The word number in your data
Word      TEXT  -- The word itself


Entry
-----
ID        INT  -- Some number to make it unique
Spam      INT  -- -1 or 1 as you described


Entry_Word
----------
EntryID   INT  -- The entry this row corresponds to
WordNo    INT  -- The number of the word
Frequency INT  -- The number of occurences of the word

要获取您可以使用的条目

SELECT ID, Spam
FROM Entry

要获取某些条目的单词频率,您可以使用:

SELECT WordNo, Frequency
FROM Entry_Word
WHERE EntryID = ?

要获得单词频率语料库,您可以使用:

SELECT
    WordNo,
    SUM(MIN(0,Spam*Frequency)) AS NotSpamFrequency,
    SUM(MAX(0,Spam*Frequency)) AS SpamFrequency
FROM Entry
INNER JOIN Entry_Word ON EntryID = ID
GROUP BY WordNo

如果您愿意,还可以包含单词本身:

SELECT
    Word,
    WordNo,
    SUM(MIN(0,Spam*Frequency)) AS NotSpamFrequency,
    SUM(MAX(0,Spam*Frequency)) AS SpamFrequency
FROM Entry
INNER JOIN Entry_Word ON EntryID = ID
LEFT JOIN Word ON Number = WordNo
GROUP BY Word, WordNo

答案 3 :(得分:0)

我会生成一个类

class Document(object):

    def __init__(self, index, label, bowdict):
        self.index = index
        self.label = label
        self.bowdict = bowdict

您将稀疏矢量存储在bowdict中,例如

{ 9:3, 94:1, 109:1,  ... } 

并将所有数据保存在Document s

列表中

获取有关给定标签的所有文档的聚合:

from collections import defaultdict

def aggregate(docs, label):
    bow = defaultdict(int)
    for doc in docs:
        if doc.label == label:
           for (word, counter) in doc.bowdict.items():
                bow[word] += counter  
    return bow    

您可以使用cPickle模块保留所有数据。

另一种方法是使用http://docs.scipy.org/doc/scipy/reference/sparse.html。您可以将弓矢量表示为具有一行的稀疏矩阵。如果你想聚合弓,你只需要添加它们。这可能比上面的简单解决方案快得多。

此外,您可以将所有稀疏文档存储在一个大矩阵中,其中Document实例包含对矩阵的引用,以及相关行的行索引。