情感分析也稱為意見挖掘,是自然語言處理(NLP)中的一個領域,它試圖在文本中識別和提取意見。
情感分析有很多的應用場景,例如社交媒體監控、品牌監控、客戶之聲、客戶服務、員工分析、產品分析、市場研究與分析等等。
實現情感分析的方法有很多,大體上分為兩大類,第一類為基於詞典規則的方法,第二類為基於機器學習的方法。
基於詞典的方法主要通過制定一系列的情感詞典和規則,對文本進行拆句、分析及匹配詞典(一般有詞性分析,句法依存分析),計算情感值,最後通過情感值來作為文本的情感傾向判斷的依據。
基於詞典的情感分析大致步驟如下:
如果是對篇章或者段落級別的情感分析任務,按照具體的情況,可以以對每個句子進行單一情感分析並融合的形式進行,也可以先抽取情感主題句後進行句子情感分析,得到最終情感分析結果。
機器學習的方法是將情感分析作為一個有監督的分類問題。對於情感極性的判斷,將目標情感分為三類:正、中、負。對訓練文本進行人工標注,然後進行有監督的機器學習過程,並對測試數據用模型來預測結果。
基於機器學習的情感分析大致步驟如下:
首先進行文本預處理。文本的預處理過程是使用機器學習作用於文本分類的基礎操作。由於文本是非結構化數據及其特殊性,計算機並不能直接理解,所以需要一系列的預處理操作後,轉換為計算機可以處理的結構化數據。在實際分析中,文本更為復雜,書寫規范也更為隨意,且很有可能摻雜部分噪聲數據。整體上來說,文本預處理模塊包括去噪、特征提取、文本結構化表示等。
中文最小語素是字,但是往往詞語才具有更明確的語義信息,但是隨著分詞,可能出現詞語關系丟失的情況。n-元文法正好解決了這個問題,它也是傳統機器學習分類任務中最常用的方法。
對抽取出來的特征,向量化是一個很重要的過程,是實現由人可以理解的文本轉換為計算機可以處理數據的重要一步。這一步最常用到的就是詞袋模型(bag-of-words )以及最近新出的連續分布詞向量模型(word Embedding)。詞袋模型長度為整個詞表的長度,詞語對應維度置為詞頻,文檔的表示往往比較稀疏且維度較高。Embedding 的表示方式,能夠有效的解決數據稀疏且降維到固定維度,更好的表示語義信息。對於文檔表示,詞袋模型可以直接疊加,而 Embedding 的方法可以使用深度學習的方法,通過 pooling 得到最終表示。
在機器學習分類算法的使用過程中,特征好壞直接影響機器的准確率及召回率。選擇有利於分類的特征,可以有效的減少訓練開支及防止模型過擬合,尤其是數據量較大的情況下,這一部分工作的重要性更加明顯。其選擇方法為,將所有的訓練語料輸入,通過一定的方法,選擇最有效的特征,主要的方法有卡方,信息熵,dp 深層感知器等等。
目前也有一些方法,從比句子粒度更細的層次去識別情感,如基於方面的情感分析(Aspect based Sentiment Analysis),他們從產品的評價屬性等更細粒度的方面對評價主體進行情感傾向性分析。
文本轉換為機器可處理的結構後,接下來便要選擇進行機器學習的分類算法。目前,使用率比較高的是深度學習(CNN,RNN)和支持向量機(SVM)。深度學習的方法,運算量大,准確率有一定的提高,所以都在做這方面的嘗試。而支持向量機則是比較傳統的方法,其准確率及數據處理能力也比較出色,很多人都在用它來做分類任務。
本次實驗的任務如下:
設計和實現分類系統,完成對文本的情感分類任務,這裡包含三種情感:中性,積極和消極。程序語言、框架、學習方法不限,可使用外部語料,不可使用已有的情感分析或文本分類庫。
由於不能使用現有的詞典,考慮到僅僅用現有的 8606 條樣例可能無法搭建出一個精准度較高的詞典,如果使用基於詞典的方法可能准確率不盡如人意。同時,基於詞典的方法的召回率一般而言會比較低。因此,我優先准備使用機器學習的方法,將情感分析當作一個有監督的三分類問題。分類算法方面,我是用支持向量機(SVM),主要是因為 SVM 分類速度比較快,也比較容易實現,而且准確率也有一定的保證。(還因為不會 LSTM)
實驗使用機器學習方法,其中分詞工具使用 jieba 分詞,使用 sklearn 中的 TfidfVectorizer 來進行詞組向量化,使用 sklearn 中的 MultinomialNB 來進行標簽分類。
代碼說明如下:
def read_json(path):
= open(path, 'rb')
return json.load(f)
該函數用於讀取 JSON 類型的數據,采用二進制讀入,避免了由於中文產生的問題。
def analyzes(text):
該函數用於處理讀入的數據,首先進行分詞操作,如果數據帶標簽,那麼就給分好的詞附帶標簽,以便之後進行分類。具體核心實現如下:
for line in text:
= re.sub('[’@!,.:;\'\"#!?。:;、]+', '', line['content'])
words.append(' '.join(jieba.lcut(t, cut_all=True)))
讀入的數據是一個字典,鍵分別為‘id’、‘content’、‘label’,其中‘content’索引到的內容為具體的評論內容。對於每一條評論,去除評論中的標點符號以及特殊字符,然後使用 jieba 分詞工具進行分詞。分詞後的單詞用空格分隔。
if len(line) == 2:
continue
如果是不帶標簽的數據,那麼僅進行分詞就結束
if line['label'] == 'positive':
labels.append(1)
elif line['label'] == 'neutral':
labels.append(0)
elif line['label'] == 'negative':
labels.append(2)
如果是帶標簽的數據,那麼對其附加標簽。其中,積極賦予 1,中性賦予 0,消極賦予 2。
def train_model(path):
該函數用於訓練分類器。核心實現如下:
text = read_json(path)
words, labels = analyzes(text)
讀入數據,進行標簽分類。
tf = TfidfVectorizer()
x_train = tf.fit_transform(words).toarray()
將分詞過的句子進行向量化,作為貝葉斯分類器的 X 向量
y_train = labels
Y 向量為詞語的情感標簽
mt = MultinomialNB(alpha=0.1)
mt.fit(x_train, y_train)
return tf, mt
訓練分類器,並將分類器返回。
主函數如下:
tf, mt = train_model('train_data.json')
訓練分類器
test_text = read_json('test.json')
test_words = analyzes(test_text)
處理待分類的數據
x_test = tf.transform(test_words).toarray()
predict = mt.predict(x_test)
使用分類器對待分類的數據進行情感分析
ans = []
for i in range(len(predict)):
ans.append([i + 1, int(predict[i])])
= open('1180300315-周牧雲.csv', 'w', encoding='utf-8', newline='')
csv_writer = csv.writer(f)
csv_writer.writerows(ans)
close()
將答案寫入 CSV 中
print("finish")