NLP(十):pytorch實現中文文本分類


一、前言

參考:https://zhuanlan.zhihu.com/p/73176084

代碼:https://link.zhihu.com/?target=https%3A//github.com/649453932/Chinese-Text-Classification-Pytorch

代碼:https://link.zhihu.com/?target=https%3A//github.com/649453932/Bert-Chinese-Text-Classification-Pytorch

使用pytorch實現了TextCNN,TextRNN,FastText,TextRCNN,BiLSTM_Attention,DPCNN,Transformer。github:Chinese-Text-Classification-Pytorch,開箱即用。

二、中文數據集:

我從THUCNews中抽取了20萬條新聞標題,文本長度在20到30之間。一共10個類別,每類2萬條。

以字為單位輸入模型,使用了預訓練詞向量:搜狗新聞 Word+Character 300d

類別:財經、房產、股票、教育、科技、社會、時政、體育、游戲、娛樂。

數據集、詞表及對應的預訓練詞向量已上傳至github,開箱即用。

模型效果:

bert,ERNIE代碼:Bert-Chinese-Text-Classification-Pytorch

1.TextCNN

TextCNN整體結構

數據處理:所有句子padding成一個長度:seq_len

1.模型輸入:
[batch_size, seq_len]

2.經過embedding層:加載預訓練詞向量或者隨機初始化, 詞向量維度為embed_size:
[batch_size, seq_len, embed_size]

3.卷積層:NLP中卷積核寬度與embed-size相同,相當於一維卷積。
3個尺寸的卷積核:(2, 3, 4),每個尺寸的卷積核有100個。卷積后得到三個特征圖:[batch_size, 100, seq_len-1]
[batch_size, 100, seq_len-2]
[batch_size, 100, seq_len-3]

4.池化層:對三個特征圖做最大池化
[batch_size, 100]
[batch_size, 100]
[batch_size, 100]

5.拼接:
[batch_size, 300]

6.全連接:num_class是預測的類別數
[batch_size, num_class]

7.預測:softmax歸一化,將num_class個數中最大的數對應的類作為最終預測
[batch_size, 1]

分析:
卷積操作相當於提取了句中的2-gram,3-gram,4-gram信息,多個卷積是為了提取多種特征,最大池化將提取到最重要的信息保留。

2.TextRNN

圖片是單向RNN,看個意思就行

1.模型輸入: [batch_size, seq_len]

2.經過embedding層:加載預訓練詞向量或者隨機初始化, 詞向量維度為embed_size: [batch_size, seq_len, embed_size]

3.雙向LSTM:隱層大小為hidden_size,得到所有時刻的隱層狀態(前向隱層和后向隱層拼接)
[batch_size, seq_len, hidden_size * 2]

4.拿出最后時刻的隱層值:
[batch_size, hidden_size * 2]

5.全連接:num_class是預測的類別數
[batch_size, num_class]

6.預測:softmax歸一化,將num_class個數中最大的數對應的類作為最終預測
[batch_size, 1]

分析:
LSTM能更好的捕捉長距離語義關系,但是由於其遞歸結構,不能並行計算,速度慢。

3.TextRNN+Attention

BiLSTM+Attention

1.模型輸入: [batch_size, seq_len]

2.經過embedding層:加載預訓練詞向量或者隨機初始化, 詞向量維度為embed_size: [batch_size, seq_len, embed_size]

3.雙向LSTM:隱層大小為hidden_size,得到所有時刻的隱層狀態(前向隱層和后向隱層拼接) [batch_size, seq_len, hidden_size * 2]

4.初始化一個可學習的權重矩陣w
w=[hidden_size * 2, 1]

5.對LSTM的輸出進行非線性激活后與w進行矩陣相乘,並經行softmax歸一化,得到每時刻的分值:
[batch_size, seq_len, 1]

6.將LSTM的每一時刻的隱層狀態乘對應的分值后求和,得到加權平均后的終極隱層值
[batch_size, hidden_size * 2]

7.對終極隱層值進行非線性激活后送入兩個連續的全連接層
[batch_size, num_class]

8.預測:softmax歸一化,將num_class個數中最大的數對應的類作為最終預測
[batch_size, 1]

分析:
其中4~6步是attention機制計算過程,其實就是對lstm每刻的隱層進行加權平均。比如句長為4,首先算出4個時刻的歸一化分值:[0.1, 0.3, 0.4, 0.2],然后

[公式]

4.TextRCNN

left context是前向RNN的隱層值,right context是后向RNN的隱層值。

1.模型輸入: [batch_size, seq_len]

2.經過embedding層:加載預訓練詞向量或者隨機初始化, 詞向量維度為embed_size: [batch_size, seq_len, embed_size]

3.雙向LSTM:隱層大小為hidden_size,得到所有時刻的隱層狀態(前向隱層和后向隱層拼接) [batch_size, seq_len, hidden_size * 2]

4.將embedding層與LSTM輸出拼接,並進行非線性激活:
[batch_size, seq_len, hidden_size * 2 + embed_size]

5.池化層:seq_len個特征中取最大的
[batch_size, hidden_size * 2 + embed_size]

6.全連接后softmax
[batch_size, num_class] ==> [batch_size, 1]

