24.9.24学习笔记

news2024/9/25 5:22:38
  1. 编码器

    • 嵌入层:将源语言单词索引转换为嵌入向量。
    • RNN层:使用LSTM处理嵌入向量,生成隐藏状态和细胞状态。
    • 输出:返回最后一个时间步的隐藏状态和细胞状态,作为上下文向量。
  2. 解码器

    • 嵌入层:将目标语言单词索引转换为嵌入向量。
    • RNN层:使用LSTM处理嵌入向量和上下文向量,生成隐藏状态和细胞状态。
    • 输出层:将隐藏状态转换为目标语言词汇表中的概率分布。

编码器的输出

编码器的主要任务是将输入序列(通常是源语言句子)编码成一个固定长度的上下文向量(也称为隐状态或编码器的最终状态)。这个上下文向量包含了输入序列的全部信息,用于帮助解码器生成目标序列。

编码器的输出
  • 隐藏状态:编码器生成的最后一个时间步的隐藏状态。
  • 细胞状态:对于LSTM,还包括最后一个时间步的细胞状态。

在编码器的前向传播过程中,输入序列被逐个处理,生成一系列隐藏状态。最终的隐藏状态和细胞状态(如果有)被传递给解码器。

解码器的输入

解码器的输入主要有两部分:

  1. 当前时间步的输入单词(通常是目标语言中的单词索引)。
  2. 前一个时间步的隐藏状态和细胞状态(来自LSTM或RNN)。

3. 编码器输出与解码器输入的关系

编码器的输出(隐藏状态和细胞状态)作为解码器的初始隐藏状态和细胞状态。这样,解码器在生成目标序列时,可以利用编码器提取的输入序列的全部信息。


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

# 定义编码器
class Encoder(nn.Module):
    def __init__(self, input_dim, emb_dim, hid_dim, n_layers, dropout):
        super().__init__()
        self.hid_dim = hid_dim  # 隐藏层维度
        self.n_layers = n_layers  # LSTM 层的数量
        self.embedding = nn.Embedding(input_dim, emb_dim)  # 嵌入层,将单词索引转换为嵌入向量
        self.rnn = nn.LSTM(emb_dim, hid_dim, n_layers, dropout=dropout)  # LSTM 层
        self.dropout = nn.Dropout(dropout)  # Dropout 层,用于防止过拟合

    def forward(self, src):
        # src: (seq_len, batch_size)
        embedded = self.dropout(self.embedding(src))  # (seq_len, batch_size, emb_dim)
        outputs, (hidden, cell) = self.rnn(embedded)  # outputs: (seq_len, batch_size, hid_dim), hidden: (n_layers, batch_size, hid_dim), cell: (n_layers, batch_size, hid_dim)
        return hidden, cell  # 返回最后一个时间步的隐藏状态和细胞状态

# 定义解码器
class Decoder(nn.Module):
    def __init__(self, output_dim, emb_dim, hid_dim, n_layers, dropout):
        super().__init__()
        self.output_dim = output_dim  # 目标语言词汇表的大小
        self.hid_dim = hid_dim  # 隐藏层维度
        self.n_layers = n_layers  # LSTM 层的数量
        self.embedding = nn.Embedding(output_dim, emb_dim)  # 嵌入层,将单词索引转换为嵌入向量
        self.rnn = nn.LSTM(emb_dim, hid_dim, n_layers, dropout=dropout)  # LSTM 层
        self.fc_out = nn.Linear(hid_dim, output_dim)  # 输出层,将隐藏状态转换为词汇表中的概率分布
        self.dropout = nn.Dropout(dropout)  # Dropout 层,用于防止过拟合

    def forward(self, input, hidden, cell):
        # input: (batch_size,)
        input = input.unsqueeze(0)  # (1, batch_size)
        embedded = self.dropout(self.embedding(input))  # (1, batch_size, emb_dim)
        output, (hidden, cell) = self.rnn(embedded, (hidden, cell))  # output: (1, batch_size, hid_dim), hidden: (n_layers, batch_size, hid_dim), cell: (n_layers, batch_size, hid_dim)
        prediction = self.fc_out(output.squeeze(0))  # (batch_size, output_dim)
        return prediction, hidden, cell  # 返回预测值、隐藏状态和细胞状态

