當前位置:
首頁 > 科技 > 深度學習在情感分析中的應用

深度學習在情感分析中的應用

本文選自圖書《Keras快速上手:基於Python的深度學習實戰》第七章。

自然語言情感分析簡介

情感分析無處不在,它是一種基於自然語言處理的分類技術。其主要解決的問題是給定一段話,判斷這段話是正面的還是負面的。例如在亞馬遜網站或者推特網站中,人們會發表評論,談論某個商品、事件或人物。商家可以利用情感分析工具知道用戶對自己的產品的使用體驗和評價。當需要大規模的情感分析時,肉眼的處理能力就變得十分有限了。

情感分析的本質就是根據已知的文字和情感符號,推測文字是正面的還是負面的。處理好了情感分析,可以大大提升人們對於事物的理解效率,也可以利用情感分析的結論為其他人或事物服務,比如不少基金公司利用人們對於某家公司、某個行業、某件事情的看法態度來預測未來股票的漲跌。

進行情感分析有如下難點:

第一,文字非結構化,有長有短,很難適合經典的機器學習分類模型。

第二,特徵不容易提取。文字可能是談論這個主題的,也可能是談論人物、商品或事件的。人工提取特徵耗費的精力太大,效果也不好。

第三,詞與詞之間有聯繫,把這部分信息納入模型中也不容易。

本章探討深度學習在情感分析中的應用。深度學習適合做文字處理和語義理解,是因為深度學習結構靈活,其底層利用詞嵌入技術可以避免文字長短不均帶來的處理困難。使用深度學習抽象特徵,可以避免大量人工提取特徵的工作。深度學習可以模擬詞與詞之間的聯繫,有局部特徵抽象化和記憶功能。正是這幾個優勢,使得深度學習在情感分析,乃至文本分析理解中發揮著舉足輕重的作用。

首先下載http://ai.stanford.edu/~amaas/data/sentiment/中的數據。

輸入下文安裝必要的軟體包:

pip install numpy scipy

pip install scikit-learn

pip install pillow

pip install h5py

下面處理數據。Keras 自帶了imdb 的數據和調取數據的函數,直接調用load.data()就可以了。

import kerasimport numpy as npfrom keras.datasets import imdb

(X_train, y_train), (X_test, y_test) = imdb.load_data()

先看一看數據長什麼樣子的。輸入命令:

X_train[0]

我們可以看到結果:

原來,Keras 自帶的load_data 函數幫我們從亞馬遜S3 中下載了數據,並且給每個詞標註了一個索引(index),創建了字典。每段文字的每個詞對應了一個數字。

print(y[:10])

得到array([1, 0, 0, 1, 0, 0, 1, 0, 1, 0]),可見y 就是標註,1 表示正面,0 表示負面。

print(X_train.shape)print(y_train.shape)

我們得到的兩個張量的維度都為(25000,)。

接下來可以看一看平均每個評論有多少個字:

avg_len = list(map(len, X_train))print(np.mean(avg_len))

可以看到平均字長為238.714。

為了直觀顯示,這裡畫一個分布圖(見圖7.1):

import matplotlib.pyplot as plt

plt.hist(avg_len, bins = range(min(avg_len), max(avg_len) + 50, 50))

plt.show()

注意,如果遇到其他類型的數據,或者自己有數據,那麼就得自己寫一套處理數據的腳本。大致步驟如下。

圖7.1 詞頻分布直方圖

第一,文字分詞。英語分詞可以按照空格分詞,中文分詞可以參考jieba。

第二,建立字典,給每個詞標號。

第三,把段落按字典翻譯成數字,變成一個array。

接下來就開始建模了。

文字情感分析建模

詞嵌入技術

為了克服文字長短不均和將詞與詞之間的聯繫納入模型中的困難,人們使用了一種技術——詞嵌入。簡單說來,就是給每個詞賦一個向量,向量代表空間里的點,含義接近的詞,其向量也接近,這樣對於詞的操作就可以轉化為對於向量的操作了,在深度學習中,這被叫作張量(tensor)。

用張量表示詞的好處在於:

第一,可以克服文字長短不均的問題,因為如果每個詞已經有對應的詞向量,那麼對於長度為N 的文本,只要選取對應的N 個詞所代表的向量並按文本中詞的先後順序排在一起,就是輸入張量了,其中每個詞向量的維度都是一樣的。

