【人工智能项目】机器学习中文垃圾邮件分类任务

本次采用机器学习模型对中文邮件是否为垃圾邮件进行判别。那么工友们,学起来吧!!!

任务说明
0,商业秘密的秘密性那是维系其商业价值和垄断地位的前提条件之一
1,南口阿玛施新春第一批限量春装到店啦 春暖花开淑女裙、冰蓝色公主衫 气质粉小西装、冰丝女王长半裙、 皇
0,带给我们大常州一场壮观的视觉盛宴
0,有原因不明的泌尿系统结石等
0,23年从盐城拉回来的麻麻的嫁妆
0,感到自减肥、跳减肥健美操、
1,感谢致电杭州萧山全金釜韩国烧烤店,本店位于金城路xxx号。韩式烧烤等,价格实惠、欢迎惠顾【全金釜韩国烧烤店】
0,这款UVe智能杀菌机器人是扫地机的最佳伴侣
最前面表示标签,0代表是正常短信,1代表垃圾短信。
可以看出邮件分类的最大问题在于语意的理解。对中英文数字夹杂的语句进行分词,去除无意义的词汇,生成语意明确的等长词向量显得尤为重要。在词向量的特征提取过程中也可以采用TF-IDF等方式,来权衡每个词的相对重要性。
导包
import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
import warnings
warnings.filterwarnings("ignore")
数据初步处理
数据集读取
原始数据短信数据共有7w多条数据,在这一步需要读取txt文档,并分割出label和text。
import os
import pandas as pd
sms_data_path = "."
sms_data = pd.read_csv(os.path.join(sms_data_path,"message.txt"),encoding="utf-8",header=None,sep = '\t',names=["label","text"])
sms_data.head()

sms_data.shape
(754843, 2)
统计垃圾邮件和非垃圾邮件的数量
# 统计垃圾和非垃圾邮件的数量
sms_data["label"].value_counts()

# 以图方式表示
sns.countplot(sms_data["label"])
plt.xlabel("Label")
plt.title("Number of ham of spam messages")

数据集划分
在模型训练前首先需要将数据集进行分割,这里将数据取出后进行一定比例的随机分割,分成训练集数据和测试集数据。
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(sms_data["text"][:6000],sms_data["label"][:6000],test_size=0.2,random_state=2019)
print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)
(4800,)
(4800,)
(1200,)
(1200,)
文本特征读取
文本特征介绍
文本特征提取
- 将文本数据转换成特征向量的过程
- 比较常用的文本特征表示法为词袋法
词袋法:
- 不考虑词语出现的顺序,每个出现过的词汇单独作为一列特征
- 这些不重复的特征词汇集合为词表
- 每一个文本都可以在很长的词表上统计出一个很多列的特征向量
- 如果每个文本都出现的词汇,一般被标记为停用词 不计入特征向量
主要有两个api来实现CounterVectorizer和TfidfVectorizer
CountVectorizer:
- 只考虑词汇在文本中出现的频率
TfidfVectorizer:
- 除了考量某词汇在文本出现的频率,还关注包含这个词汇的所有文本的数量
- 能够消减高频没有意义的词汇出现带来的影响,挖掘更有意义的特征。
TFIDF
from sklearn.feature_extraction.text import CountVectorizer,TfidfVectorizer
import pickle
# tfidf向量保存
# tfidf = TfidfVectorizer()
tfidftransformer_path = './tfidftransformer.pkl'
tfidf = pickle.load(open(tfidftransformer_path,"rb"))
# x_train_df = tfidf.fit_transform(x_train)
x_train_df = tfidf.transform(x_train)
# tfidf向量保存
# tfidftransformer_path = './tfidftransformer.pkl'
# with open(tfidftransformer_path, 'wb') as fw:
# pickle.dump(tfidf, fw)
x_test_df = tfidf.transform(x_test)
print(type(x_train_df))
print(x_train_df.shape)
print(tfidf.get_feature_names()[:1000])

朴素贝叶斯模型
寻参
from sklearn.model_selection import GridSearchCV
from sklearn.naive_bayes import MultinomialNB
param_grid = {
"alpha":np.concatenate(
[
np.arange(0.0001,0.001,0.0001),
np.arange(0.001,0.01,0.001),
np.arange(0.01,0.1,0.01),
np.arange(0.1,1,0.1),
np.arange(1,10,1),
np.arange(10,100,5)
]
)
}
model = MultinomialNB()
grid_cv_model = GridSearchCV(model,param_grid,n_jobs=-1,verbose=3,cv=3)
grid_cv_model.fit(x_train_df,y_train)

