这个教程简单地介绍了如何使用 Python 2.x 和 Weka 进行机器学习。Weka 是一个数据处理和机器学习工具。这篇文章通过实现一个简单的垃圾邮件过滤器来讲解机器学习的概念。
这篇文章是由 Codementor 团队根据他们一个关注自然语言处理的数据科学家 Benjamin Cohen 的一个师生互动来创作的。
什么是机器学习?
简单来说,机器学习是一种基本数据的学习。回到以前我们没有大量的数据和强大的计算能力的时候,人们尝试手写规则来解决许多问题。例如,当你看到{{some word}},它很可能是垃圾邮件。当邮件里出现链接,它很可能是垃圾邮件。它们确实是可用的,但是由于问题变得越来越复杂,规则组合开始变得难以掌控,包括如何记录,传递以及处理它们。许多解决这样问题的技术都属于机器学习这个范畴内。从根本上说,你要解决如何自动地从数据的某些特征中学习他们之间的关系。
在机器学习中,我们尝试解决的一个重要问题叫做分类。简单地说,它决定了把东西放进什么类。例如,识别电子邮件是否是垃圾邮件,或者识别一张图片是狗还是猫。甚至还可以把数据分为两种或多种。
也就是说,我们真正需要开发的是一个能够自动区分两个或多个类别的系统。在这次练习中,我们要实现的是一个能识别垃圾邮件和正常邮件的系统。我们不打算手动编写规则来完成所有的这些功能。完成这个工作或者其他任何机器学习的问题的一件必要的事情就是收集数据集。机器学习的基本流程是从这些数据集中学习规则(可以代表这些数据集的规则),然后用学习到的规则来预测新的数据。换句话说,我们不需要一个数据集作为支持,告诉机器什么是正确的,或者我们的数据看起来像什么,也不用为机器去开发规则。我们需要的是收集让机器学习的材料。
值得注意的是,我们要完成的任务的数据集已经准备好了。但是一般来说,当你解决一个问题的时候,你通常还没有数据,并且你不知道你需要什么数据。
如果你是写一个系统来识别垃圾邮件,那么在这个练习中我们用的数据集正是你想要的,但事实上作为一个应用程序你可能需要找到其他的数据集来交叉验证。电子邮件的地址是一个不稳定的的特征,它们会经常被关闭以至于发送人会创建许多新的邮件地址。你可以做的一件事是判断某个域名发送垃圾邮件的概率。例如,不会有许多人用 gmail 来发送垃圾邮件,因为谷歌对于检测和关闭垃圾邮件账户做的是非常棒的。然而,一些像 hotmail 这样的域名可能有一个特征:如果发送者使用了 hotmail,它很可能就是垃圾邮件,因此你完全可以从检测邮件地址中学习到特征。其他的一些我们能看到的典型特征是元信息,例如邮件是什么时间发送的。在这个练习中所有这些我们可以看到的数据事实上是来自邮件,即文本内容。
练习
这个是 Github 项目的链接,你可以创建分支并继续开发这个项目。首先确定你已经在你的机器上安装了 Weka ——一款免费的软件。
我们将要用的数据集大概包含了1300个电子邮件。你可以快速地浏览这两个文件夹看看都有什么邮件,它们分别是垃圾邮件和非垃圾邮件。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
Find Peace, Harmony, Tranquility, And Happiness Right Now!<html><head></head><body bgcolor=3Dblack> <table border=3D0 cellspacing=3D0 cellpadding=3D5 align=3Dcenter><tr><th b= gcolor=3D"#8FB3C5"> <table border=3D0 cellspacing=3D0 cellpadding=3D5 align=3Dcenter><tr><th b= gcolor=3D"#000000"> <table border=3D0 cellspacing=3D0 cellpadding=3D0 align=3Dcenter> <tr> <th><a href=3D"http://psychicrevenue.com/cgi-bin/refer.cgi?pws01014&site=3D= pw"> <img src=3D"http://giftedpsychic.com/images/r1c1.jpg" width=3D279 height=3D= 286 border=3D0></a></th> <th><a href=3D"http://psychicrevenue.com/cgi-bin/refer.cgi?pws01014&site=3D= pw"> <img src=3D"http://giftedpsychic.com/images/r1c2.gif" width=3D301 height=3D= 286 border=3D0></a></th> </tr> <tr> <th><a href=3D"http://psychicrevenue.com/cgi-bin/refer.cgi?pws01014&site=3D= pw"> <img src=3D"http://giftedpsychic.com/images/r2c1.jpg" width=3D279 height=3D= 94 border=3D0></a></th> <th><a href=3D"http://psychicrevenue.com/cgi-bin/refer.cgi?pws01014&site=3D= pw"> <img src=3D"http://giftedpsychic.com/images/r2c2.jpg" width=3D301 height=3D= 94 border=3D0></a></th> </tr> </table></th></tr></table</th></tr></table></body></html> |
这个是相当典型的垃圾邮件,然后下面这个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
Re: EntrepreneursManoj Kasichainula wrote; >http://www.snopes.com/quotes/bush.htm > >Claim: President George W. Bush proclaimed, "The problem with >the French is that they don't have a word for entrepreneur." > >Status: False. >Lloyd Grove of The Washington Post was unable to reach Baroness >Williams to gain her confirmation of the tale, but he did >receive a call from Alastair Campbell, Blair's director of >communications and strategy. "I can tell you that the prime >minister never heard George Bush say that, and he certainly >never told Shirley Williams that President Bush did say it," >Campbell told The Post. "If she put this in a speech, it must >have been a joke." So some guy failed to reach the source, but instead got spin doctor to deny it. Wot, is he thick enough to expect official confirmation that, yes, Blair is going around casting aspersions on Bush??? It's an amusing anecdote, I don't know if it's true or not, but certainly nothing here supports the authoritative sounding conclusion "Status: False". R http://xent.com/mailman/listinfo/fork |
是一个正常的邮件。
总而言之,快速的浏览了这两个文件夹以后,你会发现它们是相当有代表性的邮件,能看出来它是垃圾邮件或者不是。这确实很重要,因为如果我们的数据不具有代表性,机器学习到的东西将没有任何意义。
总结一下要点,我们要尝试判断一个特征,看它是否能让我们区分数据集中的非垃圾邮件和垃圾邮件。希望将来它可以帮助我们检测出垃圾邮件。
何时用到自然语言处理?
如果你已经注意到,来自”垃圾邮件“与“非垃圾邮件”中内容都是文字。我们作为人类可以很好的理解文字和语言,但是计算机能理解的却非常的少。在这个练习中,我们得把英语转换成计算机可以理解的语言。一般来说,可以转换成数字。这就是自然语言处理的由来,我们试着让计算机理解这些信息的上下文要点。在机器学习的部分就是理解这些数字形成模型并且在将来应用这个模型。
什么是特征?
在我们这个案例中,特征主要是我们输入信息的一种数字化的转变,或者说仅仅是一个机器可以学习的数字。我们打算获取一组数字,或者被叫做特征。它可以像这样代表一封邮件:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
The DEBT-$AVER Program SKYXTGM<HTML><HEAD> <META http-equiv=3DContent-Type content=3D"text/html; charset=3Diso-8859-1= "> </HEAD><BODY><CENTER> <A href=3D"http://marketing-fashion.com/user0205/index.asp?Afft=3DDP15"> <IMG src=3D"http://61.129.68.17/debt1.gif" border=3D0></A> <BR><BR><FONT face=3DArial,Helvetica color=3D#000000 size=3D1> Copyright 2002 - All rights reserved<BR><BR>If you would no longer like us= to contact you or feel that you have<BR>received this email in error, please <A href=3D"http://marketing-fashion.com/light/watch.asp">click here= to unsubscribe</A>.</FONT></CENTER></BODY></HTML> |
我们的数字特征挑选得越好,模型就能更有希望地识别我们的电子邮件。
在挑选任何其他特征之前,我们直接来看字数。features.py是完成这个功能的代码:
1 2 3 |
def numwords(emailtext): splittext = emailtext.split(" ") return len(splittext) |
但是,为了让Weka分析这个数据,我们需要把它转换为.arff文件。
feature_extract.py是一个脚本. 现在你不用担心这是什么,但是如果你感兴趣话这里有代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
import os, re import math, glob import features import inspect def main(): arff = open("spam.arff", "w") ben_functions = inspect.getmembers(features, inspect.isfunction) feature_funcitons = [] feature_funcitons += list([f[1] for f in ben_functions]) RELATION_NAME = "spam" arff.write("@RELATION " + RELATION_NAME + "n") for feature in feature_funcitons: arff.write("@ATTRIBUTE " + str(feature.__name__) + " REALn") #change this if we #have non-real number #values ###PREDEFINED USER FEATURES####### arff.write("@ATTRIBUTE SPAM {True, False}n") arff.write("@DATAn") spam_directory = "is-spam" |