神經(jīng)概率語(yǔ)言模型(NPLM):讓機(jī)器學(xué)會(huì)“理解”語(yǔ)言 精華
本文介紹了神經(jīng)概率語(yǔ)言模型(NPLM)的基本原理、結(jié)構(gòu)與實(shí)現(xiàn)方法。通過(guò)對(duì)比傳統(tǒng)N-gram模型,闡述了NPLM如何利用神經(jīng)網(wǎng)絡(luò)自動(dòng)學(xué)習(xí)詞語(yǔ)間的深層關(guān)系,有效提升語(yǔ)言建模的泛化能力。內(nèi)容涵蓋數(shù)據(jù)準(zhǔn)備、模型搭建、訓(xùn)練流程及推理預(yù)測(cè)。
1. 什么是神經(jīng)概率語(yǔ)言模型NPLM
2. 為什么需要神經(jīng)語(yǔ)言模型
2.1 傳統(tǒng)語(yǔ)言模型的問(wèn)題
2.2 神經(jīng)概率語(yǔ)言模型(NPLM)的誕生
3. 模型架構(gòu)詳解
4. 完整代碼實(shí)現(xiàn)
4.1 構(gòu)建語(yǔ)料庫(kù)
4.2 生成訓(xùn)練數(shù)據(jù)
4.3 模型定義
4.3 實(shí)例化NPLM模型
4.3 NPLM模型訓(xùn)練
5. 訓(xùn)練過(guò)程詳解
5.1 訓(xùn)練數(shù)據(jù)的準(zhǔn)備
5.2 訓(xùn)練的四個(gè)關(guān)鍵步驟
5.2.1 前向傳播(Forward Pass)
5.2.2 計(jì)算損失(Loss Calculation)
5.2.3 反向傳播(Backward Pass)
5.2.4 參數(shù)更新(Parameter Update)
6. 訓(xùn)練結(jié)果
7. 模型預(yù)測(cè)
8. 完整的數(shù)據(jù)流程圖
1. 什么是神經(jīng)概率語(yǔ)言模型NPLM
神經(jīng)概率語(yǔ)言模型(Neural Probabilistic Language Models, NPLM)聽起來(lái)很復(fù)雜,但我們可以把它拆解來(lái)理解:
什么是語(yǔ)言模型?
語(yǔ)言模型就像一個(gè)"語(yǔ)言預(yù)測(cè)器"。當(dāng)你在手機(jī)上打字時(shí),輸入法能夠預(yù)測(cè)你下一個(gè)要輸入的詞,這背后就是語(yǔ)言模型在工作。比如:
? 你輸入"今天天氣",模型預(yù)測(cè)下一個(gè)詞可能是"很好"、"不錯(cuò)"、"糟糕"等
? 你輸入"人工智能",模型預(yù)測(cè)下一個(gè)詞可能是"技術(shù)"、"發(fā)展"、"應(yīng)用"等
什么是概率?
概率就是某件事發(fā)生的可能性。在語(yǔ)言模型中,我們用概率來(lái)表示某個(gè)詞出現(xiàn)的可能性。比如:
? 在"今天天氣"后面,"很好"出現(xiàn)的概率可能是30%
? "不錯(cuò)"出現(xiàn)的概率可能是25%
? "糟糕"出現(xiàn)的概率可能是15%
什么是神經(jīng)網(wǎng)絡(luò)?
神經(jīng)網(wǎng)絡(luò)是一種模仿人腦工作方式的計(jì)算模型。就像人腦通過(guò)神經(jīng)元連接來(lái)處理信息一樣,神經(jīng)網(wǎng)絡(luò)通過(guò)多層計(jì)算節(jié)點(diǎn)來(lái)學(xué)習(xí)復(fù)雜的模式。
2. 為什么需要神經(jīng)語(yǔ)言模型
2.1 傳統(tǒng)語(yǔ)言模型的問(wèn)題
在神經(jīng)概率語(yǔ)言模型(NPLM)出現(xiàn)之前,N-gram模型自20世紀(jì)80年代以來(lái)一直是概率語(yǔ)言建模的主流范式 。
相關(guān)閱讀:???入門GPT(一)| N-Gram 帶你了解自然語(yǔ)言處理(1)??
傳統(tǒng)N-gram模型的局限性:
N-gram模型通過(guò)馬爾可夫假設(shè)簡(jiǎn)化了語(yǔ)言建模的復(fù)雜性后,假設(shè)一個(gè)詞的出現(xiàn)概率僅依賴于其前 n?1 個(gè)詞。
一個(gè)三元語(yǔ)法模型在預(yù)測(cè)下一個(gè)詞時(shí),只會(huì)考慮緊鄰的兩個(gè)前文詞語(yǔ) 。當(dāng)訓(xùn)練數(shù)據(jù)中出現(xiàn)未曾見過(guò)的詞序列時(shí),N-gram模型通常通過(guò)“平滑”和“回退”等技術(shù)來(lái)分配一個(gè)非零概率 。
然而,這種傳統(tǒng)方法存在顯著的局限性。N-gram模型通常只能考慮非常短的上下文窗口,例如1或2個(gè)詞,即使在某些情況下可擴(kuò)展到5個(gè)詞,但由于數(shù)據(jù)稀疏性,大多數(shù)預(yù)測(cè)仍依賴于一個(gè)比較短的上下文 。
更重要的是,N-gram模型缺乏對(duì)詞語(yǔ)之間語(yǔ)義或語(yǔ)法相似性的理解 。這意味著,如果模型在訓(xùn)練集中見過(guò)“貓?jiān)谂P室里走路”,它無(wú)法將這些知識(shí)自然地泛化到“狗在房間里跑”,因?yàn)樵贜-gram的離散表示中,“貓”和“狗”被視為完全不相關(guān)的實(shí)體。
這種局限性導(dǎo)致訓(xùn)練數(shù)據(jù)中的一個(gè)句子無(wú)法有效地為模型提供關(guān)于其語(yǔ)義鄰近句子的信息,從而限制了模型的泛化能力。
維度爆炸:
統(tǒng)計(jì)語(yǔ)言建模的一個(gè)很大的問(wèn)題在于“維度爆炸” 。
當(dāng)試圖建模大量離散隨機(jī)變量(如句子中的詞語(yǔ))的聯(lián)合分布時(shí),這個(gè)問(wèn)題尤為突出 。隨著輸入變量數(shù)量的增加,模型所需的訓(xùn)練樣本數(shù)量呈指數(shù)級(jí)增長(zhǎng) 。
例如,如果要對(duì)自然語(yǔ)言中連續(xù)十個(gè)單詞的聯(lián)合分布建模,而詞匯表大小是100,000,那么理論上就會(huì)有 個(gè)自由參數(shù)需要考慮。
在離散空間中,泛化并不像連續(xù)變量那樣有優(yōu)勢(shì),因?yàn)殡x散變量的任何改變都可能對(duì)函數(shù)值產(chǎn)生劇烈影響 。這意味著模型在測(cè)試時(shí)遇到的詞序列,與訓(xùn)練期間見過(guò)的所有詞序列很可能不同,從而導(dǎo)致模型難以對(duì)未見過(guò)的組合進(jìn)行準(zhǔn)確的概率估計(jì) 。
傳統(tǒng)N-gram模型會(huì)為詞匯表中的每個(gè)詞分配一個(gè)高維稀疏向量,其維度與詞匯量大小相同 。
N-gram模型采用局部、離散的統(tǒng)計(jì)方法,最終限制了其泛化能力和對(duì)語(yǔ)言深層語(yǔ)義的理解。
2.2 神經(jīng)概率語(yǔ)言模型(NPLM)的誕生
神經(jīng)概率語(yǔ)?模型(Neural Probabilistic Language Model,NPLM)的起源和發(fā)展可以追溯到2003年,當(dāng)時(shí)約書亞·本希奧及其團(tuán)隊(duì)發(fā)表了?篇題為“A Neural Probabilistic Language Model”(《?種神經(jīng)概率語(yǔ)?模型》)的論?.
這項(xiàng)工作標(biāo)志著語(yǔ)言建模領(lǐng)域的一個(gè)重要轉(zhuǎn)折點(diǎn),因?yàn)樗状螌⑸窠?jīng)網(wǎng)絡(luò)引入到語(yǔ)言建模中,并被認(rèn)為是“第一個(gè)(也是最簡(jiǎn)單的)用于語(yǔ)言建模的神經(jīng)網(wǎng)絡(luò)架構(gòu)” 。
NPLM的核心目標(biāo)是解決傳統(tǒng)N-gram模型面臨的“維度爆炸”問(wèn)題。
核心思想:分布式表示
NPLM提出通過(guò)學(xué)習(xí)詞語(yǔ)的“分布式表示”來(lái)對(duì)抗維度爆炸 。
分布式表示是指為詞匯表中的每個(gè)詞關(guān)聯(lián)一個(gè)連續(xù)值的向量。這些向量將詞語(yǔ)映射到一個(gè)低維的特征空間中,其中功能相似的詞語(yǔ)(無(wú)論是語(yǔ)義上還是語(yǔ)法上)在這個(gè)空間中彼此靠近 。
例如,如果模型學(xué)習(xí)了“貓”和“狗”在許多語(yǔ)境中可以互換而不改變句子的語(yǔ)法結(jié)構(gòu),它會(huì)學(xué)習(xí)到它們的嵌入向量應(yīng)該很接近。
這種表示方式使得模型能夠從每個(gè)訓(xùn)練句子中獲取信息,并將其泛化到語(yǔ)義鄰近句子上 。泛化的實(shí)現(xiàn)是因?yàn)橐粋€(gè)從未見過(guò)的詞序列,如果它由與已見過(guò)句子中的詞語(yǔ)相似(即具有接近的表示)的詞語(yǔ)組成,也能獲得高概率 。
NPLM模型同時(shí)學(xué)習(xí)兩個(gè)關(guān)鍵部分:1) 每個(gè)詞的分布式表示,以及 2) 基于這些表示的詞序列概率函數(shù) 。這種同步學(xué)習(xí)是NPLM成功的關(guān)鍵。
模型通過(guò)一個(gè)統(tǒng)一的神經(jīng)網(wǎng)絡(luò)架構(gòu)來(lái)學(xué)習(xí)從輸入詞到輸出概率的整個(gè)映射。通過(guò)將離散的詞語(yǔ)映射到連續(xù)的向量空間,NPLM有效地將高維離散空間中的數(shù)據(jù)稀疏性問(wèn)題,轉(zhuǎn)化為低維連續(xù)空間中的函數(shù)平滑性問(wèn)題 。
這使得模型能夠泛化到未見過(guò)的組合,因?yàn)椤跋嗨频脑~語(yǔ)預(yù)計(jì)會(huì)有相似的特征向量,并且概率函數(shù)是這些特征值的平滑函數(shù)” 。
NPLM的出現(xiàn)不僅僅是對(duì)N-gram模型的簡(jiǎn)單改進(jìn),它代表了語(yǔ)言建模領(lǐng)域從純粹的統(tǒng)計(jì)方法向基于神經(jīng)網(wǎng)絡(luò)的表征學(xué)習(xí)的根本性范式轉(zhuǎn)變。這種轉(zhuǎn)變不僅有效解決了維度爆炸,更為后續(xù)所有現(xiàn)代神經(jīng)網(wǎng)絡(luò)語(yǔ)言模型(包括Word2Vec、RNN、Transformer等)奠定了理論和實(shí)踐基礎(chǔ)。
3. 模型架構(gòu)詳解

