自然语言处理: 第四章Seq2Seq

这篇具有很好参考价值的文章主要介绍了自然语言处理: 第四章Seq2Seq。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

自然语言处理: 第四章Seq2Seq

理论基础

开始之前,首先提出一个问题,电脑是怎么识别人类的命令的,首先人们通过输入代码(编码) ,带入输入给计算机然后再经过处理(解码)得到最终的命令。所以可以看到这其实是一个编码 + 解码的过程。可以看到首先我们将初始的信息通过编码,得到涵盖全局的信息的特征然后再经过解码器去解码从而最终得到需要得到的信息,所以借鉴于Seq2Seq模型就借鉴于这个结构出现了。

自然语言处理: 第四章Seq2Seq,自然语言处理,自然语言处理,人工智能,机器学习



Seq2Seq 是2014年由Llya 大神在 Sequence to Sequence Learning with Neural Networks 一文中提出的,其由几个重要的优势:

  1. 实现了端到端的学习(神经网络)
  2. 处理可变长度序列,Seq2Seq可以接受可变长度的序列的输入也可以生成可变长度的输出序列
  3. 信息的压缩和抽象表示,编码器将上下文的信息整合到一个向量里,然后解码器通过这个向量输出序列
  4. 可扩展性,很容易与其他神经网络做结合,可以处理很多复杂的问题和常见

自然语言处理: 第四章Seq2Seq,自然语言处理,自然语言处理,人工智能,机器学习



适合处理的问题, 一些生成的问题:

  • 机器翻译
  • 文本摘要
  • 对话系统
  • 问答系统
  • 语音识别
  • 语音合成

不适合的问题:

  • 序列标注,命名实体识别,关系抽取,词性标注
  • 文本分类
  • 文本相似性

局限性:

  • 无法储存长序列的信息,缺少局部的信息
  • lstm训练效率比较低下


代码实现

本次代码使用的是中英翻译的数据集,一共有40000多个数据中英互译对。本次任务需要完成的是中 -> 英任务。


1. 数据预处理

# Step 1: 数据预处理
import jieba  # 使用jieba进行中文分词
import re  # 使用正则表达式对英文句子进行分词

# 读取句子
with open('all_sentences.txt', 'r', encoding='utf-8') as f:
    all_sentences = f.readlines()

# 创建用于存储中英文句子对的列表
sentences = []

# 对每个句子进行处理
for i in range(0, len(all_sentences), 2):
    # 对中文句子进行分词
    sentence_cn = ' '.join(jieba.cut(all_sentences[i].strip(), cut_all=False))
    # 对英文句子进行分词
    sentence_en = ' '.join(re.findall(r'\b\w+\b', all_sentences[i+1].strip()))
    # 构建句子对,分别添加<sos>和<eos>标记
    sentences.append([sentence_cn, '<sos> ' + sentence_en, sentence_en + ' <eos>'])

2. 构建词汇表

# Step 2: 构建词汇表
word_list_cn, word_list_en = [], []  # 初始化中英文单词列表
# 遍历每一个句子并将单词添加到单词列表中
for s in sentences:
    word_list_cn.extend(s[0].split())
    word_list_en.extend(s[1].split())
    word_list_en.extend(s[2].split())
# 去重得到不重复的单词列表
word_list_cn = list(set(word_list_cn))
word_list_en = list(set(word_list_en))

# Add special tokens to the vocabulary
word_list_cn = ['<pad>'] + word_list_cn
word_list_en = ['<pad>', '<sos>', '<eos>'] + word_list_en

# 构建单词到索引的映射
word2idx_cn = {w: i for i, w in enumerate(word_list_cn)}
word2idx_en = {w: i for i, w in enumerate(word_list_en)}

# 构建索引到单词的映射
idx2word_cn = {i: w for i, w in enumerate(word_list_cn)}
idx2word_en = {i: w for i, w in enumerate(word_list_en)}

# 计算词汇表的大小
voc_size_cn = len(word_list_cn)
voc_size_en = len(word_list_en)

3. 构建数据集

class TranslationDataset(Dataset):
    def __init__(self, sentences, word2idx_cn, word2idx_en):
        self.sentences = sentences
        self.word2idx_cn = word2idx_cn
        self.word2idx_en = word2idx_en

    def __len__(self):
        return len(self.sentences)

    def __getitem__(self, index):
        # 将句子转换为索引
        sentence_cn = [self.word2idx_cn[word] for word in self.sentences[index][0].split()]
        sentence_en_in = [self.word2idx_en[word] for word in self.sentences[index][1].split()]
        sentence_en_out = [self.word2idx_en[word] for word in self.sentences[index][2].split()]
        return torch.tensor(sentence_cn), torch.tensor(sentence_en_in), torch.tensor(sentence_en_out)

