我需要一个整洁的数据结构建议来存储一个非常大的数据集(用Python训练朴素的贝叶斯)

我需要一个整洁的数据结构建议来存储一个非常大的数据集(用Python训练朴素的贝叶斯),python,data-structures,machine-learning,spam-prevention,Python,Data Structures,Machine Learning,Spam Prevention,我将用Python实现NaiveBayes分类器,并将电子邮件分类为垃圾邮件或非垃圾邮件。我有一个非常稀疏且很长的数据集,其中包含许多条目。每个条目如下所示: 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次 我需要读取此数据集并将其存储在结构中。由于它是一个非常大且稀疏的数据集,我正在寻找一个整洁

我将用Python实现NaiveBayes分类器,并将电子邮件分类为垃圾邮件或非垃圾邮件。我有一个非常稀疏且很长的数据集,其中包含许多条目。每个条目如下所示:

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)
  • 每个电子邮件的字数和频率
  • 我还需要用标签信息创建一个包含所有单词及其频率的语料库

对这种数据结构有什么建议吗

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

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

您可以在一次过程中非常轻松地在线完成此操作,只需跟踪每个功能的这两个数字

非布尔特性意味着您必须以某种方式对特性进行离散化,但实际上您并不是在问如何进行离散化。


这就像一个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}
您可以将第二个问题建模为

doc_to_info[doc_id] = {'label': 'label_0', 'word_freqs': {'this': 3, 'is': 4, ...}}
word_to_freq[word] = {'label_0': 42, 'label_1': 314}

我将从一些关系数据库(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 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

我将生成一个类

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,  ... } 
并将所有数据保存在
文档的列表中

要获取具有给定标签的所有文档的聚合,请执行以下操作:

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
模块保存所有数据

另一种方法是使用。可以将弓形向量表示为一行稀疏矩阵。如果你想聚合弓,你只需要把它们加起来。这可能比上面简单的解决方案快得多


此外,您还可以将所有稀疏文档存储在一个大型矩阵中,其中文档实例包含对该矩阵的引用和关联行的行索引

如果你说“将其存储在结构中”,你是指内存中的结构吗?或者你们想把它存储在光盘上?你们似乎遗漏了一个关键因素:你们的数据集有多大?有多少记录和多少单词?