前言前文給大家說(shuō)了python機(jī)器學(xué)習(xí)的路徑,這光說(shuō)不練假把式,這次,羅羅攀就帶大家完成一個(gè)中文文本情感分析的機(jī)器學(xué)習(xí)項(xiàng)目,今天的流程如下: 數(shù)據(jù)情況和處理數(shù)據(jù)情況這里的數(shù)據(jù)為大眾點(diǎn)評(píng)上的評(píng)論數(shù)據(jù)(王樹(shù)義老師提供),主要就是評(píng)論文字和打分。我們首先讀入數(shù)據(jù),看下數(shù)據(jù)的情況: import numpy as np
import pandas as pd
data = pd.read_csv('data1.csv')
data.head
情感劃分對(duì)star字段看唯一值,打分有1,2,4,5。 中文文本情感分析屬于我們的分類(lèi)問(wèn)題(也就是消極和積極),這里是分?jǐn)?shù),那我們?cè)O(shè)計(jì)代碼,讓分?jǐn)?shù)小于3的為消極(0),大于3的就是積極(1)。 定義一個(gè)函數(shù),然后用apply方法,這樣就得到了一個(gè)新列(數(shù)據(jù)分析里的知識(shí)點(diǎn)) def make_label(star):
if star >3:
return1
else:
return0
data['sentiment']= data.star.apply(make_label)
工具包(snownlp)我們首先不用機(jī)器學(xué)習(xí)方法,我們用一個(gè)第三庫(kù)(snownlp),這個(gè)庫(kù)可以直接對(duì)文本進(jìn)行情感分析(記得安裝),使用方法也是很簡(jiǎn)單。返回的是積極性的概率。 from snownlp importSnowNLP
text1 ='這個(gè)東西不錯(cuò)'
text2 ='這個(gè)東西很垃圾'
s1 =SnowNLP(text1)
s2 =SnowNLP(text2)
print(s1.sentiments,s2.sentiments)
# result 0.8623218777387431 0.21406279508712744
這樣,我們就定義大于0.6,就是積極的,同樣的方法,就能得到結(jié)果。 def snow_result(comemnt):
s =SnowNLP(comemnt)
if s.sentiments >=0.6:
return1
else:
return0
data['snlp_result']= data.comment.apply(snow_result)
上面前五行的結(jié)果看上去很差(5個(gè)就2個(gè)是對(duì)的),那到底有多少是對(duì)的了?我們可以將結(jié)果與sentiment字段對(duì)比,相等的我就計(jì)數(shù),這樣在除以總樣本,就能看大概的精度了。 counts =0
for i in range(len(data)):
if data.iloc[i,2]== data.iloc[i,3]:
counts+=1
print(counts/len(data))
# result 0.763
樸素貝葉斯前面利用第三庫(kù)的方法,結(jié)果不是特別理想(0.763),而且這種方法存在一個(gè)很大的弊端:針對(duì)性差。 什么意思了?我們都知道,不同場(chǎng)景下,語(yǔ)言表達(dá)都是不同的,例如這個(gè)在商品評(píng)價(jià)中有用,在博客評(píng)論中可能就不適用了。 所以,我們需要針對(duì)這個(gè)場(chǎng)景,訓(xùn)練自己的模型。本文將使用sklearn實(shí)現(xiàn)樸素貝葉斯模型(原理在后文中講解)。slearn小抄先送上(下文有高清下載地址)。 大概流程為: 導(dǎo)入數(shù)據(jù) 切分?jǐn)?shù)據(jù) 數(shù)據(jù)預(yù)處理 訓(xùn)練模型 測(cè)試模型
jieba分詞首先,我們對(duì)評(píng)論數(shù)據(jù)分詞。為什么要分詞了?中文和英文不一樣,例如:i love python,就是通過(guò)空格來(lái)分詞的;我們中文不一樣,例如:我喜歡編程,我們要分成我/喜歡/編程(通過(guò)空格隔開(kāi)),這個(gè)主要是為了后面詞向量做準(zhǔn)備。 import jieba
def chinese_word_cut(mytext):
return' '.join(jieba.cut(mytext))
data['cut_comment']= data.comment.apply(chinese_word_cut)
劃分?jǐn)?shù)據(jù)集分類(lèi)問(wèn)題需要x(特征),和y(label)。這里分詞后的評(píng)論為x,情感為y。按8:2的比例切分為訓(xùn)練集和測(cè)試集。 X = data['cut_comment']
y = data.sentiment
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=22)
詞向量(數(shù)據(jù)處理)電腦是沒(méi)法識(shí)別文字的,只能識(shí)別數(shù)字。那文本怎么處理了,最簡(jiǎn)單的就是詞向量。什么是詞向量,我們通過(guò)一個(gè)案例來(lái)說(shuō)明下,下面是我們的文本: I love the dog
I hate the dog
簡(jiǎn)單的說(shuō),詞向量就是我們將整個(gè)文本出現(xiàn)的單詞一一排列,然后每行數(shù)據(jù)去映射到這些列上,出現(xiàn)的就是1,沒(méi)出現(xiàn)就是0,這樣,文本數(shù)據(jù)就轉(zhuǎn)換成了01稀疏矩陣(這也是上文中文分詞的原因,這樣一個(gè)詞就是一個(gè)列)。 好在,sklearn中直接有這樣的方法給我們使用。CountVectorizer方法常用的參數(shù): max_df:在超過(guò)這一比例的文檔中出現(xiàn)的關(guān)鍵詞(過(guò)于平凡),去除掉。 min_df:在低于這一數(shù)量的文檔中出現(xiàn)的關(guān)鍵詞(過(guò)于獨(dú)特),去除掉。 token_pattern:主要是通過(guò)正則處理掉數(shù)字和標(biāo)點(diǎn)符號(hào)。 stop_words:設(shè)置停用詞表,這樣的詞我們就不會(huì)統(tǒng)計(jì)出來(lái)(多半是虛擬詞,冠詞等等),需要列表結(jié)構(gòu),所以代碼中定義了一個(gè)函數(shù)來(lái)處理停用詞表。
from sklearn.feature_extraction.text importCountVectorizer
def get_custom_stopwords(stop_words_file):
with open(stop_words_file)as f:
stopwords = f.read
stopwords_list = stopwords.split('\n')
custom_stopwords_list =[i for i in stopwords_list]
return
stop_words_file ='哈工大停用詞表.txt'
stopwords = get_custom_stopwords(stop_words_file)
vect =CountVectorizer(max_df =0.8,
min_df =3,
token_pattern=u'(?u)\\b[^\\d\\W]\\w+\\b',
stop_words=frozenset(stopwords))
如果想看到底出來(lái)的是什么數(shù)據(jù),可通過(guò)下面代碼查看。 test = pd.DataFrame(vect.fit_transform(X_train).toarray, columns=vect.get_feature_names)
test.head
訓(xùn)練模型訓(xùn)練模型,很簡(jiǎn)單,用的是樸素貝葉斯算法,結(jié)果為0.899,比之前的snownlp好很多了。 from sklearn.naive_bayes importMultinomialNB
nb =MultinomialNB
X_train_vect = vect.fit_transform(X_train)
nb.fit(X_train_vect, y_train)
train_score = nb.score(X_train_vect, y_train)
print(train_score)
# result 0.899375
測(cè)試數(shù)據(jù)當(dāng)然,我們需要測(cè)試數(shù)據(jù)來(lái)驗(yàn)證精確度了,結(jié)果為0.8275,精度還是不錯(cuò)的。 X_test_vect = vect.transform(X_test)
print(nb.score(X_test_vect, y_test))
# result 0.8275
當(dāng)然,我們也可以將結(jié)果放到data數(shù)據(jù)中: X_vec = vect.transform(X)
nb_result = nb.predict(X_vec)
data['nb_result']= nb_result
樣本量少 模型沒(méi)調(diào)參 沒(méi)有交叉驗(yàn)證
代碼下載:https://github.com/panluoluo/crawler-analysis,下載完整數(shù)據(jù)和代碼。
|