從代碼學(xué)AI ——情感分類(LSTM)

前言

本篇文章會從代碼的角度說明如何基于TFlearn使用LSTM進行文本的情感分類。如果對于TFLearn和LSTM都不熟悉死嗦,沒有關(guān)系,先硬著頭皮將代碼看下(使用LSTM對IMDB數(shù)據(jù)集進行情感分類)耕蝉。從代碼的角度看都是很簡潔的铐刘,所以即使不熟悉,多看看代碼镰惦,當(dāng)代碼已經(jīng)熟練于心了迷守,后面如果有一天你漠然回首理解了其中的不解后,你的記憶更加深刻旺入。所以不懂兑凿、不熟悉沒關(guān)系,堅持下去就回明白的茵瘾。

由于實例代碼使用的是IMDB數(shù)據(jù)集礼华,所以這里會優(yōu)先介紹 一下這個數(shù)據(jù)集。

IMDB數(shù)據(jù)集

該數(shù)據(jù)集包含了電影的評論以及評論對應(yīng)的情感分類的標(biāo)簽(0,1分類)拗秘。作者的初衷是希望該數(shù)據(jù)集會成為情緒分類的一個基準(zhǔn)圣絮。這里介紹該數(shù)據(jù)集如何生成的以及如何使用提供的文件。

核心數(shù)據(jù)集包含了5萬條評論數(shù)據(jù)雕旨,這些數(shù)據(jù)被均分成訓(xùn)練集和測試集(訓(xùn)練和測試集各2.5萬)扮匠。標(biāo)簽也是均衡分布的(正負樣本各2.5萬)。也提供了5萬條無標(biāo)簽數(shù)據(jù)奸腺,以用于無監(jiān)督學(xué)習(xí)餐禁。

在數(shù)據(jù)集中,每個電影最多收集30條評論突照,因為同一個電影的評論往往具有相關(guān)性帮非。同時訓(xùn)練集和測試集采集的是不同的電影,所以嘗試去記住和電影強相關(guān)的詞匯以及相關(guān)的標(biāo)簽是不會取得顯著的提升效果的讹蘑。

在訓(xùn)練和測試集中末盔,負面結(jié)果的分值<=4,正面結(jié)果的分值>=10.中性的評論沒有包含在測試和訓(xùn)練集合中。在無監(jiān)督的數(shù)據(jù)集中包含任意評分的評論座慰。

對于下載下來的數(shù)據(jù)集的文件結(jié)構(gòu)大致如下:

有兩個頂級文件夾[train/, test/],對應(yīng)訓(xùn)練集和測試集陨舱。每個都包含了[pos/, neg/]目錄宅广,在這些文件夾中掖举,評論數(shù)據(jù)以如下方式存儲:[[id]_[rating].txt]。這里id表示唯一性ID痹兜,rating表示評分,例如[test/pos/200_8.txt]表示正面評論益缎,id是200谜慌,評分是8分。
無監(jiān)督數(shù)據(jù)集中[train/unsup/]所有的評分都是0莺奔,因為所有的評分都被省略了欣范。

數(shù)據(jù)集中也包含了每個評論對應(yīng)電影的評論頁面的URL,由于電影的評論數(shù)據(jù)是動態(tài)變化的令哟,所以不能指定評論的URL恼琼,只能指定電影評論頁面的URL。評論文件在如下文件中:
[urls_[pos, neg, unsup].txt]

對于評論的數(shù)據(jù)文件屏富,數(shù)據(jù)集中已經(jīng)包含了訓(xùn)練好的詞袋模型(BoW).這些數(shù)據(jù)存儲在.feat文件中晴竞。

每個.feat文件都是LIBSVM格式,一種用于標(biāo)記數(shù)據(jù)的ascii的稀疏向量格式役听。
這些文件中的特征索引從0開始颓鲜,且特征索引對應(yīng)的詞匯對應(yīng)著[imdb.vocab]中相應(yīng)的詞匯。所以一個在.feat文件中以0:7的形式表示[imdb.vocab]中的第一個單詞,在該評論中出現(xiàn)7次

LIBSVM相關(guān)資料參見:LIBSVM

數(shù)據(jù)集中也包含了一個[imdbEr.txt]文件典予,這里存儲了[imdb.vocab]中每個詞的情感評分甜滨。預(yù)期評級是了解數(shù)據(jù)集中單詞的平均極性的好方法。

數(shù)據(jù)集介紹就到這里瘤袖,下面開始代碼解讀衣摩。

代碼解讀

