使用 Python 的垃圾邮件过滤器
Spam filter using Python
我正在尝试使用 python 2.7 和 scikit-learn 制作一个简单的垃圾邮件过滤器。所以,我有一组用于训练的字母和一组用于测试的字母。首先,我想对训练集进行向量化并使用它来拟合逻辑回归,然后对测试集中的每个字母进行向量化并将它们分别放入分类器中。
import codecs
import json
import os
from sklearn.feature_extraction.text import CountVectorizer
from sklearn import linear_model
def classify(mail, vectorizer, logreg):
vect_mail = vectorizer.transform(mail)
res = logreg.predict(vect_mail)
return res
def make_output(test_dir, vectorizer, logreg):
with codecs.open('test.txt', 'w', 'utf-8') as out:
for f in os.listdir(test_dir):
mail = json.load(open(os.path.join(test_dir, f)), 'utf-8')
result = classify(mail['body'].encode('ascii','ignore'), vectorizer, logreg)
out.write(u'%s\t%s\n' % (f, result))
def read_train(train_dir):
for f in os.listdir(train_dir):
with open(os.path.join(train_dir, f), 'r') as fo:
mail = json.load(fo, 'utf-8')
yield mail
if __name__ == '__main__':
train_mails = list(read_train('spam_data/train'))
corpus = list()
is_spam = list()
for mail in train_mails:
corpus.append(mail['body'].encode('ascii','ignore'))
is_spam.append(mail['is_spam'])
vectorizer = CountVectorizer()
cnt_vect = vectorizer.fit_transform(corpus)
logreg = linear_model.LogisticRegression()
logreg.fit(cnt_vect, is_spam)
make_output('spam_data/test', vectorizer, logreg)
但是res = logreg.predict(vect_mail)
returns一个列表,不是一个意思。所以,我想,预测器将 vect_mail
解释为一个单词的文档样本,而不是一个包含多个单词的文档。我该如何重写这段代码?
根据 sklearn 的文档,CountVectorizer.transform
不接受要转换的单个文档,而是 iterable 文档。由于 Python 中的字符串是其字符的可迭代对象,因此 transform
会生成与字符串中的字符一样多的 "documents"。
为了解决这个问题,将单元素列表传递给 transform
:
vect_mail = vectorizer.transform([mail])
我正在尝试使用 python 2.7 和 scikit-learn 制作一个简单的垃圾邮件过滤器。所以,我有一组用于训练的字母和一组用于测试的字母。首先,我想对训练集进行向量化并使用它来拟合逻辑回归,然后对测试集中的每个字母进行向量化并将它们分别放入分类器中。
import codecs
import json
import os
from sklearn.feature_extraction.text import CountVectorizer
from sklearn import linear_model
def classify(mail, vectorizer, logreg):
vect_mail = vectorizer.transform(mail)
res = logreg.predict(vect_mail)
return res
def make_output(test_dir, vectorizer, logreg):
with codecs.open('test.txt', 'w', 'utf-8') as out:
for f in os.listdir(test_dir):
mail = json.load(open(os.path.join(test_dir, f)), 'utf-8')
result = classify(mail['body'].encode('ascii','ignore'), vectorizer, logreg)
out.write(u'%s\t%s\n' % (f, result))
def read_train(train_dir):
for f in os.listdir(train_dir):
with open(os.path.join(train_dir, f), 'r') as fo:
mail = json.load(fo, 'utf-8')
yield mail
if __name__ == '__main__':
train_mails = list(read_train('spam_data/train'))
corpus = list()
is_spam = list()
for mail in train_mails:
corpus.append(mail['body'].encode('ascii','ignore'))
is_spam.append(mail['is_spam'])
vectorizer = CountVectorizer()
cnt_vect = vectorizer.fit_transform(corpus)
logreg = linear_model.LogisticRegression()
logreg.fit(cnt_vect, is_spam)
make_output('spam_data/test', vectorizer, logreg)
但是res = logreg.predict(vect_mail)
returns一个列表,不是一个意思。所以,我想,预测器将 vect_mail
解释为一个单词的文档样本,而不是一个包含多个单词的文档。我该如何重写这段代码?
根据 sklearn 的文档,CountVectorizer.transform
不接受要转换的单个文档,而是 iterable 文档。由于 Python 中的字符串是其字符的可迭代对象,因此 transform
会生成与字符串中的字符一样多的 "documents"。
为了解决这个问题,将单元素列表传递给 transform
:
vect_mail = vectorizer.transform([mail])