在9.2 節(jié)中,我們將看到如何將文本序列映射到標(biāo)記中,其中這些標(biāo)記可以被視為一系列離散的觀察結(jié)果,例如單詞或字符。假設(shè)文本序列中的標(biāo)記長(zhǎng)度T依次是 x1,x2,…,xT. 語(yǔ)言模型的目標(biāo)是估計(jì)整個(gè)序列的聯(lián)合概率:
(9.3.1)P(x1,x2,…,xT),
其中可以應(yīng)用第 9.1 節(jié)中的統(tǒng)計(jì)工具。
語(yǔ)言模型非常有用。例如,一個(gè)理想的語(yǔ)言模型將能夠自行生成自然文本,只需一次繪制一個(gè)標(biāo)記即可 xt~P(xt∣xt?1,…,x1). 與使用打字機(jī)的猴子完全不同,從這種模型中出現(xiàn)的所有文本都將作為自然語(yǔ)言傳遞,例如英文文本。此外,只需在先前的對(duì)話片段上調(diào)節(jié)文本,就足以生成有意義的對(duì)話。顯然,我們離設(shè)計(jì)這樣一個(gè)系統(tǒng)還有很長(zhǎng)的路要走,因?yàn)樗枰斫馕谋荆粌H僅是生成語(yǔ)法合理的內(nèi)容。
盡管如此,語(yǔ)言模型即使在其有限的形式下也能提供很好的服務(wù)。例如,“to recognize speech”和“to wreck a nice beach”這兩個(gè)短語(yǔ)聽起來(lái)非常相似。這可能會(huì)導(dǎo)致語(yǔ)音識(shí)別中出現(xiàn)歧義,這很容易通過(guò)一種語(yǔ)言模型來(lái)解決,該模型拒絕將第二種翻譯認(rèn)為是古怪的。同樣,在文檔摘要算法中,值得知道“狗咬人”比“人咬狗”更頻繁,或者“我想吃奶奶”是一個(gè)相當(dāng)令人不安的陳述,而“我想吃,奶奶”要溫和得多。
import torch from d2l import torch as d2l
from mxnet import np, npx from d2l import mxnet as d2l npx.set_np()
from jax import numpy as jnp from d2l import jax as d2l
No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)
import tensorflow as tf from d2l import tensorflow as d2l
9.3.1. 學(xué)習(xí)語(yǔ)言模型
顯而易見的問(wèn)題是我們應(yīng)該如何對(duì)文檔甚至一系列標(biāo)記進(jìn)行建模。假設(shè)我們?cè)趩卧~級(jí)別標(biāo)記文本數(shù)據(jù)。讓我們從應(yīng)用基本概率規(guī)則開始:
(9.3.2)P(x1,x2,…,xT)=∏t=1TP(xt∣x1,…,xt?1).
例如,包含四個(gè)單詞的文本序列的概率為:
(9.3.3)P(deep,learning,is,fun)=P(deep)P(learning∣deep)P(is∣deep,learning)P(fun∣deep,learning,is).
9.3.1.1. 馬爾可夫模型和n-克
在9.1節(jié)的序列模型分析中,我們將馬爾可夫模型應(yīng)用到語(yǔ)言建模中。序列上的分布滿足一階馬爾可夫性質(zhì),如果 P(xt+1∣xt,…,x1)=P(xt+1∣xt). 更高的階數(shù)對(duì)應(yīng)更長(zhǎng)的依賴關(guān)系。這導(dǎo)致我們可以應(yīng)用一些近似值來(lái)對(duì)序列建模:
(9.3.4)P(x1,x2,x3,x4)=P(x1)P(x2)P(x3)P(x4),P(x1,x2,x3,x4)=P(x1)P(x2∣x1)P(x3∣x2)P(x4∣x3),P(x1,x2,x3,x4)=P(x1)P(x2∣x1)P(x3∣x1,x2)P(x4∣x2,x3).
涉及一個(gè)、兩個(gè)和三個(gè)變量的概率公式通常分別稱為一元模型、二元模型和三元模型。為了計(jì)算語(yǔ)言模型,我們需要計(jì)算單詞的概率和給定前幾個(gè)單詞的單詞的條件概率。請(qǐng)注意,此類概率是語(yǔ)言模型參數(shù)。
9.3.1.2. 詞頻
在這里,我們假設(shè)訓(xùn)練數(shù)據(jù)集是一個(gè)大型文本語(yǔ)料庫(kù),例如所有維基百科詞條、古騰堡計(jì)劃和網(wǎng)絡(luò)上發(fā)布的所有文本。可以根據(jù)訓(xùn)練數(shù)據(jù)集中給定單詞的相對(duì)單詞頻率計(jì)算單詞的概率。例如,估計(jì)P^(deep)可以計(jì)算為任何以單詞“deep”開頭的句子的概率。一種不太準(zhǔn)確的方法是計(jì)算“deep”這個(gè)詞的所有出現(xiàn)次數(shù),然后除以語(yǔ)料庫(kù)中的單詞總數(shù)。這工作得很好,特別是對(duì)于頻繁出現(xiàn)的單詞。繼續(xù),我們可以嘗試估計(jì)
(9.3.5)P^(learning∣deep)=n(deep, learning)n(deep),
在哪里n(x)和n(x,x′)分別是單個(gè)詞和連續(xù)詞對(duì)的出現(xiàn)次數(shù)。不幸的是,估計(jì)單詞對(duì)的概率有點(diǎn)困難,因?yàn)椤?a target="_blank">深度學(xué)習(xí)”的出現(xiàn)頻率要低得多。特別是,對(duì)于一些不常見的單詞組合,可能很難找到足夠多的出現(xiàn)次數(shù)來(lái)獲得準(zhǔn)確的估計(jì)。正如第 9.2.5 節(jié)中的實(shí)證結(jié)果所表明的那樣,對(duì)于三詞組合及以上,情況會(huì)變得更糟。將有許多我們可能不會(huì)在我們的數(shù)據(jù)集中看到的似是而非的三詞組合。除非我們提供一些解決方案來(lái)分配此類單詞組合的非零計(jì)數(shù),否則我們將無(wú)法在語(yǔ)言模型中使用它們。如果數(shù)據(jù)集很小或者單詞非常罕見,我們可能連一個(gè)都找不到。
9.3.1.3. 拉普拉斯平滑
一種常見的策略是執(zhí)行某種形式的拉普拉斯平滑。解決方案是為所有計(jì)數(shù)添加一個(gè)小常數(shù)。表示為n 訓(xùn)練集中的單詞總數(shù)和m唯一單詞的數(shù)量。該解決方案有助于單例,例如,通過(guò)
(9.3.6)P^(x)=n(x)+?1/mn+?1,P^(x′∣x)=n(x,x′)+?2P^(x′)n(x)+?2,P^(x″∣x,x′)=n(x,x′,x″)+?3P^(x″)n(x,x′)+?3.
這里?1,?2, 和?3是超參數(shù)。拿?1例如:當(dāng) ?1=0, 沒有應(yīng)用平滑;什么時(shí)候?1 接近正無(wú)窮大,P^(x)接近均勻概率1/m. 以上是其他技術(shù)可以實(shí)現(xiàn)的相當(dāng)原始的變體 (Wood等人,2011 年)。
不幸的是,由于以下原因,這樣的模型很快就會(huì)變得笨拙。首先,如第 9.2.5 節(jié)所述 ,許多n-grams 很少出現(xiàn),這使得拉普拉斯平滑不適合語(yǔ)言建模。其次,我們需要存儲(chǔ)所有計(jì)數(shù)。第三,這完全忽略了文字的意思。例如,“cat”和“feline”應(yīng)該出現(xiàn)在相關(guān)的語(yǔ)境中。很難將此類模型調(diào)整到其他上下文,而基于深度學(xué)習(xí)的語(yǔ)言模型非常適合將這一點(diǎn)考慮在內(nèi)。最后,長(zhǎng)單詞序列幾乎肯定是新穎的,因此簡(jiǎn)單地計(jì)算以前見過(guò)的單詞序列頻率的模型在這方面肯定表現(xiàn)不佳。因此,我們將在本章的其余部分重點(diǎn)介紹使用神經(jīng)網(wǎng)絡(luò)進(jìn)行語(yǔ)言建模。
9.3.2. 困惑
接下來(lái),讓我們討論如何衡量語(yǔ)言模型的質(zhì)量,這將在后續(xù)部分中用于評(píng)估我們的模型。一種方法是檢查文本有多令人驚訝。一個(gè)好的語(yǔ)言模型能夠用高精度的標(biāo)記來(lái)預(yù)測(cè)我們接下來(lái)會(huì)看到什么。考慮不同語(yǔ)言模型提出的短語(yǔ)“It is raining”的以下延續(xù):
“外面下雨了”
“香蕉樹下雨了”
“正在下雨 piouw;kcj pwepoiut”
就質(zhì)量而言,示例 1 顯然是最好的。言辭合情合理,邏輯連貫。雖然它可能不能完全準(zhǔn)確地反映出哪個(gè)詞在語(yǔ)義上跟隨(“在舊金山”和“在冬天”將是完全合理的擴(kuò)展),但該模型能夠捕捉到哪個(gè)詞跟隨在后面。示例 2 通過(guò)生成無(wú)意義的擴(kuò)展而變得相當(dāng)糟糕。盡管如此,至少該模型已經(jīng)學(xué)會(huì)了如何拼寫單詞以及單詞之間的某種程度的相關(guān)性。最后,示例 3 表明訓(xùn)練有素的模型無(wú)法正確擬合數(shù)據(jù)。
我們可以通過(guò)計(jì)算序列的可能性來(lái)衡量模型的質(zhì)量。不幸的是,這是一個(gè)難以理解和比較的數(shù)字。畢竟,較短的序列比較長(zhǎng)的序列更有可能出現(xiàn),因此評(píng)估托爾斯泰的巨著《戰(zhàn)爭(zhēng)與和平》中的模型將不可避免地產(chǎn)生比圣埃克蘇佩里的中篇小說(shuō)《小王子》小得多的可能性。缺少的是相當(dāng)于平均值。
信息論在這里派上用場(chǎng)。我們?cè)诮榻B softmax 回歸時(shí)定義了熵、驚奇和交叉熵(第 4.1.3 節(jié))。如果我們想壓縮文本,我們可以詢問(wèn)在給定當(dāng)前標(biāo)記集的情況下預(yù)測(cè)下一個(gè)標(biāo)記。更好的語(yǔ)言模型應(yīng)該能讓我們更準(zhǔn)確地預(yù)測(cè)下一個(gè)標(biāo)記。因此,它應(yīng)該允許我們?cè)趬嚎s序列時(shí)花費(fèi)更少的比特。所以我們可以通過(guò)對(duì)所有數(shù)據(jù)進(jìn)行平均的交叉熵?fù)p失來(lái)衡量它n序列的標(biāo)記:
(9.3.7)1n∑t=1n?log?P(xt∣xt?1,…,x1),
在哪里P由語(yǔ)言模型給出,并且xt是在時(shí)間步觀察到的實(shí)際標(biāo)記t從序列。這使得不同長(zhǎng)度文檔的性能具有可比性。由于歷史原因,自然語(yǔ)言處理領(lǐng)域的科學(xué)家更喜歡使用一種叫做困惑度的量。簡(jiǎn)而言之,它是(9.3.7)的指數(shù):
(9.3.8)exp?(?1n∑t=1nlog?P(xt∣xt?1,…,x1)).
困惑度可以最好地理解為我們?cè)跊Q定下一步選擇哪個(gè)標(biāo)記時(shí)所擁有的實(shí)際選擇數(shù)量的幾何平均值。讓我們看一些案例:
在最好的情況下,模型總是完美地將目標(biāo)標(biāo)記的概率估計(jì)為 1。在這種情況下,模型的困惑度為 1。
在最壞的情況下,模型總是預(yù)測(cè)目標(biāo)標(biāo)記的概率為 0。在這種情況下,困惑度為正無(wú)窮大。
在基線上,該模型預(yù)測(cè)詞匯表中所有可用標(biāo)記的均勻分布。在這種情況下,困惑度等于詞匯表中唯一標(biāo)記的數(shù)量。事實(shí)上,如果我們要在不進(jìn)行任何壓縮的情況下存儲(chǔ)序列,這將是我們對(duì)它進(jìn)行編碼所能做的最好的事情。因此,這提供了一個(gè)重要的上限,任何有用的模型都必須擊敗它。
9.3.3. 分區(qū)序列
我們將使用神經(jīng)網(wǎng)絡(luò)設(shè)計(jì)語(yǔ)言模型,并使用困惑度來(lái)評(píng)估模型在給定文本序列中的當(dāng)前標(biāo)記集的情況下預(yù)測(cè)下一個(gè)標(biāo)記的能力。在介紹該模型之前,我們假設(shè)它一次處理一小批具有預(yù)定義長(zhǎng)度的序列。現(xiàn)在的問(wèn)題是如何隨機(jī)讀取輸入序列和目標(biāo)序列的小批量。
假設(shè)數(shù)據(jù)集采用一系列的形式T中的令牌索引corpus。我們將把它分成子序列,其中每個(gè)子序列有n令牌(時(shí)間步長(zhǎng))。為每個(gè)時(shí)期迭代(幾乎)整個(gè)數(shù)據(jù)集的所有標(biāo)記并獲得所有可能的長(zhǎng)度 -n子序列,我們可以引入隨機(jī)性。更具體地說(shuō),在每個(gè)時(shí)代的開始,丟棄第一個(gè)d令牌,在哪里d∈[0,n)是隨機(jī)均勻采樣的。然后將序列的其余部分劃分為 m=?(T?d)/n?子序列。表示為 xt=[xt,…,xt+n?1]長(zhǎng)度-n 從令牌開始的子序列xt在時(shí)間步t. 所結(jié)果的m分區(qū)子序列是 xd,xd+n,…,xd+n(m?1).每個(gè)子序列將用作語(yǔ)言模型的輸入序列。
對(duì)于語(yǔ)言建模,目標(biāo)是根據(jù)我們目前看到的標(biāo)記預(yù)測(cè)下一個(gè)標(biāo)記,因此目標(biāo)(標(biāo)簽)是原始序列,移動(dòng)一個(gè)標(biāo)記。任何輸入序列的目標(biāo)序列xt是xt+1有長(zhǎng)度n.
圖 9.3.1從分割的長(zhǎng)度為 5 的子序列中獲得 5 對(duì)輸入序列和目標(biāo)序列。
圖 9.3.1顯示了獲得 5 對(duì)輸入序列和目標(biāo)序列的示例n=5和d=2.
@d2l.add_to_class(d2l.TimeMachine) #@save def __init__(self, batch_size, num_steps, num_train=10000, num_val=5000): super(d2l.TimeMachine, self).__init__() self.save_hyperparameters() corpus, self.vocab = self.build(self._download()) array = torch.tensor([corpus[i:i+num_steps+1] for i in range(len(corpus)-num_steps)]) self.X, self.Y = array[:,:-1], array[:,1:]
@d2l.add_to_class(d2l.TimeMachine) #@save def __init__(self, batch_size, num_steps, num_train=10000, num_val=5000): super(d2l.TimeMachine, self).__init__() self.save_hyperparameters() corpus, self.vocab = self.build(self._download()) array = np.array([corpus[i:i+num_steps+1] for i in range(len(corpus)-num_steps)]) self.X, self.Y = array[:,:-1], array[:,1:]
@d2l.add_to_class(d2l.TimeMachine) #@save def __init__(self, batch_size, num_steps, num_train=10000, num_val=5000): super(d2l.TimeMachine, self).__init__() self.save_hyperparameters() corpus, self.vocab = self.build(self._download()) array = jnp.array([corpus[i:i+num_steps+1] for i in range(len(corpus)-num_steps)]) self.X, self.Y = array[:,:-1], array[:,1:]
@d2l.add_to_class(d2l.TimeMachine) #@save def __init__(self, batch_size, num_steps, num_train=10000, num_val=5000): super(d2l.TimeMachine, self).__init__() self.save_hyperparameters() corpus, self.vocab = self.build(self._download()) array = tf.constant([corpus[i:i+num_steps+1] for i in range(len(corpus)-num_steps)]) self.X, self.Y = array[:,:-1], array[:,1:]
為了訓(xùn)練語(yǔ)言模型,我們將在小批量中隨機(jī)抽取輸入序列和目標(biāo)序列對(duì)。以下數(shù)據(jù)加載器每次從數(shù)據(jù)集中隨機(jī)生成一個(gè)小批量。參數(shù) batch_size指定每個(gè)小批量中子序列示例的數(shù)量,并且num_steps是以標(biāo)記為單位的子序列長(zhǎng)度。
@d2l.add_to_class(d2l.TimeMachine) #@save def get_dataloader(self, train): idx = slice(0, self.num_train) if train else slice( self.num_train, self.num_train + self.num_val) return self.get_tensorloader([self.X, self.Y], train, idx)
正如我們?cè)谙旅婵吹降模梢酝ㄟ^(guò)將輸入序列移動(dòng)一個(gè)標(biāo)記來(lái)獲得一小批目標(biāo)序列。
data = d2l.TimeMachine(batch_size=2, num_steps=10) for X, Y in data.train_dataloader(): print('X:', X, 'nY:', Y) break
X: tensor([[ 0, 5, 10, 14, 6, 15, 20, 10, 16, 15], [ 5, 10, 7, 7, 6, 19, 6, 15, 4, 6]]) Y: tensor([[ 5, 10, 14, 6, 15, 20, 10, 16, 15, 0], [10, 7, 7, 6, 19, 6, 15, 4, 6, 0]])
data = d2l.TimeMachine(batch_size=2, num_steps=10) for X, Y in data.train_dataloader(): print('X:', X, 'nY:', Y) break
X: [[14. 6. 15. 21. 0. 14. 26. 0. 5. 6.] [ 0. 2. 0. 7. 16. 22. 19. 21. 9. 0.]] Y: [[ 6. 15. 21. 0. 14. 26. 0. 5. 6. 2.] [ 2. 0. 7. 16. 22. 19. 21. 9. 0. 5.]]
data = d2l.TimeMachine(batch_size=2, num_steps=10) for X, Y in data.train_dataloader(): print('X:', X, 'nY:', Y) break
X: [[13 10 14 10 21 20 0 22 20 0] [ 0 14 16 23 6 20 0 10 15 21]] Y: [[10 14 10 21 20 0 22 20 0 21] [14 16 23 6 20 0 10 15 21 6]]
data = d2l.TimeMachine(batch_size=2, num_steps=10) for X, Y in data.train_dataloader(): print('X:', X, 'nY:', Y) break
X: tf.Tensor( [[13 26 0 21 24 16 0 5 10 14] [22 20 15 6 20 20 0 14 16 23]], shape=(2, 10), dtype=int32) Y: tf.Tensor( [[26 0 21 24 16 0 5 10 14 6] [20 15 6 20 20 0 14 16 23 6]], shape=(2, 10), dtype=int32)
9.3.4. 總結(jié)與討論
語(yǔ)言模型估計(jì)文本序列的聯(lián)合概率。對(duì)于長(zhǎng)序列,n-grams 通過(guò)截?cái)嘁蕾囮P(guān)系提供了一個(gè)方便的模型。然而,有很多結(jié)構(gòu)但沒有足夠的頻率來(lái)通過(guò)拉普拉斯平滑有效地處理不常見的單詞組合。因此,我們將在后續(xù)部分重點(diǎn)介紹神經(jīng)語(yǔ)言建模。為了訓(xùn)練語(yǔ)言模型,我們可以在小批量中隨機(jī)抽取輸入序列和目標(biāo)序列對(duì)。訓(xùn)練結(jié)束后,我們將使用 perplexity 來(lái)衡量語(yǔ)言模型的質(zhì)量。
語(yǔ)言模型可以隨著數(shù)據(jù)大小、模型大小和訓(xùn)練計(jì)算量的增加而擴(kuò)展。大型語(yǔ)言模型可以通過(guò)給定輸入文本指令預(yù)測(cè)輸出文本來(lái)執(zhí)行所需的任務(wù)。正如我們稍后將討論的(例如, 第 11.9 節(jié)),目前,大型語(yǔ)言模型構(gòu)成了跨不同任務(wù)的最先進(jìn)系統(tǒng)的基礎(chǔ)。
9.3.5. 練習(xí)
假設(shè)有100,000訓(xùn)練數(shù)據(jù)集中的單詞。一個(gè)四文庫(kù)需要存儲(chǔ)多少詞頻和多詞鄰頻?
你將如何模擬對(duì)話?
您還能想到哪些其他方法來(lái)讀取長(zhǎng)序列數(shù)據(jù)?
考慮我們?cè)诿總€(gè)紀(jì)元開始時(shí)丟棄前幾個(gè)標(biāo)記的均勻隨機(jī)數(shù)的方法。
它真的會(huì)導(dǎo)致文檔序列的完美均勻分布嗎?
你必須做些什么才能使事情變得更加統(tǒng)一?
如果我們想讓一個(gè)序列示例是一個(gè)完整的句子,這在小批量抽樣中會(huì)引入什么樣的問(wèn)題?我們?nèi)绾谓鉀Q這個(gè)問(wèn)題?
-
語(yǔ)言模型
+關(guān)注
關(guān)注
0文章
508瀏覽量
10245 -
pytorch
+關(guān)注
關(guān)注
2文章
803瀏覽量
13150
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論