垃圾邮件分类实战(SVM)
生活随笔
收集整理的這篇文章主要介紹了
垃圾邮件分类实战(SVM)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1. 數據集說明
trec06c是一個公開的垃圾郵件語料庫,由國際文本檢索會議提供,分為英文數據集(trec06p)和中文數據集(trec06c),其中所含的郵件均來源于真實郵件保留了郵件的原有格式和內容,下載地址:https://plg.uwaterloo.ca/~gvcormac/treccorpus06/
由于數據集分散在各個文件中,為了方便我將正樣本和負樣本分別放在了ham_data和spam_data文件夾中(處女座的強迫癥)
正樣本數:21766
負樣本數:42854
中文停用詞:chinese_stop_vocab.txt
下面使用的所有數據集都已上傳github
2. 實現思路
- 去除所有非中文字符,如標點符號、英文字符、數字、網站鏈接等特殊字符
- 對郵件內容進行分詞處理
- 過濾停用詞
- feature_maxtrix:shape=(samples, feature_word_nums)
- leabel; shape = (samples, 1)
- 詞向量的選擇:索引或word2vect,注意二者的區別
拆分數據集:訓練數據集、測試數據集和驗證數據集
選擇模型,這里選擇svm
訓練、測試、調參
3. 具體實現過程
3.1 所用到的庫
import os import jieba import pandas as pd import numpy as np from sklearn.feature_extraction.text import CountVectorizer from sklearn.model_selection import RandomizedSearchCV,train_test_split from sklearn.svm import LinearSVC from sklearn.metrics import accuracy_score from scipy.stats import uniform3.2 將郵件轉換為特征詞矩陣類
class EmailToWordFeatures:'''功能:將郵件轉換為特征詞矩陣整個過程包括:- 對郵件內容進行分詞處理- 去除所有非中文字符,如標點符號、英文字符、數字、網站鏈接等特殊字符- 過濾停用詞- 創建特征矩陣'''def __init__(self,stop_word_file=None,features_vocabulary=None):self.features_vocabulary = features_vocabularyself.stop_vocab_dict = {} # 初始化停用詞if stop_word_file is not None:self.stop_vocab_dict = self._get_stop_words(stop_word_file)def text_to_feature_matrix(self,words,vocabulary=None,threshold =10):cv = CountVectorizer()if vocabulary is None:cv.fit(words)else:cv.fit(vocabulary)words_to_vect = cv.transform(words)words_to_matrix = pd.DataFrame(words_to_vect.toarray()) # 轉換成索引矩陣print(words_to_matrix.shape)# 進行訓練特征詞選擇,給定一個閾值,當單個詞在所有郵件中出現的次數的在閾值范圍內時及選為訓練特征詞、selected_features = []selected_features_index = []for key,value in cv.vocabulary_.items():if words_to_matrix[value].sum() >= threshold: # 詞在每封郵件中出現的次數與閾值進行比較selected_features.append(key)selected_features_index.append(value)words_to_matrix.rename(columns=dict(zip(selected_features_index,selected_features)),inplace=True)return words_to_matrix[selected_features]def get_email_words(self,email_path, max_email = 600):'''由于機器配置問題,作為測試給定閾值600,及正負樣本數各位600'''self.emails = email_pathif os.path.isdir(self.emails):emails = os.listdir(self.emails)is_dir = Trueelse:emails = [self.emails,]is_dir = Falsecount = 0all_email_words = []for email in emails:if count >= max_email: # 給定讀取email數量的閾值breakif is_dir:email_path = os.path.join(self.emails,email)email_words = self._email_to_words(email_path)all_email_words.append(' '.join(email_words))count += 1return all_email_wordsdef _email_to_words(self, email):'''將郵件進行分詞處理,去除所有非中文和停用詞retrun:words_list''' email_words = []with open(email, 'rb') as pf:for line in pf.readlines():line = line.strip().decode('gbk','ignore')if not self._check_contain_chinese(line): # 判斷是否是中文continueword_list = jieba.cut(line, cut_all=False) # 進行分詞處理for word in word_list:if word in self.stop_vocab_dict or not self._check_contain_chinese(word):continue # 判斷是否為停用詞email_words.append(word)return email_wordsdef _get_stop_words(self,file):'''獲取停用詞'''stop_vocab_dict = {}with open(file,'rb') as pf:for line in pf.readlines():line = line.decode('utf-8','ignore').strip()stop_vocab_dict[line] = 1return stop_vocab_dictdef _check_contain_chinese(self,check_str):'''判斷郵件中的字符是否有中文'''for ch in check_str:if u'\u4e00' <= ch <= u'\u9fff':return Truereturn False3.3 將正負郵件數據集轉換為詞特征列表,每項為一封郵件
index_file= '.\\datasets\\trec06c\\full\\index' stop_word_file = '.\\datasets\\trec06c\\chinese_stop_vocab.txt' ham_file = '.\\datasets\\trec06c\\ham_data' spam_file = '.\\datasets\\trec06c\\spam_data' email_to_features = EmailToWordFeatures(stop_word_file=stop_word_file) ham_words = email_to_features.get_email_words(ham_file) spam_words = email_to_features.get_email_words(spam_file) print('ham email numbers:',len(ham_words)) print('spam email numbers:',len(spam_words)) ham email numbers: 600 spam email numbers: 6003.4 將所有郵件轉換為特征詞矩陣,及模型輸入數據
all_email = [] all_email.extend(ham_words) all_email.extend(spam_words) print('all test email numbers:',len(all_email)) words_to_matrix = email_to_features.text_to_feature_matrix(all_email) print(words_to_matrix) all test email numbers: 1200 (1200, 22556)故事 領導 回到 兒子 感情 有個 大概 民俗 出國 教育 ... 培訓網 商友會 網管 埃森哲 驅鼠器 條例 \ 0 1 2 1 1 1 1 1 1 1 1 ... 0 0 0 0 0 0 1 0 0 0 0 5 0 0 0 0 0 ... 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 ... .. .. .. .. .. .. .. .. .. .. ... ... ... .. ... ... .. 1195 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 1196 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 1197 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 1198 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 1199 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 智囊 教練 含雙早 王府井 0 0 0 0 0 1 0 0 0 0 2 0 0 0 0 3 0 0 0 0 4 0 0 0 0 ... .. .. ... ... 1195 0 0 0 0 1196 0 0 0 0 1197 0 0 0 0 1198 0 0 0 0 1199 0 0 0 0 [1200 rows x 3099 columns]3.5 獲取標簽矩陣
label_matrix = np.zeros((len(all_email),1)) label_matrix[0:len(ham_words),:] = 14. 使用svm模型進行訓練
# 拆分數據集 x_train,x_test,y_train,y_test = train_test_split(words_to_matrix,label_matrix,test_size=0.2,random_state=42)# 使用LinearSVC模型進行訓練 svc = LinearSVC(loss='hinge',dual=True) param_distributions = {'C':uniform(0,10)} rscv_clf =RandomizedSearchCV(estimator=svc, param_distributions=param_distributions,cv=3,n_iter=200,verbose=2) rscv_clf.fit(x_train,y_train) print('best_params:',rscv_clf.best_params_) Fitting 3 folds for each of 200 candidates, totalling 600 fits [CV] C=6.119041659192192 ............................................. [CV] .............................. C=6.119041659192192, total= 0.0s [CV] C=6.119041659192192 ............................................. [CV] .............................. C=6.119041659192192, total= 0.1s [CV] C=6.119041659192192 ............................................. [CV] .............................. C=6.119041659192192, total= 0.1s [CV] C=6.103402593686549 ............................................. ... ... ... [CV] .............................. C=4.395657632563425, total= 0.2s best_params: {'C': 0.0279898379592336} # 使用測試數據集進行測試 y_prab = rscv_clf.predict(x_test) print('accuracy:',accuracy_score(y_prab,y_test)) accuracy: 0.97916666666666665. 分別選擇一封正式郵件和垃圾郵件進行
正式郵件內容如下:
- 很久以前,我為了考人大,申請了他的ID,而現在卻不對外開放了。
申請水木的ID,真的是不知道出于什么緣故。離開校園尋找一份校園的感覺,懷著對清華的向往,還是為了偶爾無聊工作的一些調劑……
我討厭多愁善感,卻時常沉浸于其中,生活中的挫折,不幸,讓我知道自己得堅強……
可每天的灰色心情卻揮之不去,我可以把自己的心事埋于深處,笑著對待我身邊的每一個人,告訴我樂觀。身邊最親的人,也許知道或不知道我的脆弱和恐懼。而唯一知道的人,告訴我“希望你堅不可摧”。
回想多年前,為“在靠近的地方住下,能掩耳不聽煩世喧囂,要一份干凈的自由自在”而感動,那,是否是對今天的預見,無知是快樂的,而不知道責任也是快樂的。我可以逃避一時,卻始終要面對。
垃圾郵件如下:
- 這是一封善意的郵件,如給你造成不便,請隨手刪除.SOHO建站代理網誠聘兼職網站代理
一、職業要求:
1、有上網條件(在家中、辦公室、網吧等地);
2、每天能有1-2小時上網時間;
3、有網絡應用的基礎(會上論壇發貼子、發電子郵件,
與客戶QQ溝通等)。
二、工作任務:
您報名加入我公司后,公司將分配給您一個屬
于自己的冠名為SOHO致富聯盟的網站,作為站長,您的任
務就是利用各種方法宣傳這個網站,讓客戶從你的網站上
購買更多的商品,并接受你的建議,也同意加盟SOHO建站
代理網網站的兼職代理,這樣你便擁有滾滾不斷的財源。
三、工資待遇:3000元以上/月。業績累積,收入直線上升.
附
6.1 改進計劃
將特征詞矩陣改word2vect
使用mxnet神經網絡模型進行訓練
6.2 數據集整理部分的代碼
# 將正樣本和負樣本分別放在了ham_data和spam_data文件夾中 index_file= '.\\datasets\\trec06c\\full\\index' data_file = '.\\datasets\\trec06c\\data'ham_file_list = [] spam_file_list = [] # 讀index文件 with open(index_file,'r') as pf:for line in pf.readlines():content = line.strip().split('..')label,path = contentpath = path.replace('/', '\\')if label == 'spam ':spam_file_list.append(path)else:ham_file_list.append(path)import os import shutil root = '.\\datasets\\trec06c\\' new_ham_root = '.\\datasets\\trec06c\\ham_data' new_spam_root = '.\\datasets\\trec06c\\spam_data' def copy_file(filelist,new_file_path): for file in filelist:file_name = file.split('\\')path = root + fileif not os.path.exists(new_file_path):os.makedirs(new_file_path)shutil.copyfile(path, new_file_path+'\\' + file_name[-2]+ '_' + file_name[-1])轉載于:https://www.cnblogs.com/xiaobingqianrui/p/11226427.html
總結
以上是生活随笔為你收集整理的垃圾邮件分类实战(SVM)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从生产故障解锁RocketMQ集群部署的
- 下一篇: 面试官:面对千万级、亿级流量怎么处理?