Python有趣|中文文本情感分析

前言

前文給大家說了python機器學習的路徑,這光說不練假把式,這次,羅羅攀就帶大家完成一個中文文本情感分析的機器學習項目,今天的流程如下:

數據情況和處理

數據情況

這里的數據為大眾點評上的評論數據(王樹義老師提供),主要就是評論文字和打分。我們首先讀入數據,看下數據的情況:

import numpy as np
import pandas as pd
data = pd.read_csv('data1.csv')
data.head()
情感劃分

對star字段看唯一值,打分有1,2,4,5。

中文文本情感分析屬于我們的分類問題(也就是消極和積極),這里是分數,那我們設計代碼,讓分數小于3的為消極(0),大于3的就是積極(1)。

定義一個函數,然后用apply方法,這樣就得到了一個新列(數據分析里的知識點)

def make_label(star):
    if star > 3:
        return 1
    else:
        return 0
    
data['sentiment'] = data.star.apply(make_label)

工具包(snownlp)

我們首先不用機器學習方法,我們用一個第三庫(snownlp),這個庫可以直接對文本進行情感分析(記得安裝),使用方法也是很簡單。返回的是積極性的概率。

from snownlp import SnowNLP

text1 = '這個東西不錯'
text2 = '這個東西很垃圾'

s1 = SnowNLP(text1)
s2 = SnowNLP(text2)

print(s1.sentiments,s2.sentiments)
# result 0.8623218777387431 0.21406279508712744

這樣,我們就定義大于0.6,就是積極的,同樣的方法,就能得到結果。

def snow_result(comemnt):
    s = SnowNLP(comemnt)
    if s.sentiments >= 0.6:
        return 1
    else:
        return 0
    
data['snlp_result'] = data.comment.apply(snow_result)

上面前五行的結果看上去很差(5個就2個是對的),那到底有多少是對的了?我們可以將結果與sentiment字段對比,相等的我就計數,這樣在除以總樣本,就能看大概的精度了。

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

樸素貝葉斯

前面利用第三庫的方法,結果不是特別理想(0.763),而且這種方法存在一個很大的弊端:針對性差。

什么意思了?我們都知道,不同場景下,語言表達都是不同的,例如這個在商品評價中有用,在博客評論中可能就不適用了。

所以,我們需要針對這個場景,訓練自己的模型。本文將使用sklearn實現樸素貝葉斯模型(原理在后文中講解)。slearn小抄先送上(下文有高清下載地址)。

大概流程為:

  • 導入數據
  • 切分數據
  • 數據預處理
  • 訓練模型
  • 測試模型
jieba分詞

首先,我們對評論數據分詞。為什么要分詞了?中文和英文不一樣,例如:i love python,就是通過空格來分詞的;我們中文不一樣,例如:我喜歡編程,我們要分成我/喜歡/編程(通過空格隔開),這個主要是為了后面詞向量做準備。

import jieba

def chinese_word_cut(mytext):
    return " ".join(jieba.cut(mytext))

data['cut_comment'] = data.comment.apply(chinese_word_cut)
劃分數據集

分類問題需要x(特征),和y(label)。這里分詞后的評論為x,情感為y。按8:2的比例切分為訓練集和測試集。

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)
詞向量(數據處理)

電腦是沒法識別文字的,只能識別數字。那文本怎么處理了,最簡單的就是詞向量。什么是詞向量,我們通過一個案例來說明下,下面是我們的文本:

I love the dog
I hate the dog 

詞向量處理后就是這樣的:

簡單的說,詞向量就是我們將整個文本出現的單詞一一排列,然后每行數據去映射到這些列上,出現的就是1,沒出現就是0,這樣,文本數據就轉換成了01稀疏矩陣(這也是上文中文分詞的原因,這樣一個詞就是一個列)。

好在,sklearn中直接有這樣的方法給我們使用。CountVectorizer方法常用的參數:

  • max_df:在超過這一比例的文檔中出現的關鍵詞(過于平凡),去除掉。
  • min_df:在低于這一數量的文檔中出現的關鍵詞(過于獨特),去除掉。
  • token_pattern:主要是通過正則處理掉數字和標點符號。
  • stop_words:設置停用詞表,這樣的詞我們就不會統計出來(多半是虛擬詞,冠詞等等),需要列表結構,所以代碼中定義了一個函數來處理停用詞表。
from sklearn.feature_extraction.text import CountVectorizer

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 custom_stopwords_list

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))

如果想看到底出來的是什么數據,可通過下面代碼查看。

test = pd.DataFrame(vect.fit_transform(X_train).toarray(), columns=vect.get_feature_names())
test.head()
訓練模型

訓練模型,很簡單,用的是樸素貝葉斯算法,結果為0.899,比之前的snownlp好很多了。

from sklearn.naive_bayes import MultinomialNB
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
測試數據

當然,我們需要測試數據來驗證精確度了,結果為0.8275,精度還是不錯的。

X_test_vect = vect.transform(X_test)
print(nb.score(X_test_vect, y_test))

# result 0.8275

當然,我們也可以將結果放到data數據中:

X_vec = vect.transform(X)
nb_result = nb.predict(X_vec)
data['nb_result'] = nb_result
討論和不足
  • 樣本量少
  • 模型沒調參
  • 沒有交叉驗證
今日互動

代碼下載:https://github.com/panluoluo/crawler-analysis,下載完整數據和代碼。

留言打卡:說說評論杠精那些事。公眾號后臺回復【打卡】,加入打卡學習群,2019年一起搞事情。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 對,我就是這個姐姐。一個喜歡被依賴的姐姐。說真的,故事不知道從哪里講起,這里沒有戀愛故事里那么多催人淚下的苦情,也...
    南柱赫女朋友閱讀 666評論 1 1
  • 昨晚的邏輯思維羅胖舉辦的號稱“史上第二大讀書會”,從整個形式上看,徹頭徹尾的是一次營銷活動,推銷員換成了大咖而已。
    snow_kuma閱讀 295評論 0 0