1. 程式人生 > >【原創】TextCNN原理詳解(一)

【原創】TextCNN原理詳解(一)

  最近一直在研究textCNN演算法,準備寫一個系列,每週更新一篇,大致包括以下內容:

  • TextCNN基本原理和優劣勢
  • TextCNN程式碼詳解(附Github連結)
  • TextCNN模型實踐迭代經驗總結
  • TextCNN模型部署Tf-Serving實踐總結

  今天主要講TextCNN的基本原理和優劣勢,包括網路結構、如何更新引數以及應用場景等。

 

一. TextCNN 是什麼

  我們之前提前CNN時,通常會認為是屬於CV領域,用於計算機視覺方向的工作,但是在2014年,Yoon Kim針對CNN的輸入層做了一些變形,提出了文字分類模型textCNN。與傳統影象的CNN網路相比, textCNN 在網路結構上沒有任何變化(甚至更加簡單了), 從圖一可以看出textCNN 其實只有一層卷積,一層max-pooling, 最後將輸出外接softmax 來n分類。

 

圖一 textCNN 架構

  與影象當中CNN的網路相比,textCNN 最大的不同便是在輸入資料的不同:

  1. 影象是二維資料, 影象的卷積核是從左到右, 從上到下進行滑動來進行特徵抽取。 

  2. 自然語言是一維資料, 雖然經過word-embedding 生成了二維向量,但是對詞向量做從左到右滑動來進行卷積沒有意義. 比如 "今天" 對應的向量[0, 0, 0, 0, 1], 按視窗大小為 1* 2 從左到右滑動得到[0,0], [0,0], [0,0], [0, 1]這四個向量, 對應的都是"今天"這個詞彙, 這種滑動沒有幫助.

 

  TextCNN的成功, 不是網路結構的成功, 而是通過引入已經訓練好的詞向量來在多個數據集上達到了超越benchmark 的表現,進一步證明了構造更好的embedding, 是提升nlp 各項任務的關鍵能力。

 


 

二. TextCNN 的優勢

  1. TextCNN最大優勢網路結構簡單 ,在模型網路結構如此簡單的情況下,通過引入已經訓練好的詞向量依舊有很不錯的效果,在多項資料資料集上超越benchmark。 

  2. 網路結構簡單導致引數數目少, 計算量少, 訓練速度快,在單機單卡的v100機器上,訓練165萬資料, 迭代26萬步,半個小時左右可以收斂。

 

 


 

三.textCNN 的流程

1.Word Embedding 分詞構建詞向量

  如圖二所示, textCNN 首先將 "今天天氣很好,出來玩" 分詞成"今天/天氣/很好/,/出來/玩, 通過word2vec或者GLOV 等embedding 方式將每個詞成對映成一個5維(維數可以自己指定)詞向量, 如 "今天" -> [0,0,0,0,1], "天氣" ->[0,0,0,1,0], "很好" ->[0,0,1,0,0]等等。

圖二 Word Embedding

 

  這樣做的好處主要是將自然語言數值化,方便後續的處理。從這裡也可以看出不同的對映方式對最後的結果是會產生巨大的影響, nlp 當中目前最火熱的研究方向便是如何將自然語言對映成更好的詞向量。我們構建完詞向量後,將所有的詞向量拼接起來構成一個6*5的二維矩陣,作為最初的輸入

 

2. Convolution 卷積

圖三 卷積示意圖

卷積是一種數學運算元。我們用一個簡單的例子來說明一下

 

step.1 將 "今天"/"天氣"/"很好"/"," 對應的4*5 矩陣 與卷積核做一個point wise 的乘法然後求和, 便是卷積操作:

feature_map[0] =0*1 + 0*0 + 0*1 + 0*0 + 1*0  +   //(第一行)

                             0*0 + 0*0 + 0*0 + 1*0 + 0*0 +   //(第二行)

                             0*1 + 0*0 + 1*1  + 0*0 + 0*0 +   //(第三行)

                             0*1 + 1*0  + 0*1 + 0*0 + 0*0      //(第四行)

                           = 1

 

step.2 將視窗向下滑動一格(滑動的距離可以自己設定),"天氣"/"很好"/","/"出來" 對應的4*5 矩陣 與卷積核(權值不變) 繼續做point wise 乘法後求和

feature_map[1]  = 0*1 + 0*0 + 0*1 + 1*0  +  0*0  +   //(第一行)

                             0*0 + 0*0 + 1*0 + 0*0 +  0*0 +   //(第二行)

                             0*1 + 1*0 +  0*1 + 0*0 +  0*0 +   //(第三行)

                             1*1 + 0*0  + 0*1 + 0*0 +  0*0       //(第四行)

                          = 1

 

step.3 將視窗向下滑動一格(滑動的距離可以自己設定) "很好"/","/"出來"/"玩" 對應的4*5 矩陣 與卷積核(權值不變) 繼續做point wise 乘法後求和

