[NLP]subword理解:BPE,WordPiece,ULM


構建詞表是NLP任務中的一個基本要求,傳統的方法是對各個句子進行分詞,然后選取頻率最高的N個詞組成詞表。但是這樣的做法不可避免的會帶來一些問題,如OOV問題,低頻次/稀疏詞的語義很難獲取(因為沒有訓練)等。

為解決上述問題,提出了subword模型。該模型的划分粒度介於詞與字符之間,如將"looking"分割為“look”和“ing”兩個子詞,因而它能夠大大降低詞典的大小,同時對相近詞能更好的處理

subword主要有三種方法:BPE,WordPiece,UniLM

一、BPE

GPT-2和RoBERTa使用的subword算法都是BPE。

算法步驟:

①准備足夠大的訓練語料,並確定期望的subword詞表大小

②將單詞拆分為最小單元。比如英文中26個字母加上各種符號,這些作為初始詞表。

③在語料上統計單詞內相鄰單元對的頻數,選取頻數最高的單元對合並成新的subword單元。

④重復第③步直到達到第①步設定的subword詞表大小或下一個最高頻的字節對出現頻率為1

舉例說明:假設語料集經過統計后表示為:{'low':5,'lower':2,'newest':6,'widest':3},其中數字代表的是對應單詞在語料中的頻數。

①拆分單詞為最小單元,並初始化詞表。這里最小單元為字符,因此,可得到表:

語料 詞表
'l o w </w>':5 'l o w e r </w>':2 'n e w e s t </w>':6 'w i d e s t </w>':3 'l','o','w', 'e', 'r','n','s','t','i', 'd','</w>'

②在語料上統計相鄰單元的頻數。這里,“e”和“s”出現了6+3=9次,將其合並成“es”,有下表:

語料 詞表
'l o w </w>':5 'l o w e r </w>':2 'n e w es t </w>':6 'w i d es t </w>':3 'l','o','w', 'e', 'r','n','s','t','i', 'd','</w>','es'

由於語料中不存在“s”子詞,因此將其從詞表中刪除,同時加入新的子詞“es”。一增一減,詞表大小保持不變。

③繼續統計相鄰子詞的頻數。此時最高頻連續子詞對“es”和"t"出現了6+3=9次,將其合並成“est”,有下表:

語料 詞表
'l o w </w>':5 'l o w e r </w>':2 'n e w est </w>':6 'w i d est </w>':3 'l','o','w', 'e', 'r','n','s','t','i', 'd','</w>','es','est'

④接着,最高頻連續子詞對為"est"和“</w>”,有下表:

語料 詞表
'l o w </w>':5 'l o w e r </w>':2 'n e w est </w>':6 'w i d est </w>':3 'l','o','w', 'e', 'r','n','s','t','i', 'd','</w>','est','est</w>'

⑤繼續上述迭代知道達到預設的subword詞表大小或下一個最高頻的字節對出現頻率為1.

實際上,隨着合並的次數增加,詞表大小通常先增加后減小。

得到subword詞表后,針對每一個單詞,我們可以采用如下的方式進行編碼:

①將詞典中的所有子詞按照長度由大到小進行排序;

②對於單詞w,依次遍歷排好序的詞典。查看當前子詞是否是該單詞的子字符串,如果是,則輸出當前子詞,並對剩余單詞字符串繼續匹配。

③如果遍歷完字典后,仍然有子字符串沒有匹配,則將剩余字符串替換為特殊符號輸出,如“<unk>

④單詞的表示即為上述所有輸出子詞。

優點:可以有效的平衡詞匯表大小和步數(編碼句子所需的token數量)

缺點:基於貪婪和確定的符號替換,不能提供帶概率的多個分片結果

二、WordPiece

bert在分詞的時候使用的是WordPiece算法。與BPE算法類似,WordPiece算法也是從詞表中選出兩個子詞合並成新的子詞。但他們的區別是:BPE選擇頻數最高的相鄰子詞合並,而WordPiece選擇能夠提升語言模型概率最大的相鄰子詞加入詞表。

具體做法如下:假設句子S=(t1,t2,...,tn)由n個子詞組成,t_i表示子詞,且假設各個子詞之間是獨立存在的,則句子S的語言模型似然值等價於所有子詞概率的乘積:,

假設把相鄰位置的x和y兩個子詞進行合並,合並后產生的子詞記為z,此時句子S似然值的變化可表示為:

logP(tz) -(log(P(tx)) + log(P(ty))) = log(P(tx) / P(tx)P(ty))

從上面的公式可以看出,似然值的變化就是兩個子詞之間的互信息,我們選擇具有最大的互信息值的兩個詞進行合並,表明這兩個詞在語言模型上具有較強的關聯性。

3、Unigram Language Model(ULM)

ULM同WordPiece一樣,也是選擇語言模型來挑選子詞。但是ULM的計算方法是,先初始化一個大詞表,根據評估准則不斷丟棄詞表,直到滿足限定條件。ULM算法考慮了句子的不同分詞可能,因而能夠輸出帶概率的多個分詞分段。

具體過程如下:

對於句子S,x=(x1,x2,...,xm)為句子的一個分詞結果,由m個子詞組成。所以,當前分詞下句子S的似然值可表示為:P(x) = P(x1)P(x2)...P(xm)

對於句子S,挑選似然值最大的作為分詞結果,則可以表示為:x* = arg max_{x in U(x)} P(x)

這里U(x)包含了句子的所有分詞結果。因為詞表很大,直接羅列所有的分詞組合不具操作性。針對這個問題,可通過維特比算法來解決。

至於每個子詞的概率P(xi),ULM通過EM算法來估計。假設當前詞表V,則M步最大化的對象是如下似然函數:

L = sum{s=1,|D|}(logP(Xs) = sum(log(sum{x in U(Xs)}(P(x))))

其中,|D|是語料庫中語料數量。上述公式的一個直觀理解是,將語料庫中所有句子的所有分詞組合形成的概率相加。

但是,初始時,詞表V並不存在。因而,ULM算法采用不斷迭代的方法來構造詞表以及求解分詞概率:

①初始時,建立一個足夠大的詞表。一般,可用語料中的所有字符加上常見的子字符串初始化詞表,也可以通過BPE算法初始化。

②針對當前詞表,用EM算法求解每個子詞在語料上的概率

③對於每個子詞,計算當該子詞被從詞表中移除時,總的loss降低了多少,記為該子詞的loss

④將子詞按照loss大小進行排序,丟棄一定比例loss最小的子詞(比如20%),保留下來的子詞生成新的詞表。這里需要注意的是,單字符不能被丟棄,這是為了避免OOV情況。

⑤重復步驟②-④,直到詞表大小減少到設定范圍。

可以看出,ULM算法會保留那些以較高頻率出現在很多句子的分詞結果中的子詞,因為這些子詞如果被丟棄,其損失會很大。

 

SentencePiece

它是谷歌推出的子詞開源工具包,其中集成了BPE、ULM子詞算法。除此之外,SentencePiece還能支持字符和詞級別的分詞。更進一步,為了能夠處理多語言問題,sentencePiece將句子視為Unicode編碼序列,從而子詞算法不用依賴於語言的表示。

 

參考資料:

[1]https://mp.weixin.qq.com/s/la3nZNFDviRcSFNVso29oQ

[2]https://zhuanlan.zhihu.com/p/86965595


免責聲明!

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



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