文字分類(下)-卷積神經網路(CNN)在文字分類上的應用

致Great發表於2018-07-25

1 簡介

原先寫過兩篇文章,分別介紹了傳統機器學習方法在文字分類上的應用以及CNN原理,然後本篇文章結合兩篇論文展開,主要講述下CNN在文字分類上的應用。前面兩部分內容主要是來自兩位博主的文章(文章中已經給出原文連結),是對兩篇論文的解讀以及總結,基本上闡釋了CNN文字分類模型;後半部分講一個例項和專案實戰

2 論文1《Convolutional Neural Networks for Sentence Classification

模型結構

在短文字分析任務中,由於句子句長長度有限、結構緊湊、能夠獨立表達意思,使得CNN在處理這一類問題上成為可能,主要思想是將ngram模型與卷積操作結合起來

2.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.2 第一層卷積層:

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

2.3 池化層:

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

2.4 全連線+softmax層:

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

2.5 訓練方案

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

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

專案程式碼:CNN_sentence 以上部分內容來自:https://www.cnblogs.com/cl1024cl/p/6205012.html

3 論文2《A Sensitivity Analysis of (and Practitioners' Guide to) Convolutional Neural Networks for Sentence Classification

這篇論文主要工作是對“Convolutional Naural Networks for Sentence Classification”這篇論文的模型進行了各種各樣的對比試驗,並給出了調參的建議,進而得到了一些關於超引數的設定經驗。

3.1 調參實驗結論:

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

3.2 建議:

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

4 一個CNN做文字分類的簡單例子

I like this movie very much!
我們以上圖為例,圖上用紅色標籤標註了5部分,結合這5個標籤,具體解釋下整個過程的操作,來看看CNN如何解決文字分類問題的。

4.1 #sentence

上圖句子為“[I like this movie very much!” ,一共有兩個單詞加上一個感嘆號,關於這個標點符號,不同學者有不同的操作,比如去除標點符號。在這裡我們先不去除,那麼整個句子有7個詞,詞向量維度為5,那麼整個句子矩陣大小為7x5

4.2 #filters

filters的區域大小可以使不同的,在這裡取(2,3,4)3種大小,每種大小的filter有兩個不同的值的filter,所以一共是有6個filter。

4.3 #featuremaps

我們在句子矩陣和過濾器矩陣填入一些值,那麼我們可以更好理解卷積計算過程,這和CNN原理那篇文章一樣,

文字分類(下)-卷積神經網路(CNN)在文字分類上的應用
比如我們取大小為2的filter,最開始與句子矩陣的前兩行做乘積相加,得到0.6 x 0.2 + 0.5 x 0.1 + … + 0.1 x 0.1 = 0.51,然後將filter向下移動1個位置得到0.53.最終生成的feature map大小為(7-2+1x1)=6。 為了獲得feature map,我們新增一個bias項和一個啟用函式,比如Relu

4.4 #1max

因為不同大小的filter獲取到的feature map大小也不一樣,為了解決這個問題,然後新增一層max-pooling,選取一個最大值,相同大小的組合在一起 ###4.5 #concat1max 經過max-pooling操作之後,我們將固定長度的向量給sofamax,來預測文字的類別。

5 文字分類實戰

下面是利用Keras實現的CNN文字分類部分程式碼:

# 建立tensor
print("正在建立模型...")
inputs=Input(shape=(sequence_length,),dtype='int32')
embedding=Embedding(input_dim=vocabulary_size,output_dim=embedding_dim,input_length=sequence_length)(inputs)
reshape=Reshape((sequence_length,embedding_dim,1))(embedding)

# cnn
conv_0=Conv2D(num_filters,kernel_size=(filter_sizes[0],embedding_dim),padding='valid',kernel_initializer='normal',activation='relu')(reshape)
conv_1=Conv2D(num_filters,kernel_size=(filter_sizes[1],embedding_dim),padding='valid',kernel_initializer='normal',activation='relu')(reshape)
conv_2=Conv2D(num_filters,kernel_size=(filter_sizes[2],embedding_dim),padding='valid',kernel_initializer='normal',activation='relu')(reshape)

maxpool_0=MaxPool2D(pool_size=(sequence_length-filter_sizes[0]+1,1),strides=(1,1),padding='valid')(conv_0)
maxpool_1=MaxPool2D(pool_size=(sequence_length-filter_sizes[1]+1,1),strides=(1,1),padding='valid')(conv_1)
maxpool_2=MaxPool2D(pool_size=(sequence_length-filter_sizes[2]+1,1),strides=(1,1),padding='valid')(conv_2)


concatenated_tensor = Concatenate(axis=1)([maxpool_0, maxpool_1, maxpool_2])
flatten = Flatten()(concatenated_tensor)
dropout = Dropout(drop)(flatten)
output = Dense(units=2, activation='softmax')(dropout)
model=Model(inputs=inputs,outputs=output)
複製程式碼

執行結果

英文:

文字分類(下)-卷積神經網路(CNN)在文字分類上的應用
準訓練結果:驗證集76%左右

中文:

文字分類(下)-卷積神經網路(CNN)在文字分類上的應用
準訓練結果:驗證集91%左右 專案地址:https://github.com/yanqiangmiffy/Text-Classification-Application

6 相關資料

相關文章