作為一個NLP屆的菜鳥,想把自己學(xué)到的一點(diǎn)知識寫下來,一是幫助自己梳理知識;二是希望能夠幫到一些打算入門以及正在入門的NLPer.由于我的文筆挺差的兼雄,以及學(xué)識有限,有不忍直視的地方帽蝶,請多包涵赦肋。
github上有很多關(guān)于TextCNN的開源項(xiàng)目,從里面可以獲得大量練手的數(shù)據(jù)励稳。我在學(xué)TextCNN的時候佃乘,是在了解了cnn的基本原理之后,從github上下載了幾個我覺得看著比較順眼的(我就是覺得代碼風(fēng)格比較喜歡)驹尼。然后再按照自己的代碼風(fēng)格以及對于代碼的理解進(jìn)行重現(xiàn)趣避。本文重點(diǎn)介紹TextCNN在tensorflow中的實(shí)行,所有數(shù)據(jù)均來自github新翎,已有標(biāo)簽程帕。首先根據(jù)實(shí)際數(shù)據(jù)住练,介紹數(shù)據(jù)預(yù)處理過程;最后說明tensorflow中的CNN實(shí)現(xiàn)愁拭。
1.TxetCNN數(shù)據(jù)預(yù)處理
1.1 詞向量
打算自己訓(xùn)練詞向量的同學(xué)讲逛,可以使用gensim,方便快捷岭埠,當(dāng)然使用tensorflow來做也是可以的盏混。下面是使用gensim訓(xùn)練詞向量的代碼。
size是詞向量的維度枫攀,sg=0,是用cbow進(jìn)行訓(xùn)練括饶,sg=1,使用sg進(jìn)行訓(xùn)練。
1.2 文本分詞
有了打標(biāo)簽的文本来涨,接下來當(dāng)然是要處理它了啊图焰。上代碼。蹦掐。技羔。
這步的操作主要是對文本分詞,然后得到文本列表卧抗,標(biāo)簽列表藤滥。舉個??。
content=[['文本','分詞'],['標(biāo)簽','列表']社裆;label=['A','B']
1.3 建立詞典拙绊,詞典詞向量
不能是個詞我就要吧。那怎么辦呢泳秀?去停用詞标沪!去了停用詞之后,取文本(這個文本指的是所有文本嗜傅,包括訓(xùn)練金句、測試、驗(yàn)證集)中前N個詞吕嘀,表示這N個詞是比較重要的违寞,然后保存。之前訓(xùn)練的詞向量是個數(shù)據(jù)量很大集合偶房。很多詞趁曼,我已經(jīng)不需要了,我只要這N個詞的詞向量棕洋。同樣是上代碼彰阴。
我提取了文本的前9999個比較重要的詞,并按順序保存了下來拍冠。embeddings= np.zeros([10000, 100]) 表示我建立了一個10000個詞尿这,維度是100的詞向量集合簇抵。然后將9999個詞在大詞向量中的數(shù)值,按1-9999的順序射众,放入了新建的詞向量中碟摆。第0項(xiàng),讓它保持是100個0的狀態(tài)叨橱。
1.4? 建立詞典
這部分比較簡單典蜕,直接上代碼。
注意:詞典里面詞的順序罗洗,要跟新建的詞向量中詞的順序一致愉舔。
1.5 標(biāo)簽詞典
將標(biāo)簽也詞典一下。
1.6 Padding的過程
padding是將所有句子進(jìn)行等長處理伙菜,不夠的在句子最后補(bǔ)0轩缤;將標(biāo)簽轉(zhuǎn)換為one-hot編碼。
首先將句子中的詞贩绕,根據(jù)詞典中的索引火的,變成全數(shù)字的形式;標(biāo)簽也進(jìn)行同樣處理淑倾。然后馏鹤,根據(jù)max_length(句子最大長度)進(jìn)行padding,得到x_pad,標(biāo)簽轉(zhuǎn)換one-hot格式。好了娇哆,到這里文本的預(yù)處理湃累,告一段落!
1.7 讀取所需數(shù)據(jù)
我們保存了10000詞的詞向量碍讨,我們要讀取它治力,還有處理的句子,我們也要分批垄开,輸入進(jìn)模型琴许。
在代碼里税肪,我用一個例子溉躲,解釋了np.random.permutation的作用。
2.tensorflow中的TextCNN
2.1 定義占位符
2.2 embedding
vocab_size:是詞的個數(shù)益兄,在這里是10000锻梳;
embedding_size:是詞向量尺寸,這里是100净捅;
embedding_lookup:我把它看成與excel vlookup類似的查找函數(shù)疑枯,是將embedding中的詞向量根據(jù)input_x中的數(shù)字進(jìn)行索引,然后填充蛔六。比如荆永,input_x中的3废亭,將input_x中的3用embedding中的第三行的100個數(shù)字進(jìn)行填充,得到一個tensor:[batch_size,seq_length,embedding_size].
因?yàn)榫咴浚矸e神經(jīng)網(wǎng)絡(luò)中的豆村,conv2d是需要4維張量的,故用tf.expand_dims在embedding_input最后再補(bǔ)一維骂删。
3.3 卷積層
filte 高度設(shè)定為【2掌动,3,4】三種宁玫,寬度與詞向量等寬粗恢,卷積核數(shù)量設(shè)為num_filter。假設(shè)batch_size =1欧瘪,即對一個句子進(jìn)行卷積操作眷射。每一種filter卷積后,結(jié)果輸出為[1,seq_length - filter_size +1,1,num_filter]的tensor恋追。再用ksize=[1,seq_length - filter_size + 1,1,1]進(jìn)行max_pooling,得到[1,1,1,num_filter]這樣的tensor.將得到的三種結(jié)果進(jìn)行組合,得到[1,1,1,num_filter*3]的tensor.最后將結(jié)果變形一下[-1,num_filter*3]凭迹,目的是為了下面的全連接。再次有請代碼苦囱。
3.4? 全連接層
在全連接層中進(jìn)行dropout,通常保持率為0.5嗅绸。其中num_classes為文本分類的類別數(shù)目。然后得到輸出的結(jié)果scores撕彤,以及得到預(yù)測類別在標(biāo)簽詞典中對應(yīng)的數(shù)值predicitons鱼鸠。
3.5 loss
這里使用softmax交叉熵求loss, logits=self.scores 這里一定用的是未經(jīng)過softmax處理的數(shù)值。
3.6?optimizer
這里使用了梯度裁剪羹铅。首先計(jì)算梯度蚀狰,這個計(jì)算是類似L2正則化計(jì)算w的值,也就是求平方再平方根职员。然后與設(shè)定的clip裁剪值進(jìn)行比較麻蹋,如果小于等于clip,梯度不變扮授;如果大于clip,則梯度*(clip/梯度L2值)。
3.7 accuracy
最后,計(jì)算模型的準(zhǔn)確度。
3.8 訓(xùn)練模型
模型迭代次數(shù)為5质蕉,每完成一輪迭代禁悠,模型保存一次隶糕。當(dāng)global_step為100的整數(shù)倍時,輸出模型的訓(xùn)練結(jié)果以及在測試集上的測試結(jié)果尔邓。
一個batch中訓(xùn)練集最好準(zhǔn)確度達(dá)到98%,同時在測試集上的結(jié)果達(dá)到100%。接下來偿警,我們看看保存的模型在驗(yàn)證集上的效果崩掘。
3.9 模型驗(yàn)證
驗(yàn)證集有5000條語句,我用最后一次保存的模型,對5000條句子進(jìn)行預(yù)測腿倚,將預(yù)測的結(jié)果與原標(biāo)簽進(jìn)行對比暂筝,得到驗(yàn)證集上的準(zhǔn)確率胧洒,結(jié)果表明在整個驗(yàn)證集上準(zhǔn)確達(dá)到96.58%肾砂,并輸出前10條語句列赎,將預(yù)測結(jié)果與原結(jié)果進(jìn)行對比。
整個模型的流程镐确,分析完畢包吝。流程和文中的TextCNN過程圖基本一致。因?qū)W識有限源葫,文中難免有描述不對的地方诗越,請各位批評指正。希望我的文章息堂,能夠幫到大家嚷狞。
本文代碼地址:https://github.com/NLPxiaoxu/Easy_TextCnn_Rnn
參考文獻(xiàn):
《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