python 和 scikit-learn 实现垃圾邮件过滤

文本挖掘(Text Mining,从文字中获取信息)是一个比较宽泛的概念,这一技术在如今每天都有海量文本数据生成的时代越来越受到关注。目前,在机器学习模型的帮助下,包括情绪分析,文件分类,话题分类,文本总结,机器翻译等在内的诸多文本挖掘应用都已经实现了自动化。

  在这些应用中,垃圾邮件过滤算是初学者实践文件分类的一个很不错的开始,例如 Gmail 账户里的“垃圾邮箱”就是一个垃圾邮件过滤的现实应用。下面我们将基于一份公开的邮件数据集 Ling-spam,编写一个垃圾邮件的过滤器。Ling-spam 数据集的下载地址如下:

  http://t.cn/RKQBl9c

  这里我们已经从 Ling-spam 中提取了相同数量的垃圾邮件和非垃圾邮件,具体下载地址如下:

  http://t.cn/RKQBkRu

  下面我们将通过以下几个步骤,编写一个现实可用的垃圾邮件过滤器。

  1.准备文本数据;

  2.创建词典(word dictionary);

  3.特征提取;

  4.训练分类器。

  最后,我们会通过一个测试数据集对过滤器进行验证。

  

1. 准备文本数据

这里我们将数据集分成了训练集(702封邮件)和测试集(260封邮件)两部分,其中垃圾和非垃圾邮件各占 50%。这里因为每个垃圾邮件的数据集都以 spmsg 命名,因此很容易区分。

  在大部分的文本挖掘问题中,文本清理都是第一步,即首先要清理掉那些与我们的目标信息无关的词句,本例中也一样。通常邮件里一般都会包含很多无用的字符,比如标点符号,停用词,数字等等,这些字符对检测垃圾邮件没什么帮助,因此我们需要将它们清理掉。这里 Ling-spam 数据集里的邮件已经经过了以下几个步骤的处理:

  a) 清除停用词 --- 像 "and", "the", "of" 等这些停用词在英语语句中非常常见。然而,这些停用词对于判定邮件的真实身份并没有什么卵用,所以这些词已经从邮件中被移除。

  b) 词形还原 --- 这是一种把同一个词的不同形式组合在一起,以便被当做一个单独项目来分析的过程。举个栗子,"include", "includes" 和 "included" 就可以全部用 "include" 来代表。与此同时,语句的上下文含义也会通过词形还原的方法保留下来,这一点不同于词干提取 (stemming) 的方法(注:词干提取是另一种文本挖掘的方法,此法不考虑语句的含义)。

  此外,我们还需要移除一些非文字类的符号(non-words),比如标点符号或者特殊字符之类的。要实现这一步有很多方法,这里,我们将首先创建一个词典(creating a dictionary),之后再移除这些非文字类的符号。需要指出的是,这种做法其实非常方便,因为当你手上有了一个词典之后,对于每一种非文字类符号,只需要移除一次就 ok 了。

  

2. 创建词典(Creating word dictionary)

