项目实战(四) - - LSTM实现语言模型

项目实战(四) - - 语言模型

1. 任务概述

根据上下文语境基于概率预测下一个词,通过对网络训练一定程度后,最后的模型参数可当成词向量使用

2. 算法步骤

  • 构造数据集
  • 定义模型
    Layers:Embedding,LSTM,Linear
  • 训练与评估
    Loss:CrossEntropyLoss()
    Optimizer:Adam

3. 代码实现与解析

  • 导入相关包
  • 构造训练数据集
    模型的输入是一串文字,模型的输出也是一串文字,他们之间相差一个位置,因为语言模型的目标是根据之前的单词预测下一个单词
  • 定义模型
class RNNModel(nn.Module):
    def __init__(self,vocab_size,embeded_size,hidden_size):
        super(RNNModel,self).__init__()
        self.embeded=nn.Embedding(vocab_size,embeded_size)
        self.lstm=nn.LSTM(embeded_size,hidden_size)
        self.linear=nn.Linear(hidden_size,vocab_size)
        self.hidden_size=hidden_size
    
    def forward(self,text,hidden):
        emb=self.embeded(text) # text:seq_length*batch_size
        output,hidden=self.lstm(emb,hidden)
       // output:(seg_length*batch_size)*hidden_size       
       	out_vocab=self.linear(output.view(-1,output.shape[2]))      out_vocab=out_vocab.view(output.size(0),output.size(1),out_vocab.size(-1))
       // out_vocab:知道每个位置预测哪个单词,hidden:包含到目前为止所有信息
        return out_vocab,hidden     
    def init_hidden(self,bsz,requires_grad=True):
        weight=next(self.parameters())
        return (weight.new_zeros((1,bsz,self.hidden_size)),
                 weight.new_zeros((1,bsz,self.hidden_size)))
// 把一个hidden state和计算图之前的历史分离
def repackage_hidden(h):
    if isinstance(h, torch.Tensor):
        return h.detach()
    else:
        return tuple(repackage_hidden(v) for v in h)
  • 定义loss function和optimizer
loss_fn = nn.CrossEntropyLoss()
learning_rate = 0.001
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, 0.5)
  • 3.5 训练步骤

  • 模型一般需要训练若干个epoch

  • 每个epoch我们都把所有的数据分成若干个batch

  • 把每个batch的输入和输出都包装成cuda tensor

  • forward pass,通过输入的句子预测每个单词的下一个单词

  • 用模型的预测和正确的下一个单词计算cross entropy loss

  • 清空模型当前gradient

  • backward pass

  • gradient clipping,防止梯度爆炸

  • 更新模型参数

  • 每隔一定的iteration输出模型在当前iteration的loss,以及在验证集上做模型的评估

  • 将训练最好的模型保存,测试时载入

for epoch in range(NUM_EPOCHS):
    model.train()
    it = iter(train_iter)
    hidden = model.init_hidden(BATCH_SIZE)
    for i, batch in enumerate(it):
        data, target = batch.text, batch.target
        hidden = repackage_hidden(hidden)
        model.zero_grad()
        output, hidden = model(data, hidden)
        loss = loss_fn(output.view(-1, VOCAB_SIZE), target.view(-1))
        loss.backward()
        torch.nn.utils.clip_grad_norm_(model.parameters(), GRAD_CLIP)
        optimizer.step()
  • 测试
// 载入训练效果最好的模型
best_model = RNNModel("LSTM", VOCAB_SIZE, EMBEDDING_SIZE, EMBEDDING_SIZE, 2, dropout=0.5)
best_model.load_state_dict(torch.load("lm-best.th"))
// 在测试数据上计算perplexity
test_loss = evaluate(best_model, test_iter)
print("perplexity: ", np.exp(test_loss))
  • 句子生成
//此处随机一个词索引作为输入,生成长度100的句子
hidden = best_model.init_hidden(1)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
input = torch.randint(VOCAB_SIZE, (1, 1), dtype=torch.long).to(device)
words = []
for i in range(100):
    output, hidden = best_model(input, hidden)
    word_weights = output.squeeze().exp().cpu()
    word_idx = torch.multinomial(word_weights, 1)[0]
    input.fill_(word_idx)
    word = TEXT.vocab.itos[word_idx]
    words.append(word)
print(" ".join(words))
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值