NNLM 的PyTorch實(shí)現(xiàn)

本文為轉(zhuǎn)載恨憎,原文鏈接: https://wmathor.com/index.php/archives/1442/

A Neural Probabilistic Language Model

本文算是訓(xùn)練語(yǔ)言模型的經(jīng)典之作,Bengio 將神經(jīng)網(wǎng)絡(luò)引入語(yǔ)言模型的訓(xùn)練中茫蛹,并得到了詞向量這個(gè)副產(chǎn)物。詞向量對(duì)后面深度學(xué)習(xí)在自然語(yǔ)言處理方面有很大的貢獻(xiàn)烁挟,也是獲取詞的語(yǔ)義特征的有效方法

其主要架構(gòu)為三層神經(jīng)網(wǎng)絡(luò)婴洼,如下圖所示


現(xiàn)在的任務(wù)是輸入w_{t-n+1},...,w_{t-1}這前n-1個(gè)單詞,然后預(yù)測(cè)出下一個(gè)單詞w_t

數(shù)學(xué)符號(hào)說(shuō)明:

  • C(i): 單詞w對(duì)應(yīng)的詞向量撼嗓,其中i為詞w在整個(gè)詞匯表中的索引
  • C: 詞向量柬采,大小為|V| \times m的矩陣
  • |V|: 詞匯表的大小,即語(yǔ)料庫(kù)中去重后的單詞個(gè)數(shù)
  • m: 詞向量的維度且警,一般是50到200
  • H: 隱藏層的weight
  • d: 隱藏層的bias
  • U: 輸出層的weight
  • b: 輸出層的bias
  • W: 輸入層到輸出層的weight
  • h: 隱藏層神經(jīng)元個(gè)數(shù)

計(jì)算流程:

  1. 首先將輸入的n-1個(gè)單詞索引轉(zhuǎn)為詞向量粉捻,然后講這n-1個(gè)詞向量進(jìn)行concat,形成一個(gè)(n-1)*w的向量斑芜,用X表示
  2. X送入隱藏層進(jìn)行計(jì)算肩刃,hidden_{out}=tanh(d+X*H)
  3. 輸出層共有|V|個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)y_i表示預(yù)測(cè)下一個(gè)單詞i的概率,y的計(jì)算公式為y = b+X*W+hidden_{out}*U

代碼實(shí)現(xiàn)(PyTorch)

# code by Tae Hwan Jung @graykode, modify by wmathor
import torch
import torch.nn as nn
import torch.optim as optim
import torch.utils.data as Data

dtype = torch.FloatTensor

sentences = ['i like cat', 'i love coffee', 'i hate milk']

token_list = " ".join(sentences).split()
# ['i', 'like', 'cat', 'i', 'love'. 'coffee',...]
vocab = list(set(token_list))
word2idx = {w:i for i, w in enumerate(vocab)}
# {'i':0, 'like':1, 'dog':2, 'love':3, 'coffee':4, 'hate':5, 'milk':6}
idx2word = {i:w for i, w in enumerate(vocab)}
# {0:'i', 1:'like', 2:'dog', 3:'love', 4:'coffee', 5:'hate', 6:'milk'}

V = len(vocab) # number of Vocabulary, just like |V|, in this task |V|=7

# NNLM(Neural Network Language Model) Parameter
n_step = len(sentences[0].split())-1 # n-1 in paper, look back n_step words and predict next word. In this task n_step=2
n_hidden = 2 # h in paper
m = 2 # m in paper, word embedding dim

由于 PyTorch 中輸入數(shù)據(jù)是以 mini-batch 小批量進(jìn)行的树酪,下面的函數(shù)首先將原始數(shù)據(jù)(詞)全部轉(zhuǎn)為索引浅碾,然后通過(guò) TensorDataset()DataLoader() 編寫(xiě)一個(gè)實(shí)用的 mini-batch 迭代器

def make_data(sentences):
    input_data=[]
    target_data=[]
    for sen in sentences:
        sen = sen.split() #['i', 'like', 'cat']
        input_tmp = [word2idx[w] for w in sen[:-1]] # [0, 1], [0, 3], [0, 5]
        target_tmp = word2idx[sen[-1]] # 2, 4, 6

        input_data.append(input_tmp) # [[0, 1], [0, 3], [0, 5]]
        target_data.append(target_tmp) # [2, 4, 6]
    return input_data,target_data

input_data,target_data = make_data(sentences)
input_data,target_data = torch.LongTensor(input_data),torch.LongTensor(target_data)

dataset = Data.TensorDataset(input_data, target_data)
loader = Data.DataLoader(dataset, 2, True)

模型定義部分

class NNLM(nn.Module):
    def __init__(self):
        super(NNLM,self).__init__()
        self.C = nn.Embedding(V,m) # embedding lookup : [V,m]
        self.H = nn.Parameter(torch.randn(n_step*m,n_hidden).type(dtype))
        self.d = nn.Parameter(torch.randn(n_hidden).type(dtype))
        self.b = nn.Parameter(torch.randn(V).type(dtype))
        self.W = nn.Parameter(torch.randn(n_step*m,V).type(dtype))
        self.U = nn.Parameter(torch.randn(n_hidden,V).type(dtype))

    def forward(self,X):
        '''
        :param X: [batch_size, n_step]
        :return:
        '''
        X = self.C(X) # [batch_size,n_step,m]
        X = X.view(-1,n_step*m) # [batch_size,n_step*m]
        hidden_out = torch.tanh(self.d+torch.mm(X,self.H))
        output = self.b + torch.mm(X,self.W)+torch.mm(hidden_out,self.U)
        return output

