当前位置:   article > 正文

pytorch入门NLP教程(一)——NNLM_pytorch nlp

pytorch nlp

NNLM

这里我假定你已经了解了One-Hot编码和n-gram的相关知识,现在让我们学习第一个语言模型。我也是一个小白,正在艰难的入门NLP和pytorch,由于网上pytorch的nlp教程较少且pytorch版本都比较靠前,所以想的是在那个基础上稍微修改一下,水平有限,只作为自己的一个学习总结,如果对你有帮助就最好。
Neural Network Language Model直接从语言模型出发,将模型最优化过程转化成求词向量表示的过程。
目 标 函 数 : L ( θ ) = ∑ t log ⁡ P ( w t ∣ w t − n + 1 , . . . w t − 1 ) 目标函数:L(\theta) = \sum_t\log P(w_t|w_{t-n+1},...w_{t-1}) L(θ)=tlogP(wtwtn+1,...wt1)

  • 使用了非对称的前向窗函数,窗长度为n-1

  • 滑动窗口遍历整个语料库求和,计算量正比于语料库大小

  • 概率P满足归一化条件,这样不同位置t处的概率才能相加,即: ∑ ω ∈ { v o c a b u l a r y } P ( w t ∣ w t − n + 1 , . . . w t − 1 ) = 1 \sum_{\omega\in\{vocabulary\}}P(w_t|w_{t-n+1},...w_{t-1}) = 1 ω{vocabulary}P(wtwtn+1,...wt1)=1

在这里插入图片描述
目标:窗口大小为n,通过前n-1个词来推测第n的词是什么

输入:每个词的one-hot向量

投影层:就是矩阵C,设定我们想要的词编码的长度为D、字典长度为V,则矩阵C为 D × V D\times V D×V
在这里插入图片描述

之所以称为投影层是因为当我们的输入与C相乘时会得到这个词对应位置的词嵌入: D × V D \times V D×V * V × 1 V \times 1 V×1 = D × 1 D \times 1 D×1

hidden layer:将我们得到的每个词的词嵌入先做一次full connection全连接,然后激活函数采用tanh处理

softmax层:隐层出来之后,接一个SoftMax分类器,预测一下在V个词的词表中,出现每个单词出现概率有多大,即得到一个概率向量 V × 1 V\times 1 V×1

代码实现

这里的代码仔细一点,对应着上面的图就可以看懂啦~~~

import torch
import torch.nn as nn
import torch.optim as optim

dtype = torch.FloatTensor

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

# NNLM Parameter
n_step = 2  # 窗口大小,n-1 in paper
n_hidden = 2  # h in paper
m = 2  # 最终词向量的长度,m in paper


def make_batch(sentences):
    # 其实就是将句子对应成各自的向量,然后input_batch为前面的词,target_batch为要预测的词
    input_batch = []
    target_batch = []

    for sen in sentences:
        word = sen.split()
        input = [word_dict[n] for n in word[:-1]]
        target = word_dict[word[-1]]

        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.Parameter(torch.randn(n_step * m, n_hidden).type(dtype))  # 隐藏层的weight
        self.W = nn.Parameter(torch.randn(n_step * m, n_class).type(dtype))  # softmax层作用于词嵌入的weight
        self.d = nn.Parameter(torch.randn(n_hidden).type(dtype))  # 隐藏层的bias
        self.U = nn.Parameter(torch.randn(n_hidden, n_class).type(dtype))  # softmax层作用于hidden层的weight
        self.b = nn.Parameter(torch.randn(n_class).type(dtype))  # softmax层的bias

    def forward(self, X):
        X = self.C(X)  # 这里巧妙的采用embedding,取出第X行刚好就是该词我们想要的词嵌入
        X = X.view(-1, n_step * m)  # [数据个数即要训练样本数量, 窗口大小*词嵌入维度=每个训练样本的总的维度]
        tanh = torch.tanh(self.d + torch.mm(X, self.H))  # 全连接层 [batch_size, n_hidden]
        output = self.b + torch.mm(X, self.W) + torch.mm(tanh, self.U)  # softmax层[batch_size, n_class]
        return output

model = NNLM()

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

input_batch, target_batch = make_batch(sentences)
print(input_batch)
print(target_batch)
input_batch = torch.LongTensor(input_batch)  # embedded只能接受LongTensor
target_batch = torch.LongTensor(target_batch)
# Training
for epoch in range(5000):

    optimizer.zero_grad()
    output = model(input_batch)

    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] # .data只取出tensor中的数据,对于其他信息都丢弃

# Test
print([sen.split()[:2] for sen in sentences], '->', [number_dict[n.item()] for n in predict.squeeze()])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/347473
推荐阅读
相关标签
  

闽ICP备14008679号