完整演示代码请见本书GitHub上的15-4.py。
1.数据清洗与特征提取
垃圾邮件是信息时代的副产品,具有以下危害:
·占用网络带宽,造成邮件服务器拥塞,进而降低整个网络的运行效率。
·侵犯收件人的隐私权,侵占收件人信箱空间,耗费收件人的时间、精力和金钱。有的垃圾邮件还盗用他人的电子邮件地址作为发信地址,严重损害了他人的信誉。
·被黑客利用成为助纣为虐的工具。2000年2月,黑客攻击雅虎等五大热门网站就是一个例子。黑客先是侵入并控制了一些高带宽的网站,集中众多服务器的带宽能力,然后用数以亿万计的垃圾邮件猛烈袭击目标,造成被攻击网站网路堵塞,最终瘫痪。
·严重影响ISP的服务形象。在国际上,频繁转发垃圾邮件的主机会被上级国际因特网服务提供商列入国际垃圾邮件数据库,从而导致该主机不能访问国外许多网站。而且收到垃圾邮件的用户会因为ISP没有建立完善的垃圾邮件过滤机制,而转向其他ISP。一项调查表明:ISP每争取一个用户要花费75美元,但是每年因垃圾邮件要失去7.2%的用户。
·妖言惑众、骗人钱财、传播色情等内容的垃圾邮件,已经对现实社会造成了危害。
我们使用SpamBase这个入门级的垃圾邮件分类训练集来测试。SpamBase的数据不是原始的邮件内容而是已经特征化的数据,对应的特征是统计的关键字以及特殊符号的词频,一共58个属性,其中最后一个是垃圾邮件的标记位,如图15-13所示。特征数据结构举例如下:
word_freq_make: continuous. word_freq_address: continuous. word_freq_all: continuous. word_freq_3d: continuous. word_freq_our: continuous. word_freq_over: continuous. word_freq_remove: continuous. word_freq_internet: continuous. word_freq_order: continuous. word_freq_mail: continuous. word_freq_receive: continuous. word_freq_will: continuous. word_freq_people: continuous. word_freq_report: continuous. word_freq_addresses: continuous.
图15-13 SpamBase数据集特征抽取过程
数据来源为4601封邮件,其中1813封为垃圾邮件,数据内容举例如下:
0,0.64,0.64,0,0.32,0,0,0,0,0,0,0.64,0,0,0,0.32,0,1.29,1.93,0,0.96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.778,0,0,3.756,61,278,1 0.21,0.28,0.5,0,0.14,0.28,0.21,0.07,0,0.94,0.21,0.79,0.65,0.21,0.14,0.14,0.07,0.28,3.47,0,1.59,0, 0.43,0.43,0,0,0,0,0,0,0,0,0,0,0,0,0.07,0,0,0,0,0,0,0,0,0,0,0,0,0.132,0,0.372,0.18,0.048,5.114,101,1028,1
加载SpamBase数据集,使用逗号切分,并且转换成数值型:
x=[] y=[] with open(filename) as f: for line in f: line=line.strip('\n') v=line.split(',') y.append(int(v[-1])) t=[] for i in range(57): t.append(float(v[i])) t=np.array(t) x.append(t) x=np.array(x) y=np.array(y)
随机划分数据集为训练集和测试集,其中测试集占40%:
x_train, x_test, y_train, y_test=train_test_split( x,y, test_size=0.4, random_state=0) return x_train, x_test, y_train, y_test
2.训练
训练与验证过程如图15-14所示。
使用朴素贝叶斯算法进行训练:
gnb = GaussianNB() y_predict = gnb.fit(x_train, y_train).predict(x_test)
图15-14 SpamBase垃圾邮件训练与验证过程
3.验证
使用测试数据集进行分类,得到分类结果y_predict,将y_predict与训练测试集的标记y_test进行比对,得到测试结果:
score = metrics.accuracy_score(y_test, y_predict) print('Accuracy: {0:f}'.format(score))
测试结果准确率约为82%:
Accuracy: 0.826181