最近一直在研究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 最大的不同便是在輸入數據的不同:
-
圖像是二維數據, 圖像的卷積核是從左到右, 從上到下進行滑動來進行特征抽取。
-
自然語言是一維數據, 雖然經過word-embedding 生成了二維向量,但是對詞向量做從左到右滑動來進行卷積沒有意義. 比如 "今天" 對應的向量[0, 0, 0, 0, 1], 按窗口大小為 1* 2 從左到右滑動得到[0,0], [0,0], [0,0], [0, 1]這四個向量, 對應的都是"今天"這個詞匯, 這種滑動沒有幫助.
TextCNN的成功, 不是網絡結構的成功, 而是通過引入已經訓練好的詞向量來在多個數據集上達到了超越benchmark 的表現,進一步證明了構造更好的embedding, 是提升nlp 各項任務的關鍵能力。
二. TextCNN 的優勢
-
TextCNN最大優勢網絡結構簡單 ,在模型網絡結構如此簡單的情況下,通過引入已經訓練好的詞向量依舊有很不錯的效果,在多項數據數據集上超越benchmark。
-
網絡結構簡單導致參數數目少, 計算量少, 訓練速度快,在單機單卡的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 從 三維變成了一維, 好處有如下兩點:
-
降低了過擬合的風險, feature map = [1, 1, 2] 或者[1, 0, 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的具體的代碼實現。