利用sklearn 樸素貝葉斯進行評論短語的分類
阿新 • • 發佈:2018-10-31
功能:
對評論短語,比如一個文章下的評論短語進行分類通過或者刪除,也就是是垃圾 、不是垃圾。
工具:
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準確率最高,但是再小的話 準確率不會提高。
其餘說明見文中說明。