深度學習--RNN+Attention 文本分類

之前介紹過RNN的分類,本文介紹一下使用預訓練詞向量進行RNN+Attention的分類模型娃循。

RNN-Attention文本分類

本文使用雙向LSTM加上Attention,模型結(jié)構(gòu)如圖所示鹿驼。從下往上看,w這一層表示一個時間序列(在文本分類指一個句子的長度药版,seq_length),里面的元素是一個個詞匯喻犁,我們將詞匯經(jīng)過LSTM網(wǎng)絡槽片,使不具備重要性何缓,也就是與分類無關(guān)的詞語的語義給過濾掉或者保留較小的數(shù)值,從而留下較為重要的語義还栓。使用雙向LSTM,不僅要考慮句子的正向序列碌廓,還有反向序列,獲得更完整的語義剩盒,將獲得的結(jié)果經(jīng)過拼接然后再輸送到Attention層谷婆。Attention簡單來說,就是賦予權(quán)重辽聊,給不同的詞匯根據(jù)重要性賦值纪挎。最后將權(quán)重與LSTM層的結(jié)果進行線性求和,所得結(jié)果輸出到全連接層跟匆,經(jīng)過softmax得到分類結(jié)果异袄。
Attention

下面來正式開始,RNN+Attention在tensorflow中的實現(xiàn)玛臂。

運行環(huán)境

python 3.6
tensorflow 1.2
本文GITHUB

正文

1.數(shù)據(jù)預處理
2.模型構(gòu)建
3.模型訓練與測試
4.模型驗證
5.總結(jié)

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

本實驗是使用THUCNews的一個子集進行訓練與測試,文本類別涉及10個類別:categories = ['體育', '財經(jīng)', '房產(chǎn)', '家居', '教育', '科技', '時尚', '時政', '游戲', '娛樂']烤蜕。這一步的主要作用是將標簽與文本分開,然后將文本與標簽分別轉(zhuǎn)化為模型所需要的數(shù)據(jù)格式垢揩。例如:文本:[我 愛 體育]玖绿,標簽:體育。轉(zhuǎn)換成:文本[3 4 20]叁巨,標簽[1 0 0 0 0 0 0 0 0 0]斑匪。
然后是padding,按照動態(tài)RNN的做法應該是根據(jù)不同batch里面句子的長度對不同batch進行padding锋勺,但本實驗所用素材來自新聞蚀瘸,每個句子其實就是一篇報道,特別的長庶橱,故分配指定長度贮勃,長度為250,故按照這個長度來padding苏章。最后是生成batch的過程寂嘉。

2 模型構(gòu)建

模型采用的是動態(tài)雙向LSTM,對于輸出結(jié)果,采用拼接的方式枫绅,輸入詞向量的shape是[batch_size,seq_length,embedding_dim]泉孩,輸出為[batch_size,seq_length,2*hidden_dim]。

       with tf.name_scope('Cell'):
            cell_fw = tf.contrib.rnn.BasicLSTMCell(pm.hidden_dim)
            Cell_fw = tf.contrib.rnn.DropoutWrapper(cell_fw, self.keep_pro)

            cell_bw = tf.contrib.rnn.BasicLSTMCell(pm.hidden_dim)
            Cell_bw = tf.contrib.rnn.DropoutWrapper(cell_bw, self.keep_pro)

        with tf.device('/cpu:0'), tf.name_scope('embedding'):
            self.embedding = tf.get_variable('embedding', shape=[pm.vocab_size, pm.embedding_dim],
                                             initializer=tf.constant_initializer(pm.pre_trianing))
            self.embedding_input = tf.nn.embedding_lookup(self.embedding, self.input_x)

        with tf.name_scope('biRNN'):

            output, _ = tf.nn.bidirectional_dynamic_rnn(cell_fw=Cell_fw, cell_bw=Cell_bw, inputs=self.embedding_input,
                                                        sequence_length=self.seq_length, dtype=tf.float32)
            output = tf.concat(output, 2) #[batch_size, seq_length, 2*hidden_dim]