一个数据集里的样本邮件一般长这样:

  Subject: posting

  hi , ‘ m work phonetics project modern irish ‘ m hard source . anyone recommend book article english ? ‘ , specifically interest palatal ( slender ) consonant , work helpful too . thank ! laurel sutton ( sutton @ garnet . berkeley . edu

  你会发现邮件的第一行是标题,从第三行开始才是正文。这里我们只在邮件正文内容的基础上做文本分析,来判定该邮件是否为垃圾邮件。第一步,我们需要创建一个文字的词典和文字出现的频率。为了创建这样一个“词典”,这里我们利用了训练集里的 700 封邮件。具体实现详见下面这个 Python 函数:

  def make_Dictionary(train_dir):

  emails = [os.path.join(train_dir,f) for f in os.listdir(train_dir)]

  all_words = []

  for mail in emails:

  with open(mail) as m:

  for i,line in enumerate(m):

  if i == 2: #Body of email is only 3rd line of text file

  words = line.split()

  all_words += words

  dictionary = Counter(all_words)

  # Paste code for non-word removal here(code sniPPet is given belowfeifanshifan8.cn)

  return dictionary

  词典创建好之后,我们只要在上面函数的基础上再加几行代码,就可以移除之前提到的那些非文字类符号了。这里我还顺手删掉了一些与垃圾邮件的判定无关的单字符,具体参见如下的代码,注意这些代码要附在 def make_Dictionary(train_dir) 函数的末尾。

  list_to_remove = dictionary.keys()

  for item in list_to_remove:

  if item.isalpha() == False:

  del dictionary[item]

  elif len(item) == 1:

  del dictionary[item]

  dictionary = dictionary.most_common(3000)

  这里通过输入 print dictionary 指令就可以输出词典。需要注意的是,你在打印输出的词典里可能会看到许多无关紧要的词,这一点无需担心,因为我们在后续的步骤中总是有机会对其进行调整的。另外,如果你是严格按照上文提到的数据集操作的话,那么你的词典里应该会有以下这些高频词(本例中我们选取了频率最高的 3000 个词):

  [(‘order‘, 1414), (‘address‘, 1293), (‘report‘, 1216 www.yongshiyule178.com), (‘mail‘, 1127), (‘send‘, 1079), (‘language‘, 1072), (‘email‘, 1051), (‘program‘, 1001), (‘our‘, 987), (‘list‘, 935), (‘one‘, 917), (‘name‘, 878), (‘receive‘, 826), (‘money‘, 788), (‘free‘, 762)

  

3. 特征提取

词典准备好之后,我们就可以对训练集里的每一封邮件提取维度是 3000 的词数向量 word count vector(这个向量就是我们的特征),每一个词数向量都包含之前选定的 3000 个高频词具体的出现频率。当然,你可能猜到了,大部分出现的频率应该会是 0。举个栗子:比如我们字典里有 500 个词,每个词数向量包含了训练集里这 500 个词的出现频率。假设训练集有一组文本:“Get the work done, work done”。那么,这句话对应的词数向量应该是这样的:[0,0,0,0,0,…….0,0,2,0,0,0,……,0,0,1,0,0,…0,0,1,0,0,……2,0,0,0,0,0]。在这里,句中的每个词出现的频率都能显示出来:这些词分别对应长度为 500 的词数向量中的第 296,359,415 和 495 的位置,其他位置显示为 0。

  下面这个 python 函数会帮助我们生成一个特征向量矩阵,该矩阵有 700 行 3000 列。其中每一行代表训练集中 700 封邮件的的每一封邮件,每一列代表词典中的 3000 个关键词。在 “ij” 位置上的值代表了词典中第 j 个词在该邮件(第 i 封)中出现的次数。

  def extract_features(mail_dir):

  files = [os.path.join(mail_dir,fi) for fi in os.listdir(mail_dir)www.dajinnylee.cn]

  features_matrix = np.zeros((len(files),3000))

  docID = 0;

  for fil in files:

  with open(fil) as fi:

  for i,line in enumerate(fi):

  if i == 2:

  words = line.split()

  for word in words:

  wordID = 0

  for i,d in enumerate(dictionary):

  if d[0] == word:

  wordID = i

  features_matrix[docID,wordID] = words.count(word www.6788878.cn)

  docID = docID + 1

  return features_matrix

  

4.训练分类器

在这里我们会使用 scikit-learn 机器学习库来训练分类器,scikit-learn 库的相关链接如下:

  http://t.cn/SMzAoZ

  这是一个绑定在第三方 python 发行版 Anaconda 的开源机器学习库,可以跟随 Anaconda 一同下载安装,或者也可以按照以下链接中的提示独立安装:

  http://t.cn/8kkrVlQ

  安装好了之后,我们只需要将其 import 到我们的程序中就可以使用了。

  这里我们训练了两个模型,分别是朴素贝叶斯分类器和 SVM(支持向量机)。朴素贝叶斯分类器是一个传统的监督型概率分类器,在文本分类的场景中非常常用,它基于贝叶斯定理,假设每一对特征都是相互独立的。SVM 是监督型的二分类器,面对特征数量较多的场景时非常有效,其最终目标是从训练数据中分离出一组子集,称为支持向量(分离超平面的边界)。判定测试数据最终类别的 SVM 决策函数正是基于该支持向量和内核技巧(kernel trick)的。

  分类器训练完成后,我们可以在测试集上测试模型的性能。这里我们为测试集中的每封邮件提取字数向量,然后用训练好的朴素贝叶斯分类器和 SVM 模型,预测它的类别(普通邮件或垃圾邮件)。下面是垃圾邮件分类器的完整 python 代码,另外还需要包含我们在步骤 2 和步骤 3 中定义的两个函数。

  import os

  import numpy as np

  from collections import Counter

  from sklearn.naive_bayes import MultinomialNB, G www.aomenyonli.cn aussianNB, BernoulliNB

  from sklearn.svm import SVC, NuSVC, LinearSVC

  from sklearn.metrics import confusion_matrix

  # Create a dictionary of words with its frequency

  train_dir = ‘train-mails‘

  dictionary = make_Dictionary(train_dir)

  # Prepare feature vectors per training mail and its labels

  train_labels = np.zeros(702)

  train_labels[351:701] = 1

  train_matrix = extract_features(train_dir)

  # Training SVM and Naive bayes classifier

  model1 = MultinomialNB()

  model2 = LinearSVC()

  model1.fit(train_matrix,train_labels)

  model2.fit(train_matrix,train_labels)

  # Test the unseen mails for Spam

  test_dir = ‘test-mails‘

  test_matrix = extract_features(test_dir)

  test_labels = np.zeros(260)

  test_labels[130:260] = 1

  result1 = model1.predict(test_matrix)

  result2 = model2.predict(test_matrix)

  print confusion_matrix(test_labels,result1)

  print confusion_matrix(test_labels,result2)

  

性能测试

这里我们的测试集中包含 130 封垃圾邮件和 130 封非垃圾邮件,如果你已经顺利完成了之前的所有步骤,那么你将会得到如下的结果。这里显示的是两个模型在测试数据中的混淆矩阵,对角元素代表了正确识别的邮件数,非对角元素代表的则是错误的分类。

  可以看到,两个模型在测试集上有着相近的性能,但 SVM 更倾向垃圾邮件的判定。需要注意的是,这里的测试数据集既没有用于创建字典,也没有用于模型训练。

  

拓展

感兴趣的朋友可以按照上文所述的步骤进行一些拓展,这里介绍拓展相关的数据库和结果。

  拓展使用的是已经预处理好的 Euron-spam 数据库,其中包含了 6 个目录,33716 封邮件,每个目录中都包含非垃圾邮件和垃圾邮件子目录,非垃圾邮件和垃圾邮件的总数分别为 16545 封和 17171 封。Euron-spam 库的下载链接如下:

  http://t.cn/RK84mv6

  需要注意的是,由于 Euron-spam 数据库的组织形式有别于上文提到的 ling-spam 库,因此上文的一些函数也需要做少量的修改才能应用于 Euron-spam。

  这里我们将 Euron-spam 数据库按照 3:2 的比例分为训练集和测试集,按照上文的步骤,我们在 13478 封测试邮件中得到了如下结果:

  可以看到,SV www.senta77.com M 的表现略胜于朴素贝叶斯。

  

总结

在本文中我们尽量保持简单易懂的叙述,省略了许多技术性强的讲解和名词。我们希望这是一篇简单易懂的教程,希望这篇教程可以对文本分析感兴趣的初学者们有所裨益。

  有些朋友可能会对朴素贝叶斯模型和 SVM 模型背后的数学原理感到好奇,这里需要指出的是,SVM 在数学上属于比较复杂的模型,而朴素贝叶斯则相对更容易理解一些。我们当然鼓励对数学原理感兴趣的朋友们深入探索,关于这些数学模型网上有非常详细的教程和实例。除此之外,采用不同的方式实现同一个目标,也是一种很好的研究方法。例如可以调节如下一些参数,观察它们对垃圾邮件过滤的实际效果的影响:

  a) 训练数据的大小

  b) 词典的大小

  c) 不同的机器学习模型,包括 GaussianNB,BernoulliNB,SVC

  d) 不同的 SVM 模型参数

  e) 删除无关紧要的词来改进词典 (例如手动删除)

  f) 采用其他特征模型 (寻找 td-idf)

  最后,博客中提到的完整 python 代码详见如下链接:

  http://t.cn/R6ZeuiN

  若有问题,欢迎在文末留言讨论。

  雷锋网(公众号:雷锋网)相关阅读:

  Google:机器学习检测垃圾邮件准确率已达99.9%