來(lái)自《A Neural Probabilistic Language Model》
? 圖中的矩陣C?于將輸?的詞(Context,即之前的N個(gè)詞,也被稱為上下?詞)映射到?個(gè)連續(xù)的向量空間。這個(gè)過(guò)程在論?中稱為“table look-up”,因?yàn)槲覀兛梢詫⒕仃?strong>C視為?張查找表,通過(guò)查找表可以將輸?詞的索引(或One-Hot編碼)轉(zhuǎn)換為其對(duì)應(yīng)的詞向量表示。矩陣C的參數(shù)在所有詞之間共享。這意味著,對(duì)于所有的輸?詞,都使?相同的矩陣C來(lái)獲取它們的詞向量表示。這有助于減少模型的參數(shù)數(shù)量,提?模型的泛化能?。
? 通過(guò)矩陣C會(huì)得到?組詞向量,此時(shí)需要對(duì)輸?向量進(jìn)?線性變換(即矩陣乘法和偏置加法),然后將其輸?隱藏層,進(jìn)?上下?語(yǔ)義信息的學(xué)習(xí)。因?yàn)檎?發(fā)表時(shí)間較早,所以隱藏層使?雙曲正切(tanh)函數(shù)作為?線性激活函數(shù),?不是后來(lái)常?的 ReLU 函數(shù)。在這篇論?發(fā)表的2003年,算?還不是很強(qiáng),所以論?特別注明:這?部分的計(jì)算量通常較?。
? 輸出層通常是?個(gè)全連接層,?于計(jì)算給定上下?條件下每個(gè)詞的概率。圖中 “第個(gè)輸出” 這句話描述了NPLM的輸出?標(biāo)。對(duì)于每個(gè)詞 ,模型計(jì)算在給定上下?條件下,?標(biāo)詞匯 (也就是下?個(gè)詞)是詞匯表中第 個(gè)詞的概率。此處應(yīng)???softmax??函數(shù)將輸出層的值轉(zhuǎn)換為概率分布,這也是后來(lái)神經(jīng)?絡(luò)的分類輸出層的標(biāo)準(zhǔn)做法。
代碼:
class NPLM(nn.Module):
def__init__(self, voc_size, n_step, embedding_size, n_hidden):
super(NPLM, self).__init__()
self.n_step = n_step # 保存n_step用于forward方法
self.C = nn.Embedding(voc_size, embedding_size) # 定義一個(gè)詞嵌入層
# 第一個(gè)線性層,其輸入大小為 n_step * embedding_size,輸出大小為 n_hidden
self.linear1 = nn.Linear(n_step * embedding_size, n_hidden)
# 第二個(gè)線性層,其輸入大小為 n_hidden,輸出大小為 voc_size,即詞匯表大小
self.linear2 = nn.Linear(n_hidden, voc_size)
defforward(self, X): # 定義前向傳播過(guò)程
# 輸入數(shù)據(jù) X 張量的形狀為 [batch_size, n_step]
X = self.C(X) # 將 X 通過(guò)詞嵌入層,形狀變?yōu)?[batch_size, n_step, embedding_size]
X = X.view(-1, self.n_step * self.C.embedding_dim) # 形狀變?yōu)?[batch_size, n_step * embedding_size]
# 通過(guò)第一個(gè)線性層并應(yīng)用 tanh 激活函數(shù)
hidden = torch.tanh(self.linear1(X)) # hidden 張量形狀為 [batch_size, n_hidden]
# 通過(guò)第二個(gè)線性層得到輸出
output = self.linear2(hidden) # output 形狀為 [batch_size, voc_size]
return output # 返回輸出結(jié)果這?定義了?個(gè)名為 “NPLM” 的神經(jīng)概率語(yǔ)?模型類,它繼承? ??PyTorch??? 的 ??nn.Module?? 。在這個(gè)類中,我們定義了詞嵌?層和線性層
???self.C???:?個(gè)詞嵌?層,?于將輸?數(shù)據(jù)中的每個(gè)詞轉(zhuǎn)換為固定??的向量表示。??voc_size??? 表示詞匯表??,??embedding_size?? 表示詞嵌?的維度。
???self.linear1???: 第?個(gè)線性層,不考慮批次的情況下輸???為 ??n_step * embedding_size???,輸出??為 ??n_hidden???。??n_step??? 表示時(shí)間步數(shù),即每個(gè)輸?序列的?度;??embedding_size??? 表示詞嵌?的維度;??n_hidden?? 表示隱藏層的??。
???self.linear2???: 第?個(gè)線性層,不考慮批次的情況下輸???為 ??n_hidden???,輸出??為 ??voc_size???。??n_hidden??? 表示隱藏層的??,??voc_size??表示詞匯表??。
在NPLM類中,我們還定義了?個(gè)名為 ??forward??? 的?法,?于實(shí)現(xiàn)模型的前向傳播過(guò)程。在這個(gè)?法中,?先將輸?數(shù)據(jù)通過(guò)詞嵌?層??self.C??? ,然后 ??X.view(-1, n_step * embedding_size)??? 的?的是在詞嵌?維度上展平張量,也就是把每個(gè)輸?序列的詞嵌?連接起來(lái),形成?個(gè)?的向量。接著,將該張量傳?第?個(gè)線性層 ??self.linear1??? 并應(yīng)? ??tanh??? 函數(shù),得到隱藏層的輸出。最后,將隱藏層的輸出傳?第?個(gè)線性層 ??self.linear2??,得到最終的輸出結(jié)果。
4. 完整代碼實(shí)現(xiàn)
完整代碼,在公眾號(hào)「AI取經(jīng)路」發(fā)消息「NPLM」獲取
4.1 構(gòu)建語(yǔ)料庫(kù)
定義?個(gè)?常簡(jiǎn)單的數(shù)據(jù)集,作為實(shí)驗(yàn)語(yǔ)料庫(kù),并整理出該語(yǔ)料庫(kù)的詞匯表。
# 構(gòu)建一個(gè)非常簡(jiǎn)單的數(shù)據(jù)集
sentences = ["我 喜歡 玩具", "我 愛 爸爸", "我 討厭 挨打"]
# 將所有句子連接在一起,用空格分隔成多個(gè)詞,再將重復(fù)的詞去除,構(gòu)建詞匯表
word_list = list(set(" ".join(sentences).split()))
# 創(chuàng)建一個(gè)字典,將每個(gè)詞映射到一個(gè)唯一的索引
word_to_idx = {word: idx for idx, word in enumerate(word_list)}
# 創(chuàng)建一個(gè)字典,將每個(gè)索引映射到對(duì)應(yīng)的詞
idx_to_word = {idx: word for idx, word in enumerate(word_list)}
voc_size = len(word_list) # 計(jì)算詞匯表的大小
print(' 詞匯表:', word_to_idx) # 打印詞匯到索引的映射字典
print(' 詞匯表大?。?, voc_size) # 打印詞匯表大小詞匯表: {'爸爸': 0, '愛': 1, '討厭': 2, '挨打': 3, '喜歡': 4, '玩具': 5, '我': 6}
詞匯表大小: 7
4.2 生成訓(xùn)練數(shù)據(jù)
從語(yǔ)料庫(kù)中?成批處理數(shù)據(jù),作為NPLM的訓(xùn)練數(shù)據(jù),后?會(huì)將數(shù)據(jù)?批?批地輸?神經(jīng)?絡(luò)進(jìn)?訓(xùn)練。
# 構(gòu)建批處理數(shù)據(jù)
import torch # 導(dǎo)入 PyTorch 庫(kù)
import random # 導(dǎo)入 random 庫(kù)
batch_size = 2# 每批數(shù)據(jù)的大小
defmake_batch():
input_batch = [] # 定義輸入批處理列表
target_batch = [] # 定義目標(biāo)批處理列表
selected_sentences = random.sample(sentences, batch_size) # 隨機(jī)選擇句子
for sen in selected_sentences: # 遍歷每個(gè)句子
word = sen.split() # 用空格將句子分隔成多個(gè)詞
# 將除最后一個(gè)詞以外的所有詞的索引作為輸入
input = [word_to_idx[n] for n in word[:-1]] # 創(chuàng)建輸入數(shù)據(jù)
# 將最后一個(gè)詞的索引作為目標(biāo)
target = word_to_idx[word[-1]] # 創(chuàng)建目標(biāo)數(shù)據(jù)
input_batch.append(input) # 將輸入添加到輸入批處理列表
target_batch.append(target) # 將目標(biāo)添加到目標(biāo)批處理列表
input_batch = torch.LongTensor(input_batch) # 將輸入數(shù)據(jù)轉(zhuǎn)換為張量
target_batch = torch.LongTensor(target_batch) # 將目標(biāo)數(shù)據(jù)轉(zhuǎn)換為張量
return input_batch, target_batch # 返回輸入批處理和目標(biāo)批處理數(shù)據(jù)
input_batch, target_batch = make_batch() # 生成批處理數(shù)據(jù)
print(' 詞匯表:', word_to_idx) # 打印詞匯到索引的映射字典
print(" 輸入數(shù)據(jù):",input_batch) # 打印輸入批處理數(shù)據(jù)
# 將輸入批處理數(shù)據(jù)中的每個(gè)索引值轉(zhuǎn)換為對(duì)應(yīng)的原始詞
input_words = []
for input_idx in input_batch:
input_words.append([idx_to_word[idx.item()] for idx in input_idx])
print(" 輸入數(shù)據(jù)對(duì)應(yīng)的原始詞:",input_words)
print(" 目標(biāo)數(shù)據(jù):",target_batch) # 打印目標(biāo)批處理數(shù)據(jù)
# 將目標(biāo)批處理數(shù)據(jù)中的每個(gè)索引值轉(zhuǎn)換為對(duì)應(yīng)的原始詞
target_words = [idx_to_word[idx.item()] for idx in target_batch]
print(" 目標(biāo)數(shù)據(jù)對(duì)應(yīng)的原始詞:",target_words)詞匯表: {'爸爸': 0, '愛': 1, '討厭': 2, '挨打': 3, '喜歡': 4, '玩具': 5, '我': 6}
輸入數(shù)據(jù): tensor([[6, 2], [6, 4]]) 輸入數(shù)據(jù)對(duì)應(yīng)的原始詞: [['我', '討厭'], ['我', '喜歡']]
目標(biāo)數(shù)據(jù): tensor([3, 5]) 目標(biāo)數(shù)據(jù)對(duì)應(yīng)的原始詞: ['挨打', '玩具']
4.3 模型定義
見第3章
4.3 實(shí)例化NPLM模型
n_step = 2 # 時(shí)間步數(shù),表示每個(gè)輸入序列的長(zhǎng)度,也就是上下文長(zhǎng)度
n_hidden = 2 # 隱藏層大小
embedding_size = 2 # 詞嵌入大小
model = NPLM(n_step, voc_size, embedding_size, n_hidden) # 創(chuàng)建神經(jīng)概率語(yǔ)言模型實(shí)例
print(' NPLM 模型結(jié)構(gòu):', model) # 打印模型的結(jié)構(gòu)NPLM 模型結(jié)構(gòu): NPLM(
(C): Embedding(7, 2)
(linear1): Linear(in_features=4, out_features=2, bias=True)
(linear2): Linear(in_features=2, out_features=7, bias=True)
)
4.3 NPLM模型訓(xùn)練
訓(xùn)練設(shè)置:
import torch.optim as optim # 導(dǎo)入優(yōu)化器模塊
criterion = nn.CrossEntropyLoss() # 定義損失函數(shù)為交叉熵?fù)p失
optimizer = optim.Adam(model.parameters(), lr=0.1) # 定義優(yōu)化器為 Adam,學(xué)習(xí)率為 0.1訓(xùn)練循環(huán):
# 訓(xùn)練模型
for epoch in range(5000): # 設(shè)置訓(xùn)練迭代次數(shù)
optimizer.zero_grad() # 清除優(yōu)化器的梯度
input_batch, target_batch = make_batch() # 創(chuàng)建輸入和目標(biāo)批處理數(shù)據(jù)
output = model(input_batch) # 將輸入數(shù)據(jù)傳入模型,得到輸出結(jié)果
loss = criterion(output, target_batch) # 計(jì)算損失值
if (epoch + 1) % 1000 == 0: # 每 1000 次迭代,打印損失值
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
loss.backward() # 反向傳播計(jì)算梯度
optimizer.step() # 更新模型參數(shù)5. 訓(xùn)練過(guò)程詳解
5.1 訓(xùn)練數(shù)據(jù)的準(zhǔn)備
我們使用的訓(xùn)練數(shù)據(jù)非常簡(jiǎn)單:
原始文本:
"我 喜歡 玩具"
"我 愛 爸爸"
"我 討厭 挨打"轉(zhuǎn)換為訓(xùn)練數(shù)據(jù)集:
上下文: ["我", "喜歡"] → 目標(biāo): "玩具"
上下文: ["我", "愛"] → 目標(biāo): "爸爸"
上下文: ["我", "討厭"] → 目標(biāo): "挨打"核心思想: 給定前面的n_step個(gè)詞匯(這里是2個(gè)),預(yù)測(cè)的下一個(gè)目標(biāo)詞匯
5.2 訓(xùn)練的四個(gè)關(guān)鍵步驟
5.2.1 前向傳播(Forward Pass)
這一步計(jì)算模型的預(yù)測(cè)結(jié)果:
- 輸入處理:將上下文詞匯轉(zhuǎn)換為索引
- 詞嵌入:查找每個(gè)詞匯對(duì)應(yīng)的2維向量
- 向量拼接:將2個(gè)詞的向量拼接成4維向量
- 隱藏層計(jì)算:通過(guò)tanh激活函數(shù)處理
- 輸出分?jǐn)?shù):得到每個(gè)詞匯的原始分?jǐn)?shù)
# 前向傳播過(guò)程
output = model(input_batch) # 形狀: [1, 7]
# output 包含7個(gè)詞匯的分?jǐn)?shù),對(duì)應(yīng)詞匯表中的每個(gè)詞5.2.2 計(jì)算損失(Loss Calculation)
使用交叉熵?fù)p失函數(shù)來(lái)衡量預(yù)測(cè)準(zhǔn)確性:
代碼實(shí)現(xiàn):
import torch.optim as optim
criterion = nn.CrossEntropyLoss() # 定義損失函數(shù)為交叉熵?fù)p失
optimizer = optim.Adam(model.parameters(), lr=0.1) # Adam優(yōu)化器,學(xué)習(xí)率0.1
# 計(jì)算損失
input_batch, target_batch = make_batch() # 獲取批次數(shù)據(jù)
output = model(input_batch) # 前向傳播
loss = criterion(output, target_batch) # 計(jì)算損失5.2.3 反向傳播(Backward Pass)
使用PyTorch的自動(dòng)微分計(jì)算梯度:
代碼實(shí)現(xiàn):
optimizer.zero_grad() # 清除之前的梯度
loss.backward() # 反向傳播計(jì)算梯度5.2.4 參數(shù)更新(Parameter Update)
使用Adam優(yōu)化器更新模型參數(shù):
代碼實(shí)現(xiàn):
optimizer.step() # 更新模型參數(shù)6. 訓(xùn)練結(jié)果
模型訓(xùn)練過(guò)程如下:
Epoch: 1000 cost = 0.000403
Epoch: 2000 cost = 0.000120
Epoch: 3000 cost = 0.000055
Epoch: 4000 cost = 0.000028
Epoch: 5000 cost = 0.000016?損失快速下降:從初始的高損失快速降低到接近0
?收斂良好:5000次迭代后損失穩(wěn)定在很小的值
?學(xué)習(xí)成功:模型成功學(xué)會(huì)了簡(jiǎn)單的語(yǔ)言模式
7. 模型預(yù)測(cè)
訓(xùn)練完成后,可以測(cè)試模型的預(yù)測(cè)能力:
# 進(jìn)行預(yù)測(cè)
input_strs = [['我', '討厭'], ['我', '喜歡']] # 需要預(yù)測(cè)的輸入序列
# 將輸入序列轉(zhuǎn)換為對(duì)應(yīng)的索引
input_indices = [[word_to_idx[word] for word in seq] for seq in input_strs]
# 將輸入序列的索引轉(zhuǎn)換為張量
input_batch = torch.LongTensor(input_indices)
# 對(duì)輸入序列進(jìn)行預(yù)測(cè),取輸出中概率最大的類別
predict = model(input_batch).data.max(1)[1]
# 將預(yù)測(cè)結(jié)果的索引轉(zhuǎn)換為對(duì)應(yīng)的詞
predict_strs = [idx_to_word[n.item()] for n in predict.squeeze()]
for input_seq, pred in zip(input_strs, predict_strs):
print(input_seq, '->', pred) # 打印輸入序列和預(yù)測(cè)結(jié)果預(yù)期預(yù)測(cè)結(jié)果:
['我', '討厭'] -> 挨打
['我', '喜歡'] -> 玩具這表明模型成功學(xué)會(huì)了語(yǔ)言模式:
? 理解"我 討厭"后面應(yīng)該跟"挨打"
? 理解"我 喜歡"后面應(yīng)該跟"玩具"
8. 完整的數(shù)據(jù)流程圖
下圖展示了NPLM模型的完整數(shù)據(jù)處理流程:

詳細(xì)步驟說(shuō)明:
輸入文本:["我", "喜歡"]
目標(biāo):預(yù)測(cè)下一個(gè)詞
第1步:詞匯索引化
["我", "喜歡"] → [2, 5] # 根據(jù)詞匯表映射
第2步:詞嵌入(每個(gè)詞2維)
[2, 5] → [[0.1, -0.2], [0.3, 0.1]] # 查找嵌入矩陣
第3步:向量拼接
[[0.1, -0.2], [0.3, 0.1]] → [0.1, -0.2, 0.3, 0.1] # 4維向量
第4步:隱藏層計(jì)算(輸出2維)
[4維向量] → [2維向量] # 通過(guò) Linear(4, 2) + tanh
第5步:輸出層計(jì)算
[2維向量] → [7維向量] # 通過(guò) Linear(2, 7),每個(gè)位置是一個(gè)詞的分?jǐn)?shù)
第6步:Softmax轉(zhuǎn)換
[2.1, 0.5, -1.0, -2.0, -1.5, -2.0, -1.8] → [0.75, 0.17, 0.04, ...] # 概率分布
第7步:預(yù)測(cè)結(jié)果
最高概率對(duì)應(yīng)"玩具"(索引3),所以預(yù)測(cè)下一個(gè)詞是"玩具"張量形狀變化:
輸入: [batch_size, 2]
→ 嵌入: [batch_size, 2, 2]
→ 拼接: [batch_size, 4]
→ 隱藏層: [batch_size, 2]
→ 輸出層: [batch_size, 7]
→ 概率: [batch_size, 7]本文轉(zhuǎn)載自?????AI取經(jīng)路??,作者:AI取經(jīng)路

















