使用贝叶斯规则进行垃圾邮件分类
最近开始学习机器学习算法, 比如常用的贝叶斯规则, 常用来对做文本分类:作者归属, 垃圾邮件检测等。这里我使用python 做了一个分类器。
说下思路:1.准备训练集于测试集,包含垃圾邮件与普通邮件。2.使用jieba对训练集数据分词, 得到每封邮件【word1 word2, word3 word4,...]对 分类标签labels [1,0,....]。3.使用TF算法抽取词频高的词语。4.转换器转换高维文本向量。5.构造分类器 6.测试数据集
涉及到的知识点:朴素贝叶斯分类规则, 比如一封邮件。我们需要知道该邮件出现的单词,在垃圾邮件与正常邮件中的占比。A词占比 pw_s = spamEmail[word]/spamEmailFileLen (pw_s表示在垃圾邮件中该单词的出现的概率) spamEmail[word] 在所有垃圾邮件中该词的占比概率。spamEmailFilelen垃圾邮件长度 。然后计算pw_n = normEmail[word]/normEmailFileLen (pw_n表示普通邮件中该单词的概率),后面是一样。然后使用贝叶斯规则计算ps_w 也就是如果word出现,是垃圾邮件的概率为多少. ps_w = pw_s / pw_s+pw_n (贝叶斯公式) .
当得到所有的词概率后,进行全概率计算 ps_w1 *ps_w2*ps_w3.... 得到ps_w 然后pn_w1=(1-ps_w1)类似上面的公式得到总概率 pn_w.计算 p = ps_w/ps_w+pn_w 就能够得到该邮件是垃圾邮件的概率了。
python关键代码:
1.设计分词函数
def get_word_list(content,wordsList,stopList,file_words_list):
#分词结果放入res_list并返回单词列表
res_list=list(jieba.cut(content))
foriinres_list:
ifinot instopListandi.strip()!=''andi!=None:
ifinot inwordsList:
wordsList.append(i)
#对普通邮件进行分词,将分词结果放入words_list中,每封邮件以逗号分隔每个词以 空格隔开
normal_files=os.listdir("data/normal")
spam_files=os.listdir("data/spam")
wordsList=[]
file_words_list=[]
spam_words_list=[]
forfinnormal_files:
wordsList.clear()
forlineinopen("data/normal/"+f):
rule=re.compile(r"[^\u4e00-\u9fa5]")
line=rule.sub("",line)
get_word_list(line,wordsList,stopList,file_words_list)
file_words_list.append(' '.join(wordsList))
#垃圾邮件同上
#拿到训练集与标签后,可以进行特征提取了。
#文本向量化,提取重要词变量最大出现的概率为50%
vectorizer=TfidfVectorizer(sublinear_tf=True,max_df=0.5)
features_train_transformed=vectorizer.fit_transform(features_train)
features_test_transformed=vectorizer.transform(features_test)
#根据训练集选择合适的特征
#进行特征转换
selector=SelectPercentile(f_classif,percentile=10)
selector.fit(features_train_transformed,labels_train)
features_train_transformed=selector.transform(features_train_transformed).toarray()
features_test_transformed=selector.transform(features_test_transformed).toarray()
###邮件统计信息
print("no. of spam training emails:",sum(labels_train))
print("no. of norm training emails:",len(labels_train)-sum(labels_train))
#进行预测clf=GaussianNB()
clf.fit(features_train_transformed,labels_train)
pred=clf.predict(features_test_transformed)
#acc计算准确率
acc=accuracy_score(labels_test,pred)