接下來并淋,就是Attention層寓搬。
Attention過程

我們設置三個變量,分別是w,b,u县耽,下標分別是小寫的w句喷,公式2是一個softmax過程镣典,公式3是線性加權(quán)求和。在實際模型中唾琼,是需要對參數(shù)進行很多變型的兄春,我們結(jié)合代碼看一下。

        with tf.name_scope('attention'):
            u_list = []
            seq_size = output.shape[1].value
            hidden_size = output.shape[2].value #[2*hidden_dim]
            attention_w = tf.Variable(tf.truncated_normal([hidden_size, pm.attention_size], stddev=0.1), name='attention_w')
            attention_u = tf.Variable(tf.truncated_normal([pm.attention_size, 1], stddev=0.1), name='attention_u')
            attention_b = tf.Variable(tf.constant(0.1, shape=[pm.attention_size]), name='attention_b')
            for t in range(seq_size):
                #u_t:[batch,attention]
                u_t = tf.tanh(tf.matmul(output[:, t, :], attention_w) + tf.reshape(attention_b, [1, -1]))
                u = tf.matmul(u_t, attention_u)
                u_list.append(u)
            logit = tf.concat(u_list, axis=1)
            #[batch:seq_size]
            weights = tf.nn.softmax(logit, name='attention_weights')
            #weight:[batch:seq_size]
            out_final = tf.reduce_sum(output * tf.reshape(weights, [-1, seq_size, 1]), 1)
            #out_final:[batch,hidden_size]   

為了給每個詞賦予權(quán)重父叙,那么權(quán)重的shape應該是[batch,seq_length]神郊。
為了得到每個詞的權(quán)重,在程序中趾唱,對句子序列做了一個for循環(huán),一個循環(huán)蜻懦,得到的是同一個batch中不同序列同一步詞的語義甜癞。
例如:batch=64,t=1,也就是64個句子,每個句子第一個詞的語義宛乃。所以每一步取出的output形狀是[batch,hidden_size]悠咱。
那么u_t輸出為[batch,attention];
下一步征炼,u輸出得到的結(jié)果是[batch,1]析既;
u_list是將seq_length個u的結(jié)果存入列表中;
將列表按照第一維進行拼接谆奥,得到結(jié)果logit的形狀[batch,seq_length]--以上是公式一的步驟;
經(jīng)過softmax眼坏,得到weights,shape依舊為[batch,seq_length]--公式二步驟酸些;
將weigths經(jīng)過變形宰译,[bacth,seq_length,1],然后使用點乘“*”魄懂,表示對應數(shù)值相乘沿侈;然后將第一維的值進行相加,也就是seq_length這一維度市栗。這個步驟的意思:對于每一個句子缀拭,該句詞匯與對應權(quán)重相乘,然后得到的和再相加填帽,最后輸出的形狀[batch,hidden_size]蛛淋。

模型的最后,是全連+softmax層盲赊。這一步相對來說比較簡單铣鹏。

        with tf.name_scope('dropout'):
            self.out_drop = tf.nn.dropout(out_final, keep_prob=self.keep_pro)

        with tf.name_scope('output'):
            w = tf.Variable(tf.truncated_normal([hidden_size, pm.num_classes], stddev=0.1), name='w')
            b = tf.Variable(tf.zeros([pm.num_classes]), name='b')
            self.logits = tf.matmul(self.out_drop, w) + b
            self.predict = tf.argmax(tf.nn.softmax(self.logits), 1, name='predict')

3 模型訓練與測試

訓練時,每迭代一次哀蘑,將訓練得到的結(jié)果诚卸,保存到checkpoints葵第;
loss,accuracy的情況,保留到tensorboard中合溺;
每100個batch,輸出此時的訓練結(jié)果與測試結(jié)果卒密。

   for epoch in range(pm.num_epochs):
       print('Epoch:', epoch+1)
       num_batchs = int((len(x_train) - 1) / pm.batch_size) + 1
       batch_train = batch_iter(x_train, y_train, batch_size=pm.batch_size)
       for x_batch, y_batch in batch_train:
           seq_len = sequence(x_batch)
           feed_dict = model.feed_data(x_batch, y_batch, seq_len, pm.keep_prob)
           _, global_step, _summary, train_loss, train_accuracy = session.run([model.optimizer, model.global_step, merged_summary,
                                                                               model.loss, model.accuracy],feed_dict=feed_dict)
           if global_step % 100 == 0:
               test_loss, test_accuracy = model.evaluate(session, x_test, y_test)
               print('global_step:', global_step, 'train_loss:', train_loss, 'train_accuracy:', train_accuracy,
                     'test_loss:', test_loss, 'test_accuracy:', test_accuracy)

           if global_step % num_batchs == 0:
               print('Saving Model...')
               saver.save(session, save_path, global_step=global_step)

訓練與測試的情況如圖所示,訓練結(jié)果表明棠赛,模型收斂情況良好哮奇,準確度也較為理想。
訓練與測試

4 模型驗證

驗證集數(shù)據(jù)量是500*10睛约,使用最后保存的模型對驗證集進行預測鼎俘,并計算準確率。
模型驗證

從驗證的情況來看辩涝,準確率達到了96.5%贸伐,從預測的前10項情況來看,模型較為理想怔揩。

5 總結(jié)

相對與之前的兩層LSTM模型對文本進行分類捉邢,本文采用的雙向LSTM+Attention模型。都進行了3次迭代商膊,從結(jié)果上看伏伐,兩層LSTM模型,準確率略高一點晕拆;但本文并沒有用兩層LSTM+Attention模型藐翎,所以對于這兩次的結(jié)果不好做比較,有興趣的可以下載github代碼潦匈,把代碼改成兩層的結(jié)構(gòu)阱高。但從訓練時間上來說,RNN網(wǎng)絡越深茬缩,時間耗費的越久赤惊。
加上之前,共介紹了4種文本分類的深度學習模型凰锡,基本可以滿足一般的情況未舟,這幾種模型不僅可以用來進行文本分類,對于其他分類情況掂为,稍微變動下裕膀,也是適應的,比如情感分類勇哗。
對于深度學習分類的介紹昼扛,到此為止。以后會介紹深度學習、傳統(tǒng)機器學習在中文分詞抄谐,詞性標注等應用的模型渺鹦。

參考

https://blog.csdn.net/thriving_fcl/article/details/73381217
https://zhuanlan.zhihu.com/p/46313756

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蛹含,隨后出現(xiàn)的幾起案子毅厚,更是在濱河造成了極大的恐慌,老刑警劉巖浦箱,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吸耿,死亡現(xiàn)場離奇詭異,居然都是意外死亡酷窥,警方通過查閱死者的電腦和手機咽安,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蓬推,“玉大人板乙,你說我怎么就攤上這事∪猓” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵蛋铆,是天一觀的道長馋评。 經(jīng)常有香客問我,道長刺啦,這世上最難降的妖魔是什么留特? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮玛瘸,結(jié)果婚禮上蜕青,老公的妹妹穿的比我還像新娘。我一直安慰自己糊渊,他們只是感情好右核,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著渺绒,像睡著了一般贺喝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宗兼,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天躏鱼,我揣著相機與錄音,去河邊找鬼殷绍。 笑死染苛,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的主到。 我是一名探鬼主播茶行,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼躯概,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拢军?” 一聲冷哼從身側(cè)響起楞陷,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎茉唉,沒想到半個月后固蛾,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡度陆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年艾凯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片懂傀。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡趾诗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蹬蚁,到底是詐尸還是另有隱情恃泪,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布犀斋,位于F島的核電站贝乎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏叽粹。R本人自食惡果不足惜览效,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望虫几。 院中可真熱鬧锤灿,春花似錦、人聲如沸辆脸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽每强。三九已至始腾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間空执,已是汗流浹背浪箭。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留辨绊,地道東北人奶栖。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親宣鄙。 傳聞我的和親對象是個殘疾皇子袍镀,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

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