《Convolutional Neural Networks for Sentence Classification》 文本分類


文本分類任務中可以利用CNN來提取句子中類似 n-gram 的關鍵信息。

TextCNN的詳細過程原理圖見下:

 

 

 keras 代碼:

 1 def convs_block(data, convs=[3, 3, 4, 5, 5, 7, 7], f=256):
 2     pools = []
 3     for c in convs:
 4         conv = Activation(activation="relu")(BatchNormalization()(
 5             Conv1D(filters=f, kernel_size=c, padding="valid")(data)))
 6         pool = GlobalMaxPool1D()(conv)
 7         pools.append(pool)
 8     return concatenate(pools)
 9 
10 
11 def rnn_v1(seq_length, embed_weight, pretrain=False):
12  
13     main_input = Input(shape=(seq_length,), dtype='float64')
14 
15     in_dim, out_dim = embed_weight.shape
16     embedding = Embedding(input_dim=in_dim, weights=[
17         embed_weight], output_dim=out_dim, trainable=False)
18     content = Activation(activation="relu")(
19         BatchNormalization()((TimeDistributed(Dense(256))(embedding(main_input)))))
20     content = Bidirectional(GRU(256))(content)
21     content = Dropout(0.3)(content)
22     fc = Activation(activation="relu")(
23         BatchNormalization()(Dense(256)(content)))
24     main_output = Dense(3,
25                         activation='softmax')(fc)
26 
27     model = Model(inputs=main_input, outputs=main_output)
28     model.compile(optimizer='adam',
29                   loss='categorical_crossentropy',
30                   metrics=['accuracy'])
31     model.summary()
32     return model

 

說明如下:

  • 輸入層

如圖所示,,假設句子有 n 個詞,vector的維數為 k ,那么這個矩陣就是 n×k 的。

這個矩陣的類型可以是靜態的(static),也可以是動態的(non static)。靜態就是word vector是固定不變的,而動態則是在模型訓練過程中,word vector也當做是可優化的參數,通常把反向誤差傳播導致word vector中值發生變化的這一過程稱為Fine tune

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

  • 第一層卷積層

輸入層通過卷積操作得到若干個Feature Map,卷積窗口的大小為 m*k ,其中 m表示n_gram中的n,通過卷積將得到F個列數為1的Feature Map,F表示卷積核的個數。

  • 池化層

接下來的池化層,文中用了一種稱為Max-over-time Pooling的方法。這種方法就是簡單地從之前一維的Feature Map中提出最大的值,文中解釋最大值代表着最重要的信號。

最終池化層的輸出為各個Feature Map的最大值,即一個一維的向量。polling之后得到的是1*F的一維向量。

  • 全連接 + Softmax層

池化層的一維向量的輸出通過全連接的方式,連接一個Softmax層。

最終實現時,我們可以在倒數第二層的全連接部分上使用Dropout技術,即對全連接層上的權值參數給予L2正則化的限制。這樣做的好處是防止隱藏層單元自適應(或者對稱),從而減輕過擬合的程度。

實驗部分

1. 數據

實驗用到的數據集如下(具體的名稱和來源可以參考論文):

2. 模型訓練和調參

  • 修正線性單元(Rectified linear units)
  • 濾波器的h大小:3,4,5;對應的Feature Map的數量為100;
  • Dropout率為0.5,L2正則化限制權值大小不超過3;
  • mini-batch的大小為50;

這些參數的選擇都是基於SST-2 dev數據集,通過網格搜索方法(Grid Search)得到的最優參數。另外,訓練過程中采用隨機梯度下降方法,基於shuffled mini-batches之上的,使用了Adadelta update rule(Zeiler, 2012)。

3. 預訓練的Word Vector

這里的word vector使用的是公開的數據,即連續詞袋模型(COW)在Google News上的訓練結果。未登錄次的vector值是隨機初始化的。

4. 實驗結果

實驗結果如下圖:

其中,前四個模型是上文中所提出的基本模型的各個變種:

  • CNN-rand: 所有的word vector都是隨機初始化的,可以訓練的參數。
  • CNN-static: Google的Word2Vector工具(CBOW模型)得到的結果,不可訓練;
  • CNN-non-static: Google的Word2Vector工具(CBOW模型)得到的結果,但是會在訓練過程中被Fine tuned
  • CNN-multichannel: CNN-static和CNN-non-static的混合版本,即兩種類型的輸入;

5. 結論

  • CNN-static較與CNN-rand好,說明pre-training的word vector確實有較大的提升作用(因為pre-training的word vector顯然利用了更大規模的文本數據信息);
  • CNN-non-static較於CNN-static大部分要好,說明適當的Fine tune也是有利的,是因為使得vectors更加貼近於具體的任務
  • CNN-multichannel較於CNN-single在小規模的數據集上有更好的表現,實際上CNN-multichannel體現了一種折中思想,即既不希望Fine tuned的vector距離原始值太遠,但同時保留其一定的變化空間。

