作者|ARAVIND PAI
編譯|VK
來源|Analytics Vidhya
概述
-
標識化是處理文本資料的一個關鍵
-
我們將討論標識化的各種細微差別,包括如何處理詞匯表外單詞(OOV)
介紹
從零開始掌握一門新的語言令人望而生畏,如果你曾經學過一種不是你母語的語言,你就會理解!有太多的層次需要考慮,例如語法需要考慮,這是一個相當大的挑戰,
為了讓我們的計算機理解任何文本,我們需要用機器能夠理解的方式把這個詞分解,這就是自然語言處理(NLP)中標識化的概念,
簡單地說,標識化(Tokenization)對于處理文本資料十分重要,

下面是關于標識化的有趣的事情,它不僅僅是分解文本,標識化在處理文本資料中起著重要的作用,因此,在本文中,我們將探討自然語言處理中的標識化,以及如何在Python中實作它,
目錄
-
標識化
-
標識化背后的真正原因
-
我們應該使用哪種(單詞、字符或子單詞)?
-
在Python中實作Byte Pair編碼
標識化
標識化(Tokenization)是自然語言處理(NLP)中的一項常見任務,這是傳統NLP方法(如Count Vectorizer)和高級的基于深度學習的體系結構(如Transformers)的基本步驟,
單詞是自然語言的組成部分,
標識化是一種將文本分割成稱為標識的較小單元的方法,在這里,標識可以是單詞、字符或子單詞,因此,標識化可以大致分為三種型別:單詞、字符和子單詞(n-gram字符)標識化,
例如,想想這句話:“Never give up”,
最常見的詞的形成方式是基于空間,假設空格作為分隔符,句子的標識化會產生3個詞,Never-give-up,由于每個標識都是一個單詞,因此它成為單詞標識化的一個示例,
類似地,標識(token)可以是字符或子單詞,例如,讓我們考慮smarter”:
-
字符標識:s-m-a-r-t-e-r
-
子單詞(subword)標識:smart-er
但這有必要嗎?我們真的需要標識化來完成這一切嗎?
標識化背后的真正原因
由于詞語是自然語言的構建塊,所以處理原始文本的最常見方式發生在單詞級別,
例如,基于Transformer的模型(NLP中的最新(SOTA)深度學習架構)在單詞級別處理原始文本,類似地,對于NLP最流行的深度學習架構,如RNN、GRU和LSTM,也在單詞級別處理原始文本,

如圖所示,RNN在特定的時間步接收和處理每個單詞,
因此,標識化是文本資料建模的首要步驟,對語料庫執行標識化以獲取單詞,然后使用以下單詞準備詞匯表,詞匯是指語料庫中出現過的單詞,請記住,詞匯表可以通過考慮語料庫中每個唯一的單詞或考慮前K個頻繁出現的單詞來構建,
創建詞匯表是標識化的最終目標,
提高NLP模型性能的一個最簡單的技巧是使用top K的單詞創建一個詞匯表,
現在,讓我們了解一下詞匯在傳統的和高級的基于深度學習的NLP方法中的用法,
-
傳統的NLP方法如單詞頻率計數和TF-IDF使用詞匯作為特征,詞匯表中的每個單詞都被視為一個獨特的特征:

-
在基于深度學習的高級NLP體系結構中,詞匯表用于創建輸入陳述句,最后,這些單詞作為輸入傳遞給模型
我們應該使用哪種(單詞、字符或子單詞)?
如前所述,標識化可以在單詞、字符或子單詞級別執行,這是一個常見的問題-在解決NLP任務時應該使用哪種標識化?讓我們在這里討論這個問題,
單詞級標識化
詞標識化是最常用的標識化演算法,它根據特定的分隔符將一段文本(英文)拆分為單個單詞,根據分隔符的不同,將形成不同的字級標識,預訓練的單詞嵌入,如Word2Vec和GloVe屬于單詞標識化,
這種只有少量缺點,
單詞級標識化的缺點
單詞標識的主要問題之一是處理詞匯表外(OOV)單詞,OOV詞是指在測驗中遇到的新詞,這些生詞在詞匯表中不存在,因此,這些方法無法處理OOV單詞,
但是,等等,不要妄下結論!
-
一個小技巧可以將單詞標識化器從OOV單詞中解救出來,訣竅是用前K個頻繁詞組成詞匯表,并用未知標識(UNK)替換訓練資料中的稀有詞,這有助于模型使用UNK學習OOV單詞的表示
-
因此,在測驗期間,詞匯表中不存在的任何單詞都將映射到UNK標識,這就是我們如何解決標識化器中的OOV問題,
-
這種方法的問題是,當我們將OOV映射到UNK單詞時,單詞的整個資訊都會丟失,單詞的結構可能有助于準確地表示單詞,另一個問題是每個OOV單詞都有相同的表示