# Collate function to pad sentences in a batch
def collate_fn(batch):
    # Sort the batch by the length of the sentences in descending order
    batch.sort(key=lambda x: len(x[0]), reverse=True)
    sentence_cn, sentence_en_in, sentence_en_out = zip(*batch)
    # Pad the sentences
    sentence_cn = nn.utils.rnn.pad_sequence(sentence_cn, padding_value=word2idx_cn['<pad>'])
    sentence_en_in = nn.utils.rnn.pad_sequence(sentence_en_in, padding_value=word2idx_en['<sos>'])
    sentence_en_out = nn.utils.rnn.pad_sequence(sentence_en_out, padding_value=word2idx_en['<eos>'])
    return sentence_cn, sentence_en_in, sentence_en_out

# 创建数据集
dataset = TranslationDataset(sentences, word2idx_cn, word2idx_en)
# 创建数据加载器,pass collate_fn to DataLoader
dataloader = DataLoader(dataset, batch_size=64, shuffle=True, collate_fn=collate_fn)

4. 构建模型

4.1 RNN版本
import torch.nn as nn
class Seq2Seq(nn.Module):
    def __init__(self, input_size, hidden_size, output_size, dropout=0.1):
        super(Seq2Seq, self).__init__()
        self.hidden_size = hidden_size
        self.embedding = nn.Embedding(input_size, hidden_size)
        self.rnn = nn.GRU(hidden_size, hidden_size, bidirectional=True)
        self.dropout = nn.Dropout(dropout)
        self.fc = nn.Linear(hidden_size * 2, output_size)
  
    def forward(self, input, hidden):
        embedded = self.dropout(self.embedding(input))
        output, hidden = self.rnn(embedded, hidden)
        output = self.fc(output.squeeze(0))
        return output, hidden

    def init_hidden(self, batch_size):
        return torch.zeros(2, batch_size, self.hidden_size)
  
# Check if a GPU is available and if not, use a CPU
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')


model = Seq2Seq(voc_size_cn, 256, voc_size_en)
# Move the model to the device (GPU if available, otherwise CPU)
model = model.to(device)

4.2 LSTM版
class Seq2Seq(nn.Module):
    def __init__(self, input_size, hidden_size, output_size, dropout = 0.1 ,num_layers = 1 ):
        super(Seq2Seq, self).__init__()
        self.hidden_size = hidden_size
        self.embedding = nn.Embedding(input_size, hidden_size)
        # self.rnn = nn.GRU(hidden_size, hidden_size, bidirectional=True)
        self.lstm = nn.LSTM(hidden_size, hidden_size , bidirectional=True , num_layers = num_layers)
        self.dropout = nn.Dropout(dropout)
        self.fc = nn.Linear(hidden_size * 2, output_size)
  
    def forward(self, input, hidden):
        embedded = self.dropout(self.embedding(input))
#         print(embedded.shape)
        output,(h_n,c_n) = self.lstm(embedded)
        output = self.fc(output.squeeze(0))
        return output, hidden

    def init_hidden(self, batch_size):
        return torch.zeros(2, batch_size, self.hidden_size)

5. 模型训练

# Step 5: 训练模型
from tqdm import tqdm
optimizer = torch.optim.Adam(model.parameters())
criterion = nn.CrossEntropyLoss()

from torchtext.data.metrics import bleu_score # 计算blue 分数
def compute_bleu(model, dataloader):
    model.eval()
    total_score = 0.0
    with torch.no_grad():
        for sentence_cn, sentence_en_in, sentence_en_out in dataloader:
            sentence_cn = sentence_cn.to(device)
            sentence_en_in = sentence_en_in.to(device)
            sentence_en_out = sentence_en_out.to(device)
        
            hidden = model.init_hidden(sentence_cn.size(1)).to(device)
            output, hidden = model(sentence_en_in, hidden)
        
            # Convert output to predicted tokens
            pred_tokens = output.argmax(2).detach().cpu().numpy().tolist()
            target_tokens = sentence_en_out.cpu().numpy().tolist()

            pred_sentences = [[str(token) for token in sentence] for sentence in pred_tokens]
            target_sentences = [[[str(token) for token in sentence]] for sentence in target_tokens]

            # Calculate BLEU score
            for pred_sentence, target_sentence in zip(pred_sentences, target_sentences):
                total_score += bleu_score([pred_sentence], [target_sentence])

    return total_score / len(dataloader)

for epoch in range(10):
    model.train()
    total_loss = 0
    progress_bar = tqdm(dataloader, desc='Epoch {:03d}'.format(epoch + 1), leave=False, disable=False)
    for sentence_cn, sentence_en_in, sentence_en_out in progress_bar:
        sentence_cn = sentence_cn.to(device)
        sentence_en_in = sentence_en_in.to(device)
        sentence_en_out = sentence_en_out.to(device)
    
        hidden = model.init_hidden(sentence_cn.size(1)).to(device)
        optimizer.zero_grad()
        output, hidden = model(sentence_en_in, hidden)
        loss = criterion(output.view(-1, voc_size_en), sentence_en_out.view(-1))
        total_loss += loss.item()
        loss.backward()
        optimizer.step()

        progress_bar.set_postfix({'training_loss': '{:.6f}'.format(loss.item()/len(sentence_cn))})

    print(f"Epoch: {epoch+1}, Loss: {total_loss/len(dataloader)}")
    bleu = compute_bleu(model, dataloader)
    print(f"Bleu Score: {bleu}")

