# TextCNN學習筆記
論文原文: [Convolutional Neural Networks for Sentence Classification](https://arxiv.org/pdf/1408.5882.pdf)
[論文中文導讀&大部分資料參考](https://blog.csdn.net/oldmao_2001/article/details/101170988)
[Kereas運行](https://www.kaggle.com/code/hamishdickson/cnn-for-sentence-classification-by-yoon-kim/notebook)
## 預備知識 Word Vector(詞向量)
將文字轉化為向量,使的電腦可以理解,變為詞向量的形式。
那有什麼方法呢,本文介紹兩種經典方法,1-of-N Encoding跟Word Embedding,那當然還有其他方法如: Bag-of-Words,但在本文並不介紹。
先從1-of-N Encoding說起,那是一種簡單的方法,將句子中的個別"單字"對應字典中一個vector。那這種方法呢,大家應該可以很直觀的想像,詞向量的維度會隨字典的大小增加而增加,而這個向量含有的資訊密度是相當低的。另外,每個向量兩兩之間的內積皆為 0 ,也就是說我們無法從這些詞向量中得知詞與詞之間的關係。
![](https://hackmd.io/_uploads/rkiyMbKIh.png =500x300)
那對於文字而言呢,當然希望資訊密度高、維度少,而非如同1-of-N Encoding方式的資訊密度低、維度高的方式,對文字而言是非常沒有效率的。
因此,就有了Word Embedding(詞嵌入)的方式,透過將每個單字project到更高的dimensional上(雖然說更高,但實際會比Encoding方式低很多),那向量空間與空間中的詞向量有著一個特性,當詞與詞的意思越相近,他們在向量空間中就會越接近、兩者的夾角會越小。那這邊所謂相近的意思,可以用一個單字上下文之間出現的頻率來解釋,也就是說,你可以透過一個詞的上下文來理解這個詞的意思。更具體一點來說,當兩個詞常出現在相似的上下文中,那麼這兩個詞的兩個詞向量,在向量空間中會是接近的。
那有下面兩種方法可以進行:
* 隨機初始化詞向量矩陣
>這種方式很容易理解,就是使用 `self.embedding = torch.nn.Embedding(vocab_size, embed_dim)` 命令直接隨機生成個初始化的詞向量矩陣,此時的向量值符合正態分布N(0,1),embed_dim是指表征每個詞時,向量的維度(可自定義,如256)。對於隨機初始化詞向量矩陣的方式,詞向量文件的生成方式一般是將當前所有的文本數據(包括訓練數據、驗證數據、測試數據)進行切詞,再對所有詞進行聚合統計,保留詞的數量大於某個閾值(比如3)的詞,並進行索引編號(編號從1開始,0作為上面提到的不在詞向量文件中的其他詞的索引),進而生成詞向量文件。順便提一句,詞向量矩陣的初始化的方式也有很多種,比如Xavier、Kaiming初始化方法。
* 使用預訓練的詞向量文件初始化詞向量矩陣
> 本質上,詞向量矩陣的作用是實現文本的向量表征,因此,如何用更合適的向量表示文本,逐漸成為了一個熱門研究方向。預訓練的詞向量文件便是其中的一個研究成果,如通過word2vec、glove等預訓練模型生成的詞向量文件,通過大量的訓練數據,來生成詞的向量表征。
那為何不使用cluster的方式呢?從下圖中可以看到Word Class的方法中呢,透過建立各種類別,可以看到分成了動物、動作、植物三類,雖然這樣子讓我們知道了一些資訊,但這種方是沒辦法知道class與class之間的相對關係,相比詞嵌入而言資訊量是不足的。
![](https://hackmd.io/_uploads/HkTN7ltIh.png )
---
## 論文簡述
0. Abstract
-使用簡單的CNN模型在預訓練詞向量基本上進行微調就可以在文本分類任務上得到很好的結果。
-通過對詞向量進行微調而獲得的任務指向的詞向量能夠得到更好的結果。
-我們也提出了一種即使用靜態預訓練詞向量又使用任務指向詞向量的文本分類模型
-最終我們在7個文本分類任務中的4個上都取得了最好的分類準確率。
1. Introduction
-Deep Learning的發展
-詞向量發展&介紹
-CNN發展&在NLP中的運用
-本項目的簡介
-其他類似項目的對於本文貢獻
2. Model
-模型架構
2.1 Regularization
-使用正則化來提高模型泛化能力
3. Datasets and Experimental Setup
-實驗使用的Dataset
3.1 Hyperparameters and Training
-訓練配置
3.2 Pre-trained Word Vectors
-使用預訓練詞向量
3.3 Model Variations
-本論文研究模型的不同變體
4. Results and Discussion
-實驗結果簡述
4.1 Multichannel vs.Single Channel Models
-單通道與多通道差異
4.2 Static vs.Non-static Representations
-靜態與非靜態模型的表現
4.3 Further Observations
-其餘觀察
5. Conclusion
關鍵點
-預訓練的詞向量—Word2Vec、Glove
-卷積神經網絡結構—一維卷積、池化層
-超參選擇—卷積核選擇、詞向量方式選擇
創新點
-提出了基於CNN的文本分類模型TextCNN
-提出了多種詞向量設置方式
-在四個文本分類任務上取得最優的結果
-對超參進行大量實驗和分析
啟發點
-在預訓練模型的基礎上微調就能夠得到非常好的結果,這說明預訓練詞向量學習到了一些通用的特征。
-在預訓練詞向量的基礎上使用簡單模型比覆雜模型表現的還要好
-對於不在預訓練詞向量中的詞,微調能夠使得它們能夠學習更多的意義。
---
## Model 模型架構
![](https://hackmd.io/_uploads/B17xbaFIh.png )
*<center>圖為TextCNN模型架構</center>*
### 輸入層Input Layer
輸入層的作用就是將輸入文本切詞後,通過詞向量文件及詞向量矩陣,將文本向量化,後續才能進行卷積池化等操作。具體來說,分為以下幾步:
* **文本切詞**
將輸入文本切分為若干個詞。例如“wait for the video and don't rent it”,分詞後變為【“wait”, “for”, “the”, “video”, “and”,“do”,“n't”,“rent”,“it”】。除了文本輸入時,需要進行切詞,接下來要介紹的詞向量,在構建詞向量文件時,也需要進行切詞操作。
* **詞向量矩陣初始化**
先簡要介紹下詞向量文件及詞向量矩陣。詞向量文件的表現形式,通常是json文件,以dict形式存在,如{"wait": 1, "for": 2, ……},詞向量文件的作用是,在對輸入文本進行切詞後,需要獲取每個詞的向量表征,則先通過詞向量文件獲取詞對應的索引,再通過索引在詞向量矩陣中獲取詞的向量表征。詞向量矩陣及詞向量文件生成的兩種方式,有<font color=#FF0000>隨機初始化詞向量矩陣</font>跟<font color=#FF0000>預訓練的詞向量文件初始化詞向量矩陣</font>,詳細可以參考文章上分"詞向量"的部分
* **輸入文本向量化**
經過上述兩步,輸入文本已經完成分詞,且詞向量矩陣也完成初始化,這時便可對輸入文本進行向量化操作,總結下,會根據文本切詞後,每個詞在詞向量文件中的索引,確定這個詞在詞向量矩陣中的位置,從而獲取這個詞的向量表征,最終組合出輸入文本的向量表征,即輸入文本對應的向量矩陣,這個矩陣的直行和詞向量矩陣的行數一致,橫列不固定了,依賴於文本切詞後詞的數量。
那根據上面步驟過後就可以得到論文中模型輸入層的架構 $n\times k$ 的矩陣,$n$ 代表了最長句子中的單詞個數(文章中為64,不足的可用padding),$k$則是詞向量的維度數(文章中為300),$x_i\in R_k$ 代表句子中第 $i$ 個單字的 $k$ 維詞向量,那長度為 $n$ 的句子就可以表示為 $x_{1:n}= x_1\bigoplus x_2\bigoplus ...x_n$,其中 $\bigoplus$ 代表的是連接運算符,這便是TextCNN的輸入層架構。
### 卷積層Convolutional Layer
卷積和(kernel/fliter)為$\bf w$, $\bf w\in \mathbb{R}^{hk}$ 用高度為 $h$ 的窗口來產生新的特徵,舉例來說特徵 $c_i$ 是由高度 $h$ 的窗口為 $x_{i:i+h-1}$ 產生的,可以用 $c_i=f(w \cdot x_{i:i+h-1}+ b )$ 來表示,其中 $b$ 為bias,$f$為非線性函數(像是tanh),那對於所有fliter $\bf w$ 產生的feature map 就可以用 $c=[c_1,c_2,...,C_{n-h+1}]$ 來表示。
那在上圖呢可以看到有黃色的h=3跟紅色的h=2,以h=2來說就是用周圍兩個詞來預測中間的詞,那這種方法被稱為n-gram。
### 池化層Pooling Layer
對$\hat{c}=max \lbrace c \rbrace$,對C的每一維都取最大值,可以得知值越大代表越重要,同時另一個作用是可以處理長度會變長的句子(因為最後仍是取最大值,只會有一個輸出),最後再將結果聚合得到$z=[\hat c_1,...,\hat c_m]$
### 全連接層Fulled-connected Layer
透過池化層聚合後獲得的輸出Z,透過帶dropout的全連接層softmax函數來獲得個類別的機率分佈
### 正則化
為了防止過擬合問題
$y=w \cdot z+b$
在倒數第二層網路,加上Dropout(一定機率p使得神經元不工作,以增加泛化能力),r為失活向量有機率為1,否則為0,那就會變成
$y=w \cdot (z⊙r)+b$
並且對$w$進行L2正則化,當$||w||_2 > s$時,會重新縮放使$||w||_2 = s$
---
## Datasets and Experimental Setup(引用上方論文中文導讀)
### Dataset
MR:電影評論極性判斷數據集
SST-1:斯坦福情感分類標準數據集(5類:(very positive, positive, neutral, negative, very negative)
SST-2:斯坦福情感二分類數據集
Subj:主客觀判斷數據集
TREC:TREC問題類型數據集
CR:商品(cameras, MP3s etc.)評價極性判斷數據集
MPQA:MPQA的觀點極性判斷數據集
下表中,c代表分類數量
l應該是句子的最大長度
N是數據集大小
V是詞表大小
Vpre是在預訓練詞表中出現的單詞數量
test表示是否劃分驗證集,如果沒有劃分則采用CV(cross valid交叉驗證的方式劃分)
![](https://hackmd.io/_uploads/B1FqXG5U2.png =450x350)
### 參數設置
部份超參數設置:
線性整流單元
filter windows (h): 3, 4, 5
卷積核特征圖大小:100
Dropout概率:0.5
L2正則化約束:3
batchsize:50
優化算法:
Adadelta
預訓練詞向量:
word2vec/random
### 實驗設置
CNN-rand: 詞向量隨機初始化,同時當做訓練過程中優化的參數;Baseline
CNN-static: 詞向量使用word2vec,同時固定不變;如果沒有在詞表出現的單詞則隨機初始化
CNN-non-static: 詞向量使用word2vec,但是會在訓練過程中微調(fine tuned);
CNN-multichannel: CNN-static和CNN-non-static的混合版本,即有兩種類型的輸入
---
## Experiment Results(引用上方論文中文導讀)
![](https://hackmd.io/_uploads/ByHdHGcU2.png)
實驗主要對比了之前基於機器學習和人工特征的方法,整體來看:
隨機初始化詞向量(CNN-rand)的方法性能並不好;
使用預訓練詞向量(CNN-static)的方法效果普遍較好;
對預訓練詞向量進行微調(CNN-non-static)效果又有提升;
CNN-multichannel在小規模的數據集上有更好的表現,體現了一種折中思想,即既不希望微調後的詞向量距離原始值太遠,但又允許其具有一定的變化空間。
![](https://hackmd.io/_uploads/BkrKSM9In.png)
原始的詞向量訓練結果中,bad對應的最相近詞為good,因為其上下文語境是極其類似的;在non-static的版本中,bad對應的最相近詞為terrible,因為在微調的過程中,詞向量值發生改變,從而更加貼切任務數據集(這里是一個情感分類的數據集)句子中的【!】最接近一些表達形式較為激進的詞匯,如lush等;而【,】則接近於一些連接詞,這和我們的主觀感受也是相符的。
---
## 結論
在這項研究中,我們描述了一系列基於word2vec的卷積神經網絡的實驗。盡管幾乎沒有進行超參數的調整,但只有一層卷積的簡單CNN表現得相當出色。我們的結果進一步證實了這樣一個既定的事實,那就是在深度學習的自然語言處理(NLP)中,無監督預訓練詞向量是一個重要的步驟。
TextCNN 的優勢:
TextCNN最大優勢網絡結構簡單 ,在模型網絡結構如此簡單的情況下,通過引入已經訓練好的詞向量依舊有很不錯的效果,在多項數據數據集上超越benchmark。
網絡結構簡單導致參數數目少, 計算量少, 訓練速度快,在單機單卡的v100機器上,訓練165萬數據, 疊代26萬步,半個小時左右可以收斂。
TextCNN 的缺點:
模型可解釋型不強,在調優模型的時候,很難根據訓練的結果去針對性的調整具體的特征,因為在textCNN中沒有類似gbdt模型中特征重要度(feature importance)的概念, 所以很難去評估每個特征的重要度。
----
## 心得
目前在台灣的語料庫很少,是個不錯的方向。
---
## 參考資料
https://tw.coderbridge.com/series/2ec9cf0af3f74ed99371952f4849ae33/posts/0c71ef945cf14e2da414e4a31b1f4381
https://zhuanlan.zhihu.com/p/129808195
https://zhuanlan.zhihu.com/p/553032432