【NLP】授人以渔:分享我的文本分类经验总结
在我們做一個項目或業務之前,需要了解為什么要做它,比如為什么要做文本分類?項目開發需要,還是文本類數據值得挖掘。
1、介紹
目前討論文本分類幾乎都是基于深度學習的方法,本質上還是一個建模的過程,包括數據準備-預處理-模型選擇-模型調優-模型上線這樣的一套流程。在本地進行文本分類開發我們需要關注的兩個主要的問題:數據處理和模型選擇,這兩者是相互依賴的。
圖1 文本分類的步驟
文本分類可以根據文本的大小可以分為如下幾種:
文本級別:?對整篇文章進行分類
段落級別:?對單獨的段落分類
句子級別:?對句子進行分類
子句級別:?對句子的一部分進行識別(命名體識別不就是這個嗎)
介紹圖所示也分為三個部分,特征提取、分類模型、評估指標。
2、特征提取(Representation)
介紹文本數據清洗的幾種方法和兩種特征提取方法,Embedding和Weighted Words。
2.1 數據清洗
在自然語言處理(NLP)中,大多數文本和文檔都包含許多冗余的單詞,例如StopWords,Miss-Mermilings,Slangs等。在許多算法中,如統計和概率學習方法,噪聲和不必要的特征可以對整體性能產生負面影響。
Tokenization
中文有的翻譯稱之為分詞,將句子切成小塊稱之為token。
python中
from nltk.tokenize import word_tokenizetext = "After sleeping for four hours, he decided to sleep for another four"tokens = word_tokenize(text)print(tokens)# result['After',?'sleeping',?'for',?'four',?'hours',?',',?'he',?'decided',?'to',?'sleep',?'for',?'another',?'four']# 中文文本text = "我在華為工作"print(" ".join([s for s in jieba.cut(text)]))# results我 在 華為 工作Stop words
中文翻譯:停用詞。通過社交媒體(如Twitter,Facebook等)的文本和文檔分類通常受到文本語料中的嘈雜性質(縮寫,不規則形式)的影響。簡而言之,過濾掉一些詞。
from nltk.corpus import stopwords from nltk.tokenize import word_tokenizeexample_sent = "This is a sample sentence, showing off the stop words filtration." stop_words = set(stopwords.words('english')) word_tokens = word_tokenize(example_sent) filtered_sentence = [w for w in word_tokens if not w in stop_words]print(word_tokens) print(filtered_sentence) # results ['This', 'is', 'a', 'sample', 'sentence', ',', 'showing', 'off', 'the', 'stop', 'words', 'filtration', '.'] ['This',?'sample',?'sentence',?',',?'showing',?'stop',?'words','filtration',?'.']使用stopwords也是很簡單,分詞做一個字典或者集合進行篩選即可,這里不再贅述。
Capitalization
中文名字:資本化?句子可以包含大寫和小寫字母的混合。多個句子構成文本文檔。為了減少問題空間,最常見的方法是將一切降低到小寫。這將在同一空間的文檔中帶來所有單詞,但它通常會改變某些詞的含義,例如“美國”到“我們”,第一個代表美國和第二個是代名詞。要解決此問題,可以應用俚語和縮寫轉換器。什么叫縮寫轉換器?盲猜應該就是一個hashmap。
text = "The United States of America (USA) or America, is a federal republic composed of 50 states" print(text) print(text.lower()) # results 'The United States of America (USA) or America, is a federal republic composed of 50 states' 'the united states of america (usa) or america, is a federal republic composed of 50 states'Slangs and Abbreviations
諺語和縮寫。在進行常規的文本分類的時候,希望將諺語翻譯,縮寫變為全稱是的數據分布保持一致。當然,不一定非得對此進行處理,如果針對縮寫和諺語的數據集和模型構建那則不需要考慮此問題。
Noise Removal
噪音消除。其實就是使用正則表達式過濾掉一些錯誤或者無關緊要的字符,使得數據盡可能對齊。
英文常用的手段
def text_cleaner(text):rules = [{r'>\s+': u'>'}, # remove spaces after a tag opens or closes{r'\s+': u' '}, # replace consecutive spaces{r'\s*<br\s*/?>\s*': u'\n'}, # newline after a <br>{r'</(div)\s*>\s*': u'\n'}, # newline after </p> and </div> and <h1/>...{r'</(p|h\d)\s*>\s*': u'\n\n'}, # newline after </p> and </div> and <h1/>...{r'<head>.*<\s*(/head|body)[^>]*>': u''}, # remove <head> to </head>{r'<a\s+href="([^"]+)"[^>]*>.*</a>': r'\1'}, # show links instead of texts{r'[ \t]*<[^<]*?/?>': u''}, # remove remaining tags{r'^\s+': u''} # remove spaces at the beginning]for rule in rules:for (k, v) in rule.items():regex = re.compile(k)text = regex.sub(v, text)text = text.rstrip()return text.lower()處理中文的時候我們可能需要刪除一些無用的英文字符,或者無效的數字。
Spelling Correction
語法錯誤自動糾正。
英文案例比較簡單
from autocorrect import Speller slr = Speller() print(slr.autocorrect_word('caaaar')) print(slr.autocorrect_word(u'mussage')) print(slr.autocorrect_word(u'survice')) print(slr.autocorrect_word(u'hte')) # results "aaaaaa" "message" "service" "the"中文的自動糾錯?
import pycorrector corrected_sent, detail = pycorrector.correct('少先隊員因該為老人讓坐') print(corrected_sent, detail) # results 少先隊員應該為老人讓座 [['因該', '應該', 4, 6], ['坐', '座', 10, 11]]修正后在分詞,目前也有基于深度學習的文本糾正。
2.2 Weighted Words
term-frequency~(TF)
基于出現的頻率做單詞到數字的映射。
出現的次數。
出現次數的對數。或者使用布爾值表示?
如果使用一個等長的向量,其中的位置表示為單詞的頻率信息,這樣做容易導致的問題是什么?出現頻率高的單詞決定了單詞的表示。
加權字表示,TF-IDF在文檔中術語重量的數學表示:
其中n是文檔的數量,df(t)是包含語料庫中術語t的文檔的數量。
可以通過 如下方式實現。
from sklearn.feature_extraction.text import TfidfVectorizer2.3 Embedding
使用較低維度的向量表示文本中的單詞。
機器學習中的編碼思路。
方法一:one-hot
存在的問題:
1. 效率低下,一個獨熱編碼向量十分稀疏(這意味著大多數索引為零);
2. 數據中的單詞集合越大,編碼后的向量長度越長3. 任意兩個詞正交,無法較好的度量詞之間的相關性;
方法二:int
存在的問題:
1. 整數編碼是任意的(它不會捕獲單詞之間的任何關系);2. 對于要解釋的模型而言,整數編碼頗具挑戰。例如,線性分類器針對每個特征學習一個權重。由于任何兩個單詞的相似性與其編碼的相似性之間都沒有關系,因此這種特征權重組合沒有意義;
Embedding 層
不同的框架下的Embedding層的作用是什么?需要注意的兩點
解決one-hot編碼無法提取詞之間的相關性的問題,方法是通過訓練一個權重矩陣(矩陣的大小為(m,n)m表示訓練數據中的單詞集合的大小,n通常稱之為詞向量的大小,即壓縮后的維度大小。矩陣中的參數通過目標任務反向傳播進行學習。
在前向傳播不采用one-hot編碼后的矩陣進行輸入,采用int編碼進行查表操作來代替矩陣相乘來加速。
Word2Vec
Embedding層雖然可以學習到詞的低維度表示,但是在數據樣本比較小的情況下,僅僅通過目標任務學習巨大的Embedding矩陣往往效果不是理想。
聯想到,圖片分類中的image數據的預訓練權重,在文本分類中也希望通過巨大預料數據提前得到單詞的預訓練權重,然后在小的數據集上進行遷移學習以提升模型的精度。Word2Vec是在此想法下的產物,與文本分類預訓練有幾點不同。
以Skip-gram為例簡單介紹:
The wide road shimmered in the hot sun.句子中的每個單詞的上下文詞被窗口打下指定,樣例如下。對于窗口長度n,考慮上下文,意味著每個單詞對應的窗口長度為2*n+1。
詞編碼在Embedding中寫過,首先使用one-hot編碼然后喂入網絡,在word2vec中也使一樣的。不過這里的目標是給定一個詞的one-hot編碼,學習的是skip-gram pair,因此網絡定義如下:
如上圖所示:隱層沒有使用任何激活函數,但是輸出層使用了sotfmax。基于成對的單詞來對神經網絡進行訓練,訓練樣本是 ( input word, output word ) 這樣的單詞對,10000表示詞本中單詞的個數,input word和output word都是one-hot編碼的向量。最終模型的輸出是一個概率分布。
FastText
FastText和Word2Vec之間有什么聯系和區別。
相同點,學習得到低維度詞向量表示。
不同點,FastText使用了subwords這種更細粒度的特征。
FastText的結構如下,可以直接應用于文本分類任務,隱藏層使用求和使得模型十分高效。
GloVe
全局向量表示,使用詞頻信息+上下文信息的一種詞向量表示。官方網站:https://nlp.stanford.edu/projects/glove/
三步走:
根據語料庫(corpus)構建一個共現矩陣(Co-ocurrence Matrix)X,矩陣中的每一個元素Xij代表單詞i和上下文單詞j在特定大小的上下文窗口(context window)內共同出現的次數。一般而言,這個次數的最小單位是1,但是GloVe不這么認為:它根據兩個單詞在上下文窗口的距離d,提出了一個衰減函數(decreasing weighting):decay=1/d用于計算權重,也就是說距離越遠的兩個單詞所占總計數(total count)的權重越小。
構建詞向量(Word Vector)和共現矩陣(Co-ocurrence Matrix)之間的近似關系,論文的作者提出以下的公式可以近似地表達兩者之間的關系:
其中,wiT和wj~是我們最終要求解的詞向量;bi和bj~分別是兩個詞向量的偏置。
損失函數
這個loss function的基本形式就是最簡單的mean square loss,只不過在此基礎上加了一個權重函數f(Xij),那么這個函數起了什么作用,為什么要添加這個函數呢?我們知道在一個語料庫中,肯定存在很多單詞他們在一起出現的次數是很多的(frequent co-occurrences),那么我們希望:
1.這些單詞的權重要大于那些很少在一起出現的單詞(rare co-occurrences),所以這個函數要是非遞減函數(non-decreasing);
2.但我們也不希望這個權重過大(overweighted),當到達一定程度之后應該不再增加;
3.如果兩個單詞沒有在一起出現,也就是Xij=0,那么他們應該不參與到loss function的計算當中去,也就是f(x)要滿足f(0)=0
滿足以上兩個條件的函數有很多,作者采用了如下形式的分段函數,(xmax=100,α=0.75):
Contextualized Word Representations
預訓練是否存在其他的表征方式,word2vec這種表示方法的缺點是什么?
缺乏語義信息
中文的預訓練模型:https://github.com/HIT-SCIR/ELMoForManyLangs
上下文詞表示,ELMO是一個深刻的語境化詞表示,可以處理(1)單詞的復雜特征(例如,語法和語義)(2)這些用途在語言上下文(即,模型多義)上的不同方式變化。這些單詞vectors是學習的深度雙向語言模型(BILM)的內部狀態的函數,該函數在大型文本語料庫上預先訓練。
ELMo representations are:
Contextual:?每個單詞的表示取決于它使用的整個上下文。
Deep:?每個單詞的表示組合了深度預先訓練的神經網絡的所有層。
Character based:?Elmo表示是基于純字符級別的,允許網絡使用形態線索學習不屬于詞表中的單詞表示。
2.3 不同特征提取的優缺點
一、Weighted Words:
優點:
容易計算
使用此方法容易計算兩個文檔的相似度
提取文檔具有代表性的基礎指標
未知單詞也可以工作
缺點:
不能捕捉位置關系
不能捕捉語義信息
高頻單詞容易影響結果(例如 is,as)
二、TF-IDF:
優點:
容易計算
使用此方法容易計算兩個文檔的相似度
提取文檔具有代表性的基礎指標
高頻單詞影響較小
缺點:
不能捕捉位置關系
不能捕捉語義信息
三、Word2Vec:
優點:
捕捉位置關系
捕捉語義信息
缺點:
無法從文本中捕捉單詞的意思,多義性無法支持
受詞表限制
四、GloVe (Pre-Trained):
優點:
捕捉位置關系
捕捉語義信息
基于大語料訓練
缺點:
無法從文本中捕捉單詞的意思,多義性無法支持
內存消耗嚴重,需要存儲近似矩陣
受詞表限制
五、GloVe (Trained):
優點:
非常簡單,捕捉線性關系優異(performs better than Word2vec)
對于高度頻繁的單詞對的重量較低,例如“am”,“is”等的單詞將不會影響太大
缺點:
內存消耗嚴重,需要存儲近似矩陣
需要大量的語料數據支持
受詞表限制
無法從文本中捕捉單詞的意思,多義性無法支持
六、FastText:
優點:
適用于少量的單詞
在字符水平中用n-gram解決受詞表限制的問題
缺點:
無法從文本中捕捉單詞的意思,多義性無法支持
內存消耗嚴重
計算開銷比GloVe 和 Word2Vec更大
七、Contextualized Word Representations:
優點:
動態的單詞表示
缺點:
存儲開銷大
顯著提高下游性能但是計算開銷大
需要額外的word embedding
受詞表限制
僅能服務于句子和文章級別
3、模型介紹
在做文本分類的過程中,模型的設計其實包括上述介紹的詞向量的獲得,盡可能希望得到如下的信息
詞向量可以充分表征文本原來的意思
詞向量可以表征語義信息
模型可以提取樣本級別的整體特征表示,然后+Softmax便可以實現分類
3.1 基于靜態詞向量的網絡
為啥使用靜態詞向量+LSTM前后文無法充分表征語義信息?個人揣測,使用靜態詞向量的網絡通常是在小數據上基于給定任務訓練,難以捕捉比較好的語義信息。
3.1.1 FastText
本質上應該屬于Word2Vec+單層的網絡+H-softmax。
3.1.2 TextCNN
本質上使用Word2Vec+CNN
TextCNN詳細過程:
Embedding:第一層是圖中最左邊的7乘5的句子矩陣,每行是詞向量,維度=5,這個可以類比為圖像中的原始像素點。
Convolution:然后經過 kernel_sizes=(2,3,4) 的一維卷積層,每個kernel_size 有兩個輸出 channel。
MaxPolling:第三層是一個1-max pooling層,這樣不同長度句子經過pooling層之后都能變成定長的表示。
FullConnection and Softmax:最后接一層全連接的softmax層,輸出每個類別的概率。
3.1.3 TextRNN
3.2 基于動態詞向量的網絡
為什么使用動態此向量?
word級別到數值向量的映射不足以完全表征上下文的信息,我們希望基于上下文訓練對應的詞向量表示,即我們希望在句子級別或者更高的級別對文本進行編碼。
就好比,我僅使用mlp對圖像進行學習不如CNN可以提取空間信息更加有效的意思?
主要的模型有:
GPT、Bert、XLNet等,這部分的技術原理仍舊需要時間來仔細分析,但是我們最終的目的是如何在項目中有效使用,所以做一下簡要的介紹。
3.2.1 Bert
BERT是一種預訓練語言表示的方法,他將NLP模型的建立分為了兩個階段:Pre-training和fine-tuning。Pre-training是為了在大量文本語料(維基百科)上訓練了一個通用的“語言理解”模型,然后用這個模型去執行想做的NLP任務。Fine-training則是在具體的NLP任務上進行相應的微調學習。
Bert模型結構主要是采用了transformer的編碼結構,其主要創新點在于其訓練方式采用了1)它在訓練雙向語言模型時以減小的概率把少量的詞替成了Mask或者另一個隨機的詞。感覺其目的在于使模型被迫增加對上下文的記憶。2)增加了一個預測下一句的loss,迫使模型學習到句子之間的關系。
輸入表示:
論文的輸入表示(input representation)能夠在一個token序列中明確地表示單個文本句子或一對文本句子(例如, [Question, Answer])。對于給定token,其輸入表示通過對相應的token、segment和position embeddings進行求和來構造。圖2是輸入表示的直觀表示:
關鍵創新:預訓練任務
任務1: Masked LM
為了訓練一個深度雙向表示(deep bidirectional representation),研究團隊采用了一種簡單的方法,即隨機屏蔽(masking)部分輸入token,然后只預測那些被屏蔽的token。
數據生成器將執行以下操作,而不是始終用[MASK]替換所選單詞:
80%的時間:用[MASK]標記替換單詞,例如,my dog is hairy → my dog is [MASK]
10%的時間:用一個隨機的單詞替換該單詞,例如,my dog is hairy → my dog is apple
10%的時間:保持單詞不變,例如,my dog is hairy → my dog is hairy. 這樣做的目的是將表示偏向于實際觀察到的單詞。
任務2:下一句預測
在為了訓練一個理解句子的模型關系,預先訓練一個二進制化的下一句測任務,這一任務可以從任何單語語料庫中生成。具體地說,當選擇句子A和B作為預訓練樣本時,B有50%的可能是A的下一個句子,也有50%的可能是來自語料庫的隨機句子。
通過采用以上兩種預訓練方式,使得模型能夠具有語義表征性質,在fine-tuning階段就可以搭連一個NN結構完成文本分類任務。
4、評估指標
ACC
Top-K ACC
F1
AUC
ROC曲線,是一個圖解,它說明了二值分類器系統在其判別閾值變化時的性能。它是通過在不同的閾值設置下繪制陽性中的真陽性部分(TPR=真陽性率)與陰性中的假陽性部分(FPR=假陽性率)來創建的。TPR也稱為敏感性,FPR是1減去特異性或真陰性率。
AUC是ROC曲線下的面積。
from?sklearn.metrics?import?roc_auc_score往期精彩回顧適合初學者入門人工智能的路線及資料下載中國大學慕課《機器學習》(黃海廣主講)機器學習及深度學習筆記等資料打印機器學習在線手冊深度學習筆記專輯《統計學習方法》的代碼復現專輯 AI基礎下載本站qq群955171419,加入微信群請掃碼: 與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的【NLP】授人以渔:分享我的文本分类经验总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【预训练模型】一文串起从NLP到CV 预
- 下一篇: threejs 局部辉光