分析:
雙向LSTM每一時刻的隱層值(前向+后向)都可以表示當前詞的前向和后向語義信息,將隱藏值與embedding值拼接來表示一個詞;然后用最大池化層來篩選出有用的特征信息。emm...就做了一個池化,就能稱之為RCNN...
需要注意的是,我的實現和論文中略有不同,論文中其實用的不是我們平時見的RNN,其實從圖中能看出來,看公式的區別:

傳統RNN:

[公式]

論文中:

符號看不懂不要緊,我給轉換一下:

[公式]

 

5.FastText

簡單粗暴的FastText

0.用哈希算法將2-gram、3-gram信息分別映射到兩張表內。

1.模型輸入: [batch_size, seq_len]

2.embedding層:隨機初始化, 詞向量維度為embed_size,2-gram和3-gram同理:
word: [batch_size, seq_len, embed_size]
2-gram:[batch_size, seq_len, embed_size]
3-gram:[batch_size, seq_len, embed_size]

3.拼接embedding層:
[batch_size, seq_len, embed_size * 3]

4.求所有seq_len個詞的均值
[batch_size, embed_size * 3]

5.全連接+非線性激活:隱層大小hidden_size
[batch_size, hidden_size]

6.全連接+softmax歸一化:
[batch_size, num_class]==>[batch_size, 1]

分析:
不加N-Gram信息,就是詞袋模型,准確率89.59%,加上2-gram和3-gram后准確率92.23%。N-Gram的哈希映射算法見utils_fasttext.py中注釋------gram-------處。
N-Gram的詞表我設的25W,相對於前面幾個模型,這個模型稍慢一點,FastText被我搞成SlowText了。。?但是效果不錯呀。。哈哈

有人私信問我這個N-Gram,我大體講一下。對於N-Gram,我們設定一個詞表,詞表大小自己定,當然越大效果越好,但是你得結合實際情況,對於2-Gram,5000個字(字表大小)的兩兩組合有多少種你算算,3-Gram的組合有多少種,組合太多了,詞表設大效果是好了,但是機器它受不了啊。
所以N-Gram詞表大小的設定是要適中的,那么適中的詞表就放不下所有N-Gram了,不同的N-Gram用哈希算法可能會映射到詞表同一位置,這確實是個弊端,但是問題不大:5000個字不可能每兩個字都兩兩組合出現,很多兩個字是永遠不會組成2-Gram的,所以真正出現的N-Gram不會特別多,映射到同一詞表位置的N-Gram也就不多了。
N-Gram詞表大小我定的25w,比較大了,比小詞表訓練慢了很多,效果也提升了。這么形容N-Gram詞表大小對效果的影響吧:一分價錢1分貨,十分價錢1.1分貨。

 

6.DPCNN

1.模型輸入: [batch_size, seq_len]

2.經過embedding層:加載預訓練詞向量或者隨機初始化, 詞向量維度為embed_size: [batch_size, seq_len, embed_size]

3.進行卷積,250個尺寸為3的卷積核,論文中稱這層為region embedding。
[batch_size, 250, seq_len - 3 + 1]

4.接兩層卷積(+relu),每層都是250個尺寸為3的卷積核,(等長卷積,先padding再卷積,保證卷積前后的序列長度不變)
[batch_size, 250, seq_len - 3 + 1]

5.接下來進行上圖中小框中的操作。
I. 進行 大小為3,步長為2的最大池化,將序列長度壓縮為原來的二分之一。(進行采樣)
II. 接兩層等長卷積(+relu),每層都是250個尺寸為3的卷積核。
III. I的結果加上II的結果。(殘差連接)
重復以上操作,直至序列長度等於1。
[batch_size, 250, 1]

6.全連接+softmax歸一化:
[batch_size, num_class]==>[batch_size, 1]

分析:
TextCNN的過程類似於提取N-Gram信息,而且只有一層,難以捕捉長距離特征。
反觀DPCNN,可以看出來它的region embedding就是一個去掉池化層的TextCNN,再將卷積層疊加。

每層序列長度都減半(如上圖所示),可以這么理解:相當於在N-Gram上再做N-Gram。越往后的層,每個位置融合的信息越多,最后一層提取的就是整個序列的語義信息。

7.Transformer

代碼已上傳

# TODO:圖文

總結

再貼一遍github地址:Chinese-Text-Classification-Pytorch,覺得有用別忘了回來點贊。如果代碼中有問題或者有什么建議,歡迎提出。之后會更新中文的長文本數據集和英文數據集,敬請期待,這個倉庫我會一直更新維護,歡迎關注!

Reference:

[1] Convolutional Neural Networks for Sentence Classification
[2] A Sensitivity Analysis of Convolutional Neural Networks for Sentence Classification
[3] Recurrent Neural Network for Text Classification with Multi-Task Learning
[4] Attention-Based Bidirectional Long Short-Term Memory Networks for Relation Classification
[5] Recurrent Convolutional Neural Networks for Text Classification
[6] Bag of Tricks for Efficient Text Classification
[7] Deep Pyramid Convolutional Neural Networks for Text Categorization
[8] Attention Is All You Need


免責聲明!

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



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