NNLM初學習
NNLM
在了解NNLM之前先了解一下詞向量
詞向量
我們人學過單詞,漢字等等,能明白一句話,但是計算機只認識0和1,如何把語言讓計算機看懂,將文本轉化為向量,
詞向量的方法是「one-hot(獨熱編碼)表示法」
是最早的表示詞向量的方法, 首先我們有一個詞表,里面包括了我們可能會用到的所有詞,每個詞占據一個位置,那么詞向量就是一個該詞表維度大小的向量,詞所在位置取值1,其它位置取值0,例如我們的詞表有下面9個詞:
你,我,他,是,誰,哪,里,來,自
“我”表示為向量[0, 1, 0, 0, 0, 0, 0, 0, 0],“是”表示為[0, 0, 0, 1, 0, 0, 0, 0, 0]
這樣會可能會產生【維度災難】和【語意鴻溝】
【維度災難】:是因為如果詞表過大,向量維度也過大,而且向量特別稀疏
【語意鴻溝】:因為每一個詞向量1的位置不同,可以認為彼此相互正交(內積為0),任何兩個內積為0,沒有任何差別,體現不出來相似性,
為了彌補one-hot向量的這些缺陷,分布式向量(distributed representation) ,相似的詞向量相似,這個與word enbedding關系, Representation → Distributed Reprensentation → word embedding ,詞在基于神經網路的分布表示,好像同一個意思,
參考鏈接 (7 封私信 / 80 條訊息) word2vec和word embedding有什么區別? - 知乎 (zhihu.com)
NNLM
? Yoshua Bengio等人于2003年發表的《A Neural Probabilistic Language Model》針對N-gram模型的問題進行了解決,這是第一篇提出神經網路語言模型的論文,它在得到語言模型的同時也產生了副產品詞向量,
論文鏈接:《A Neural Probabilistic Language Model》

輸入層:
? 通過前n個詞,來預測第n個單詞
? 詞向量W:是一個one-hot向量,大小=[10W,1],W(t)表示第t個詞語的one hot(一個元素為1,其余全為0
? 投影矩陣C:維度[D*V],V=10W,引數D根據文本大小不同來設定:谷歌測驗時選取D=300,
計算程序:
- 投影矩陣C[300 * 10W] X 詞向量W(t)[10W *1] 得到= 矩陣[300 * 1]
- 比如根據前3個詞來預測第4個詞語,那么上述操作會重復三次,得到3個[300*1]的矩陣
- ? 將這3個[300*1]的矩陣按行拼接,得到[900x1]的矩陣,
形式類似:
隱藏層:
存在一個向量矩陣[Hx1],H根據文本集合情況設定(谷歌測驗時選取H=500)
該層完成的功能主要是全連接!
說通俗一些:把輸入層計算得到的矩陣[900x1],轉換為矩陣[Hx1],完成輸入層到隱藏層的資料傳輸,并且在全連接的程序中存在計算的權重,
最終得到矩陣[500x1]
輸出層:
我們的詞語大小為V=10W,隱藏層計算得到矩陣[500x1],要將這[500x1]的計算結果轉化為[10Wx1],以此來預測第4個詞語是什么?
得到矩陣[10Wx1],也就是所謂第4個詞ont-hot,最終經過SoftMax激活函式,選取行向量最大值,就是預測詞語,
# code by Tae Hwan Jung @graykode
import torch
import torch.nn as nn
import torch.optim as optim
def make_batch():
input_batch = []
target_batch = []
for sen in sentences:
word = sen.split() # space tokenizer
input = [word_dict[n] for n in word[:-1]] # create (1~n-1) as input
target = word_dict[word[-1]] # create (n) as target, We usually call this 'casual language model'
input_batch.append(input)
target_batch.append(target)
return input_batch, target_batch
# Model
class NNLM(nn.Module):
def __init__(self):
super(NNLM, self).__init__()
self.C = nn.Embedding(n_class, m)
self.H = nn.Linear(n_step * m, n_hidden, bias=False)
self.d = nn.Parameter(torch.ones(n_hidden))
self.U = nn.Linear(n_hidden, n_class, bias=False)
self.W = nn.Linear(n_step * m, n_class, bias=False)
self.b = nn.Parameter(torch.ones(n_class))
def forward(self, X):
X = self.C(X) # X : [batch_size, n_step, m]
X = X.view(-1, n_step * m) # resize [batch_size, n_step * m]
tanh = torch.tanh(self.d + self.H(X)) # [batch_size, n_hidden]
output = self.b + self.W(X) + self.U(tanh) # [batch_size, n_class]
return output
if __name__ == '__main__':
n_step = 2 # number of steps, n-1 in paper,
n_hidden = 2 # number of hidden size, h in paper
m = 2 # embedding size, m in paper
sentences = ["i like dog", "i love coffee", "i hate milk"]
word_list = " ".join(sentences).split()
word_list = list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}
number_dict = {i: w for i, w in enumerate(word_list)}
n_class = len(word_dict) # number of Vocabulary
model = NNLM()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
input_batch, target_batch = make_batch()
input_batch = torch.LongTensor(input_batch)
target_batch = torch.LongTensor(target_batch)
# Training
for epoch in range(5000):
optimizer.zero_grad()
output = model(input_batch)
# output : [batch_size, n_class], target_batch : [batch_size]
loss = criterion(output, target_batch)
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()[:2] for sen in sentences], '->', [number_dict[n.item()] for n in predict.squeeze()])
nn.Embedding( num_embeddings , embedding_dim )詳解:
? num_embeddings - 詞嵌入字典大小,即一個字典里要有多少個詞
? embedding_dim - 每個詞嵌入向量的大小,
? input_batch[3:2 ]------>C(X)------->[3,2,2],input_batch每個不相同數都有一個2維向量,相同數的向量相同,
nn.Linear(in_features,out_features,bias=False)詳解:
? in_features指的是輸入的二維張量的大小,即輸入的[batch_size, size]中的size,
??out_features指的是輸出的二維張量的大小,即輸出的二維張量的形狀為[batch_size,output_size],當然,它也代表了該全連接層的神經元個數,
??從輸入輸出的張量的shape角度來理解,相當于一個輸入為[batch_size, in_features]的張量變換成了[batch_size, out_features]的輸出張量,
input = [1 , 100]
nn.Linear(in_features = 100, out_features = 1)
output = [1,1]
參考鏈接:
- 【語言模型】NNLM(神經網路語言模型)
- 神經網路語言模型NNLM
- 入門通俗易懂的神經網路語言模型(NNLM)詳解
- 代碼專案地址
- NN.linear
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/550149.html
標籤:其他
下一篇:看了幾集狂飆,大佬說我變了?
