文本分類--CNN

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

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

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

1.1 詞向量

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

gensim詞向量

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

1.2 文本分詞

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

分詞處理

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

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

1.3 建立詞典,詞典詞向量

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

詞向量

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

1.4? 建立詞典

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

建立詞典

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

1.5 標簽詞典

標簽詞典

將標簽也詞典一下。

1.6 Padding的過程

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

padding過程

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

1.7 讀取所需數(shù)據(jù)

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

讀取所需數(shù)據(jù)

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

2.tensorflow中的TextCNN

TextCNN過程圖

2.1 定義占位符

占位符

2.2 embedding

embedding

vocab_size:是詞的個數(shù),在這里是10000;

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

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

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

3.3 卷積層

filte 高度設定為【2,3,4】三種,寬度與詞向量等寬,卷積核數(shù)量設為num_filter。假設batch_size =1,即對一個句子進行卷積操作。每一種filter卷積后,結(jié)果輸出為[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.將得到的三種結(jié)果進行組合,得到[1,1,1,num_filter*3]的tensor.最后將結(jié)果變形一下[-1,num_filter*3],目的是為了下面的全連接。再次有請代碼。

卷積層

3.4? 全連接層

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

全連接層

3.5 loss

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

loss

3.6?optimizer

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

optimizer

3.7 accuracy

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

accuracy

3.8 訓練模型

訓練與測試

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

訓練結(jié)果

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

3.9 模型驗證

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

部分驗證代碼
驗證結(jié)果

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

本文代碼地址: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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容