#对指标评价
print("{}{}".format("Best Estimator: ",grid_cv_model.best_estimator_))
print("{}{}".format("Besr Params: ",grid_cv_model.best_params_))
print("{}{}".format("Bset Scores: ",grid_cv_model.best_score_))

贝叶斯模型建立以及训练
建立贝叶斯模型
NB_model = MultinomialNB(alpha=0.1, class_prior=None, fit_prior=True)
贝叶斯模型训练
NB_model.fit(x_train_df,y_train)
贝叶斯模型保存
from sklearn.externals import joblib
joblib.dump(NB_model, "nb_model.m")
贝叶斯模型预测
prediction = dict()
prediction["MultinomialNB"] = NB_model.predict(x_test_df)
贝叶斯模型评估
from sklearn.metrics import accuracy_score,f1_score,confusion_matrix,classification_report
print(classification_report(y_test,prediction["MultinomialNB"],target_names=["Ham","Spam"]))

-
TP(True Positive):被正确分类的正样本
-
FP(False Positive):被错误分类的正样本
-
TN(True Negative):被正确分类的负样本
-
FN(False Negative):被错误分类的负样本
-
Precision精度;Recall召回率
-
Precision = TP/(TP+FP)即分类器认为是正类且确实是正类的部分占分类器认为是正类的比例
-
Recall = TP/(TP+FN)即分类器认为是正类且确实是正类站所有确实是正类的比例。
# 混淆矩阵
def plot_confusion_matrix(y_test,y_pred,title=""):
conf_mat=confusion_matrix(y_test,y_pred)
conf_mat_normalized=conf_mat.astype("float")/conf_mat.sum(axis=1)[:,np.newaxis]
figsize=(22,5)
ticksize=18
titlesize=ticksize+8
labelsize=ticksize+5
xlabel="Predicted label"
ylabel="True label"
params={"figure.figsize":figsize,
"axes.labelsize":labelsize,
"axes.titlesize":titlesize,
"xtick.labelsize":ticksize,
"ytick.labelsize":ticksize}
plt.rcParams.update(params)
plt.subplot(121)
sns.heatmap(conf_mat,annot=True)
plt.title(title)
plt.xlabel(xlabel)
plt.ylabel(ylabel)
plt.subplot(122)
sns.heatmap(conf_mat_normalized,annot=True)
plt.title(title)
plt.xlabel(xlabel)
plt.ylabel(ylabel)
plt.show()
print("Confusion Matrix:\n")
print(conf_mat)
print("\n\nConfusion Matrix Normalized:\n")
print(conf_mat_normalized)
plot_confusion_matrix(y_test,prediction["MultinomialNB"],title="MultinomialNB")

x_test[y_test<prediction["MultinomialNB"]]

x_test[y_test>prediction["MultinomialNB"]]

其它的机器学习算法
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.naive_bayes import MultinomialNB
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import AdaBoostClassifier,RandomForestClassifier,BaggingClassifier,ExtraTreesClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score,f1_score,confusion_matrix,classification_report
from sklearn.externals import joblib
models = {
"KNeighborsClassifier":KNeighborsClassifier(),
"LogisticRegression":LogisticRegression(),
"DecisionTreeClassifier":DecisionTreeClassifier(),
"RandomForestClassifier":RandomForestClassifier(),
"ExtraTreesClassifier":ExtraTreesClassifier()
}
prediction = dict()
score_map = {}
for model_name in models:
print(model_name)
model = models[model_name]
print("training..")
model.fit(x_train_df,y_train)
print("saving...")
joblib.dump(model,model_name+".m")
print("predicting...")
prediction[model_name]=model.predict(x_test_df)
score=accuracy_score(y_test,prediction[model_name])
score_map[model_name]=score
print(score)

预测
# 带预测的文本
predict_text = "商业秘密的秘密性那是维系其商业价值和垄断地位的前提条件之一"
predict_text = [predict_text]
# 加载tfidf向量
import pickle
tfidftransformer_path = './tfidftransformer.pkl'
tfidf = pickle.load(open(tfidftransformer_path,"rb"))
# 文本特征提取
predict_vector = tfidf.transform(predict_text)
# 加载贝叶斯算法
from sklearn.externals import joblib
model = joblib.load("nb_model.m")
# 预测
predict_score = model.predict(predict_vector)
predict_proba = model.predict_proba(predict_vector)
predict_proba
array([[0.97234983, 0.02765017]])
predict_proba[0][predict_score]
array([0.97234983])
predict_score
array([0], dtype=int64)
if predict_score == 0:
print("这条短信是正常短信!")
elif predict_score == 1:
print("这条短信是垃圾短信!")
这条短信是正常短信!
小结
那么本次任务就到此结束了,回头见!!!

6532



被折叠的 条评论
为什么被折叠?