结果

自然语言处理: 第四章Seq2Seq,自然语言处理,自然语言处理,人工智能,机器学习自然语言处理: 第四章Seq2Seq,自然语言处理,自然语言处理,人工智能,机器学习

自然语言处理: 第四章Seq2Seq,自然语言处理,自然语言处理,人工智能,机器学习

上图三个结果从左至右分别是: 单层rnn , 单层lstm , 双层lstm,通过对比可以发现三者其实差异不大,甚至rnn效果还好点,然后对比lstm不同的数量,可能是由于加的层数对比不是很明显,可以发现双层的反而过拟合了。文章来源地址https://www.toymoban.com/news/detail-517112.html

到了这里,关于自然语言处理: 第四章Seq2Seq的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MySQL学习记录:第四章 TCL语言

    /* TCL语言 :transaction control language 事务控制语言 事务 : 一个或一组语句组成的一个执行单元,该执行单元要么全执行,要么全不执行 事务由单独单元的一个或多个SQL语句组成,在这个单元中,每个MySQL语句是相互依赖的。而整个单独单元作为一个不可分割的整体,如果单元

    2024年02月14日
    浏览(32)
  • (数字图像处理MATLAB+Python)第四章图像正交变换-第四、五节:Radon变换和小波变换

    Radon变换 :是一种用于将图像从空间域转换到投影域的数学工具,其基本思想是将图像中每个点的灰度值投影到一组直线上,然后将这些投影合并在一起形成投影域。Radon变换可以用于多种图像处理任务,包括图像重建、特征提取、图像分割等 Radon变换原理 :给定一个函数

    2023年04月20日
    浏览(31)
  • 图像处理与计算机视觉--第四章-图像滤波与增强-第二部分

    目录 1.图像噪声化处理与卷积平滑 2.图像傅里叶快速变换处理 3.图像腐蚀和膨胀处理 4 图像灰度调整处理 5.图像抖动处理算法    

    2024年02月07日
    浏览(33)
  • 图像处理与计算机视觉--第四章-图像滤波与增强-第一部分

    目录 1.灰度图亮度调整 2.图像模板匹配 3.图像裁剪处理 4.图像旋转处理 5.图像邻域与数据块处理

    2024年02月07日
    浏览(42)
  • (数字图像处理MATLAB+Python)第四章图像正交变换-第一节:离散傅里叶变换

    一维离散傅里叶变换(Discrete Fourier Transform,DFT) :是一种数学技术,用于将代表离散时间信号的N个复数序列从 时域转换到频域 。DFT被广泛用于许多应用,如音频和图像处理、通信和控制系统。DFT是傅里叶变换的离散版本,傅里叶变换是一种用于分析频域信号的连续数学技

    2023年04月13日
    浏览(71)
  • 第四章 应用SysML基本特性集的汽车示例 P1|系统建模语言SysML实用指南学习

    仅供个人学习记录 主要就是应用练习建模了 Automobile Domain包 将模型组织入包的包图 汽车规范中包含系统需求的需求图 汽车域块定义图 描述车辆主要功能的用例图

    2024年02月06日
    浏览(34)
  • 【自然语言处理】自然语言处理 --- NLP入门指南

    NLP的全称是 Natuarl Language Processing ,中文意思是自然语言处理,是人工智能领域的一个重要方向 自然语言处理(NLP)的一个最伟大的方面是跨越多个领域的计算研究,从人工智能到计算语言学的多个计算研究领域都在研究计算机与人类语言之间的相互作用。它主要关注计算机

    2024年02月03日
    浏览(41)
  • [自然语言处理] 自然语言处理库spaCy使用指北

    spaCy是一个基于Python编写的开源自然语言处理库。基于自然处理领域的最新研究,spaCy提供了一系列高效且易用的工具,用于文本预处理、文本解析、命名实体识别、词性标注、句法分析和文本分类等任务。 spaCy的官方仓库地址为:spaCy-github。本文主要参考其官方网站的文档,

    2024年02月15日
    浏览(67)
  • 自然语言处理从入门到应用——自然语言处理的常见任务

    分类目录:《自然语言处理从入门到应用》总目录 语言模型(Language Model,LM)(也称统计语言模型)是描述自然语言概率分布的模型,是一个非常基础和重要的自然语言处理任务。利用语言模型,可以计算一个词序列或一句话的概率,也可以在给定上文的条件下对接下来可

    2024年02月07日
    浏览(37)
  • ROS高效进阶第四章 -- 机器视觉处理之图像格式,usb_cam,摄像头标定,opencv和cv_bridge引入

    从本文开始,我们用四篇文章学习ROS机器视觉处理,本文先学习一些外围的知识,为后面的人脸识别,目标跟踪和yolov5目标检测做准备。 我的笔记本是Thinkpad T14 i7 + Nvidia MX450,系统是ubuntu20.04,ros是noetic。由于很多驱动与硬件强相关,请读者注意这点。 本文的参考资料有:

    2024年02月04日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包