# 定义序列到序列模型
class Seq2Seq(nn.Module):
    def __init__(self, encoder, decoder, device):
        super().__init__()
        self.encoder = encoder  # 编码器
        self.decoder = decoder  # 解码器
        self.device = device  # 设备(CPU 或 GPU)

    def forward(self, src, trg, teacher_forcing_ratio=0.5):
        # src: (src_seq_len, batch_size)
        # trg: (trg_seq_len, batch_size)
        batch_size = trg.shape[1]  # 批次大小
        trg_len = trg.shape[0]  # 目标序列的长度
        trg_vocab_size = self.decoder.output_dim  # 目标语言词汇表的大小
        outputs = torch.zeros(trg_len, batch_size, trg_vocab_size).to(self.device)  # 初始化输出张量

        # 通过编码器生成隐藏状态和细胞状态
        hidden, cell = self.encoder(src)

        # 初始化解码器的输入为 <sos> 标记
        input = trg[0, :]

        for t in range(1, trg_len):
            # 通过解码器生成当前时间步的输出
            output, hidden, cell = self.decoder(input, hidden, cell)
            outputs[t] = output  # 存储当前时间步的输出
            top1 = output.argmax(1)  # 获取当前时间步的预测单词索引
            # 根据教师强制比例决定下一个时间步的输入
            input = trg[t] if random.random() < teacher_forcing_ratio else top1

        return outputs  # 返回所有时间步的输出

# 参数设置
INPUT_DIM = 10000  # 假设源语言词汇表大小
OUTPUT_DIM = 10000  # 假设目标语言词汇表大小
ENC_EMB_DIM = 256  # 编码器嵌入层维度
DEC_EMB_DIM = 256  # 解码器嵌入层维度
HID_DIM = 512  # 隐藏层维度
N_LAYERS = 2  # LSTM 层的数量
ENC_DROPOUT = 0.5  # 编码器的 Dropout 概率
DEC_DROPOUT = 0.5  # 解码器的 Dropout 概率

# 创建模型实例
encoder = Encoder(INPUT_DIM, ENC_EMB_DIM, HID_DIM, N_LAYERS, ENC_DROPOUT)
decoder = Decoder(OUTPUT_DIM, DEC_EMB_DIM, HID_DIM, N_LAYERS, DEC_DROPOUT)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = Seq2Seq(encoder, decoder, device).to(device)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss(ignore_index=0)  # 损失函数,忽略 padding token (0)
optimizer = optim.Adam(model.parameters())  # 优化器,使用 Adam

# 训练循环
num_epochs = 10  # 训练轮数
for epoch in range(num_epochs):
    model.train()  # 设置模型为训练模式
    epoch_loss = 0  # 初始化每轮的损失
    for batch in train_iterator:  # 遍历训练数据
        src = batch.src  # 获取源语言序列
        trg = batch.trg  # 获取目标语言序列
        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()  # 反向传播
        optimizer.step()  # 更新模型参数
        epoch_loss += loss.item()  # 累加每批次的损失
    print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {epoch_loss / len(train_iterator):.4f}')  # 打印每轮的平均损失

# 评估循环
model.eval()  # 设置模型为评估模式
epoch_loss = 0  # 初始化每轮的损失
with torch.no_grad():  # 关闭梯度计算
    for batch in valid_iterator:  # 遍历验证数据
        src = batch.src  # 获取源语言序列
        trg = batch.trg  # 获取目标语言序列
        output = model(src, trg, 0)  # 前向传播,生成输出,关闭教师强制
        output_dim = output.shape[-1]  # 获取输出的词汇表大小
        output = output[1:].view(-1, output_dim)  # 重塑输出张量,去掉第一个时间步
        trg = trg[1:].view(-1)  # 重塑目标张量,去掉第一个时间步
        loss = criterion(output, trg)  # 计算损失
        epoch_loss += loss.item()  # 累加每批次的损失
