当前位置: 首页 > news >正文

基于Python的自然语言处理系列(12):使用TorchText和LSTM进行序列到序列(seq2seq)翻译

        在前面的文章中,我们探索了如何使用卷积神经网络(CNN)进行文本分类。这次,我们将深入探讨一种经典的深度学习模型——序列到序列模型(seq2seq),并结合长短期记忆网络(LSTM)来处理序列生成任务。本篇将展示如何使用TorchText加载数据,并构建基于LSTM的seq2seq模型来进行德语到英语的翻译任务。

1. 序列到序列模型简介

        seq2seq模型最常用于解决将一个序列映射到另一个序列的问题,如机器翻译和文本摘要。它的核心思想是通过编码器-解码器的结构,将输入序列压缩为一个上下文向量,并依赖这个向量生成输出序列。这个模型的结构如下:

        在模型中,输入序列首先被嵌入为词向量,然后经过编码器(通常是RNN或者LSTM)来生成上下文向量,接着解码器根据上下文向量逐步生成目标序列。在训练中,解码器的输入可能会使用实际的目标序列(称为Teacher Forcing),也可能使用模型上一步的预测。

2. 数据加载与预处理

        首先,我们将使用TorchText加载德语到英语的翻译数据集,并使用spacy进行文本标记化和词汇构建。

from torchtext.datasets import Multi30k
from torchtext.data.utils import get_tokenizerSRC_LANGUAGE = 'de'
TRG_LANGUAGE = 'en'# 加载Multi30k数据集
train = Multi30k(split=('train'), language_pair=(SRC_LANGUAGE, TRG_LANGUAGE))# 使用spacy进行标记化
token_transform = {}
token_transform[SRC_LANGUAGE] = get_tokenizer('spacy', language='de_core_news_sm')
token_transform[TRG_LANGUAGE] = get_tokenizer('spacy', language='en_core_web_sm')# 词汇构建
from torchtext.vocab import build_vocab_from_iteratordef yield_tokens(data, language):for data_sample in data:yield token_transform[language](data_sample[language])vocab_transform = {}
vocab_transform[SRC_LANGUAGE] = build_vocab_from_iterator(yield_tokens(train, SRC_LANGUAGE), min_freq=2)
vocab_transform[TRG_LANGUAGE] = build_vocab_from_iterator(yield_tokens(train, TRG_LANGUAGE), min_freq=2)

        我们定义了词汇表并准备了数据加载器,接下来我们将进行序列标记的数值化,并创建输入输出的张量。

3. 模型设计:基于LSTM的Encoder和Decoder

Encoder

        编码器负责将输入序列转换为上下文向量。我们将使用多层LSTM来实现,它能够捕捉输入序列中的长短期依赖关系。

import torch.nn as nnclass Encoder(nn.Module):def __init__(self, input_dim, emb_dim, hid_dim, n_layers, dropout):super().__init__()self.embedding = nn.Embedding(input_dim, emb_dim)self.lstm = nn.LSTM(emb_dim, hid_dim, n_layers, dropout=dropout)self.dropout = nn.Dropout(dropout)def forward(self, src):embedded = self.dropout(self.embedding(src))outputs, (hidden, cell) = self.lstm(embedded)return hidden, cell

Decoder

        解码器使用编码器生成的上下文向量,并逐步生成目标序列。解码器的输出是每一步生成的单词。

class Decoder(nn.Module):def __init__(self, output_dim, emb_dim, hid_dim, n_layers, dropout):super().__init__()self.embedding = nn.Embedding(output_dim, emb_dim)self.lstm = nn.LSTM(emb_dim, hid_dim, n_layers, dropout=dropout)self.fc_out = nn.Linear(hid_dim, output_dim)self.dropout = nn.Dropout(dropout)def forward(self, input, hidden, cell):input = input.unsqueeze(0)embedded = self.dropout(self.embedding(input))output, (hidden, cell) = self.lstm(embedded, (hidden, cell))prediction = self.fc_out(output.squeeze(0))return prediction, hidden, cell

Seq2Seq模型

        最后,我们将编码器和解码器整合在一个Seq2Seq模型中,控制输入和输出的流动。