时间: 2024-10-18 08:02:55

python 和 scikit-learn 实现垃圾邮件过滤的相关文章

《机器学习实战》学习笔记:基于朴素贝叶斯的垃圾邮件过滤

概率是许多机器学习算法的基础,在前面生成决策树的过程中使用了一小部分关于概率的知识,即统计特征在数据集中取某个特定值的次数,然后除以数据集的实例总数,得到特征取该值的概率. 之前的基础实验中简单实现了朴素贝叶斯分类器,并正确执行了文本分类,这一节将贝叶斯运用到实际场景,垃圾邮件过滤这一实际应用. 实例:使用朴素贝叶斯过滤垃圾邮件 在上一节:http://blog.csdn.net/liyuefeilong/article/details/48383175中,使用了简单的文本文件,并从中提取了字符

基于C#的机器学习--垃圾邮件过滤

在这一章,我们将建立一个垃圾邮件过滤分类模型.我们将使用一个包含垃圾邮件和非垃圾邮件的原始电子邮件数据集,并使用它来训练我们的ML模型.我们将开始遵循上一章讨论的开发ML模型的步骤.这将帮助我们理解工作流程. 在本章中,我们将讨论以下主题: l  定义问题 l  准备数据 l  数据分析 l  构建数据的特征 l  逻辑回归与朴素贝叶斯的Email垃圾邮件过滤 l  验证分类模型 定义问题 让我们从定义本章要解决的问题开始.我们可能已经对垃圾邮件很熟悉了;垃圾邮件过滤是众电子邮件服务的基本功能.

