一、前言
在上篇文章中,我們介紹了Word2Vec以及它的作用,總的來說:
-
Word2Vec是我們理解NLP的第一站
-
Word2Vec將詞變成了“向量”—— 終于可以用機器理解詞語的相似度
-
我們獲得了例如“國王 - 男人 + 女人 ≈ 女王” 的類比能力
-
我們可以將Word2Vec這種算法能力,應用到各種創新場景,例如基于Graph的推薦系統,后續如果小伙伴有需要,可以一起深入交流。
但同時也指出了它的不足:
-
一個詞=一個固定向量(靜態詞向量)
-
上下文無感知:“蘋果”無論是手機還是水果,向量相同
-
是詞的映射,不是對語言的理解
那如果讓我們來設計下一代的算法,什么最重要?
——我們需要“能讀懂句子”的模型。
接下來我們一步步實現,直至引出bert。
?二、Word2Vec是怎么工作的?
在上文,我們介紹到Word2Vec使用周圍詞預測中間詞來獲取詞向量能力,這個被稱為CBOW,同理也可以用中間詞預測周圍詞,這個稱為Skip-Gram。本質來講,Word2Vec是一個淺層神經網絡,結構如下:
from torch import nn
class Word2VecModel(nn.Module):def __init__(self, vocab_size, embedding_dim):"""vocab_size:詞總數embedding_dim:超參,詞對應的向量維度,例如64、128"""super().__init__()self.embed = nn.Embedding(num_embeddings=vocab_size, embedding_dim=embedding_dim)
最終可訓練部分是self.embed部分。
三、我們需要一個分詞器
在前文中,我們輸入的都是一個一個分好的詞,但是呢,有幾個問題:
- 怎么分詞的?
- 分詞的目的是什么?
- 中文怎么分詞?英文怎么分詞?其他語言怎么分詞?
- 分詞在對整句語義理解上的重要程度是怎樣的?
1. 怎么分詞的?
我們平時寫作時,不像英文每個單詞中間有空格,而是一個字一個字連著寫直至整句話完成。例如“今天你真漂亮”,我們希望分成?今天 你 真 漂亮。
在中文分詞研究歷史中,有著比較漫長的過程。整體可認為是統計概率建模的過程,比如建立一個巨大的詞表,然后通過一堆的算法,例如隱馬爾克夫鏈,建立前詞和當前詞的轉移概率。蹭蹭蹭,我們獲得了一個分詞模型。哈哈,此處我們不做具體原理講解。如果需要,最近可著重看HMM和CRF,再往前推,有基于最長詞的分詞算法。總的來說,統計概率建模,就是獲取所有影響分詞結果的因素,對其進行建模以及學習其權重。例如針對CRF,本質是學習狀態轉移概率矩陣、發射概率矩陣,最終形成一個有向詞網,節點為詞,獲取最大概率那條路徑,就是分詞結果。
現在也有一堆基于神經網絡的分詞工具,整體都可認為是命名實體標注任務,如果有需要小伙伴,可以一起交流。
如果只是為了工程應用,可使用jieba、HanLP、LAC等。
2.?分詞的目的是什么?
我們為什么要分詞?不分詞行不行,直接一句/段話直接輸入給模型不就行了。這里牽扯到對語言建模輸入最小粒度問題,可以將“今天你真漂亮”切分成一個一個字,也可以切分成上面的結果,以這個結果作為網絡的輸入。
OOV(Out-of-Vocabulary)問題,這個小伙伴在體驗Word2Vec能力時可能已經發現,針對一些俚語,會發現這個詞不在Word2Vec表內。那就導致無法獲取這個詞的詞向量。
3. 中文怎么分詞?英文怎么分詞?其他語言怎么分詞?
有沒有一個統一算法,可以支持任意一種語言的分詞。有!這個就是大名鼎鼎Bert用到的WordPiece。
注意,如前面所說,分詞更偏向是中文領域一個特定的任務,而對于英文,可能就直接按照空格就完成了分詞任務。所以,請將分詞概念延伸至Tokenization概念,分的詞被稱為Token,分詞的動作稱之為Tokenizer。
WordPiece是一種將詞分解成更小單元的方法。
具體如何實現此處不涉及。以及現在也有其他tokenizer方法,例如BPE等。
4. 分詞在對整句語義理解上的重要程度是怎樣的?
嚴格意義上來講這里有提升空間,包括目前大模型所使用到的。為什么這么講,因為分詞作為最初輸入,其準確率影響后續的計算結果。“南京市長江大橋結婚了。”,這句話是不是沒有任何語義歧義,不像“白天鵝在湖中游”,“大學生活好”,“黑暗的夜總會迎來黎明”吧。
至此,模型的輸入我們搞定啦。
四、我們需要設計訓練任務
在Word2Vec的CBOW模型中,是用周圍詞預測中心詞。我們可以將這個條件延伸下:
-
預測中心詞這個事,我們將中心詞掩蓋掉這個事情稱為[MASK]。
-
為什么非要預測中心詞呢?我們完全可以隨機掩蓋掉一句話中某個詞。
例如輸入一句話“今天天氣真不錯”,經過上面tokenizer后,變成了“今天?天氣?真?不錯”,隨機掩蓋掉某個詞(例如真),變成了“今天?天氣?[MASK]?不錯”,那我們的目標是預測[MASK]部分的標簽是“真”,由此我們獲得了輸入與輸出。
五、我們需要一個強大的網絡
在Word2Vec中,我們的網絡結構只有一個nn.Embedding,即詞和向量的映射表,整個結構還太簡單。那我們再引入一個新的算法架構——Transformer。
有的小伙伴可能提前已經了解過一些深度學習算法,例如LSTM,那會問LSTM不能處理這種序列問題嗎?當然,完全可以,至此我們做到了,每個token都有一個上下文相關的向量表示。
到這里我們發明了Masked Language Model(MLM)。
當然bert的預訓練不止mask這一個任務,還有被稱為NSP(Next Sentence Prediction)任務,即給定兩句話A和B,讓模型判斷B是否是A的下一句。
當然這個任務在后面的研究(例如Roberta)中被證明此任務作用并不大,不過我們知道下就行了。
關于BERT更具體原理講解,有需要的話后面可一步步實現。
特點 | Word2Vec | BERT |
---|---|---|
向量類型 | 靜態 | 動態(與上下文相關) |
模型結構 | 淺層神經網絡 | 多層 Transformer |
能否理解語境 | 否 | 是 |
預訓練目標 | 預測詞 | Mask + NSP |
六、BERT模型有什么用?
這是一個好問題,上面蹭蹭說到了一堆似乎和應用無關的東西,總而言之,BERT的出現:
- 我們獲得了一個通用的語義理解模型,基于這個模型,我們可以和更多現實應用建立起橋梁。
- 降低了算法訓練與應用難度,BERT作為一個預訓練模型,由于其本身已經獲取到通用語言場景下的語義理解能力,那么相關的NLP任務都更為容易做成。例如文本分類、情感分析、命名實體識別、搜索等。
七、如何應用?
Bert作為預訓練模型,其本身并不能做太多事情,例如MASK和NSP。我們一般會在Bert模型之后再接一些其他的Layer來做具體任務。下面我放幾個應用截圖,這些都是Bert可以做到的。如果有感興趣的我可以一步步實現哦。
與情分析
命名實體/情感分析?