print(f'Validation Loss: {epoch_loss / len(valid_iterator):.4f}')  # 打印验证集的平均损失

 

为什么要去掉第一个时间步?

在很多序列生成任务中,第一个时间步通常是一个特殊的起始符号(如 <sos>),用于标记序列的开始。在训练过程中,模型需要学习如何从这个起始符号开始生成序列。


 

序列到序列学习(Sequence-to-Sequence Learning,简称Seq2Seq)是一种用于处理序列数据的深度学习框架,广泛应用于自然语言处理任务,如机器翻译、文本摘要、对话系统等。Seq2Seq 模型的核心思想是将一个输入序列转换为另一个输出序列。下面我们将详细讲解Seq2Seq模型的各个组成部分及其工作原理。

1. 模型概述

Seq2Seq 模型通常由两部分组成:

  1. 编码器(Encoder):将输入序列编码成一个固定长度的上下文向量(也称为隐状态或编码器的最终状态)。
  2. 解码器(Decoder):根据编码器生成的上下文向量,逐步生成目标序列。

2. 编码器

2.1 结构

编码器通常是一个递归神经网络(RNN),最常见的选择是长短期记忆网络(LSTM)或门控循环单元(GRU)。编码器的任务是将输入序列编码成一个固定长度的上下文向量。

2.2 工作流程
  1. 输入:编码器的输入是一个源语言句子的单词索引序列,形状为 (seq_len, batch_size)
  2. 嵌入层:将输入序列中的单词索引转换为嵌入向量,形状为 (seq_len, batch_size, emb_dim)
  3. RNN层:通过RNN层(如LSTM)处理嵌入向量,生成每个时间步的隐藏状态和细胞状态。
  4. 输出编码器的输出是最后一个时间步的隐藏状态和细胞状态,这些状态作为解码器的初始状态。

3. 解码器

3.1 结构

解码器也是一个RNN,通常也是LSTM或GRU。解码器的任务是根据编码器生成的上下文向量,逐步生成目标序列。

3.2 工作流程
  1. 初始输入:解码器的初始输入通常是目标语言的起始标记 <sos>
  2. 嵌入层:将输入单词索引转换为嵌入向量。
  3. RNN层:通过RNN层处理嵌入向量,生成当前时间步的隐藏状态和细胞状态。
  4. 输出层:将隐藏状态通过全连接层转换为词汇表中的概率分布,选择概率最高的单词作为当前时间步的输出。
  5. 教师强制:在训练时,可以使用教师强制技术,即在每个时间步使用真实的上一个单词作为输入,而不是模型预测的单词。这有助于加快训练过程,但可能会导致模型在推理时表现不佳。::::
  • 训练过程

  • 初始化

    • 我们从特殊的起始符号 <sos> 开始生成中文句子。
  • 第一个时间步

    • 教师强制:我们使用真实的下一个单词  作为输入。
    • 非教师强制:模型可能会预测一个单词,比如 今天
  • 第二个时间步

    • 教师强制:我们使用真实的下一个单词 热爱 作为输入。
    • 非教师强制:模型可能会预测另一个单词,比如 
  • 第三个时间步

    • 教师强制:我们使用真实的下一个单词 编程 作为输入。
    • 非教师强制:模型可能会预测另一个单词,比如 中国
  • 第四个时间步

    • 教师强制:我们使用特殊的结束符号 <eos> 作为输入,表示句子结束。
    • 非教师强制:模型可能会预测另一个单词,但我们将其停止。
  1. 循环:重复上述步骤,直到生成目标序列的结束标记 <eos> 或达到最大序列长度。

4. 模型训练

4.1 数据准备
  • 输入数据:源语言句子的单词索引序列。
  • 目标数据:目标语言句子的单词索引序列。
4.2 损失函数
  • 交叉熵损失:常用的损失函数是交叉熵损失,它衡量模型预测的概率分布与真实标签之间的差异。通常会忽略填充标记(如0)的损失。