feature_map[2] = 0*1 + 0*0 + 1*1  + 1*0 + 0*0  +   //(第一行)

                             0*0 + 1*0 + 0*0 + 0*0 + 0*0 +   //(第二行)

                             1*1 + 0*0 +  0*1 + 0*0 + 0*0 +   //(第三行)

                             0*1 + 0*0  + 0*1 + 1*0 + 1*0       //(第四行)

                          = 2

 

  feature_map 便是卷積之後的輸出, 通過卷積操作 將輸入的6*5 矩陣對映成一個 3*1 的矩陣,這個對映過程和特徵抽取的結果很像,於是便將最後的輸出稱作feature map。一般來說在卷積之後會跟一個啟用函式,在這裡為了簡化說明需要,我們將啟用函式設定為f(x) = x

 

3. 關於channel 的說明

圖四 channel 說明

  在CNN 中常常會提到一個詞channel, 圖三 中 深紅矩陣與 淺紅矩陣 便構成了兩個channel 統稱一個卷積核, 從這個圖中也可以看出每個channel 不必嚴格一樣, 每個4*5 矩陣與輸入矩陣做一次卷積操作得到一個feature map. 在計算機視覺中,由於彩色影象存在 R, G, B 三種顏色, 每個顏色便代表一種channel。

  根據原論文作者的描述, 一開始引入channel 是希望防止過擬合(通過保證學習到的vectors 不要偏離輸入太多)來在小資料集合獲得比單channel更好的表現,後來發現其實直接使用正則化效果更好。

  不過使用多channel 相比與單channel, 每個channel 可以使用不同的word embedding, 比如可以在no-static(梯度可以反向傳播) 的channel 來fine tune 詞向量,讓詞向量更加適用於當前的訓練。 

  對於channel在textCNN 是否有用, 從論文的實驗結果來看多channels並沒有明顯提升模型的分類能力, 七個資料集上的五個資料集 單channel 的textCNN 表現都要優於 多channels的textCNN。

 

圖五 textCNN 實驗

我們在這裡也介紹一下論文中四個model 的不同

  • CNN-rand (單channel), 設計好 embedding_size 這個 Hyperparameter 後, 對不同單詞的向量作隨機初始化, 後續BP的時候作調整.

  • CNN-static(單channel), 拿 pre-trained vectors from word2vec, FastText or GloVe 直接用, 訓練過程中不再調整詞向量.

  • CNN-non-static(單channel), pre-trained vectors + fine tuning , 即拿word2vec訓練好的詞向量初始化, 訓練過程中再對它們微調.

  • CNN-multiple channel(多channels), 類比於影象中的RGB通道, 這裡也可以用 static 與 non-static 搭兩個通道來做.

 

4.max-pooling

 

圖六: max-pooling 說明

  得到feamap = [1,1,2] 後, 從中選取一個最大值[2] 作為輸出, 便是max-pooling。max-pooling 在保持主要特徵的情況下, 大大降低了引數的數目, 從圖五中可以看出 feature map 從 三維變成了一維, 好處有如下兩點: 

  1. 降低了過擬合的風險, feature map = [1, 1, 2] 或者[1, 0, 2] 最後的輸出都是[2], 表明開始的輸入即使有輕微變形, 也不影響最後的識別。

  2. 引數減少, 進一步加速計算。

  pooling 本身無法帶來平移不變性(圖片有個字母A, 這個字母A 無論出現在圖片的哪個位置, 在CNN的網路中都可以識別出來),卷積核的權值共享才能. 

  max-pooling的原理主要是從多個值中取一個最大值,做不到這一點。cnn 能夠做到平移不變性,是因為在滑動卷積核的時候,使用的卷積核權值是保持固定的(權值共享), 假設這個卷積核被訓練的就能識別字母A, 當這個卷積核在整張圖片上滑動的時候,當然可以把整張圖片的A都識別出來。

 

5.使用softmax k分類

圖六:softmax 示意圖

  如圖六所示, 我們將 max-pooling的結果拼接起來, 送入到softmax當中, 得到各個類別比如 label 為1 的概率以及label 為-1的概率。如果是預測的話,到這裡整個textCNN的流程遍結束了。

   如果是訓練的話,此時便會根據預測label以及實際label來計算損失函式, 計算出softmax 函式,max-pooling 函式, 啟用函式以及卷積核函式 四個函式當中引數需要更新的梯度, 來依次更新這四個函式中的引數,完成一輪訓練 。

 


 

五.textCNN的總結

  本次我們介紹的textCNN是一個應用了CNN網路的文字分類模型。

  • textCNN的流程:先將文字分詞做embeeding得到詞向量, 將詞向量經過一層卷積,一層max-pooling, 最後將輸出外接softmax 來做n分類。 

  • textCNN 的優勢:模型簡單, 訓練速度快,效果不錯。

  • textCNN的缺點:模型可解釋型不強,在調優模型的時候,很難根據訓練的結果去針對性的調整具體的特徵,因為在textCNN中沒有類似gbdt模型中特徵重要度(feature importance)的概念, 所以很難去評估每個特徵的重要度。 

  關於如何調優textCNN的經驗總結,會在第三篇來總結,在下一篇,我們會來聊聊textCNN的具體的程式碼實