# -*- coding: utf-8 -*-
"""

https://www.tensorflow.org/versions/master/programmers_guide/embedding

https://github.com/tflearn/tflearn/blob/master/tflearn/datasets/imdb.py

采用LSTM進行情感分類的實例,數(shù)據(jù)集采用IMDB數(shù)據(jù)集


LSTM論文鏈接:

    http://deeplearning.cs.cmu.edu/pdfs/Hochreiter97_lstm.pdf

IMDB數(shù)據(jù)集鏈接

    http://ai.stanford.edu/~amaas/data/sentiment/

"""

引入相關(guān)的模塊和方法

from __future__ import division, print_function, absolute_import

import tflearn
from tflearn.data_utils import to_categorical, pad_sequences
from tflearn.datasets import imdb

獲得測試和訓(xùn)練數(shù)據(jù)

# 導(dǎo)入IMDB的數(shù)據(jù)集,n_words表示構(gòu)建詞向量的時候捂敌,考慮最常用的10000個詞,valid_portion表示訓(xùn)練過程中采用1/10的數(shù)據(jù)進行驗證
# load_data的結(jié)果是train[0][0:]表示訓(xùn)練數(shù)據(jù),train[1][0:]表示對應(yīng)的標(biāo)簽艾扮,即train[0]是訓(xùn)練矩陣,train[1]是標(biāo)簽矩陣
train, test, _ = imdb.load_data(path='imdb.pkl', n_words=10000,valid_portion=0.1)
# 獲得訓(xùn)練集對應(yīng)的數(shù)據(jù)和標(biāo)簽
trainX, trainY = train
# 獲得測試集對應(yīng)的數(shù)據(jù)和標(biāo)簽
testX, testY = test

數(shù)據(jù)預(yù)處理

# 進行數(shù)據(jù)處理占婉,補充長度泡嘴,長度全為100,不足的0補位,每條訓(xùn)練數(shù)據(jù)都變成100位的向量
trainX = pad_sequences(trainX, maxlen=100, value=0.)
testX = pad_sequences(testX, maxlen=100, value=0.)
# 將數(shù)據(jù)的打標(biāo)轉(zhuǎn)化為向量 原來是0->[1,0],原來是1->[0,1]
trainY = to_categorical(trainY, nb_classes=2)
testY = to_categorical(testY, nb_classes=2)

網(wǎng)絡(luò)構(gòu)建

# 構(gòu)建網(wǎng)絡(luò)
# 1.先指定輸入數(shù)據(jù)數(shù)據(jù)量大小不指定逆济,和placeholder類似酌予,在運行時指定,每個向量100維  <tf.Tensor 'InputData/X:0' shape=(?, 100) dtype=float32>
net = tflearn.input_data([None, 100])
# 2.進行詞嵌套奖慌,相當(dāng)于將離散的變?yōu)檫B續(xù)的抛虫,輸入詞詞有10000個ID,每個ID對應(yīng)一個詞简僧,將每個詞變?yōu)橐粋€128維的向量
# <tf.Tensor 'Embedding/embedding_lookup:0' shape=(?, 100, 128) dtype=float32>

#Embedding可以將離散的輸入應(yīng)用于機器學(xué)習(xí)處理方法中建椰。傳統(tǒng)的分類器和神經(jīng)網(wǎng)絡(luò)一般來講更適合處理連續(xù)的向量,
#如果有些離散對象自然被編碼為離散的原子岛马,例如獨特的ID棉姐,它們不利于機器學(xué)習(xí)的使用和泛化屠列。
#可以理解embedding是將非矢量對象轉(zhuǎn)換為利于機器學(xué)習(xí)處理的輸入。
net = tflearn.embedding(net, input_dim=10000, output_dim=128)
# 3.LSTM伞矩,輸出<tf.Tensor 'LSTM/LSTM/cond_199/Merge:0' shape=(?, 128) dtype=float32>
net = tflearn.lstm(net, 128, dropout=0.8)
# 4.全連接層  輸出<tf.Tensor 'FullyConnected/Softmax:0' shape=(?, 2) dtype=float32>
# 就是將學(xué)到的特征表示映射到樣本標(biāo)記空間
net = tflearn.fully_connected(net, 2, activation='softmax')
# 5.回歸層 指定優(yōu)化方法脸哀、學(xué)習(xí)速率(步長)、以及損失函數(shù)
net = tflearn.regression(net, optimizer='adam', learning_rate=0.001,loss='categorical_crossentropy')

構(gòu)建模型并訓(xùn)練

# 構(gòu)建深度模型扭吁,tensorboard需要的日志文件存儲在/tmp/tflearn_logs中
model = tflearn.DNN(net, tensorboard_verbose=0)
# 訓(xùn)練模型,指定訓(xùn)練數(shù)據(jù)集盲镶、測試數(shù)據(jù)集
model.fit(trainX, trainY, validation_set=(testX, testY), show_metric=True,batch_size=32)

到這里整個代碼就結(jié)束了,這里有兩個地方需要說明一下侥袜,一個是embedding,一個是fully_connected溉贿,分別表示詞嵌套和全連接枫吧。這里對這兩部分簡要說下,不會進行詳盡的公式推導(dǎo)和闡釋宇色。

首先說說這里的embedding.

在注釋部分已經(jīng)注釋的比較明確了九杂,其目的就是將要表示的東西進行向量化表示。原來每個字用一個ID表示宣蠕,這樣能表示的信息太少了例隆,不能夠表達詞所在語料內(nèi)更多的意思,比如和那個詞更相近。通過詞嵌套將一個單一的ID表示為一個128緯度(此處是128)的向量抢蚀,能夠表達更多的意思镀层。詞嵌套是向量化的一個重要手段,這個技巧一定要掌握的皿曲。

再聊聊這里的fully_connected

全連接層(fully connected layers唱逢,F(xiàn)C),在整個神經(jīng)網(wǎng)絡(luò)中起到類似于“分類器”的作用屋休。如果說卷積層坞古、池化層和激活函數(shù)層等操作是將原始數(shù)據(jù)映射到隱層特征空間的話,那么全連接層則起到將學(xué)到的“分布式特征表示”映射到樣本標(biāo)記空間的作用劫樟。在代碼中tflearn.fully_connected(net, 2,activation='softmax')痪枫,這里的第二個參數(shù)2,表示的就是輸出神經(jīng)元的個數(shù)毅哗,即訓(xùn)練集中對應(yīng)的打標(biāo)的向量听怕,也就是說將學(xué)習(xí)到的分布式特征轉(zhuǎn)化為一個只包含兩個元素的向量。

全連接層的每一個結(jié)點都與上一層的所有結(jié)點相連虑绵,用來把前邊提取到的特征綜合起來尿瞭。由于其全相連的特性,一般全連接層的參數(shù)也是最多的翅睛。不負責(zé)任的講声搁,全連接層一般由兩部分組成黑竞,即線性部分和非線性部分。線性部分主要做線性轉(zhuǎn)換疏旨,輸入用X表示很魂,輸出用Z表示。

線性部分的運算方法基本上就是線性加權(quán)求和的感覺檐涝,如果對于一個輸入向量

x=[x_0,x_1,...x_n]^T遏匆,

線性部分的輸出向量是

z=[z_0,z_1,z_2,...z_m]^T,

那么線性部分的參數(shù)就可以想象一個m*n的矩陣W谁榜,再加上一個偏置項

b=[b_0,...b_m]^T

于是有:

W*x+b=z

對于非線性部分幅聘,那當(dāng)然是做非線性變換了,輸入用線性部分的輸出Z表示窃植,輸出用Y表示帝蒿,假設(shè)用sigmoid作為非線性激活,那么有

Y = sigmoid(Z)

那么為什么要有非線性部分呢巷怜?個人理解葛超,其一是作數(shù)據(jù)的歸一化。不管前面的線性部分做了怎樣的工作延塑,到了非線性這里绣张,所有的數(shù)值將被限制在一個范圍內(nèi),這樣后面的網(wǎng)絡(luò)層如果要基于前面層的數(shù)據(jù)繼續(xù)計算关带,這個數(shù)值就相對可控了胖替。其二就是打破之前的線性映射關(guān)系。如果全連接層沒有非線性部分豫缨,只有線性部分独令,我們在模型中疊加多層神經(jīng)網(wǎng)絡(luò)是沒有意義的,我們假設(shè)有一個2層全連接神經(jīng)網(wǎng)絡(luò)好芭,其中沒有非線性層燃箭,那么對于第一層有:

W^0*x^0+b^0=z^1

對于第二層有:

W^1*z^1+b^1=z^2

兩式合并,有:

W^1*(W^0*x^0+b^0)+b^1=z^2
W^1*W^0*x^0+(W^1*b^0+b^1)=z^2

所以我們只要令:

W^{0'}=W^1*W^0 , 
b^{0'}=W^1*b^0+b^1舍败,

就可以用一層神經(jīng)網(wǎng)絡(luò)表示之前的兩層神經(jīng)網(wǎng)絡(luò)了招狸。所以非線性層的加入,使得多層神經(jīng)網(wǎng)絡(luò)的存在有了意義邻薯。

關(guān)于非線性激活常用的函數(shù)裙戏,以及什么樣的激活函數(shù)才是好的激活函數(shù)后面會專門介紹,這里不再贅述厕诡。

我們在看一下tflearn中fully_connected的函數(shù)的參數(shù)解釋累榜,當(dāng)然tensorflow中也有相關(guān)函數(shù),這里暫不進行注解。

tflearn.layers.core.fully_connected

incoming: 輸入Tensor壹罚,維度不小于2

n_units: 整型葛作,表示輸出神經(jīng)元個數(shù)

activation: 激活函數(shù),輸入激活函數(shù)的名稱或者函數(shù)定義(自定義非線性激活函數(shù))猖凛,默認值:'linear',參見 tflearn.activations

bias: 布爾值赂蠢,表示是否使用偏置項

weights_init: 初始化權(quán)重W的參數(shù),String 或者一個Tensor,默認是truncated_normal辨泳,參見tflearn.initializations

bias_init: 初始化偏置項虱岂,String或Tensor,默認'zeros'。參見tflearn.initializations

regularizer: 規(guī)范化函數(shù)菠红,String或者一個Tensor,對權(quán)重W進行規(guī)范化操作量瓜,默認不進行,參見tflearn.regularizers
    
weight_decay: 浮點數(shù)途乃,規(guī)范化方法的衰減參數(shù),默認值 0.001.

trainable: 可選參數(shù)扔傅,布爾值耍共,如果為True,那么變量將會加到圖模型中猎塞。同tf.Variable的trainable

restore: bool. If True, this layer weights will be restored when loading a model.

reuse: 可選參數(shù)试读,布爾類型,如果指定了Scope且當(dāng)前參數(shù)置為True,那么該layer的變量可復(fù)用

scope: 可選參數(shù)荠耽,String類型钩骇,定義layer的Scope(指定Scope可以在不同層間共享變量,但需要注意Scope可被覆蓋铝量,需自行控制其唯一性)

name: 可選值倘屹,表示該層的名稱,默認值: 'FullyConnected'.

總結(jié)

基于tflearn進行深度學(xué)習(xí)相關(guān)功能的實現(xiàn)慢叨,要比基于原生的tensorflow要簡單的多纽匙,封裝的比較干凈。本篇只介紹了使用LSTM進行NLP的相關(guān)任務(wù)處理拍谐,讀者完全可以自行下載代碼進行改造烛缔,這里希望讀者能夠了解embedding和fully_connected的意思,知道其作用轩拨,如果希望深入了解践瓷,可以參考相關(guān)論文和他人注解的blog,本篇就寫到這里亡蓉,歡迎拍磚晕翠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市砍濒,隨后出現(xiàn)的幾起案子崖面,更是在濱河造成了極大的恐慌元咙,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件巫员,死亡現(xiàn)場離奇詭異庶香,居然都是意外死亡,警方通過查閱死者的電腦和手機简识,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門赶掖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人七扰,你說我怎么就攤上這事奢赂。” “怎么了颈走?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵膳灶,是天一觀的道長。 經(jīng)常有香客問我立由,道長轧钓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任锐膜,我火速辦了婚禮毕箍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘道盏。我一直安慰自己而柑,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布荷逞。 她就那樣靜靜地躺著媒咳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪种远。 梳的紋絲不亂的頭發(fā)上伟葫,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音院促,去河邊找鬼筏养。 笑死,一個胖子當(dāng)著我的面吹牛常拓,可吹牛的內(nèi)容都是我干的渐溶。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼弄抬,長吁一口氣:“原來是場噩夢啊……” “哼茎辐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤拖陆,失蹤者是張志新(化名)和其女友劉穎弛槐,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體依啰,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡乎串,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了速警。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片叹誉。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖闷旧,靈堂內(nèi)的尸體忽然破棺而出长豁,到底是詐尸還是另有隱情,我是刑警寧澤忙灼,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布匠襟,位于F島的核電站,受9級特大地震影響该园,放射性物質(zhì)發(fā)生泄漏酸舍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一爬范、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧弱匪,春花似錦青瀑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至帘饶,卻和暖如春哑诊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背及刻。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工镀裤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人缴饭。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓暑劝,卻偏偏與公主長得像,于是被迫代替她去往敵國和親颗搂。 傳聞我的和親對象是個殘疾皇子担猛,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容