第二,詞本身無法形成特徵,但是張量就是抽象的量化,它是通過多層神經網路的層層抽象計算出來的。

第三,文本是由片語成的,文本的特徵可以由詞的張量組合。文本的張量蘊含了多個詞之間的組合含義,這可以被認為是文本的特徵工程,進而為機器學習文本分類提供基礎。

詞的嵌入最經典的作品是Word2Vec,可以參見:https://code.google.com/archive/p/word2vec/。通過對具有數十億詞的新聞文章進行訓練,Google 提供了一組詞向量的結果,可以從http://word2vec.googlecode.com/svn/trunk/獲取。其主要思想依然是把詞表示成向量的形式,而不是One Hot 編碼。圖7.2展示了這個模型裡面詞與詞的關係。

圖7.2 詞向量示意圖(圖片來源:https://deeplearning4j.org/word2vec)

多層全連接神經網路訓練情感分析

不同於已經訓練好的詞向量,Keras 提供了設計嵌入層(Embedding Layer)的模板。只要在建模的時候加一行Embedding Layer 函數的代碼就可以。注意,嵌入層一般是需要通過數據學習的,讀者也可以借用已經訓練好的嵌入層比如Word2Vec 中預訓練好的詞向量直接放入模型,或者把預訓練好的詞向量作為嵌入層初始值,進行再訓練。

Embedding 函數定義了嵌入層的框架,其一般有3 個變數:字典的長度(即文本中有多少詞向量)、詞向量的維度和每個文本輸入的長度。注意,前文提到過每個文本可長可短,所以可以採用Padding 技術取最長的文本長度作為文本的輸入長度,而不足長度的都用空格填滿,即把空格當成一個特殊字元處理。空格本身一般也會被賦予詞向量,這可以通過機器學習訓練出來。Keras 提供了sequence.pad_sequences 函數幫我們做文本的處理和填充工作。

先把代碼進行整理:

(X_train, y_train), (X_test, y_test) = imdb.load_data()

使用下面的命令計算最長的文本長度:

m = max(list(map(len, X_train)), list(map(len, X_test)))

print(m)

從中我們會發現有一個文本特別長,居然有2494 個字元。這種異常值需要排除,考慮到文本的平均長度為230 個字元,可以設定最多輸入的文本長度為400 個字元,不足400 個字元的文本用空格填充,超過400 個字元的文本截取400 個字元,Keras 默認截取後400 個字元。

maxword = 400X_train = sequence.pad_sequences(X_train, maxlen = maxword)

X_test = sequence.pad_sequences(X_test, maxlen = maxword)

vocab_size = np.max([np.max(X_train[i]) for i in range(X_train.shape[0])]) + 1

這裡1 代表空格,其索引被認為是0。

下面先從最簡單的多層神經網路開始嘗試:

首先建立序列模型,逐步往上搭建網路。

model = Sequential()

model.add(Embedding(vocab_size, 64, input_length = maxword))

第一層是嵌入層,定義了嵌入層的矩陣為vocab_size 64。每個訓練段落為其中的maxword 64 矩陣,作為數據的輸入,填入輸入層。

model.add(Flatten())

把輸入層壓平,原來是maxword × 64 的矩陣,現在變成一維的長度為maxword × 64的向量。

接下來不斷搭建全連接神經網路,使用relu 函數。relu 是簡單的非線性函數:f(x) =max(0; x)。注意到神經網路的本質是把輸入進行非線性變換。

model.add(Dense(2000, activation = relu ))

model.add(Dense(500, activation = relu ))

model.add(Dense(200, activation = relu ))

model.add(Dense(50, activation = relu ))

model.add(Dense(1, activation = sigmoid ))

這裡最後一層用Sigmoid,預測0,1 變數的概率,類似於logistic regression 的鏈接函數,目的是把線性變成非線性,並把目標值控制在0~1。因此這裡計算的是最後輸出的是0 或者1 的概率。

model.compile(loss = binary_crossentropy , optimizer = adam , metrics = [ accuracy ])2 print(model.summary())

這裡有幾個概念要提一下:交叉熵(Cross Entropy)和Adam Optimizer。

交叉熵主要是衡量預測的0,1 概率分布和實際的0,1 值是不是匹配,交叉熵越小,說明匹配得越準確,模型精度越高。

其具體形式為

這裡把交叉熵作為目標函數。我們的目的是選擇合適的模型,使這個目標函數在未知數據集上的平均值越低越好。所以,我們要看的是模型在測試數據(訓練時需要被屏蔽)上的表現。

Adam Optimizer 是一種優化辦法,目的是在模型訓練中使用的梯度下降方法中,合理地動態選擇學習速度(Learning Rate),也就是每步梯度下降的幅度。直觀地說,如果在訓練中損失函數接近最小值了,則每步梯度下降幅度自然需要減小,而如果損失函數的曲線還很陡,則下降幅度可以稍大一些。從優化的角度講,深度學習網路還有其他一些梯度下降優化方法,比如Adagrad 等。它們的本質都是解決在調整神經網路模型過程中如何控制學習速度的問題。

Keras 提供的建模API 讓我們既能訓練數據,又能在驗證數據時看到模型測試效果。

model.fit(X_train, y_train, validation_data = (X_test, y_test), epochs = 20,batch_size = 100, verbose = 1)

score = model.evaluate(X_test, y_test)

其精確度大約在85%。如果多做幾次迭代,則精確度會更高。讀者可以試著嘗試一下多跑幾個循環。

以上提到的是最常用的多層全連接神經網路模型。它假設模型中的所有上一層和下一層是互相連接的,是最廣泛的模型。

卷積神經網路訓練情感分析

全連接神經網路幾乎對網路模型沒有任何限制,但缺點是過度擬合,即擬合了過多雜訊。全連接神經網路模型的特點是靈活、參數多。在實際應用中,我們可能會對模型加上一些限制,使其適合數據的特點。並且由於模型的限制,其參數會大幅減少。這降低了模型的複雜度,模型的普適性進而會提高。

接下來我們介紹卷積神經網路(CNN)在自然語言的典型應用。

在自然語言領域,卷積的作用在於利用文字的局部特徵。一個詞的前後幾個詞必然和這個詞本身相關,這組成該詞所代表的詞群。詞群進而會對段落文字的意思進行影響,決定這個段落到底是正向的還是負向的。對比傳統方法,利用詞包(Bag of Words),和TF-IDF 等,其思想有相通之處。但最大的不同點在於,傳統方法是人為構造用於分類的特徵,而深度學習中的卷積讓神經網路去構造特徵。

以上便是卷積在自然語言處理中有著廣泛應用的原因。

接下來介紹如何利用Keras 搭建卷積神經網路來處理情感分析的分類問題。下面的代碼構造了卷積神經網路的結構。

from keras.layers import Dense, Dropout, Activation, Flattenfrom keras.layers import Conv1D, MaxPooling1D

model = Sequential()

model.add(Embedding(vocab_size, 64, input_length = maxword))

model.add(Conv1D(filters = 64, kernel_size = 3, padding = same , activation= relu ))

model.add(MaxPooling1D(pool_size = 2))

model.add(Dropout(0.25))

model.add(Conv1D(filters = 128, kernel_size = 3, padding = same ,activation= relu ))

model.add(MaxPooling1D(pool_size = 2))

model.add(Dropout(0.25))

model.add(Flatten())

model.add(Dense(64, activation = relu ))

model.add(Dense(32, activation = relu ))

model.add(Dense(1, activation = sigmoid ))

model.compile(loss = binary_crossentropy , optimizer = rmsprop , metrics =[ accuracy ])

print(model.summary())

下面對模型進行擬合。

model.fit(X_train, y_train, validation_data = (X_test, y_test), epochs = 20,batch_size = 100)

scores = model.evaluate(X_test, y_test, verbose = 1)print(scores)

精確度提高了一點,在85.5% 左右。讀者可以試著調整模型的參數,增加訓練次數等,或者使用其他的優化方法。這裡還要提一句,代碼里用了一個Dropout 的技巧,大致意思是在每個批量訓練過程中,對每個節點,不論是在輸入層還是隱藏層,都有獨立的概率讓節點變成0。這樣的好處在於,每次批量訓練相當於在不同的小神經網路中進行計算,當訓練數據大的時候,每個節點的權重都會被調整過多次。

另外,在每次訓練的時候,系統會努力在有限的節點和小神經網路中找到最佳的權重,這樣可以最大化地找到重要特徵,避免過度擬合。這就是為什麼Dropout 會得到廣泛的應用。

循環神經網路訓練情感分析

下面介紹如何用長短記憶模型(LSTM)處理情感分類。

LSTM 是循環神經網路的一種。本質上,它按照時間順序,把信息進行有效的整合和篩選,有的信息得到保留,有的信息被丟棄。在時間t,你獲得到的信息(比如對段落文字的理解)理所應當會包含之前的信息(之前提到的事件、人物等)。LSTM 說,根據我手裡的訓練數據,我得找出一個方法來如何進行有效的信息取捨,從而把最有價值的信息保留到最後。那麼最自然的想法是總結出一個規律用來處理前一時刻的信息。

由於遞歸性,在處理前一個時刻信息時,會考慮到再之前的信息,所以到時間t 時,所有從時間點1 到現在的信息都或多或少地被保留一部分,也會被丟棄一部分。LSTM 對信息的處理主要通過矩陣的乘積運算來實現的(見圖7.3)。

圖7.3 長短記憶神經網路示意圖(圖片來源:http://colah.github.io/posts/2015-08-Understanding-LSTMs/)

構造LSTM 神經網路的結構可以使用如下的代碼。

from keras.layers import LSTM

model = Sequential()

model.add(Embedding(vocab_size, 64, input_length = maxword))

model.add(LSTM(128, return_sequences=True))

model.add(Dropout(0.2))

model.add(LSTM(64, return_sequences=True))

model.add(Dropout(0.2))

model.add(LSTM(32))

model.add(Dropout(0.2))

model.add(Dense(1, activation = sigmoid ))

然後把模型打包。

model.compile(loss = binary_crossentropy , optimizer = rmsprop , metrics =[ accuracy ])print(model.summary())

最後輸入數據集訓練模型。

model.fit(X_train, y_train, validation_data = (X_test, y_test), epochs = 5,batch_size = 100)

scores = model.evaluate(X_test, y_test)

print(scores)

預測的精確度大致為86.7%,讀者可以試著調試不同參數和增加循環次數,從而得到更好的效果。

總結

本文介紹了不同種類的神經網路,有多層神經網路(MLP),卷積神經網路(CNN)和長短記憶模型(LSTM)。它們的共同點是有很多參數,需要通過後向傳播來更新參數。

CNN 和LSTM 作為神經網路的不同類型的模型,需要的參數相對較少,這也反映了它們的一個共性:參數共享。這和傳統的機器學習原理很類似:對參數或者模型加的限制越多,模型的自由度越小,越不容易過度擬合。反過來,模型參數越多,模型越靈活,越容易擬合雜訊,從而對預測造成負面影響。通常,我們通過交叉驗證技術選取最優參數(比如,幾層模型、每層節點數、Dropout 概率等)。

最後需要說明的是,情感分析本質是一個分類問題,是監督學習的一種。除了上述模型,讀者也可以試試其他經典機器學習模型,比如SVM、隨機森林、邏輯回歸等,並和神經網路模型進行比較。


點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 CSDN 的精彩文章:

首席架構師:面向大數據的分散式調度
微API設計模式
5種Docker日誌最佳實踐
北京一工程師離職後刪僱主網站源代碼被判刑五年,究竟是誰的錯?
Docker、Kubernetes和Mesos:为什么你知道的可能都是错的?

TAG:CSDN |

您可能感興趣

就喜歡看綜述論文:情感分析中的深度學習
愛情中的大忌——過度情感需求
情感中的深情與豁達
深度解析渣男的情感世界
感情需要用情至深,但也需要情感的對等
情感夜讀·感情中最好的心態……
互動情感解壓閥 | 我的態度,我會盡情釋放
心理測試:哪個女孩用情至深,測在情感中你的本性有多痴情
談關係中的情感矛盾和壓力
情感|一個人的魅力在於他的精神深度。
在 Netflix 評論中做情感分析的深度學習模型
手相感情線透視你對待情感的態度及感情線短的人對待感情比較隨便
深度好文,美好的愛情,總在不知不覺中塑造了人生更好的情感
深度測試:解析你的優缺點和情感模式
婚戀情感中的情緒與關係
手相中感情線末端的分支,對婚姻情感的影響!
我們與學生——把握好教學中的情感交流
山水之中情感深厚 這些適合用於玄關掛畫
如何解決戀愛和婚姻中的情感倦怠?過來人分享了實用經驗
淺談語音情感識別技術在互金質檢領域的應用