4.3 优化器
  • Adam:常用的优化器是Adam,它结合了动量和RMSProp的优点,适用于大多数深度学习任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2162550.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

峟思助力堤防工程安全:构建多功能防洪屏障

堤防工程&#xff0c;作为水利建设中至关重要的防护体系&#xff0c;不仅守护着江河、湖泊及滨海区域的安全&#xff0c;更是确保人民生命财产安全的坚固防线。在现代社会&#xff0c;随着技术的进步与安全意识的提升&#xff0c;堤防工程不仅限于传统的防洪功能&#xff0c;更…

SpringBoot和JPA初探

目录 SpringBoot和JPA初探0.准备条件1.创建JPA项目2.项目3.总结 SpringBoot和JPA初探 我们使用SpringBootJPA做一个简单的API接口演示&#xff0c;通过一个简单的例子让大家对Spring Data JPA有一个整体的认知。 0.准备条件 IntelliJ IDEAjdk 1.8mysql 8.0maven 3.8.x 1.创…

代码随想录算法训练营第三十九天 | 198.打家劫舍 ,213.打家劫舍II,337.打家劫舍III

第三十九天打卡&#xff0c;今天解决打家劫舍系列问题&#xff0c;树形dp比较难。 198.打家劫舍 题目链接 解题过程 dp[i]&#xff1a;考虑下标i&#xff08;包括i&#xff09;以内的房屋&#xff0c;最多可以偷窃的金额为dp[i]。 要么不偷这一间&#xff0c;那就是前面那间…

开源链动 2+1 模式、AI 智能名片与 S2B2C 商城小程序:以问题解决为导向的盈利新模式

摘要&#xff1a;本文探讨了问题解决盈利模式的重要性&#xff0c;并结合开源链动 21 模式、AI 智能名片以及 S2B2C 商城小程序等创新工具&#xff0c;阐述了如何以用户为中心&#xff0c;通过深刻洞察用户需求&#xff0c;解决用户问题&#xff0c;实现盈利增长。强调了在当今…

[利用python进行数据分析01] “来⾃Bitly的USA.gov数据” 分析出各个地区的 windows和非windows用户

2011 年&#xff0c; URL 缩短服务 Bitly 跟美国政府⽹站 USA.gov 合作&#xff0c;提供 了⼀份从⽣成 .gov 或 .mil 短链接的⽤户那⾥收集来的匿名数据。 在 2011 年&#xff0c;除实时数据之外&#xff0c;还可以下载⽂本⽂件形式的每⼩时 快照。 数据集下载&#xff1a;通…

LabVIEW项目编码器选择

在LabVIEW项目中&#xff0c;选择增量式&#xff08;Incremental Encoder&#xff09;和绝对式&#xff08;Absolute Encoder&#xff09;编码器取决于项目的具体需求。增量式编码器和绝对式编码器在工作原理、应用场景、精度和成本等方面存在显著差异。以下从多方面详细阐述两…

通过service访问Pod

假设Pod中的容器可能因为各种原因发生故障而死掉&#xff0c;Deployment等controller会通过动态创建和销毁Pod来保证应用整体的健壮性&#xff0c;换句话说&#xff0c;Pod是脆弱的&#xff0c;但应用是健壮的 每个Pod都有自己的Ip&#xff0c;当controller用新的Pod替代发生故…

SDK(2 note)

复习上一次内容&#xff1a; 把前一次笔记中的代码&#xff0c;简写一下 #include <windows.h> #include<tchar.h> #include <stdio.h> #include <strsafe.h> VOID showerrormassage() {LPVOID lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFF…

TS-AI:一种用于多模态个体化脑区划分的深度学习管道,并结合任务对比合成|文献速递-Transformer架构在医学影像分析中的应用

Title 题目 TS-AI: A deep learning pipeline for multimodal subject-specific parcellation with task contrasts synthesis TS-AI&#xff1a;一种用于多模态个体化脑区划分的深度学习管道&#xff0c;并结合任务对比合成 01 文献速递介绍 人类大脑在结构和功能组织上表…

nfs版本问题导致挂载失败