class Seq2Seq(nn.Module):def __init__(self, encoder, decoder, device):super().__init__()self.encoder = encoderself.decoder = decoderself.device = devicedef forward(self, src, trg, teacher_forcing_ratio=0.5):trg_len = trg.shape[0]batch_size = trg.shape[1]trg_vocab_size = self.decoder.output_dimoutputs = torch.zeros(trg_len, batch_size, trg_vocab_size).to(self.device)hidden, cell = self.encoder(src)input = trg[0, :]for t in range(1, trg_len):output, hidden, cell = self.decoder(input, hidden, cell)outputs[t] = outputteacher_force = random.random() < teacher_forcing_ratioinput = trg[t] if teacher_force else output.argmax(1)return outputs

4. 模型训练与评估

        我们使用交叉熵损失函数,并定义训练和评估的函数。

criterion = nn.CrossEntropyLoss(ignore_index=PAD_IDX)def train(model, iterator, optimizer, criterion, clip):model.train()epoch_loss = 0for i, (src, trg) in enumerate(iterator):src = src.to(device)trg = trg.to(device)optimizer.zero_grad()output = model(src, trg)output_dim = output.shape[-1]output = output[1:].view(-1, output_dim)trg = trg[1:].view(-1)loss = criterion(output, trg)loss.backward()torch.nn.utils.clip_grad_norm_(model.parameters(), clip)optimizer.step()epoch_loss += loss.item()return epoch_loss / len(iterator)def evaluate(model, iterator, criterion):model.eval()epoch_loss = 0with torch.no_grad():for i, (src, trg) in enumerate(iterator):src = src.to(device)trg = trg.to(device)output = model(src, trg, 0)  # 关闭Teacher Forcingoutput_dim = output.shape[-1]output = output[1:].view(-1, output_dim)trg = trg[1:].view(-1)loss = criterion(output, trg)epoch_loss += loss.item()return epoch_loss / len(iterator)

5. 测试与预测

        训练完成后,我们可以使用该模型进行翻译任务。以下是如何测试模型的简单示例。

model.eval()
with torch.no_grad():output = model(src, trg, 0)  # 关闭Teacher Forcingpredicted_tokens = output.argmax(2)for token in predicted_tokens:print(vocab_transform[TRG_LANGUAGE].get_itos()[token.item()])

结语

        在本文中,我们详细介绍了如何使用TorchText和LSTM构建序列到序列翻译模型。通过这种结构,我们能够将一个序列映射为另一个序列,这在机器翻译、文本生成等任务中非常常见。

        不过,seq2seq模型在处理长序列时可能会遇到一些问题,尤其是在生成的序列与输入序列相差较远时。为了解决这个问题,下一篇文章中我们将引入另一种循环神经网络结构——门控循环单元(GRU),并探讨如何重复使用上下文向量和更有效的Teacher Forcing策略,从而提升模型在长序列生成任务中的表现。

如果你觉得这篇博文对你有帮助,请点赞、收藏、关注我,并且可以打赏支持我!

欢迎关注我的后续博文,我将分享更多关于人工智能、自然语言处理和计算机视觉的精彩内容。

谢谢大家的支持!


http://www.mrgr.cn/news/30068.html

相关文章:

  • 2024年03月中国电子学会青少年软件编程(图形化)等级考试试卷(一级)答案 + 解析
  • 基于python+django+vue的图书管理系统
  • 【AI视频】Runway文生视频Gen-2、Gen-3详解
  • 【AIGC半月报】AIGC大模型启元:2024.09(下)
  • 【数据结构】排序算法---归并排序
  • Halcon OCR检测 免训练版
  • GEC6818初次连接使用
  • C++(学习)2024.9.18
  • 新手教学系列——非正常关机导致MySQL权限表(db)损坏及修复详解
  • 健康监测功能或暂缓亮相,Apple Watch Series 10最新爆料解析
  • Find My太阳镜|苹果Find My技术与太阳镜结合,智能防丢,全球定位
  • 关于联想笔记本开机无法正常进入到桌面,提示Check Date and Time settings错误的解决方法
  • JavaAPI-String和StringBuffer
  • 【AI大模型】LLM主流开源大模型介绍
  • 网络安全自学笔记
  • iOS17找不到developer mode
  • # 软考 -- 软件设计师 -- 二轮复习(5) -- 面向对象(持续更新)
  • 记软件开发者画图(UML),使用WPS应用制图
  • 【人工智能】如何利用AI高效解决Linux中出现的严重问题?程序员必看小技巧!
  • 【C++笔记】八、结构体 [ 1 ]