NLP與深度學習(一)NLP任務流程


1. 自然語言處理簡介

根據工業界的估計,僅有21% 的數據是以結構化的形式展現的[1]。在日常生活中,大量的數據是以文本、語音的方式產生(例如短信、微博、錄音、聊天記錄等等),這種方式是高度無結構化的。如何去對這些文本數據進行系統化分析、理解、以及做信息提取,就是自然語言處理(Natural Language Processing,NLP)需要做的事情。

在NLP中,常見的任務包括:自動摘要、機器翻譯、命名體識別(NER)、關系提取、情感分析、語音識別、主題分割,等等……

 

在NLP與深度學習系列文章中,不會逐一解釋各個NLP任務,而是主要介紹深度學習模型在NLP中的應用。整體分為以下幾點:

  1. 首先介紹NLP基本流程以及在數據預處理方面的技術
  2. 而后會介紹最初期使用的神經網絡:SimpleRNN、LSTM
  3. 繼而引入使得文本處理性能得到很大提升的Attention機制以及Transformer模型
  4. 最后介紹近幾年非常熱門的預訓練模型BERT,以及如何使用BERT預訓練模型的例子

 

下面首先介紹的NLP任務的一個基本工作流程。

 

2. NLP 任務流程

典型的NLP任務分為以下幾步:

  1. 數據收集
  2. 數據標注
  3. 文本標准化(Normalization)
  4. 文本向量化/特征化(Vectorization/Featuring)
  5. 建模

 

前期主要是數據收集,並根據任務類型對數據做標注(例如情感分析中,對好、壞評價做標注)。接下來的2個步驟均是對文本進行預處理的步驟,為了提取文本中隱含的信息,最后通過機器學習建模,達到任務目標。其中 3 – 5 這幾步是迭代的流程,為了模型的精度更准確,需要迭代這個過程,進行不斷嘗試。

 

數據收集以及標注並非在本文討論范圍內,接下來介紹文本標准化的目標與方法。

 

3. 文本標准化

由於文本數據在可用的數據中是非常無結構的,它內部會包含很多不同類型的噪點。所以在對文本進行預處理之前,它暫時是不適合被用於做直接分析的。

文本預處理過程主要是對 文本數據進行清洗與標准化。這個過程會讓我們的數據沒有噪聲,並可以對它直接做分析。

而文本標准化是NLP任務里的一個數據預處理過程。它的主要目標與常規數據預處理的目標一致:提升文本質量,使得文本數據更便於模型訓練。

 

文本標准化主要包含4個步驟:

  1. 大小寫標准化(Case Normalization)
  2. 分詞(Tokenization)與 停止詞移除(stop word removal)
  3. 詞性(Parts-of-Speech,POS)標注(Tagging)
  4. 詞干提取(Stemming)

 

3.1. 大小寫標准化

大小寫標准化是將大寫字符轉為小寫字符,一般在西語中會用到。但是對於中文,不需要做此操作。而且Case Normalization 也並非是在所有任務場景中都有用,例如在英文垃圾郵件分類中,一般一個明顯的特征就是充斥着大寫單詞,所以在這種情況下,並不需要將單詞轉為小寫。

 

3.2. 分詞

文本數據一般序列的形式存在,分詞是為了將文本轉為單詞列表,這個過程稱為分詞(tokenization),轉為的單詞稱為token。根據任務的類別,單詞並非是分詞的最小單位,最小單位為字符。在一個英語單詞序列中,例如 ride a bike,單詞分詞的結果為 [ride, a, bkie]。字符分詞的結果為[r, i, d, e, a, b, k, e]。

在中文中,分詞的最小單元可以不是單個字,而是詞語。

 

3.3. 停止詞移除