nn.Parameter()的作用是將該參數(shù)添加進(jìn)模型中,使其能夠通過(guò) model.parameters()找到续语、管理垂谢、并且更新。更具體的來(lái)說(shuō)就是:

  1. nn.Parameter()nn.Module一起使用時(shí)會(huì)有一些特殊的屬性疮茄,其會(huì)被自動(dòng)加到 Module 的 parameters() 迭代器中
  2. 使用很簡(jiǎn)單:torch.nn.Parameter(data, requires_grad=True)滥朱,其中 data 為 tensor

簡(jiǎn)單解釋一下執(zhí)行 X=self.C(X) 這一步之后 X 發(fā)生了什么變化,假設(shè)初始 X=[[0, 1], [0, 3]]

通過(guò) Embedding() 之后力试,會(huì)將每一個(gè)詞的索引徙邻,替換為對(duì)應(yīng)的詞向量,例如 love 這個(gè)詞的索引是 3畸裳,通過(guò)查詢(xún) Word Embedding 表得到行索引為 3 的向量為 [0.2, 0.1]缰犁,于是就會(huì)將原來(lái) X 中 3 的值替換為該向量,所有值都替換完之后怖糊,X=[[[0.3, 0.8], [0.2, 0.4]], [[0.3, 0.8], [0.2, 0.1]]]

# Training
for epoch in range(5000):
  for batch_x, batch_y in loader:
    optimizer.zero_grad()
    output = model(batch_x)

    # output : [batch_size, n_class], batch_y : [batch_size] (LongTensor, not one-hot)
    loss = criterion(output, batch_y)
    if (epoch + 1)%1000 == 0:
        print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))

    loss.backward()
    optimizer.step()

# Predict
predict = model(input_batch).data.max(1, keepdim=True)[1]

# Test
print([sen.split()[:n_step] for sen in sentences], '->', [number_dict[n.item()] for n in predict.squeeze()])

參考文獻(xiàn)

A Neural Probabilitic Language Model 論文閱讀及實(shí)戰(zhàn)
NLP-tutorial

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末帅容,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子伍伤,更是在濱河造成了極大的恐慌并徘,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扰魂,死亡現(xiàn)場(chǎng)離奇詭異麦乞,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)劝评,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)姐直,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人付翁,你說(shuō)我怎么就攤上這事简肴』翁” “怎么了百侧?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)能扒。 經(jīng)常有香客問(wèn)我佣渴,道長(zhǎng),這世上最難降的妖魔是什么初斑? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任辛润,我火速辦了婚禮,結(jié)果婚禮上见秤,老公的妹妹穿的比我還像新娘砂竖。我一直安慰自己真椿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布乎澄。 她就那樣靜靜地躺著突硝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪置济。 梳的紋絲不亂的頭發(fā)上解恰,一...
    開(kāi)封第一講書(shū)人閱讀 52,682評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音浙于,去河邊找鬼护盈。 笑死,一個(gè)胖子當(dāng)著我的面吹牛羞酗,可吹牛的內(nèi)容都是我干的腐宋。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼檀轨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼脏款!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起裤园,我...
    開(kāi)封第一講書(shū)人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤撤师,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后拧揽,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體剃盾,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年淤袜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了痒谴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡铡羡,死狀恐怖积蔚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情烦周,我是刑警寧澤尽爆,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站读慎,受9級(jí)特大地震影響漱贱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜夭委,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一幅狮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦崇摄、人聲如沸擎值。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)幅恋。三九已至,卻和暖如春泵肄,著一層夾襖步出監(jiān)牢的瞬間捆交,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工腐巢, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留品追,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓冯丙,卻偏偏與公主長(zhǎng)得像肉瓦,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子胃惜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 對(duì)教材《深度學(xué)習(xí)框架pytorch:入門(mén)與實(shí)踐》和一些技術(shù)博客及實(shí)踐過(guò)程中的總結(jié)泞莉,比較精煉。 網(wǎng)絡(luò)模型定義 一般通...
    ou源仔閱讀 260評(píng)論 0 0
  • 在深度學(xué)習(xí)中要用到各種各樣的損失函數(shù)(loss function)船殉,這些損失函數(shù)可看作是一種特殊的 layer 鲫趁,...
    殘劍天下論閱讀 3,664評(píng)論 0 1
  • 自然語(yǔ)言處理是典型的序列問(wèn)題,其底層算法在最近幾年迅速發(fā)展利虫,比如去年年底發(fā)布的BERT在11項(xiàng)自然語(yǔ)言處理任務(wù)中表...
    xieyan0811閱讀 1,880評(píng)論 0 0
  • 今天感恩節(jié)哎挨厚,感謝一直在我身邊的親朋好友。感恩相遇糠惫!感恩不離不棄疫剃。 中午開(kāi)了第一次的黨會(huì),身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,576評(píng)論 0 11
  • 彩排完硼讽,天已黑
    劉凱書(shū)法閱讀 4,232評(píng)論 1 3