功能:
对评论短语,比如一个文章下的评论短语进行分类通过或者删除,也就是是垃圾 、不是垃圾。
工具:
Spyder,jieba分词,numpy,joblib,sklearn
程序:
# -*- coding: utf-8 -*-"""
Created on Mon May 14 10:12:38 2018
@author: Administrator
"""
import codecs
import jieba
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import CountVectorizer,TfidfVectorizer
import numpy as np
from sklearn.externals import joblib
import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve, auc
"""
CountVectorizer:
只考虑词汇在文本中出现的频率
验证文件并计算令牌的出现次数并将其作为稀疏矩阵返回
TfidfVectorizer:
除了考量某词汇在文本出现的频率,还关注包含这个词汇的所有文本的数量
能够削减高频没有意义的词汇出现带来的影响, 挖掘更有意义的特征
相比之下,文本条目越多,Tfid的效果会越显著
将术语频率逆序文档频率归一化为发生次数的稀疏矩阵。
"""
#获取停用词表
stop_words = "E:/Python/data/totalstop.txt"
stopwords = codecs.open(stop_words,'rb',encoding='utf-8').readlines()
stopwords = [ w.strip() for w in stopwords ]
train_data_path="E:/Python/data/四万.txt"
test_data_path="E:/Python/data/两万.txt"
model_save_path="E:/Python/model/NB/NB_model.m"
#获取数据
def get_data(path):
data=[]
target=[]
fileIn = codecs.open(path,'rb',encoding='utf-8')
for line in fileIn.readlines():
lineArr = line.strip().split()
target.append(int(lineArr[0].encode('utf-8').decode('utf-8-sig')))
data.append(lineArr[1])
target=np.array(target)
return data,target
#去掉停用词
def del_stopwords(data_get):
data=[]
for word in data_get:
n=0
word_cut = [words for words in jieba.cut(word)]
result=""
for cut_word in word_cut:
if cut_word not in stopwords:
result+=cut_word
n+=1
if(n<len(word_cut)):
result+=" "
data.append(result)
return data
#训练模型
def train_NN(data,target):
clf=Pipeline([('vect',TfidfVectorizer()),('clf',MultinomialNB(alpha=0.001)),])#alpha参数,也叫平滑参数,其默认值为1.0
clf.fit(data,target)
#joblib.dump(clf,model_save_path)
return clf
#测试模型
"""
TP: 将正类预测为正类数
FN: 将正类预测为负类数
FP: 将负类预测为正类数
TN: 将负类预测为负类数
查准率TP/(TP+FP)查准率关心的是”预测出正例的正确率”即从正反例子中挑选出正例的问题。
查全率TP/(TP+FN)查全率关心的是”预测出正例的保证性”即从正例中挑选出正例的问题。
"""
def test(data,target,clf):
n=0
TP=0
TN=0
FP=0
FN=0
sore_list=[]
for word in data:
sore_list.append(clf.predict_proba([word])[0][1])###结果为1的得分
label=clf.predict([word]) #预测结果
if(label==1 and target[n]==1):
TP+=1
elif(label==0 and target[n]==0):
TN+=1
elif(label==1 and target[n]==0):
FP+=1
else:
FN+=1
n+=1
print("data:",word)
print("label:",label)
ccuracy = (TP+TN)/(TP+FN+FP+TN)
precision = TP/(TP+FP)
recall = TP/(TP+FN)
F1=2*precision*recall/(precision+recall)
print("F1:",F1)
print("准确率:",ccuracy)
print("查准率:",precision)
print("召回率:",recall)
return sore_list
train_data,train_target=get_data(train_data_path)
train_data=del_stopwords(train_data)
#获取测试数据并去除停用词
test_data,test_target=get_data(test_data_path)
test_data=del_stopwords(test_data)
#测试
clf=train_NN(train_data,train_target)
sore_list=test(test_data,test_target,clf)
data=np.append([sore_list],[test_target],axis=0).T#把得分和原始labe 组合在一起
data=data[np.lexsort(-data[:,::-1].T)]### 把得分系数按从大到小排序
sore=data[:,0]
label=data[:,1]
false_positive_rate, true_positive_rate, thresholds = roc_curve(label, sore)
roc_auc = auc(false_positive_rate, true_positive_rate)
plt.title('ROC')
plt.plot(false_positive_rate, true_positive_rate, 'b',
label='AUC = %0.2f'% roc_auc)
plt.legend(loc='lower right')
plt.plot([0,1],[0,1],'r--')
plt.xlim([-0.1,1])
plt.ylim([0,1.1])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()
"""
调用模型进行测试
test_data,test_target=get_data(test_data_path)
test_data=del_stopwords(test_data)
clf = joblib.load("E:/Python/model/NB/NB_model.m")
test(test_data,test_target,clf)
"""
结果:
解释:
我的训练数据是四万条,是txt模式保存在本地。
类别分为0,1, 0是删除,1是通过。
测试数据是2万条,同样格式保存在本地。
数据获取之后 去掉停用词。
模型训练完毕之后保存在本地,下次可以直接调用模型。
alpha数值默认为1,但是经过调试 发现设置为0.001准确率最高,但是再小的话 准确率不会提高。
其余说明见文中说明。