如何用50行代碼構建情感分類器

Submitted by huzhenda on Sun, 07/15/2018 - 11:58

情感分析背后的動機?

人類自己無法理解語言是如何被大腦處理的。那么,我們能教一臺機器學習我們的語言嗎?通過廣泛研究,人們已經開發了許多方法來幫助機器理解語言。自然語言處理(NLP)是研究人類語言與計算機交互的領域。自然語言處理的一個子問題是情感分析,即把一個語句分類為積極或消極。把語句分類為積極或消極有什么用呢?以亞馬遜網站為例。在亞馬遜上,用戶可以對一個產品發表評論,說明它是好是壞,甚至可以是中性的。然而,使用人工閱讀所有評論并獲得客戶對產品的總體反饋既昂貴又耗時。再說說我們的機器學習模型。機器學習模型可以通過大量數據進行推斷,對評論進行分類。利用這種機器學習模型,亞馬遜可以通過客戶評論改進其產品,從而為公司帶來更多收入。

情感分析并不像看起來那么簡單。如果你認為含有「好的」、「很棒」等詞的評論可歸為積極評論,而含有「壞的」、「苦惱的」等詞的評論可歸為消極評論,那你需要三思。例如,「完全沒有好味道」和「一份好的快餐,但沒有什么特別的」分別代表消極和中立的反饋,即使都有「好」字。因此,這項任務可能沒有看起來那么簡單。接下來讓我們看看即將使用的數據。

數據集

我們將使用亞馬遜產品評論、IMDB 電影評論和 Yelp 評論來構建情感分析模型。

數據下載鏈接:https://www.kaggle.com/marklvl/sentiment-labelled-sentences-data-set/data

所有數據都已經過注釋,0 表示消極反饋,1 表示積極反饋。亞馬遜的數據與下圖相似。

5.1

代碼

我們可以寫一些代碼:

with open("/Users/rohith/Documents/Datasets/sentiment_labelled_sentences/amazon_cells_labelled.txt") as f1:
? ? lines = f1.readlines()

with open("/Users/rohith/Documents/Datasets/sentiment_labelled_sentences/imdb_labelled.txt") as f1:
? ? temp = f1.readlines()
? ? lines=lines+temp

with open("/Users/rohith/Documents/Datasets/sentiment_labelled_sentences/yelp_labelled.txt") as f1:
? ? temp = f1.readlines()
? ? lines=lines+temp

數據存儲于不同的文本文件中。我們打開每個文件并閱讀所有的文本行,文本行還包括每個文本的標簽。然后我們將其存儲在一個名為「lines」的列表中。

x = []
y = []
for value in lines:
? ? temp = value.split('\t')
? ? x.append(temp[0])
? ? temp[1].replace('\n','')
? ? y.append(int(temp[1]))

數據集的每一行都包含文本,文本后是四個字符空間,還有該文本的標簽(0 或 1)。因此,我們先將包含文本的第一部分添加到 features(x) 中,然后獲取標簽,標簽的末尾有「\n」。所以標簽被移除,然后添加到我們的標簽列表 labels(y)。

from keras.preprocessing.text import Tokenizer

tokenizer = Tokenizer(num_words=2500,split=' ')
tokenizer.fit_on_texts(x)

Keras 有一個內置的 API,使得準備計算文本變得更容易。tokenizer 類共有 4 個屬性,可用于特征準備。請看下面的示例,了解 tokenizer 的實際功能。

## CODE
tokenizer = Tokenizer()
texts = ["The sun is shining in June!","September is grey.","Life is beautiful in August.","I like it","This and other things?"]
tokenizer.fit_on_texts(texts)
print(tokenizer.word_index)
tokenizer.texts_to_sequences(["June is beautiful and I like it!"])
## OUPUT
{'sun': 3, 'september': 4, 'june': 5, 'other': 6, 'the': 7, 'and': 8, 'like': 9, 'in': 2, 'beautiful': 11, 'grey': 12, 'life': 17, 'it': 16, 'i': 14, 'is': 1, 'august': 15, 'things': 10, 'shining': 13, 'this': 18}
[[5, 1, 11, 8, 14, 9, 16]]

tokenizer 為句子中的每個單詞分配索引值,并且可以使用該索引值表示新句子。由于我們使用的文本語料庫包含大量不同的單詞,因此我們設置了一個上限,只使用最經常出現的 2500 個單詞。

from keras.preprocessing.sequence import pad_sequences

X = tokenizer.texts_to_sequences(x)
X = pad_sequences(X)

現在,我們將文本轉換為如上所示的數字序列,并填充數字序列。因為句子可以有不同的長度,它們的序列長度也會不同。因此,pad_sequences 會找出最長的句子,并用 0 填充其他較短語句以匹配該長度。

## Pad Sequences Example
pad_sequences([[1, 2, 3], [3, 4, 5, 6], [7, 8]])
array([[0, 1, 2, 3],
? ? ? ?[3, 4, 5, 6],
? ? ? ?[0, 0, 7, 8]], dtype=int32)

import numpy as np?
from sklearn.model_selection import train_test_split
?

Y = []
for val in y:
? ? if(val == 0):
? ? ? ? Y.append([1,0])
? ? else:
? ? ? ? Y.append([0,1])
Y = np.array(Y)

x_train, x_test, y_train, y_test = train_test_split(X,Y,train_size=0.8)

我們將標簽轉換為 one hot 編碼,這有助于 LSTM 網絡預測文本的標簽?,F在,我們已經準備好了文本數據,可以把它分為訓練樣本和測試樣本。將 80% 的數據用于訓練,20% 的數據用于測試模型。

import keras?
from keras.layers import Embedding, LSTM, Dense
from keras.models import Sequential

model = Sequential()
model.add(Embedding(2500,128,input_length=X.shape[1],dropout=0.2))
model.add(LSTM(300, dropout_U=0.2,dropout_W=0.2))
model.add(Dense(2,activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,optimizer='adam',metrics=['accuracy'])

model.fit(x_train,y_train,epochs=10,verbose=2,batch_size=32)

print(model.evaluate(x_test,y_test)[1])

我們現在建立了模型,并對其進行編譯、訓練和測試。該模型具有嵌入層。輸入序列是文本的稀疏表征,因為詞匯表巨大,并且給定單詞將由大向量表示。如果我們能夠構建序列的某種密集表征,那么網絡將更容易進行預測。2500 個單詞的詞嵌入/密集表征是通過嵌入層對模型進行訓練獲得的。然后,我們將 LSTM 和密集層添加到模型中。LSTM 單元負責進行上下文推斷,并幫助預測句子是否積極。密集層輸出每個類的概率。本文不詳細介紹 LSTM,若想了解其更多信息,請參閱此博客:http://colah.github.io/posts/2015-08-Understanding-LSTMs/。

5.2

訓練

5.3

測試

完成!你剛剛用 50 行代碼構建了一個情感分類器~?

(原文鏈接:https://towardsdatascience.com/sentiment-analysis-through-lstms-3d6f9506805c)

(翻譯:機器之心)

冯仰妍破处门