單詞標識的另一個問題與詞匯表的大小有關,一般來說,預訓練的模型是在大量的文本語料庫上訓練的,所以,想象一下在這么大的一個語料庫中用所有單詞構建詞匯表,這會大大增加詞匯量!
這打開了字符級標識化的大門,
字符級標識化
字符標識化將每個文本分割成一組字符,它克服了我們在上面看到的關于單詞標識化的缺點,
-
字符標識化器通過保存單詞的資訊來連貫地處理OOV單詞,它將OOV單詞分解成字符,并用這些字符表示單詞
-
它也限制了詞匯量的大小,想猜猜詞匯量嗎?答案是26個,
字符標識化的缺點
字符標識解決了OOV問題,但是當我們將一個句子表示為一個字符序列時,輸入和輸出句子的長度會迅速增加,因此,學習單詞之間的關系以形成有意義的詞就變得很有挑戰性,
這將我們帶到另一個稱為子單詞標識化(Subword)的標識化,它介于字和字符標識化之間,
子單詞標識化
子單詞標識化將文本分割成子單詞(或n個字符),例如,lower這樣的詞可以被分割為low-er,smartest和smart-est,等等,
基于轉換的模型(NLP中的SOTA)依賴于子單詞標識化演算法來準備詞匯表,現在,我將討論一種最流行的子單詞標識化演算法,稱為Byte Pair Encoding 位元組對編碼(BPE),
使用BPE
Byte Pair 編碼,BPE是基于轉換器的模型中廣泛使用的一種標識化方法,BPE解決了單詞和字符標識化器的問題:
-
BPE有效地解決了OOV問題,它將OOV分割為子單詞,并用這些子單詞表示單詞
-
與字符標識化相比,BPE后輸入和輸出陳述句的長度更短
BPE是一種標識化演算法,它迭代合并最頻繁出現的字符或字符序列,下面是一個逐步學習BPE的教程,
學習BPE的步驟
-
附加結尾符號
-
用語料庫中的唯一字符初始化詞匯
-
計算語料庫中pair或字符序列的頻率
-
合并語料庫中最頻繁的pair
-
把最好的pair保留到詞匯表中
-
對一定數量的迭代重復步驟3到5
我們將通過一個例子來理解這些步驟,
考慮語料庫

1a)在語料庫中的每個單詞后面附加單詞的結尾符號(比如說):

1b)將語料庫中的單詞分為字符:

2.初始化詞匯表:

迭代1:
3.計算頻率:

4.合并最常見的pair:

5.保存最佳pair:

從現在開始對每個迭代重復步驟3-5,讓我再演示一次迭代,
迭代2:
3.計算頻率:

4.合并最常見的pair:

5.保存最佳pair:

經過10次迭代后,BPE合并操作如下所示:

很直截了當,對吧?
BPE在OOV詞中的應用
但是,我們如何在測驗時使用BPE來表示OOV單詞呢?有什么想法嗎?我們現在來回答這個問題,
在測驗時,OOV單詞被分割成字符序列,然后應用所學的操作將字符合并成更大的已知符號,
下面是表示OOV單詞的表示程序:
-
追加后將OOV單詞拆分為字符
-
計算一個單詞中的pair或字符序列
-
選擇學習過的存在的pair
-
合并最常見的pair
-
重復步驟2和3,直到可以合并
接下來讓我們來看看這一切!
在Python中實作Byte Pair編碼
我們現在知道BPE是如何學習和應用OOV詞匯的,所以,是時候用Python實作了,
BPE的Python代碼已經在原來的論文發布的代碼中可用,
讀取語料庫
我們將考慮一個簡單的語料庫來說明BPE的思想,然而,同樣的想法也適用于另一個語料庫:
#匯入庫
import pandas as pd
#正在讀取.txt檔案
text = pd.read_csv("sample.txt",header=None)
#將資料幀轉換為單個串列
corpus=[]
for row in text.values:
tokens = row[0].split(" ")
for token in tokens:
corpus.append(token)
文本預處理
將單詞分割為語料庫中的字符,并在每個單詞的末尾附加:
#初始化詞匯
vocab = list(set(" ".join(corpus)))
vocab.remove(' ')
#把這個詞分成字符
corpus = [" ".join(token) for token in corpus]
#追加</w>
corpus=[token+' </w>' for token in corpus]
學習BPE
計算語料庫中每個單詞的頻率:
import collections
#回傳每個單詞的頻率
corpus = collections.Counter(corpus)
#將計數器物件轉換為字典
corpus = dict(corpus)
print("Corpus:",corpus)
輸出:

讓我們定義一個函式來計算pair或字符序列的頻率,它接受語料庫并回傳頻率:
#pair或字符序列的頻率
#引數是語料并且回傳每個pair的頻率
def get_stats(corpus):
pairs = collections.defaultdict(int)
for word, freq in corpus.items():
symbols = word.split()
for i in range(len(symbols)-1):
pairs[symbols[i],symbols[i+1]] += freq
return pairs
現在,下一個任務是合并語料庫中最頻繁的pair,我們將定義一個函式來接受語料庫、最佳pair,并回傳修改后的語料庫:
#合并語料庫中最常見的pair
#接受語料庫和最佳pair
import re
def merge_vocab(pair, corpus_in):
corpus_out = {}
bigram = re.escape(' '.join(pair))
p = re.compile(r'(?<!\S)' + bigram + r'(?!\S)')
for word in corpus_in:
w_out = p.sub(''.join(pair), word)
corpus_out[w_out] = corpus_in[word]
return corpus_out
接下來,是學習BPE操作的時候了,由于BPE是一個迭代程序,我們將執行并理解一次迭代的步驟,讓我們計算bi-gram的頻率:
#bi-gram的頻率
pairs = get_stats(corpus)
print(pairs)
輸出:

找到最常見的:
#計算最佳pair
best = max(pairs, key=pairs.get)
print("Most Frequent pair:",best)
輸出:(‘e’, ‘s’)
最后,合并最佳pair并保存到詞匯表中:
#語料庫中頻繁pair的合并
corpus = merge_vocab(best, corpus)
print("After Merging:", corpus)
#將元組轉換為字串
best = "".join(list(best))
#合并到merges和vocab
merges = []
merges.append(best)
vocab.append(best)
輸出:

我們將遵循類似的步驟:
num_merges = 10
for i in range(num_merges):
#計算bi-gram的頻率
pairs = get_stats(corpus)
#計算最佳pair
best = max(pairs, key=pairs.get)
#合并語料庫中的頻繁pair
corpus = merge_vocab(best, corpus)
#合并到merges和vocab
merges.append(best)
vocab.append(best)
#將元組轉換為字串
merges_in_string = ["".join(list(i)) for i in merges]
print("BPE Merge Operations:",merges_in_string)
輸出:

最有趣的部分還在后面呢!將BPE應用于OOV詞匯,
BPE在OOV詞匯中的應用
現在,我們將看到如何應用BPE在OOV單詞上,例如OOV單詞是“lowest”:
#BPE在OOV詞匯中的應用
oov ='lowest'
#將OOV分割為字符
oov = " ".join(list(oov))
#添加 </w>
oov = oov + ' </w>'
#創建字典
oov = { oov : 1}
將BPE應用于OOV單詞也是一個迭代程序,我們將執行本文前面討論的步驟:
i=0
while(True):
#計算頻率
pairs = get_stats(oov)
#提取keys
pairs = pairs.keys()
#找出之前學習中可用的pair
ind=[merges.index(i) for i in pairs if i in merges]
if(len(ind)==0):
print("\nBPE Completed...")
break
#選擇最常學習的操作
best = merges[min(ind)]
#合并最佳pair
oov = merge_vocab(best, oov)
print("Iteration ",i+1, list(oov.keys())[0])
i=i+1
輸出:

如你所見,OOV單詞“low est”被分割為low-est,
結尾
標識化是處理文本資料的一種強大方法,我們在本文中看到了這一點,并使用Python實作了標識化,
繼續在任何基于文本的資料集上嘗試這個方法,練習得越多,就越能理解標識化是如何作業的(以及為什么它是一個如此關鍵的NLP概念),
原文鏈接:https://www.analyticsvidhya.com/blog/2020/05/what-is-tokenization-nlp/
歡迎關注磐創AI博客站:
http://panchuang.net/
sklearn機器學習中文官方檔案:
http://sklearn123.com/
歡迎關注磐創博客資源匯總站:
http://docs.panchuang.net/
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/10853.html
標籤:其他
上一篇:ov7725如何做到縮放效果
