文本分類--CNN

作為一個NLP屆的菜鳥,想把自己學到的一點知識寫下來,一是幫助自己梳理知識;二是希望能夠幫到一些打算入門以及正在入門的NLPer.由于我的文筆挺差的,以及學識有限,有不忍直視的地方,請多包涵。

github上有很多關于TextCNN的開源項目,從里面可以獲得大量練手的數據。我在學TextCNN的時候,是在了解了cnn的基本原理之后,從github上下載了幾個我覺得看著比較順眼的(我就是覺得代碼風格比較喜歡)。然后再按照自己的代碼風格以及對于代碼的理解進行重現。本文重點介紹TextCNN在tensorflow中的實行,所有數據均來自github,已有標簽。首先根據實際數據,介紹數據預處理過程;最后說明tensorflow中的CNN實現。

1.TxetCNN數據預處理

1.1 詞向量

打算自己訓練詞向量的同學,可以使用gensim,方便快捷,當然使用tensorflow來做也是可以的。下面是使用gensim訓練詞向量的代碼。

gensim詞向量

size是詞向量的維度,sg=0,是用cbow進行訓練,sg=1,使用sg進行訓練。

1.2 文本分詞

有了打標簽的文本,接下來當然是要處理它了啊。上代碼。。。

分詞處理

這步的操作主要是對文本分詞,然后得到文本列表,標簽列表。舉個??。

content=[['文本','分詞'],['標簽','列表'];label=['A','B']

1.3 建立詞典,詞典詞向量

不能是個詞我就要吧。那怎么辦呢?去停用詞!去了停用詞之后,取文本(這個文本指的是所有文本,包括訓練、測試、驗證集)中前N個詞,表示這N個詞是比較重要的,然后保存。之前訓練的詞向量是個數據量很大集合。很多詞,我已經不需要了,我只要這N個詞的詞向量。同樣是上代碼。

詞向量

我提取了文本的前9999個比較重要的詞,并按順序保存了下來。embeddings= np.zeros([10000, 100]) 表示我建立了一個10000個詞,維度是100的詞向量集合。然后將9999個詞在大詞向量中的數值,按1-9999的順序,放入了新建的詞向量中。第0項,讓它保持是100個0的狀態。

1.4? 建立詞典

這部分比較簡單,直接上代碼。

建立詞典

注意:詞典里面詞的順序,要跟新建的詞向量中詞的順序一致。

1.5 標簽詞典

標簽詞典

將標簽也詞典一下。

1.6 Padding的過程

padding是將所有句子進行等長處理,不夠的在句子最后補0;將標簽轉換為one-hot編碼。

padding過程

首先將句子中的詞,根據詞典中的索引,變成全數字的形式;標簽也進行同樣處理。然后,根據max_length(句子最大長度)進行padding,得到x_pad,標簽轉換one-hot格式。好了,到這里文本的預處理,告一段落!

1.7 讀取所需數據

我們保存了10000詞的詞向量,我們要讀取它,還有處理的句子,我們也要分批,輸入進模型。

讀取所需數據

在代碼里,我用一個例子,解釋了np.random.permutation的作用。

2.tensorflow中的TextCNN

TextCNN過程圖

2.1 定義占位符

占位符

2.2 embedding

embedding

vocab_size:是詞的個數,在這里是10000;

embedding_size:是詞向量尺寸,這里是100;

embedding_lookup:我把它看成與excel vlookup類似的查找函數,是將embedding中的詞向量根據input_x中的數字進行索引,然后填充。比如,input_x中的3,將input_x中的3用embedding中的第三行的100個數字進行填充,得到一個tensor:[batch_size,seq_length,embedding_size].

因為,卷積神經網絡中的,conv2d是需要4維張量的,故用tf.expand_dims在embedding_input最后再補一維。

3.3 卷積層

filte 高度設定為【2,3,4】三種,寬度與詞向量等寬,卷積核數量設為num_filter。假設batch_size =1,即對一個句子進行卷積操作。每一種filter卷積后,結果輸出為[1,seq_length - filter_size +1,1,num_filter]的tensor。再用ksize=[1,seq_length - filter_size + 1,1,1]進行max_pooling,得到[1,1,1,num_filter]這樣的tensor.將得到的三種結果進行組合,得到[1,1,1,num_filter*3]的tensor.最后將結果變形一下[-1,num_filter*3],目的是為了下面的全連接。再次有請代碼。

卷積層

3.4? 全連接層

在全連接層中進行dropout,通常保持率為0.5。其中num_classes為文本分類的類別數目。然后得到輸出的結果scores,以及得到預測類別在標簽詞典中對應的數值predicitons。

全連接層

3.5 loss

這里使用softmax交叉熵求loss, logits=self.scores 這里一定用的是未經過softmax處理的數值。

loss

3.6?optimizer

這里使用了梯度裁剪。首先計算梯度,這個計算是類似L2正則化計算w的值,也就是求平方再平方根。然后與設定的clip裁剪值進行比較,如果小于等于clip,梯度不變;如果大于clip,則梯度*(clip/梯度L2值)。

optimizer

3.7 accuracy

最后,計算模型的準確度。

accuracy

3.8 訓練模型

訓練與測試

模型迭代次數為5,每完成一輪迭代,模型保存一次。當global_step為100的整數倍時,輸出模型的訓練結果以及在測試集上的測試結果。

訓練結果

一個batch中訓練集最好準確度達到98%,同時在測試集上的結果達到100%。接下來,我們看看保存的模型在驗證集上的效果。

3.9 模型驗證

驗證集有5000條語句,我用最后一次保存的模型,對5000條句子進行預測,將預測的結果與原標簽進行對比,得到驗證集上的準確率,結果表明在整個驗證集上準確達到96.58%,并輸出前10條語句,將預測結果與原結果進行對比。

部分驗證代碼
驗證結果

整個模型的流程,分析完畢。流程和文中的TextCNN過程圖基本一致。因學識有限,文中難免有描述不對的地方,請各位批評指正。希望我的文章,能夠幫到大家。

本文代碼地址:https://github.com/NLPxiaoxu/Easy_TextCnn_Rnn

參考文獻:

《Convolutional Neural Networks for Sentence Classification》

https://github.com/cjymz886/text-cnn

http://www.wildml.com/2015/12/implementing-a-cnn-for-text-classification-in-tensorflow

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容