垃圾邮件过滤优化方法

垃圾邮件过滤优化方法 通过honeypot project 搜集大量垃圾邮件数据 通过解析邮件header 获取垃圾邮件发送路径和服务器相关信息 对编写错误的单词的修正 比如:w4tch 对相同含义的词进行归类处理,比如:discount 和discounts   (可以通过porter stemmer,下面就是该算法c语言的一种实现) /* This is the Porter stemming algorithm, coded up in ANSI C by the author. It m

垃圾邮件过滤技术

1.1 反垃圾邮件的研究与发展 1.1.1 垃圾邮件定义 垃圾邮件,基本上在20世纪末期开始泛滥开来,邮件的广泛使用,以其成本低廉,传输便利的优势,使得邮件得到了商业组织的重视.在商业利益的驱动下,垃圾邮件开始在互联网上泛滥成灾. 1> 垃圾邮件(Email Spam)是指未经用户同意而接收到的电子邮件.具有以下特点[7]: (1) 未经用户同意,与用户不相关: (2) 以欺骗的形式获取邮件地址: (3) 具有虚假性广告,散布量大等 (4) 电子邮件用户收发电子邮件的方式调查 2> 垃圾邮件的

机器学习算法整理(六)— 贝叶斯算法_实现垃圾邮件过滤

垃圾邮件过滤实例 原文地址:https://www.cnblogs.com/douzujun/p/8457865.html

初窥电子邮件未来功能发展 ——越来越强大的垃圾邮件过滤功能

作为互联网最悠久的通讯协议,电子邮箱这十多年都没有什么大的改进,面对垃圾邮件的轰炸.日渐繁琐的格式以及即时通讯软件的轰炸,电子邮箱已默默退出了个人通讯的舞台.但是因发送的内容不限格式,你可以添加任何格式的文件到附件中,且保存稳定不易丢失,所以电子邮箱依旧坚守在企业办公领域. 当然,为了解决电子邮箱的弊端,一直以来都有很多邮箱大佬与垃圾邮件战斗者.其中尤以Gmail做的最出色.近日Google宣布为增强Gmail对垃圾邮件的过滤能力加入了人工智能技术,并提供企业工具检查自己的电子邮件是否被误判成垃

使用朴素贝叶斯算法简单实现垃圾邮件过滤

一.算法介绍 朴素贝叶斯法,简称NB算法,是贝叶斯决策理论的一部分,是基于贝叶斯定理与特征条件独立假设的分类方法: 首先理解两个概念: · 先验概率是指根据以往经验和分析得到的概率,它往往作为"由因求果"问题中的"因"出现: · 后验概率是指在得到"结果"的信息后重新修正的概率,是"执果寻因"问题中的"因" . 1 贝叶斯定理 贝叶斯理论是以18世纪的一位神学家托马斯贝叶斯(Thomas Bayes)命名.

机器学习算法整理(六)— 贝叶斯算法_拼写纠正实例_垃圾邮件过滤实例

(p(h): 先验概率) 垃圾邮箱过滤实例 原文地址:https://www.cnblogs.com/douzujun/p/8457806.html

使用朴素贝叶斯算法简单实现垃圾邮件过滤之算法介绍实现过程

一.算法介绍https://www.cnblogs.com/love528/p/10125089.html 二.实现过程 实验步骤 (1)收集数据:提供文本文件. (2)准备数据:将文本文件解析成词条向量. (3)分析数据:检查词条确保解析的正确性. (4)训练算法:计算不同的独立特征的条件概率. (5)测试算法:计算错误率. (6)使用算法:构建一个完整的程序对一组文档进行分类. 主要代码解析 (1)    分词 使用正则表达式将邮件文本其划分成一个个单词的形式 import re def t