值得注意的是,static的vector和non-static的相比,有一些有意思的現象如下表格:

  • 原始的word2vector訓練結果中,bad對應的最相近詞為good,原因是這兩個詞在句法上的使用是極其類似的(可以簡單替換,不會出現語句毛病);而在non-static的版本中,bad對應的最相近詞為terrible,這是因為在Fune tune的過程中,vector的值發生改變從而更加貼切數據集(是一個情感分類的數據集),所以在情感表達的角度這兩個詞會更加接近;
  • 句子中的!最接近一些表達形式較為激進的詞匯,如lush等;而,則接近於一些連接詞,這和我們的主觀感受也是相符的。

Kim Y的這個模型很簡單,但是卻有着很好的性能。后續Denny用TensorFlow實現了這個模型的簡單版本,可參考這篇博文;以及Ye Zhang等人對這個模型進行了大量的實驗,並給出了調參的建議,可參考這篇論文

下面總結一下Ye Zhang等人基於Kim Y的模型做了大量的調參實驗之后的結論:

  • 由於模型訓練過程中的隨機性因素,如隨機初始化的權重參數,mini-batch,隨機梯度下降優化算法等,造成模型在數據集上的結果有一定的浮動,如准確率(accuracy)能達到1.5%的浮動,而AUC則有3.4%的浮動;
  • 詞向量是使用word2vec還是GloVe,對實驗結果有一定的影響,具體哪個更好依賴於任務本身;
  • Filter的大小對模型性能有較大的影響,並且Filter的參數應該是可以更新的;
  • Feature Map的數量也有一定影響,但是需要兼顧模型的訓練效率;
  • 1-max pooling的方式已經足夠好了,相比於其他的pooling方式而言;
  • 正則化的作用微乎其微。

Ye Zhang等人給予模型調參者的建議如下:

  • 使用non-static版本的word2vec或者GloVe要比單純的one-hot representation取得的效果好得多;
  • 為了找到最優的過濾器(Filter)大小,可以使用線性搜索的方法。通常過濾器的大小范圍在1-10之間,當然對於長句,使用更大的過濾器也是有必要的;
  • Feature Map的數量在100-600之間;
  • 可以盡量多嘗試激活函數,實驗發現ReLUtanh兩種激活函數表現較佳;
  • 使用簡單的1-max pooling就已經足夠了,可以沒必要設置太復雜的pooling方式;
  • 當發現增加Feature Map的數量使得模型的性能下降時,可以考慮增大正則的力度,如調高dropout的概率;
  • 為了檢驗模型的性能水平,多次反復的交叉驗證是必要的,這可以確保模型的高性能並不是偶然。

論文附錄中還附上了各種調參結果,感興趣的可以前往閱讀之。

TextCNN詳細過程:第一層是圖中最左邊的7乘5的句子矩陣,每行是詞向量,維度=5,這個可以類比為圖像中的原始像素點了。然后經過有 filter_size=(2,3,4) 的一維卷積層,每個filter_size 有兩個輸出 channel。第三層是一個1-max pooling層,這樣不同長度句子經過pooling層之后都能變成定長的表示了,最后接一層全連接的 softmax 層,輸出每個類別的概率。

 

特征:這里的特征就是詞向量,有靜態(static)和非靜態(non-static)方式。static方式采用比如word2vec預訓練的詞向量,訓練過程不更新詞向量,實質上屬於遷移學習了,特別是數據量比較小的情況下,采用靜態的詞向量往往效果不錯。non-static則是在訓練過程中更新詞向量。推薦的方式是 non-static 中的 fine-tunning方式,它是以預訓練(pre-train)的word2vec向量初始化詞向量,訓練過程中調整詞向量,能加速收斂,當然如果有充足的訓練數據和資源,直接隨機初始化詞向量效果也是可以的。

通道(Channels):圖像中可以利用 (R, G, B) 作為不同channel,而文本的輸入的channel通常是不同方式的embedding方式(比如 word2vec或Glove),實踐中也有利用靜態詞向量和fine-tunning詞向量作為不同channel的做法。

一維卷積(conv-1d):圖像是二維數據,經過詞向量表達的文本為一維數據,因此在TextCNN卷積用的是一維卷積。一維卷積帶來的問題是需要設計通過不同 filter_size 的 filter 獲取不同寬度的視野。

Pooling層:利用CNN解決文本分類問題的文章還是很多的,比如這篇 A Convolutional Neural Network for Modelling Sentences 最有意思的輸入是在 pooling 改成 (dynamic) k-max pooling ,pooling階段保留 k 個最大的信息,保留了全局的序列信息。比如在情感分析場景,舉個例子:

            “ 我覺得這個地方景色還不錯,但是人也實在太多了 ”

雖然前半部分體現情感是正向的,全局文本表達的是偏負面的情感,利用 k-max pooling能夠很好捕捉這類信息。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM