1. 程式人生 > >CNN在中文文字分類的應用

CNN在中文文字分類的應用

深度學習近一段時間以來在影象處理和NLP任務上都取得了不俗的成績。通常,影象處理的任務是藉助CNN來完成的,其特有的卷積、池化結構能夠提取影象中各種不同程度的紋理、結構,並最終結合全連線網路實現資訊的彙總和輸出。RNN由於其記憶功能為處理NLP中的上下文提供了途徑。

在短文字分析任務中,由於句子句長長度有限、結構緊湊、能夠獨立表達意思,使得CNN在處理這一類問題上成為可能。論文Convolutional Neural Networks for Sentence Classification(論文作者Yoon Kim)即在這一類問題上做了嘗試。首先來看看論文中介紹的模型結構及原理:

CNN模型結構如下:


一共包括4部分:

1、  輸入層:

如圖所示,輸入層是句子中的詞語對應的wordvector依次(從上到下)排列的矩陣,假設句子有 n 個詞,vector的維數為  k  ,那麼這個矩陣就是  n × k 的(在CNN中可以看作一副高度為n、寬度為k的影象)。

這個矩陣的型別可以是靜態的(static),也可以是動態的(non static)。靜態就是word vector是固定不變的,而動態則是在模型訓練過程中,word vector也當做是可優化的引數,通常把反向誤差傳播導致word vector中值發生變化的這一過程稱為Fine tune。(這裡如果word vector如果是隨機初始化的,不僅訓練得到了CNN分類模型,還得到了word2vec這個副產品了,如果已經有訓練的word vector,那麼其實是一個遷移學習的過程)

對於未登入詞的vector,可以用0或者隨機小的正數來填充。

2、  第一層卷積層:

輸入層通過卷積操作得到若干個Feature Map,卷積視窗的大小為 h ×k ,其中 h  表示縱向詞語的個數,而  k  表示word vector的維數。通過這樣一個大型的卷積視窗,將得到若干個列數為1的Feature Map。(熟悉NLP中N-GRAM模型的讀者應該懂得這個意思)。

3、  池化層:

接下來的池化層,文中用了一種稱為Max-over-timePooling的方法。這種方法就是簡單地從之前一維的Feature Map中提出最大的值,文中解釋最大值代表著最重要的訊號。可以看出,這種Pooling方式可以解決可變長度的句子輸入問題(因為不管Feature Map中有多少個值,只需要提取其中的最大值)。最終池化層的輸出為各個Feature Map的最大值們,即一個一維的向量。

4、  全連線+softmax層:

池化層的一維向量的輸出通過全連線的方式,連線一個Softmax層,Softmax層可根據任務的需要設定(通常反映著最終類別上的概率分佈)。

訓練方案:

在倒數第二層的全連線部分上使用Dropout技術,Dropout是指在模型訓練時隨機讓網路某些隱含層節點的權重不工作,不工作的那些節點可以暫時認為不是網路結構的一部分,但是它的權重得保留下來(只是暫時不更新而已),因為下次樣本輸入時它可能又得工作了,它是防止模型過擬合的一種常用的trikc。同時對全連線層上的權值引數給予L2正則化的限制。這樣做的好處是防止隱藏層單元自適應(或者對稱),從而減輕過擬合的程度。

在樣本處理上使用minibatch方式來降低一次模型擬合計算量,使用shuffle_batch的方式來降低各批次輸入樣本之間的相關性(在機器學習中,如果訓練資料之間相關性很大,可能會讓結果很差、泛化能力得不到訓練、這時通常需要將訓練資料打散,稱之為shuffle_batch)。

論文作者也公佈了自己的實現程式(下載戳這裡),同時有一位同行對上述論文給出瞭解讀並基於上述程式做了對比實驗(論文解讀戳這裡)。本人上面的分析也是基於原始論文和解讀,算是錦上添花吧。

實驗流程及結果:

參考上述論文和源程式,本人對其在中文短文字分類問題上進行了實驗。

實驗要求:

       Python環境

       安裝結巴分析的python版本

       安裝numpy、pandas等一系列科學計算相關庫,windows下藉助Anaconda進行安裝比較方便

       安裝theano,這個參考各種安裝、使用教程吧。

語料庫:使用的是搜狗語料庫,搜尋SogouC.reduced可找到下載連線。

文字預處理:

       使用jieba分詞後將一些實詞漢詞提取出來,同時,由於CNN輸入視窗的大小是一定的,對於長度小於N的句子,使用Pad with zeroes的方式,對於長度大於N的句子,將其切分為若干段長度小於等於N的句子。使用軍事和教育兩個題材的預料進行處理後,樣本總數量大致在2W的樣子。

訓練調參:

       模型結構與trikc均與原文一直,在處理word vector size時,採用原始論文采用的300時,效果不是太理想,將該引數調低,採用szie=50、size=100,最終效果還算可以。同時,feature_map的數量要比word vector size值大一些,以儘可能提取更為豐富的句子資訊。

       下面是訓練過程中的一些結果:


word vector size=50& feature_maps size = 100

來看看訓練得到的wordvector在語義空間的對映效果如果,以該詞對應的向量空間的餘弦積的形式衡量詞之間的相似性:


左:word vector size=50 & feature_maps size= 100 右:word vector size=100& feature_maps size = 100

軍事題材類的詞,語義表達的效果較好,而醫療衛生相關的則效果一般。如果原始預料集更大,可能效果還會進一步提升的。同時,也可以考慮使用word2vec模型訓練得到word vector,在使用上述模型訓練CNN分類模型,同時更新word vector。

本文同時在知加發表,歡迎圍觀。

最後,進過本人使用的實驗程式碼可從github下載(Theano),對作者的原始程式碼做了比較詳盡的註釋,同時增加漢語的分詞預處理模組和後面的word vector展現模組

個人採用Tensorflow實現的版本:github (Tensorflow版本),歡迎一起交流學習~~~