TextMining(文本挖掘,从文本中获取信息)是一个比较宽泛的概念。越来越受到重视。目前,在机器学习模型的帮助下,许多文本挖掘应用,包括情感分析、文档分类、主题分类、文本摘要、机器翻译等,都已经实现了自动化。在这些应用程序中,垃圾邮件过滤是初学者练习文件分类的良好开端。例如Gmail账户中的“垃圾邮箱”就是垃圾邮件过滤的一个实际应用。接下来,我们将编写一个基于公共邮件数据集Ling-spam的垃圾邮件过滤器。Ling-spam数据集下载地址如下:http://t.cn/RKQBl9c这里我们从Ling-spam中提取了等量的垃圾邮件和非垃圾邮件,具体下载地址如下:http://t。cn/RKQBkRu下面我们将通过以下步骤来编写一个实用的垃圾邮件过滤器。1、准备文本数据;2.创建单词词典;3、特征提取;4.训练分类器。***,我们将在测试数据集上验证过滤器。1.准备文本数据这里我们将数据集分为训练集(702封邮件)和测试集(260封邮件),其中垃圾邮件和非垃圾邮件各占50%。这里因为每个垃圾邮件数据集都是以spmsg命名的,所以很容易区分。在大多数文本挖掘问题中,文本清理是第一步,即我们必须先清理那些与我们的目标信息不相关的词和句子,在本例中也是如此。通常邮件中通常会包含很多无用的字符,比如标点符号、停用词、数字等,这些字符对检测垃圾邮件没有帮助,所以我们需要清理它们。这里,Ling-spam数据集中的电子邮件已按以下步骤处理:a)删除停用词——停用词,如“and”、“the”、“of”在英语句子中很常见。然而,这些停用词对于确定电子邮件的真实身份并不是很有用,因此这些词已从电子邮件中删除。b)Lemmatization---这是将同一个词的不同形式组合在一起的过程,以便可以将它们作为一个项目进行分析。例如,“include”、“includes”、“included”都可以用“include”表示。同时,通过lemmatization的方法也会保留句子的上下文意义,这与stemming的方法不同(注:stemming是文本挖掘的另一种方法,该方法不考虑句子的意义).此外,我们还需要去除一些非单词,例如标点符号或特殊字符。实现这一步的方法有很多种,这里,我们先创建一个字典(creatingadictionary),然后去掉这些非文字符号。需要指出的是,这种做法其实很方便,因为当你手上有一本字典时,只需要对每个非文字符号去掉一次即可。2.创建词典(Creatingworddictionary)数据集中的示例电子邮件通常如下所示:.berkeley.edu,你会发现邮件第一行是标题,第三行是正文,这里我们只是根据邮件的文本内容做文本分析,判断邮件是否是垃圾邮件.第一步,我们需要创建一个单词及其频率的字典。为了创建这样一个“字典”,这里我们使用训练集中的700封电子邮件。有关详细信息,请参阅以下Python函数:defmake_Dictionary(train_dir):emails=[os.path.join(train_dir,f)forfinos.listdir(train_dir)]all_words=[]formaillinemails:withopen(mail)asm:fori,lineinenumerate(m):ifi==2:#Bodyofemailisonly3rdlineoftextfilewords=line.split()all_words+=wordsdictionary=Counter(all_words)#Pastecodefornon-wordremovalhere(codesnippetisgivenbelow)returndictionary字典创建完成,我们只需要在其基础上添加几行代码上面的函数,可以去掉之前提到的非文字符号。这里我也删除了一些与判断垃圾邮件无关的单个字符。详情请参考以下代码。请注意,这些代码应附加在defmake_Dictionary(train_dir)函数的末尾。list_to_remove=dictionary.keys()foriteminlist_to_remove:ifitem.isalpha()==False:deldictionary[item]eliflen(item)==1:deldictionary[item]dictionary=dictionary.most_common(3000)这里可以输入打印字典命令输出字典。请注意,您可能会在打印输出的词典中看到许多不相关的单词。这没什么好担心的,因为我们总是有机会在后续步骤中对其进行调整。另外,如果你严格按照上面提到的数据集来操作,那么你的字典中应该有如下高频词(本例中我们选取了频率最高的3000个词):[('order',1414),('地址',1293),('报告',1216),('邮件',1127),('发送',1079),('语言',1072),('电子邮件',1051),('program',1001),('our',987),('list',935),('one',917),('name',878),('receive',826),('money',788),('free',762)3.特征提取字典准备好后,我们可以为训练集中的每封邮件提取一个维度为3000的词数向量(这个向量就是我们的特征),每个词数向量包含了之前选取的3000个高频词的具体出现频率。当然,你可能已经猜到大部分频率应该是0了。举个栗子:比如我们的词典里有500个词,每个词数向量包含这500个词在训练集中出现的频率。假设训练集有一组文本:“Gettheworkdone,workdone”。那么,这句话对应的词数向量应该是这样的:[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条消息)中出现的次数。defextract_features(mail_dir):files=[os.path.join(mail_dir,fi)forfiinos.listdir(mail_dir)]features_matrix=np.zeros((len(files),3000))docID=0;forfilinfiles:withopen(fil)asfi:fori,lineinumerate(fi):ifi==2:words=line.split()forwordinwords:wordID=0fori,dinenumerate(dictionary):ifd[0]==word:wordID=ifeatures_matrix[docID,wordID]=单词.count(word)docID=docID+1returnfeatures_matrix4。训练分类器这里我们将使用scikit-learn机器学习库来训练分类器。scikit-learn库的相关链接如下:http://t.cn/SMzAoZ这是一个绑定第三方python发行版Anaconda的开源机器学习库,可以随Anaconda一起下载安装,或者可以按照以下链接中的提示独立安装:http://t.cn/8kkrVlQ安装完成后,我们将其导入到我们的程序中即可使用。这里我们训练了两个模型,朴素贝叶斯分类器和SVM(支持向量机)。朴素贝叶斯分类器是一种传统的监督概率分类器,在文本分类场景中应用非常广泛。它基于贝叶斯定理并假设每对特征相互独立。SVM是一种有监督的二元分类器,在具有大量特征的场景中非常有效。它的最终目标是从训练数据中分离出一组子集,称为支持向量(分离超平面的边界)。确定测试数据最终类别的SVM决策函数就是基于这个支持向量和内核技巧。分类器训练好后,我们可以在测试集上测试模型的性能。这里我们提取测试集中每封电子邮件的字数向量,然后使用经过训练的朴素贝叶斯分类器和SVM模型来预测其类别(普通电子邮件或垃圾邮件)。下面是垃圾邮件分类器的完整python代码,加上我们在步骤2和3中定义的两个函数需要包含在内。importosimportnumpyasnpfromcollectionsimportCounterfromsklearn.naive_bayesimportMultinomialNB,GaussianNB,BernoulliNBfromsklearn.svmimportSVC,NuSVC,LinearSVCfromsklearn.metricsimportconfusion_matrix#Createadictionaryofwordswithitsfrequencytrain_dir='train-mails'dictionary=make_Dictionary(train_dir)#Preparefeaturevectorspertrainingmailanditslabelstrain_labels=np.zeros(702)train_labels[351:701]=1train_matrix=extract_features(train_dir)#TrainingSVMandNaivebayesclassifiermodel1=MultinomialNB()model2=LinearSVC()model1.fit(train_matrix,train_labels)model2.fit(train_matrix,train_labels)#TesttheunseenmailsforSpamtest_dir='test-mails'test_matrix=extract_features(test_zedirs(n_labels)2ros)6testtest_labels[:260]=1result1=model1.predict(test_matrix)result2=model2.predict(test_matrix)printconfusion_matrix(test_labels,result1)printconfusion_matrix(test_labels,result2)性能测试这里我们的测试集包含130个垃圾邮件和130个非垃圾邮件,如果你有成功完成了前面的所有步骤s,那么你会得到如下结果。这里显示的是两个模型在测试数据上的混淆矩阵,对角线元素表示正确识别的电子邮件数量,非对角线元素表示错误分类。可以看出,两个模型在测试集上的表现相似,但SVM更倾向于判断垃圾邮件。需要注意的是,这里的测试数据集既不用于创建字典,也不用于模型训练。对扩展感兴趣的朋友可以按照上面提到的步骤进行一些扩展。这里介绍数据库和扩展相关的结果。扩展使用经过预处理的Euron-spam数据库,包含6个目录和33716封邮件。每个目录包含非垃圾邮件和垃圾邮件子目录。非垃圾邮件和垃圾邮件总数分别为16545封和17171封。Euron-垃圾邮件库的下载链接如下:http://t.cn/RK84mv6需要注意的是,由于Euron-垃圾邮件库的组织形式spamdatabase不同于上面提到的ling-spam库,上面的一些功能也需要稍作修改才能应用到Euron-spam。这里我们将Euron-spam数据库按照3:2的比例分为训练集和测试集。根据以上步骤,我们在13478封测试邮件中得到了如下结果:可以看出,SVM的性能略优于普通贝叶斯。总结在本文中,我们尽量使描述简单易懂,省略了许多技术解释和名词。我们希望这是一个通俗易懂的教程,希望本教程能够对对文本分析感兴趣的初学者有所帮助。可能有些朋友对朴素贝叶斯模型和SVM模型背后的数学原理很好奇。这里需要指出的是,SVM是数学上比较复杂的模型,而朴素贝叶斯相对比较容易理解。当然,我们鼓励对数学原理感兴趣的朋友深入探索。关于这些数学模型,网上有非常详细的教程和例子。此外,用不同的方法达到相同的目的也是一种很好的研究方法。例如,您可以调整以下参数,观察它们对垃圾邮件过滤实际效果的影响:a)训练数据的大小b)字典的大小c)不同的机器学习模型,包括GaussianNB、BernoulliNB、SVCd)不同的SVM模型参数e)去除不相关的词以改进词典(例如手动去除)f)使用其他特征模型(找到td-idf)***,博客中提到的完整python代码详见以下链接:http://t。cn/R6ZeuiN如有疑问,欢迎在文末留言讨论。本文转载自雷锋网。原文来自国外某位高手的博客。由雷锋网字幕组彭艳蕾、林丽红编译。
