1 文本分類
文本分類是自然語言處理領域最活躍的研究方向之一,目前文本分類在工業界的應用場景非常普遍,從新聞的分類、商品評論信息的情感分類到微博信息打標簽輔助推薦系統,了解文本分類技術是NLP初學者比較好的切入點,較簡單且應用場景高頻。
2 數據準備
數據決定了模型最終的高度,不斷優化的模型只不過是為了不斷逼近這個高度而已。
文本分類作為一種有監督學習的任務,毫無疑問的需要一個可用于有監督學習的語料集(X,Y)。本文中使用以下標記,X為特征,文本分類中即為文本序列,Y是標簽,即文本的分類名稱。
機器學習與傳統編程技術的明顯區別就是機器學習是以數據為驅動的,傳統的編程中,我們核心任務是人工設計分類規則(指令代碼),然后實現輸入特征X獲得分類標簽Y。而在機器學習的方式中,我們首要的是獲得一個高質量的、大數據量的有監督語料集(X,Y),然后機器學習的方式會自動的從已構建的數據集上歸納出(訓練出)一套分類規則(分類模型),最后我們利用獲得的分類規則來實現對未標記文本的分類。
傳統的編程方式輸入的是指令代碼,而機器學習輸入的是結構化數據。
因此,在機器學習任務中,數據的質量與數量對最終模型的預測結果好壞具有決定性的作用。
在文本分類中,語料集(X,Y)的質量、數量決定了文本分類模型的分類效果。
語料集的質量:即數據集的特征X對應的標簽Y是否標記的正確,一般在眾包平臺中會采用多人重復標記,然后基于投票的機制來控制語料集的標記質量。
語料集的數量:有監督語料集的標注復雜度,想要獲得海量的高質量語料集的成本是十分高昂的,這也限制的語料集的數量。
在實際的文本分類任務中,一般通過搜集開源的數據集,或者利用爬蟲獲取結構化的網頁信息來構建特定任務的語料集。不過,我還是更喜歡關注一些公開的競賽項目,能夠獲得企業準備的高質量、應對真實業務場景的數據集,例如:kaggle、知乎的看山杯、mrc2018-cipsc等,但大多數情況下企業只給脫敏之后的數據。
搜狗的新聞語料集:http://www.sogou.com/labs/resource/cs.php
3 文本的預處理
文本的預處理,主要針對剔除無意義的符號信息,或其它的冗余信息。
例如,在使用爬蟲獲取的語料集上可能存在一些html標簽,這些符號對于文本分類任務來說應該是冗余的無意義信息,可以剔除掉。
針對中文、日語等無空格切分字詞的語言,還需要進行分詞處理,將一段文本序列劃分為合理的詞(字)序列。
英文中天生的就有空格把每個詞匯分割開來,所以不需要分詞操作,但由于英文存在時態、縮寫等問題,在預處理階段會有詞干提取、詞性還原、大小寫轉換等。
去除停用詞。
中文分詞的工具有非常多的方案,我一般習慣于使用Python版的JieBa分詞工具包來進行分詞的操作,使用非常的簡單,使用pip install jieba就可以很方便的安裝該工具包,jieba常用的API可以查看GitHub主頁的實例。
分詞工具:
中科院計算所NLPIRhttp://ictclas.nlpir.org/nlpir/
ansj分詞器https://github.com/NLPchina/ansj_seg
哈工大的LTPhttps://github.com/HIT-SCIR/ltp
清華大學THULAChttps://github.com/thunlp/THULAC
斯坦福分詞器,Java實現的CRF算法。https://nlp.stanford.edu/software/segmenter.shtml
Hanlp分詞器,求解的是最短路徑。https://github.com/hankcs/HanLP
結巴分詞,基于前綴詞典,生成句子中所有可能成詞所構成的有向無環圖 (DAG),采用動態規劃查找最大概率路徑, 找出基于詞頻的最大切分組合,對于未登錄詞,采用了 HMM 模型,使用 Viterbi 算法。https://github.com/yanyiwu/cppjieba
KCWS分詞器(字嵌入+Bi-LSTM+CRF),本質上是序列標注。https://github.com/koth/kcws
ZParhttps://github.com/frcchang/zpar/releases
IKAnalyzerhttps://github.com/wks/ik-analyzer
4 文本的數值化【詞向量技術】
文本的數值化,即使用數字代表特定的詞匯,因為計算機無法直接處理人類創造的詞匯。為了讓計算機能夠理解詞匯,我們需要將詞匯信息映射到一個數值化的語義空間中,這個語義空間我們可以稱之為詞向量空間(詞向量模型)。
文本的數值化方式有很多種,例如:TF-IDF、BOW、One-Hot、分布式的表示方式(word2vec、Glove)等。
一般常用的就是最經典的word2vec工具,該工具在NLP領域具有非常重要的意義!
word2ve工具,它是一種無監督的學習模型,可以在一個語料集上(不需要標記,主要思想是“具有相似鄰近詞分布的中心詞之之間具有一定的語義相似度”),實現詞匯信息到語義空間的映射,最終獲得一個詞向量模型(每個詞匯對應一個指定維度的數組)。
它的核心優勢就是實現了兩個詞匯信息之間的語義相似度的可計算性,也可以理解為是一種遷移學習的思想,word2vec獲取的意義空間信息作為后續文本分類模型的輸入。
python 中使用word2vec工具也是非常的便利,通過pip install gensim安裝gensim工具包,此包匯總包含了word2vec工具。
Gensim官網:https://radimrehurek.com/gensim/models/word2vec.html
深度學習中將單詞表示成向量是很普遍的情況,深度學習模型以詞向量序列的形式讀取序列化的單詞,而不是以文本的形式。
今天大多數用于自然語言處理的深度學習模型都依賴詞向量來代表單個單詞的含義。對于不太熟悉這領域的人而言,可以這樣簡單的理解:我們把每一種語言中的每一個單詞都與一串被叫做向量的數字聯系起來了。
以上就是深度學習模型需要的數據格式的核心處理流程,在整個處理過程中樣本數據的處理流程如下圖所示:
5 文本分類模型
文本分類模型,可以大體上分為基于傳統機器學習的文本分類模型,基于深度學習的文本分類模型,目前基于深度學習模型的文本分類模型已經成為了主流,下面基于CNN的文本分類模型。
文本分類模型,從最經典的2013年Kim提出Text-CNN模型開始,深度學習模型在文本分類任務上具有廣泛的應用。2016年Kim跳槽FaceBook后提出了工業界的文本分類模型的“新寵”—FastText。
為了實現文本分類模型,需要借助開源的深度學習框架,這樣在開發中就不需要自己從零實現整個深度學習模型的各個功能模塊。如果你之前做過Java Web開發的話,肯定也使用過SSH或SSM等框架來簡化你的開發工作。
深度學習框架有很多優秀的框架,我一般使用比較流行的tensorflow計算框架,該框架的使用者比較多,可以查閱的學習資料非常多,Github上的開源代碼也比較多,非常有利于我們學習。
目前深度學習在NLP的文本分類任務中已經具有比較廣泛的探究,其中經典的深度學習模型結構有以下三種:
本文選擇使用2013年Kim提出的Text-CNN模型作為文本分類模型,通過驗證實驗以及業界的共識,在文本分類任務中,CNN模型已經能夠取到比較好的結果,雖然在某些數據集上效果可能會比RNN稍差一點,但是CNN模型訓練的效率更高。所以,一般認為CNN模型在文本分類任務中是兼具效率與質量的理想模型。
卷積神經網絡(CNN)的特點:
CNN的三個優點:
sparse interaction(稀疏的交互)
parameter sharing(參數共享)
equivalent respresentation(等價表示)。
經典的簡化卷積公式表示如下:
假設每個詞用三維向量表示,左邊是4個詞,右邊是卷積矩陣,那么得到輸出為:
如果基于這個結果做1-MaxPool池化(最大值池化),那么就取卷積層結果?o?中的最大值,即提取最顯著的特征。
針對海量的文本多分類數據,也可以嘗試一下淺層的深度學習模型FastText模型,該模型的分類效率更高。
Kim提出的經典Text-CNN模型的整體網絡架構如圖所示,如果你學習過CNN或者CNN在圖像中的使用,應該很容易就理解,因為該模型就是一個最簡單、基礎的CNN網絡結構。
整個模型由四部分構成:輸入層、卷積層、池化層、全連接層。
1.輸入層(詞嵌入層):
Text-CNN模型的輸入層需要輸入一個定長的文本序列,我們需要通過分析語料集樣本的長度指定一個輸入序列的長度L,比L短的樣本序列需要填充(自己定義填充符),比L長的序列需要截取。最終輸入層輸入的是文本序列中各個詞匯對應的分布式表示,即詞向量。
對于輸入層輸入的詞向量的表達方式,Text-CNN模型的作者Kim在論文中也分析了幾個變種的方式:
1.static(靜態詞向量)
使用預訓練的詞向量,即利用word2vec、fastText或者Glove等詞向量工具,在開放領域數據上進行無監督的學習,獲得詞匯的具體詞向量表示方式,拿來直接作為輸入層的輸入,并且在TextCNN模型訓練過程中不再調整詞向量, 這屬于遷移學習在NLP領域的一種具體的應用。
2.non-static(非靜態詞向量)
預訓練的詞向量+ 動態調整 , 即拿word2vec訓練好的詞向量初始化, 訓練過程中再對詞向量進行微調。
3.multiple channel(多通道)
借鑒圖像中的RGB三通道的思想, 這里也可以用 static 與 non-static 兩種詞向量初始化方式來搭建兩個通道。
4.CNN-rand(隨機初始化)
指定詞向量的維度embedding_size后,文本分類模型對不同單詞的向量作隨機初始化, 后續有監督學習過程中,通過BP的方向更新輸入層的各個詞匯對應的詞向量。
2.卷積層:
在NLP領域一般卷積核只進行一維的滑動,即卷積核的寬度與詞向量的維度等寬,卷積核只進行一維的滑動。
在Text-CNN模型中一般使用多個不同尺寸的卷積核。卷積核的高度,即窗口值,可以理解為N-gram模型中的N,即利用的局部詞序的長度,窗口值也是一個超參數,需要在任務中嘗試,一般選取2-8之間的值。
3.池化層:
在Text-CNN模型的池化層中使用了Max-pool(最大值池化),即減少模型的參數,又保證了在不定長的卷基層的輸出上獲得一個定長的全連接層的輸入。
池化層除了最大值池化之外,也有論文討論過 Top K最大值池化,即選取每一個卷積層輸出的Top k個最大值作為池化層的輸出。
卷積層與池化層在分類模型的核心作用就是提取特征,從輸入的定長文本序列中,利用局部詞序信息,提取初級的特征,并組合初級的特征為高級特征,通過卷積與池化操作,省去了傳統機器學習中的特征工程的步驟。
但TextCNN的一個明顯缺點就是,卷積、池化操作丟失了文本序列中的詞匯的順序、位置信息,比較難以捕獲文本序列中的否定、反義等語義信息。
4.全連接層:
全連接層的作用就是分類器,原始的Text-CNN模型使用了只有一層隱藏層的全連接網絡,相當于把卷積與池化層提取的特征輸入到一個LR分類器中進行分類。
至此,Text-CNN的模型結構就算大體了解了,有人把深度學習模型看作一個黑盒子,知道格式化的輸入,我們就可以利用別人搭建好的模型框架訓練在自己的數據集上實現一定的功能。但是在不同的數據集上,模型的最佳狀態也不唯一,這就需需要我們在新的數據集上需要進行調優(調參)。
6 模型的效果評估與調優
針對分類問題,一般可以使用準確率、召回率、F1值、混淆矩陣等指標,在文本多標簽分類中一般還會考慮標簽的位置加權等問題。
分類模型中的主要參數:詞向量的維度、卷積核的個數、卷積核的窗口值、L2的參數、DropOut的參數、學習率等。
這是在模型優化的過程中需要重點關注的參數。此外,一般數據集的類別不均衡問題對模型的影響也是比較顯著的,可以嘗試使用不同的方法,評估不同方案的模型效果。
7 文本分類中經常遇到的問題
1.數據集類別不均衡
即語料集中,各個類別下的樣本數量差異較大,會影響最終文本分類模型的效果。
主要存在兩類解決方案:
(1)調整數據:數據增強處理,NLP中一般隨分詞后的詞序列進行隨機的打亂順序、丟棄某些詞匯然后分層的采樣的方式來構造新的樣本數據。
(2)使用代價敏感函數:例如圖像識別中的Focal Loss等。
2.文本分類模型的泛化能力
首先,對于一個未知的樣本數據,分類模型只能給出分類標簽中的一個,無法解決不屬于分類標簽體系的樣本。
我們無法預知未來的數據會是什么樣的,也不能保證未來的所有分類情況在訓練集中都已經出現過!
剩下影響分類模型泛化能力的就是模型過擬合的問題了。
如何防止過擬合?那就是老生常談的問題了:
(1)數據上:交叉驗證
(2)模型上:使用DropOut、BatchNorm、正則項、Early Stop。
3.關于模型的上線方案:
1、基于Java的:
請參考:https://www.ioiogoo.cn/2018/04/03/java%E8%B0%83%E7%94%A8keras%E3%80%81tensorflow%E6%A8%A1%E5%9E%8B/
2、基于Flask等python的web框架:
請參考:https://guillaumegenthial.github.io/serving.html
3、基于google官方的tensorflow Serving框架:
請參考:http://www.lxweimin.com/p/c1cd2d127ae2
阿里的基于容器部署的方案:https://yq.aliyun.com/articles/60894?spm=a2c4e.11153959.blogcont60601.11.815eea72lw2ij
8 基于Text-CNN模型的中文文本分類Demo
我從搜狗的開源的的新聞數據集(small版)中,選擇了兩個類別的數據:計算機與交通兩個類別,構建了一個中文文本二分類的數據集。
實現文本二分類的Demo代碼以及腳本運行的說明放在GitHub中:https://github.com/yongfengxuemei/NLP/tree/master/CNN_ChineseTextBinaryClassify
以上就是簡單的介紹了NLP中文本分類所涉及的主要流程,并給出了一個中文文本二分類的Demo代碼。下面推薦一些拓展的資料,感興趣的童鞋可以繼續深入研究。
補充資源:
各種文本分類模型的實例代碼:https://github.com/brightmart/text_classification
中文文本分類對比:https://github.com/Edward1Chou/Textclassification
CNN-RNN中文文本分類,基于TensorFlow :https://github.com/gaussic/text-classification-cnn-rnn
9 Window上跑的效果
10 參考
中文分詞常用方法簡述:http://www.lxweimin.com/p/6c085bf1086f
吾愛NLP(4)—基于Text-CNN模型的中文文本分類實戰:http://www.lxweimin.com/p/f69e8a306862