一、系统环境 环境版本操作系统Linux Mint 22 Wilma内核版本6.8.0-44-genericgcc 版本arm-none-linux-gnueabihf-gcc (GNU Toolchain for the A-profile Architecture 9.2-2019.12 (arm-9.10)) 9.2.1 20191025uboot 版本2020.01开发板Linux版本5.4.31 二、问题描述 内核通过…

拒绝信息泄露!VMD滚动分解 + Informer-BiLSTM并行预测模型

前言 在时间序列预测任务中&#xff0c;像 EMD&#xff08;经验模态分解&#xff09;、CEEMDAN&#xff08;完全集合经验模态分解&#xff09;、VMD&#xff08;变分模态分解&#xff09; 等分解算法的使用有可能引入信息泄露&#xff0c;具体情况取决于这些方法的应用方式。信…

通过WebTopo在ARMxy边缘计算网关上实现系统集成

随着工业互联网技术的发展&#xff0c;边缘计算成为了连接物理世界与数字世界的桥梁&#xff0c;其重要性日益凸显。边缘计算网关作为数据采集、处理与传输的核心设备&#xff0c;在智能制造、智慧城市等领域发挥着关键作用。 1. BL340系列概述 BL340系列是基于全志科技T507-…

yolov8/9关键点检测模型检测俯卧撑动作并计数【源码免费+数据集+python环境+GUI系统】

yolov89模型检测俯卧撑动作并计数【源码免费数据集python环境GUI系统】 yolov8/9关键点检测模型检测俯卧撑动作并计数【源码免费数据集python环境GUI系统】 YOLO算法原理 YOLO&#xff08;You Only Look Once&#xff09;关键点检测的算法原理主要基于YOLO目标检测算法进行改进…

R包:VennDiagram韦恩图

加载R包 library(VennDiagram)数据 # Prepare character vectors v1 <- c("DKK1", "NPC1", "NAPG", "ERG", "VHL", "BTD", "MALL", "HAUS1") v2 <- c("SMAD4", "DKK1…

VMware虚拟网络的连接模式探究与实践

VMware安装完成虚拟机后&#xff0c;大多要进行网络配置&#xff0c;实现网络的互联互联&#xff0c;初学者往往感觉与一台实体主机的网络配置不同&#xff0c;局域网中一台实体主机一个物理网卡&#xff0c;配置一个IP地址&#xff1b;或直接通过WAN上网&#xff0c;比较直观&…

基于python的django微博内容网络分析系统,实现文本划分词结构

本项目旨在开发一个基于Python的Django框架的微博内容网络分析系统&#xff0c;聚焦于微博文本的分词处理、名词提取和主成分分析。该系统通过数据收集与预处理、分词及结构化文本分析&#xff0c;为舆情监测、话题分析和用户行为研究提供了一体化的解决方案。 主要功能包括&a…

数据分析学习之学习路线

前言 我们之前通过cda认证了解到数据分析行业&#xff0c;但是获取到证书&#xff0c;并不代表着&#xff0c;我们已经拥有的数据分析的能力&#xff0c;所以通过系统的学习数据分析需要掌握的能力&#xff0c;并学习大佬们的分析经验、分析思路&#xff0c;才是成为数据分析师…

TDengine 学习与使用经验分享:业务落地实践与架构升级探索

前言 随着物联网、工业互联网等行业的快速发展&#xff0c;时间序列数据的管理和处理需求急剧增加。传统的关系型数据库在处理大规模、高频次的时序数据时性能存在瓶颈&#xff0c;而专门针对时序数据设计的数据库系统则显示出其独特优势。TDengine 是其中的佼佼者&#xff0c;…

给pycharm项目设置conda环境新

创建虚拟环境 conda create -n llama python3.11 激活虚拟环境 conda activate llama 设置Pycharm环境

【初阶数据结构】排序——插入排序

目录 前言直接插入排序希尔排序 前言 排序&#xff1a;所谓排序就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。排序算法&#xff0c;就是如何使得记录按照要求排列的方法。   例如&#xff1a;买东西时会根据销量或价…