|
作者:張貴發(fā) 研究方向:自然語言處理 NLPNLP:自然語言處理(NLP)是信息時代最重要的技術(shù)之一。理解復(fù)雜的語言也是人工智能的重要組成部分。而自google在2018年10月底公布BERT在11項(xiàng)nlp任務(wù)中的卓越表后,BERT(Bidirectional Encoder Representation from Transformers)就成為NLP一枝獨(dú)秀,本文將為大家層層剖析bert。
Word Embedding首先我們需要對文本進(jìn)行編碼,使之成為計(jì)算機(jī)可以讀懂的語言,在編碼時,我們期望句子之間保持詞語間的相似行,詞的向量表示是進(jìn)行機(jī)器學(xué)習(xí)和深度學(xué)習(xí)的基礎(chǔ)。 如上圖英語和西班牙語映射到語義空間,語義相同的數(shù)字他們在語義空間分布的位置是相同的 在句子的空間結(jié)構(gòu)上我們期望獲取更底層的之間的關(guān)系比如:
king和queen之間的關(guān)系相比與man與woman的關(guān)系大體應(yīng)該相同的,那么他們通過矩陣運(yùn)算,維持住這種關(guān)系 簡單回顧一下word embedding,對于nlp來說,我們輸入的是一個個離散的符號,對于神經(jīng)網(wǎng)絡(luò)來說,它處理的都是向量或者矩陣。所以第一步,我們需要把一個詞編碼成向量。最簡單的就是one-hot的表示方法。如下圖所示: one-hot encoding編碼 通常我們有很多的詞,那只在出現(xiàn)的位置顯示會,那么勢必會存在一些問題
兩個詞語義上無法正確表示,我們更希望低維的相似的比較接近,語義相近的詞距離比較近,語義不想近的詞,距離也比較遠(yuǎn)。 Neural Network Language Model(神經(jīng)網(wǎng)絡(luò)語言模型) 我們都知道word2vec,glove。其實(shí)更早之前的神經(jīng)網(wǎng)絡(luò)語言模型里出現(xiàn)。已經(jīng)有比較早的一個詞向量了。語言模型是nlp的一個基本任務(wù),是給定一個句子w,包括k個詞,我們需要計(jì)算這個句子的概率。使用分解成條件概率乘積的形式。變成條件概率的計(jì)算。 傳統(tǒng)的方法,統(tǒng)計(jì)的n-gram的,詞頻統(tǒng)計(jì)的形式,出現(xiàn)的多,概率就高,出現(xiàn)少概率就低,。
神經(jīng)網(wǎng)絡(luò)語言模型架構(gòu)如上圖: 將每個詞向量拼接成句子矩陣。每一列都是一個詞, 如北京、上海、 天津比較近,大致相同一塊區(qū)域,所以當(dāng)預(yù)測時,可以給出大概相同的概率,不僅僅與預(yù)料中統(tǒng)計(jì)結(jié)果有關(guān)系。矩陣相乘就可以提取出這個詞,但是為了提取一個詞,我們要進(jìn)行一次矩陣運(yùn)算,這個比較低效,所以比較成熟的框架都提供了查表的方法,他的效率更高。 因?yàn)樯舷挛沫h(huán)境很相似,會共享類似的context,在問我要去 (__)概率會比較大。這也是神經(jīng)網(wǎng)絡(luò)語言模型的一個好處。我們通過神經(jīng)網(wǎng)絡(luò)語言模型得到一個詞向量。當(dāng)然我們也可以用其他的任務(wù)來做,一樣得到詞向量,比如句法分析,但是那些任務(wù)大部分是有監(jiān)督的學(xué)習(xí),需要大量的標(biāo)注信息。 語言模型是非監(jiān)督的,資料獲取不需要很大的成本。 word2vec和神經(jīng)網(wǎng)絡(luò)語言模型不同,直接來學(xué)習(xí)這個詞向量,使用的基本假設(shè)是分布式假設(shè),如果兩個詞的上下文時相似的,那么他們語義也是相似的。 word2vec分為cbow(根據(jù)context預(yù)測中心詞)和skip-gram(根據(jù)中心詞預(yù)測context)兩種。 我們可以通過word2vec或者 glove這種模型在大量的未標(biāo)注的語料上學(xué)習(xí),我們可以學(xué)習(xí)到比較好的向量表示,可以學(xué)習(xí)到詞語之間的一些關(guān)系。比如男性和女性的關(guān)系距離,時態(tài)的關(guān)系,學(xué)到這種關(guān)系之后我們就可以把它作為特征用于后續(xù)的任務(wù),從而提高模型的泛化能力。
RNN/LSTM/GRU那么這種上下文的語義可以通過RNN/LSTM/GRU來解決,RNN與普通深度學(xué)習(xí)不同的是,RNN是一種序列的模型,會有一定的記憶單元,能夠記住之前的歷史信息,從而可以建模這種上下文相關(guān)的一些語義。RNN中的記憶單元可以記住當(dāng)前詞之前的信息。 RR可以解決,理論上我們希望學(xué)到很長的關(guān)系,但是由于梯度消失的問題,所以長時依賴不能很好的訓(xùn)練。 其實(shí)lstm可以解決RNN長時依賴梯度消失的問題。 seq2seq對于翻譯,我們不可能要求英語第一個詞一定對應(yīng)法語的第一個詞,不能要求長度一樣,對于這樣一個rnn不能解決這一問題。我們使用兩個rnn拼接成seq2seq來解決。
比如經(jīng)典的翻譯例子法語到英語的翻譯,由encoder編碼到語義空間和decoder根據(jù)語義空間解碼翻譯成一個個的英語句子。 pay attention 做內(nèi)積。越大越相近 約重要, 后續(xù)的attention、transformer都是對seq2seq的一個改進(jìn),通過這種可以解決word embbeing沒有上下文的一個問題。 加上attention機(jī)制,我們就取得了很大的成績,但是仍然存在一個問題, ![]()
Contextual Word Embedding要解決RNN的問題,就引入了contextual word embedding。
attention是需要兩個句子的,我們很多時候只有一個句子,這就需要self-attention。提取信息的時候、編碼時self-atenntion是自驅(qū)動的,self-attention關(guān)注的詞的前后整個上下文。 ![]() transformer:本質(zhì)也是一個encoder與decoder的過程,最起初時6個encoder與6個decoder堆疊起來,如果是LSTM的話,通常很難訓(xùn)練的很深,不能很好的并行 ![]() 每一層結(jié)構(gòu)都是相同的,我們拿出一層進(jìn)行解析,每一層有self-attention和feed-forward,decoder還有普通的attention輸入來自encoder,和seq-2seq一樣,我在翻譯某一個詞的時候會考慮到encoder的輸出,來做一個普通的attention ![]() 如下圖例子給定兩個詞 thinking和machies,首先通過word embedding把它變成向量,通過self-attention,把它變成一個向量,這里的sefl-attention時考慮上下文的。然后再接全連接層,計(jì)算z1的時候我要依賴x1 、x2 、x3整個序列的,才能算z1,z2也一樣,我算r1的時候時不需要z2的,只要有z1我就可以算r1.只要有z2就能算r2,這個是比較大的一個區(qū)別,這樣就可以并行計(jì)算。 ![]() 我們來看看self-attention具體是怎么計(jì)算的 ![]() 假設(shè)只有兩個詞,映射成長度只有四的向量,接下來使用三個變換矩陣wq wk wv,分別把每個向量變換成三個向量 q1 k1 v1 q2 k2 v2這里是與設(shè)映的向量相乘得到的 ![]() 得到向量之后就可以進(jìn)行編碼了,考慮上下文,如上文提到的bank同時有多個語義,編碼這個詞的時候要考慮到其他的詞,具體的計(jì)算是q1 k1做內(nèi)積 q2 k2 做內(nèi)積得到score,內(nèi)積越大,表示約相似,softmax進(jìn)行變成概率?;?.88的概率注意Thinking,0.12注意macheins這個詞 ![]() 就可以計(jì)算z1了,z1=0.88v1+0.12z2 z2的計(jì)算也是類似的, ![]() q表示為了編碼自己去查詢其他的詞,k表示被查詢,v表示這個詞的真正語義,經(jīng)過變換就變成真正的包含上下文的信息,普通attention可以理解為self-attention的一個特例, ![]() 實(shí)際中是多個head, 即多個attention(多組qkv),通過訓(xùn)練學(xué)習(xí)出來的。不同attention關(guān)注不同的信息,指代消解 上下位關(guān)系,多個head,原始論文中有8個,每個attention得到一個三維的矩陣 ![]() ![]() 將8個3維的拼成24維,信息太多 經(jīng)過24 *4進(jìn)行壓縮成4維。 ![]() 位置編碼:
self-attention是不考慮位置關(guān)系的,兩個句子中北京,初始映射是一樣的,由于上下文一樣,qkv也是一樣的,最終得到的向量也是一樣的。這樣一個句子中調(diào)換位置,其實(shí)attention的向量是一樣的。實(shí)際是不一樣的,一個是出發(fā)城市,一個是到達(dá)城市。 ![]() 引入位置編碼,絕對位置編碼,每個位置一個 Embedding 每個位置一個embedding,同樣句子,多了個詞 就又不一樣了,編碼就又不一樣了
tranformer原始論文使用相對位置編碼,后面的bert open gpt使用的是簡單絕對位置編碼: ![]() 大家可以嘗試bert換一下相對位置會不會更好: transformer中encoder的完整結(jié)構(gòu),加上了殘差連接和layerNorm ![]() decoder加上了普通的attention,最后一刻的輸出,會輸入 ![]() transformer的decoder不能利用未知的信息,即單向信息流問題。 transformer 解決的問題: 如何解決transformer的問題,就引入了elmo ![]() 一個個的預(yù)測的語言模型: 雙向的lstm,每個向量2n,是一種特征提取的方法,考慮的上下文的,編碼完,就定住了, elmo:將上下文當(dāng)作特征,但是無監(jiān)督的語料和我們真實(shí)的語料還是有區(qū)別的,不一定的符合我們特定的任務(wù),是一種雙向的特征提取。 openai gpt就做了一個改進(jìn),也是通過transformer學(xué)習(xí)出來一個語言模型,不是固定的,通過任務(wù) finetuning,用transfomer代替elmo的lstm。 openAI gpt雖然可以進(jìn)行fine-tuning,但是有些特殊任務(wù)與pretraining輸入有出入,單個句子與兩個句子不一致的情況,很難解決,還有就是decoder只能看到前面的信息。 bertbert從這幾方面做了改進(jìn):
bert為什么更好呢?
bert的輸入是兩個句子,分割符sep,cls表示開始,對輸入的兩個句子,使用位置編碼, segment embeding 根據(jù)這個可以知道 該詞屬于哪個句子,學(xué)習(xí)會更加簡單??梢院芮宄赖谝痪渥有枰幋a什么信息,第二個句子可以編碼什么信息。 ![]() 單向信息流問題:mask ml 有點(diǎn)類似與完形填空,根據(jù)上下文信息猜其中信息,計(jì)算出最大概率,隨機(jī)丟掉15%的詞來bert來進(jìn)行預(yù)測,考慮前后雙向的信息,怎么搞兩個句子? -50%概率抽連續(xù)句子 正樣本1
這樣學(xué)習(xí)到兩個句子的關(guān)系,可以預(yù)測句子關(guān)系,在一些問答場景下很重要。 finetuning:
bert的實(shí)際應(yīng)用比較簡單,不過多贅述內(nèi)容,推薦簡單的demo樣例: |
|
|