停止詞移除是將文本中的標點、停頓詞(例如 is,in,of等等)、特殊符號(如@、#等)移除。大部分情況下,此步驟能提升模型效果,但也並非在任何時候都有用。例如在騷擾郵件、垃圾郵件識別中,特殊字符相對較多,對於分辨是否是垃圾郵件有一定幫助。

 

3.4. 詞性標注

語言是有語法結構的,在大部分語言中,單詞可以被大體分為動詞、名詞、形容詞、副詞等等。詞性標注的目的就是就是為了一條語句中的單詞標注它的詞性。

 

3.5. 詞干提取

在部分語言中,例如英語,一個單詞會有多種表示形式。例如play,它的不同形式有played,plays,playing等,都是play的變種。雖然他們的意思稍微有些區別,但是大部分情況下它們的意思是相近的。詞干提取就是提取出詞根(例如play 就是它各種不同形式的單詞的詞根),這樣可以減少詞庫的大小,並且增加單詞匹配的精度。

 

這些文本標准化的步驟,可以用於對文本進行預處理。在進一步基於這些文本數據進行分析時,我們需要將它轉化為特征。根據使用用途不同,文本特征可以根據各種技術建立而成。如:句法分析(Syntactical Parsing),N元語法(N-grams),基於單詞計數的特征,統計學特征,以及詞向量(word embeddings)等。

其中詞向量是當前主要的技術,下面主要介紹詞向量。

 

4.文本向量化/特征化

向量化是將單詞轉為詞向量的過程,也稱為詞嵌入(word embedding),這里嵌入的意思是說將單詞所包含的信息嵌入到了向量中。

在word embedding出現之前,有2種文本向量化的方式,下面簡單地介紹一下。

 

4.1. 基於單詞計數的特征

此方法非常簡單,首先將語料庫文本進行分詞,得到單詞數。然后在對句子構建向量時,可以根據句子中包含的單詞數構建向量。

舉個例子,假設語料庫為“我愛我的家,我的家是中國”。在進行分詞后可以得到:

{'愛', '是', ',', '我', '中', '國', '家', '的'}

 

對於一個新的句子,例如”我愛我的國“,基於單詞計數的表示即為:

[1, 0, 0, 2, 0, 1, 0, 1]

可以看到這種方法僅是對句子中的單詞進行了統計,並不包含單詞具體代表的含義(例如多義詞的意義無法在此體現)。這種稱為不包含上下文(context-free)的向量化。不過它提供了一種用於衡量兩個文檔相似度的方法。一般會通過余弦相似度或是距離來比較兩個文檔的相近程度。

 

4.2. 基於統計學的特征

在對文本做向量化時,一個常用的技術是詞頻-逆文檔頻率(Term Frequency – Inverse Document Frequency),常稱為TF-IDF。TF-IDF 最初源於解決信息檢索問題。它的目的是在於:基於單詞在文檔里出現的頻率(不考慮嚴格的排序),將文檔轉化為向量模型。

 

這里Term Frequency很好理解,就是某個單詞在文檔中出現的頻率。

在介紹Inverse Document Frequency(IDF)前,我們看一個例子。假設現在要通過單詞檢索文檔,這里文檔主要為各類食譜。如果我們使用單詞如蘋果、醋、醬油這類經常在食譜中出現的單詞,則會有大量的文檔可以匹配。而若是我們使用一些不常見的詞,例如黑莓,則可以顯著縮小要搜索的食譜文檔。也就是說,若是一個單詞越是不常見,則越有助於檢索需要的文檔。所以對於這類不常見的詞,我們希望給它一個更高的分數。反之,對於在各個文檔中都頻繁出現的詞,希望給它們更低的分數。這就是IDF的思想。

 

TF-IDF 的計算,數學上表示可以寫為:

TF-IDF = TF(t, d) x IDF(t)

 

這里t表示term,也就是單詞;D表示Document,文檔。

 

IDF的定義為:

IDF(t) = log( N/(1+nt) )

 

這里N表示語料庫中的文檔總數,nt表示有多少文檔中存在單詞t。這個加1是為了防止除以0。

 

4.3. 詞向量

上面介紹了2種方式,僅僅是解決了用一個向量代表了一個文檔,但無法體現詞與詞之間的關系。而從常理來看,詞與詞之間是存在聯系的。例如,炒鍋與鍋鏟,這2個詞,從直覺上來看,會經常在一起出現。而炒鍋與人行橫道,應該基本不會出現在一起。

詞向量,也稱為詞嵌入,是將單詞映射(或稱嵌入)到一個高維空間中,使得意義相近的詞在空間內距離相近;意義不同的詞在空間內距離相遠。

 

4.3.1. Word2Vec

在詞嵌入技術中,一個具有時代意義的方法是Word2Vec,於2013年由Google的工程師提出。它本身算是神經網絡處理任務的一個副產品。例如,搭建一個神經網絡,每次取一個批次的5個單詞,中間的單詞作為target,周圍的4個詞作為輸入,來訓練神經網絡。初始的輸入詞向量使用one-hot編碼。這樣再訓練完成后,第一層的輸入層參數,即為所得的詞向量矩陣。

Word2Vec論文提出了2種訓練方式:continuous bag-of-word(CBOW)和continuous skip-gram。在論文提出時,CBOW是當時主流方法;不過最后skip-gram模型與負采樣的集成方法,已經成了Word2Vec的代名詞。

Word2Vec已經有很多優秀的文章講解過,在此不再贅述。下面主要舉例說明skip-gram負采樣的方式。

 

假設語料庫中有一條句子為:“需要把魚煎到棕黃再翻面”。

我們設置一個單詞數為5的窗口,也就是一次處理5個單詞,例如“要把魚煎到”這5個詞。中間的詞“魚”會被用於輸入到搭建好的神經網絡中,用於預測它前面的2個詞(“要把”),以及后面的2個詞(“煎到”)。

假設語料庫中有10000個單詞,神經網絡的任務就是要判斷給定一組詞,它們是否相關。例如,對(魚,煎)判斷為true,對(魚,樹)判定為false。這種方法就是Skip-Gram Negative Sampling(SGNS),基於的假設就是:與某個詞相關的詞會更高概率一起出現(或是離的不遠),所以可以從一段短語中拿出一個詞,用於預測它周圍的詞。

 

SGNS的方法可以顯著降低訓練超大型語料庫的時間,最終第一層輸入層的權重矩陣即為詞向量矩陣。

當然,Word2Vec也有它的局限性,一個典型的局限就是沒有全局的統計信息,因為它在訓練的時候最長是以一個窗口為單位,能看到的只有窗口內的上下文信息。

 

4.3.2. GloVe

GloVe (Global Vectors for Word Representation) 模型於2014年提出,於Word2Vec論文發表1年后。它們生成詞向量的方法非常相似,都是通過一個詞(例如上述例子中的“魚”)周圍的詞,來生成這個詞(例如“魚”)的詞嵌入。不過相對於Word2Vec,GloVe利用了全局的文本統計信息,也就是構建語料庫的共現矩陣。 共現矩陣簡單來說,就是2個單詞在窗口中一同出現的次數,以矩陣的形式表示。在有了全局統計信息(共現矩陣)后,接下來的問題是如何將全局信息應用到詞向量生成中。

 

在原論文中,作者用了2個單詞ice和steam來描述這個理念。假設有另一單詞solid,用來探查ice與steam之間的關系。在steam上下文中出現solid的概率為 p(solid | steam),從直覺上來看,它的概率應該會很小(因為steam與solid從直覺上同時出現的概率不會很高)。

而對於ice上下文中出現solid的概率 p(solid | ice),直覺上應該會很高(因為ice是固體,直覺上它們同時出現的概率會很高)。

那如果我們計算p(solid | ice)/ p(solid | steam) 的比值,則預期的結果應該會很高。

而若是用gas作為探測詞,則 p(gas | ice)/p(gas | steam) 的比值應該會很低(因為gas是氣體,在直覺上在steam的上下文中出現的概率高,而在ice的上下文中出現的概率低)。

而若是用water這類與ice和steam相關性都很低的詞作為探測詞,則p(water | ice)/p(water | steam) 的概率應該接近於1。論文中也舉了另一個與ice和steam不相干關的詞fasion,p(fasion | ice)/p(fasion | steam) 的結果也近似於1。

 

也就是說,共現矩陣的概率的比值,可以用來區分詞。GloVe的過程就是確保這種關系被用於生成詞嵌入,將全局信息引入到了詞向量的生成過程中。

 

若是對GloVe方法有興趣,可以閱讀這位博主的介紹:

https://blog.csdn.net/XB_please/article/details/103602964

 

或是GloVe論文:

https://nlp.stanford.edu/pubs/glove.pdf

 

對於GloVe的效果,論文中提到是遠高於word2vec。

 

在使用GloVe時,可以直接從stanford的官網下載預訓練的GloVe詞嵌入,分為50、100、200、300維的詞嵌入。地址為:

http://nlp.stanford.edu/data/glove.6B.zip

 

4.3.3. BERT

Word2vec與GloVe都有一個特點,就是它們是上下文無關(context-free)的詞嵌入。所以它們沒有解決:一個單詞在不同上下文中代表不同的含義的問題。例如,對於單詞bank,它在不同的上下文中,有銀行、河畔這種差別非常大的含義。BERT的出現,解決了此問題,並極大地提升了baseline。

 

另一方面,BERT還解決了GloVe的一個局限性問題,就是:詞庫不夠。例如在使用GloVe預訓練的詞嵌入應用到 IMDB數據集上時,大約有15%的詞不在GloVe的詞庫中。當然,這也是由於一個詞會有多種形式,導致所需詞庫巨大。

在BERT中,使用了WordPiece的分詞方法,詞庫大小為30000。其實這個大小是遠小於GloVe的詞庫大小,GloVe詞庫為40000。這是由於BERT使用的subword分詞方法可以顯著減少詞庫的大小,WordPiece基於的是BPE(Byte Pair Encoding),BPE屬於subword分詞法中的一種。

 

簡單地說,subword分詞法主要做的就是將單詞進行進一步的拆分,讓詞庫更加精簡。更精簡的詞庫可以降低訓練時間,並減少內存使用。Subword分詞法,以英語語言為例,舉個簡單的例子,例如在詞庫中引入2個新的詞,分別為-ing與-ion。則任何結尾為-ing或-ion的詞,均可分為2個詞,一個是前綴詞,一個是-ing或-ion中的任何一個。這樣就極大減少了詞庫的大小。當然,WordPiece以及BPE中使用的方法並沒有這么簡單。若是對BPE與WordPiece算法有興趣,可以閱讀這位博主的介紹:

https://www.cnblogs.com/huangyc/p/10223075.html

 

在BERT中,對它使用的WordPiece分詞,我們可以看一個例子:

#!pip install transformers==3.0.2
import tensorflow as tf
from transformers import BertTokenizer
import numpy as np

bert_name = 'bert-base-cased'
tokenizer = BertTokenizer.from_pretrained(bert_name, add_special_tokens=True, do_lower_case=False, max_length=150, pad_to_max_length=True)

# tokenize single sequence
tokens = tokenizer.encode_plus("Don't be lured", 
                      add_special_tokens=True, 
                      max_length=9, 
                      pad_to_max_length=True,
                      truncation='longest_first',
                      return_token_type_ids=True)


res = []
reverse_dic = [(id, item) for item, id in tokenizer.vocab.items()]
   
for tk in tokens['input_ids']:
    res.append(reverse_dic[tk][1])

print(res)
['[CLS]', 'Don', "'", 't', 'be', 'lure', '##d', '[SEP]', '[PAD]']


可以看到其中lured被拆分成‘lure’與‘##d’。另外的[CLS] 、[SEP] 與[PAD] 是BERT Tokenizer中的保留詞,分別代表“分類任務”、“Sequences之間的間隔”,以及序列補全(序列補全與截斷是NLP任務中常用的方法,用於將不同長度的文本統一長度)。 

更多有關BERT的具體內容會在后續BERT章節進行介紹。

 

5. 總結

在文本數據進行了標准化與向量化后,即可根據任務類型進行建模,將數據輸入到模型中進行訓練。文本標准化 => 向量化 => 建模,也是一個迭代的過程。下一章會介紹NLP任務早期建模使用的神經網絡:SimpleRNN、LSTM以及雙向循環神經網絡。

 

 

References

[1] Natural Language Processing | NLP in Python | NLP Libraries (analyticsvidhya.com)

[2] Essentials of NLP | Advanced Natural Language Processing with TensorFlow 2 (oreilly.com)

[3] Word2Vec與Glove:詞嵌入方法的動機和直覺 - 知乎 (zhihu.com)


免責聲明!

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



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