pytorch自然语言处理基础模型之六:BiLSTM

       上一篇文章我们介绍了LSTM的基本原理,本文我们将构建一个双向LSTM网络去生成一个语言模型。所谓语言模型就是估算一个单词在一个序列中出现的概率,简单讲就是给定一段话,通过神经网络的学习之后,可以通过前面的词和句子去预测下一个词。

1、模型原理

       BiLSTM是Bi-directional Long Short-Term Memory的缩写,是由前向LSTM与后向LSTM组合而成。通过上篇文章我们可以得知,使用LSTM模型可以更好的捕捉到较长距离的依赖关系,但是利用LSTM对句子进行建模还存在一个问题:无法编码从后到前的信息。有些时候预测可能需要由前面若干输入和后面若干输入共同决定,这样会更加准确,通过BiLSTM可以更好的捕捉双向的语义依赖。

2、代码实现

1. 导入需要的库,设置数据类型

import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from torch.autograd import Variable

dtype = torch.FloatTensor

2. 创建数据和字典

//一段没有意义的拉丁文
sentence = ('Lorem ipsum dolor sit amet consectetur adipisicing elit '
            'sed do eiusmod tempor incididunt ut labore et dolore magna '
            'aliqua Ut enim ad minim veniam quis nostrud exercitation')
            
n_class = len(word_dict)   //词表的数量
max_len = len(sentence.split())    //句子的长度(所有单词的数量)
n_hidden = 5   //LSTM网络隐藏层的个数

3. 创建batch

def make_batch(sentence):
    input_batch = []
    target_batch = []
    
    words = sentence.split()
    //构建batch,依次用句子中前面的词组成的序列去预测下一个词
    for i, word in enumerate(words[:-1]):  
        input = [word_dict[w] for w in words[:(i + 1)]]
        input = input + [0] * (max_len-len(input))
        target = word_dict[words[i+1]]
        input_batch.append(np.eye(n_class)[input])
        target_batch.append(target)
    
    return  Variable(torch.Tensor(input_batch)), Variable(torch.LongTensor(target_batch))

//input_batch : [batch, seq_len, input_size]
input_batch, target_batch = make_batch(sentence)

4. 创建网络

class BiLSTM(nn.Module):
    def __init__(self):
        super().__init__()
        //bidirectional=True表示使用双向LSTM
        self.lstm = nn.LSTM(input_size=n_class, hidden_size=n_hidden, bidirectional=True)
        self.W = nn.Parameter(torch.randn(n_hidden*2, n_class).type(dtype))
        self.b = nn.Parameter(torch.randn(n_class).type(dtype))
        
    def forward(self, x):
    	//input_batch : [batch, seq_len, input_size] -> [seq_len, batch, input_size]
        inputs = x.transpose(0, 1)   
        //h_0 : [num_layers(=1) * num_directions(=2), batch_size, n_hidden]
        h_0 = Variable(torch.zeros(1*2, len(x), n_hidden)) 
        //c_0 : [num_layers(=1) * num_directions(=2), batch_size, n_hidden]
        c_0 = Variable(torch.zeros(1*2, len(x), n_hidden))
        outputs, (_, _) = self.lstm(inputs, (h_0, c_0))
        //output: [seq_len, batch, hidden_size * num_directions] -> [batch, hidden_size * num_directions]
        outputs = outputs[-1]  
        model = torch.mm(outputs, self.W) + self.b  # model : [batch_size, n_class]
        return model 

5. 训练模型

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

//开始训练
for epoch in range(10000):
    optimizer.zero_grad()
    output = model(input_batch)
    loss = loss_fn(output, target_batch)
    if (epoch+1) % 1000 == 0:
        print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
    loss.backward()
    optimizer.step()

训练结果如下:

Epoch: 1000 cost = 1.709147
Epoch: 2000 cost = 1.028320
Epoch: 3000 cost = 0.674200
Epoch: 4000 cost = 0.490916
Epoch: 5000 cost = 0.325878
Epoch: 6000 cost = 0.217596
Epoch: 7000 cost = 0.139017
Epoch: 8000 cost = 0.106443
Epoch: 9000 cost = 0.085764
Epoch: 10000 cost = 0.079945

6. 查看训练结果

//troch.max(1)[1], 返回每一行中最大值的那个元素的索引,data 只返回variable中的数据部分
predict = model(input_batch).data.max(1)[1]
//item()方法得到张量的值
print(sentence)
print([number_dict[n.item()] for n in predict])

结果如下:

Lorem ipsum dolor sit amet consectetur adipisicing elit sed do eiusmod 
tempor incididunt ut labore et dolore magna aliqua Ut enim ad minim veniam 
quis nostrud exercitation
['ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipisicing', 'elit', 'sed', 'do', 'do', 
'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore', 'magna', 'aliqua', 'Ut', 'enim', 
'ad', 'minim', 'veniam', 'quis', 'nostrud', 'exercitation']

可以看到只有"eiusmod "没有预测出来,其他的都词都通过前面的词预测了出来。

参考链接
https://www.jiqizhixin.com/articles/2018-10-24-13
https://github.com/graykode/nlp-tutorial

你可能感兴趣的:(自然语言处理)