5.11 程序示例--垃圾邮件检测-机器学习笔记-斯坦福吴恩达教授
程序示例–垃圾郵件檢測
郵件內(nèi)容的預(yù)處理
下面展示了一封常見的 email,郵件內(nèi)容包含了一個(gè) URL (http://www.rackspace.com/),一個(gè)郵箱地址(groupname-unsubscribe@egroups.com),若干數(shù)字,美元符號(hào)等:
Anyone knows how much it costs to host a web portal ?Well, it depends on how many visitors youre expecting. This can be anywhere from less than 10 bucks a month to a couple of $100. You should checkout http://www.rackspace.com/ or perhaps Amazon EC2 if youre running something big..To unsubscribe yourself from this mailing list, send an email to: groupname-unsubscribe@egroups.com許多其他郵件可能也包含了這些信息,因此,在對郵件內(nèi)容的預(yù)處理階段,就是要 “標(biāo)準(zhǔn)化” 這些參數(shù)。例如,我們需要將所有的 URL鏈接都替換為 httpaddr,這能讓垃圾郵件分類器在獲得決策邊界時(shí)不受限于某個(gè)具體的 URL。標(biāo)準(zhǔn)化的手段能顯著提升分類器的性能,這是因?yàn)?#xff0c;垃圾郵件通常會(huì)隨機(jī)產(chǎn)生 URL,因此,在新的垃圾郵件中,發(fā)現(xiàn)之前見過的 URL 的可能性是不高的。
在預(yù)處理郵件內(nèi)容階段,我們將完成如下內(nèi)容:
- 轉(zhuǎn)換內(nèi)容為小寫:郵件的所有單詞都會(huì)被轉(zhuǎn)化為小寫。
- 去除 HTML 標(biāo)簽:
- 標(biāo)準(zhǔn)化 URL:將所有的 URL 鏈接替換為 httpaddr。
- 標(biāo)準(zhǔn)化郵箱地址:將所有的郵箱地址替換為 emailaddr。
- 標(biāo)準(zhǔn)化所有的數(shù)字:將所有的數(shù)字替換為 number。
- 標(biāo)準(zhǔn)化所有的美元符號(hào):將所有的美元符號(hào) $ 替換為 dollar。
- 詞干提取(Word-Stemming):例如,我們會(huì)將 “discount”、“discounts”、“discounted” 及 “discounting” 都替換為 “discount”。
- 刪去非單詞字符:將空格、tab、換行符等刪去。
上述郵件經(jīng)過預(yù)處理后,內(nèi)容如下:
anyon know how much it cost to host a web portal well it depend on how mani visitor your expect thi can be anywher from less than number buck a month to a coupl of dollarnumb you should checkout httpaddr or perhap amazon ecnumb if your run someth big to unsubscrib yourself from thi mail list send an email to emailaddr接下來,我們需要確定用于垃圾郵件分類器的單詞,亦即,需要構(gòu)建一個(gè)用于垃圾郵件分類器的詞匯列表。在本例中,將選擇在垃圾郵件語料庫(spam corpus)中,出現(xiàn)至少 100 次的單詞。這么做的原因是,如果選擇將出現(xiàn)寥寥的單詞放到訓(xùn)練樣本中,可能就會(huì)造成模型的過擬合。最終完整的詞匯列表存入了文件 vocab.txt 中,當(dāng)中含有共計(jì) 1899 個(gè)單詞:
1 aa 2 ab 3 abil ... 86 anyon ... 916 know ... 1898 zero 1899 zip在生產(chǎn)環(huán)境中,詞匯列表的規(guī)模在 10,000 到 50,000 個(gè)單詞之間。
有了詞匯表之后,我們現(xiàn)在就能將預(yù)處理后的郵件映射為一個(gè)坐標(biāo)集,每個(gè)坐標(biāo)反映了郵件中單詞在詞匯表的位置:
86 916 794 1077 883 370 1699 790 1822 1831 883 431 1171 794 1002 1893 1364 592 1676 238 162 89 688 945 1663 1120 1062 1699 375 1162 479 1893 1510 799 1182 1237 810 1895 1440 1547 181 1699 1758 1896 688 1676 992 961 1477 71 530 1699 531特別地,“anyone” 被標(biāo)準(zhǔn)化了詞匯表的第86個(gè)單詞 “anyon”。
預(yù)處理的代碼片如下,我們用到了函數(shù)式編程庫 pydash 以及詞干提取庫 stemming:
# coding: utf8 # svm/spam.py# ... def processEmail(email):"""預(yù)處理郵件Args:email 郵件內(nèi)容Returns:indices 單詞在詞表中的位置"""# 轉(zhuǎn)換為小寫 --> 標(biāo)準(zhǔn)化 URL --> 標(biāo)準(zhǔn)化 郵箱地址# --> 去除 HTML 標(biāo)簽 --> 標(biāo)準(zhǔn)化數(shù)字# --> 標(biāo)準(zhǔn)化美元 --> 刪除非空格字符return py_(email) \.strip_tags() \.reg_exp_replace(r'(http|https)://[^\s]*', 'httpaddr') \.reg_exp_replace(r'[^\s]+@[^\s]+', 'emailaddr') \.reg_exp_replace(r'\d+', 'number') \.reg_exp_replace(r'[$]+', 'dollar') \.lower_case() \.trim() \.words() \.map(stem) \.map(lambda word : py_.index_of(vocabList, word) + 1) \.value()郵件特征提取
我們定義特征 x(i)x^{(i)}x(i) 為:
x(i)={1,如果詞匯表的第i個(gè)單詞出現(xiàn)0,otherwisex^{(i)}=\begin{cases}1,\quad\quad 如果詞匯表的第\ i\ 個(gè)單詞出現(xiàn)\\ 0,\quad\quad otherwise\end{cases}x(i)={1,如果詞匯表的第?i?個(gè)單詞出現(xiàn)0,otherwise?
則知, x∈Rnx∈\R^nx∈Rn , nnn 為詞匯表長度。
特征提取的代碼同樣封裝到了項(xiàng)目的 svm/spam.py中:
# coding: utf8 # svm/spam.py# .... def extractFeatures(indices):"""提取特征Args:indices 單詞索引Returns:feature 郵件特征"""feature = py_.map(range(1, len(vocabList) + 1),lambda index: py_.index_of(indices, index) > -1)return np.array(feature, dtype=np.uint)Top Predictors
在 SVM 訓(xùn)練后獲得的模型中,權(quán)值向量 www 評估了每個(gè)特征的重要性,對應(yīng)到詞匯表的坐標(biāo)中,我們也就知道了那些詞匯最能分辨垃圾郵件,這些詞匯稱為 Top Predictors。
# coding: utf8 # svm/spam.py# .... def getTopPredictors(weights, count):"""獲得最佳標(biāo)識(shí)詞匯Args:weights 權(quán)值count top countReturns:predictors predicators"""return py_(vocabList) \.map(lambda word, idx: (word, weights[idx])) \.sort_by(lambda item: item[1], reverse = True) \.take(count) \.value()測試
下面,我們會(huì)使用 sklearn 提供的 SVM 模型進(jìn)行訓(xùn)練以加快訓(xùn)練效率,它是基于 libsvm 的,有不錯(cuò)的運(yùn)算性能:
# coding: utf8 # svm/test_spam.py import spam import numpy as np from scipy.io import loadmat from sklearn.svm import SVC import matplotlib.pyplot as plt# 垃圾郵件分類器 data = loadmat('data/spamTrain.mat') X = np.mat(data['X']) y = data['y'] m, n = X.shape C = 0.1 tol = 1e-3# 使用訓(xùn)練集訓(xùn)練分類器 clf = SVC(C=C, kernel='linear', tol=tol) clf.fit(X, y.ravel()) predictions = np.mat([clf.predict(X[i, :]) for i in range(m)]) accuracy = 100 * np.mean(predictions == y) print 'Training set accuracy: %0.2f %%' % accuracy# 使用測試集評估訓(xùn)練結(jié)果 data = loadmat('data/spamTest.mat') XTest = np.mat(data['Xtest']) yTest = data['ytest'] mTest, _ = XTest.shapeclf.fit(XTest, yTest.ravel()) print 'Evaluating the trained Linear SVM on a test set ...' predictions = np.mat([clf.predict(XTest[i, :]) for i in range(mTest)]) accuracy = 100 * np.mean(predictions == yTest) print 'Test set accuracy: %0.2f %%' % accuracy# 獲得最能標(biāo)識(shí)垃圾郵件的詞匯(在模型中獲得高權(quán)值的) weights = abs(clf.coef_.flatten()) top = 15 predictors = spam.getTopPredictors(weights, top) print 'Top %d predictors of spam:'%top for word, weight in predictors:print '%-15s (%f)' % (word, weight)# 使用郵件測試 def genExample(f):email = open(f).read()indices = spam.processEmail(email)features = spam.extractFeatures(indices)return featuresfiles = ['data/emailSample1.txt','data/emailSample1.txt','data/spamSample1.txt','data/spamSample2.txt' ]emails = np.mat([genExample(f) for f in files], dtype=np.uint8) labels = np.array([[0, 0, 1, 1]]).reshape(-1, 1) predictions = np.mat([clf.predict(emails[i, :]) for i in range(len(files))]) accuracy = 100 * np.mean(predictions == labels) print('Test set accuracy for own datasets: %0.2f %%' % accuracy)測試結(jié)果為:
Training set accuracy: 99.83 % Test set accuracy: 99.90 %Top 15 predictors of spam: click (0.477352) url (0.332529) date (0.316182) wrote (0.282825) spamassassin (0.266681) remov (0.250697) there (0.248973) numbertnumb (0.240243) the (0.238051) pleas (0.235655) our (0.233895) do (0.226717) basenumb (0.218456) we (0.218421) free (0.214057)Test set accuracy for own datasets: 100.00 %總結(jié)
以上是生活随笔為你收集整理的5.11 程序示例--垃圾邮件检测-机器学习笔记-斯坦福吴恩达教授的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 5.10 程序示例--模型选择-机器学习
- 下一篇: 6.1 无监督学习-机器学习笔记-斯坦福