0基础跟德姆(dom)一起学AI 自然语言处理18-解码器部分实现

news/2025/1/23 0:03:27/

1 解码器介绍

解码器部分:

  • 由N个解码器层堆叠而成
  • 每个解码器层由三个子层连接结构组成
  • 第一个子层连接结构包括一个多头自注意力子层和规范化层以及一个残差连接
  • 第二个子层连接结构包括一个多头注意力子层和规范化层以及一个残差连接
  • 第三个子层连接结构包括一个前馈全连接子层和规范化层以及一个残差连接

  • 说明:
  • 解码器层中的各个部分,如,多头注意力机制,规范化层,前馈全连接网络,子层连接结构都与编码器中的实现相同. 因此这里可以直接拿来构建解码器层.

2 解码器层

2.1 解码器层的作用

  • 作为解码器的组成单元, 每个解码器层根据给定的输入向目标方向进行特征提取操作,即解码过程.

2.2 解码器层的代码实现

# 解码器层类 DecoderLayer 实现思路分析
# init函数 (self, size, self_attn, src_attn, feed_forward, dropout)# 词嵌入维度尺寸大小size 自注意力机制层对象self_attn 一般注意力机制层对象src_attn 前馈全连接层对象feed_forward# clones3子层连接结构 self.sublayer = clones(SublayerConnection(size,dropout),3)
# forward函数 (self, x, memory, source_mask, target_mask)# 数据经过子层连接结构1 self.sublayer[0](x, lambda x:self.self_attn(x, x, x, target_mask))# 数据经过子层连接结构2 self.sublayer[1](x, lambda x:self.src_attn(x, m, m, source_mask))# 数据经过子层连接结构3 self.sublayer[2](x, self.feed_forward)class DecoderLayer(nn.Module):def __init__(self, size, self_attn, src_attn, feed_forward, dropout):super(DecoderLayer, self).__init__()# 词嵌入维度尺寸大小self.size = size# 自注意力机制层对象 q=k=vself.self_attn = self_attn# 一遍注意力机制对象 q!=k=vself.src_attn = src_attn# 前馈全连接层对象self.feed_forward = feed_forward# clones3子层连接结构self.sublayer = clones(SublayerConnection(size, dropout), 3)def forward(self, x, memory, source_mask, target_mask):m = memory# 数据经过子层连接结构1x = self.sublayer[0](x, lambda x:self.self_attn(x, x, x, target_mask))# 数据经过子层连接结构2x = self.sublayer[1](x, lambda x:self.src_attn (x, m, m, source_mask))# 数据经过子层连接结构3x = self.sublayer[2](x, self.feed_forward)return  x
  • 函数调用
def dm_test_DecoderLayer():d_model = 512vocab = 1000  # 词表大小是1000# 输入x 是一个使用Variable封装的长整型张量, 形状是2 x 4x = Variable(torch.LongTensor([[100, 2, 421, 508], [491, 998, 1, 221]]))emb = Embeddings(d_model, vocab)embr = emb(x)dropout = 0.2max_len = 60  # 句子最大长度x = embr  # [2, 4, 512]pe = PositionalEncoding(d_model, dropout, max_len)pe_result = pe(x)x = pe_result  # 获取位置编码器层 编码以后的结果# 类的实例化参数与解码器层类似, 相比多出了src_attn, 但是和self_attn是同一个类.head = 8d_ff = 64size = 512self_attn = src_attn = MultiHeadedAttention(head, d_model, dropout)# 前馈全连接层也和之前相同ff = PositionwiseFeedForward(d_model, d_ff, dropout)x = pe_result# 产生编码器结果 # 注意此函数返回编码以后的结果 要有返回值en_result = dm_test_Encoder()memory = en_resultmask = Variable(torch.zeros(8, 4, 4))source_mask = target_mask = mask# 实例化解码器层 对象dl = DecoderLayer(size, self_attn, src_attn, ff, dropout)# 对象调用dl_result = dl(x, memory, source_mask, target_mask)print(dl_result.shape)print(dl_result)
  • 输出效果
torch.Size([2, 4, 512])
tensor([[[-27.4382,   0.6516,   6.6735,  ..., -42.2930, -44.9728,   0.1264],[-28.7835,  26.4919,  -0.5608,  ...,   0.5652,  -2.9634,   9.7438],[-19.6998,  13.5164,  45.8216,  ...,  23.9127,  22.0259,  34.0195],[ -0.1647,   0.2331, -36.4173,  ..., -20.0557,  29.4576,   2.5048]],[[ 29.1466,  50.7677,  26.4624,  ..., -39.1015, -27.9200,  19.6819],[-10.7069,  28.0897,  -0.4107,  ..., -35.7795,   9.6881,   0.3228],[ -6.9027, -16.0590,  -0.8897,  ...,   4.0253,   2.5961,  37.4659],[  9.8892,  32.7008,  -6.6772,  ..., -11.4273, -21.4676,  32.5692]]],grad_fn=<AddBackward0>)

2.3 解码器层总结¶

  • 学习了解码器层的作用:

    • 作为解码器的组成单元, 每个解码器层根据给定的输入向目标方向进行特征提取操作,即解码过程.
  • 学习并实现了解码器层的类: DecoderLayer

    • 类的初始化函数的参数有5个, 分别是size,代表词嵌入的维度大小, 同时也代表解码器层的尺寸,第二个是self_attn,多头自注意力对象,也就是说这个注意力机制需要Q=K=V,第三个是src_attn,多头注意力对象,这里Q!=K=V, 第四个是前馈全连接层对象,最后就是droupout置0比率.
    • forward函数的参数有4个,分别是来自上一层的输入x,来自编码器层的语义存储变量mermory, 以及源数据掩码张量和目标数据掩码张量.
    • 最终输出了由编码器输入和目标数据一同作用的特征提取结果.

3 解码器

3.1 解码器的作用

  • 根据编码器的结果以及上一次预测的结果, 对下一次可能出现的'值'进行特征表示.

3.2 解码器的代码分析

# 解码器类 Decoder 实现思路分析
# init函数 (self, layer, N):# self.layers clones N个解码器层clones(layer, N)# self.norm 定义规范化层 LayerNorm(layer.size)
# forward函数 (self, x, memory, source_mask, target_mask)# 数据以此经过各个子层  x = layer(x, memory, source_mask, target_mask)# 数据最后经过规范化层  return self.norm(x)# 返回处理好的数据class Decoder(nn.Module):def __init__(self, layer, N):# 参数layer 解码器层对象# 参数N 解码器层对象的个数super(Decoder, self).__init__()# clones N个解码器层self.layers = clones(layer, N)# 定义规范化层self.norm = LayerNorm(layer.size)def forward(self, x, memory, source_mask, target_mask):# 数据以此经过各个子层for layer in self.layers:x = layer(x, memory, source_mask, target_mask)# 数据最后经过规范化层return self.norm(x)
  • 函数调用
# 测试 解码器
def dm_test_Decoder():d_model = 512vocab = 1000  # 词表大小是1000# 输入x 是一个使用Variable封装的长整型张量, 形状是2 x 4x = Variable(torch.LongTensor([[100, 2, 421, 508], [491, 998, 1, 221]]))emb = Embeddings(d_model, vocab)embr = emb(x)dropout = 0.2max_len = 60  # 句子最大长度x = embr  # [2, 4, 512]pe = PositionalEncoding(d_model, dropout, max_len)pe_result = pe(x)x = pe_result  # 获取位置编码器层 编码以后的结果# 分别是解码器层layer和解码器层的个数Nsize = 512d_model = 512head = 8d_ff = 64dropout = 0.2c = copy.deepcopy# 多头注意力对象attn = MultiHeadedAttention(head, d_model)# 前馈全连接层ff = PositionwiseFeedForward(d_model, d_ff, dropout)# 解码器层layer = DecoderLayer(d_model, c(attn), c(attn), c(ff), dropout)N = 6# 输入参数与解码器层的输入参数相同x = pe_result# 产生编码器结果en_result = demo238_test_Encoder()memory = en_result# 掩码对象mask = Variable(torch.zeros(8, 4, 4))# sorce掩码 target掩码source_mask = target_mask = mask# 创建 解码器 对象de = Decoder(layer, N)# 解码器对象 解码de_result = de(x, memory, source_mask, target_mask)print(de_result)print(de_result.shape)
  • 输出结果
tensor([[[ 0.1853, -0.8858, -0.0393,  ..., -1.4989, -1.4008,  0.8456],[-1.0841, -0.0777,  0.0836,  ..., -1.5568,  1.4074, -0.0848],[-0.4107, -0.1306, -0.0069,  ..., -0.2370, -0.1259,  0.7591],[ 1.2895,  0.2655,  1.1799,  ..., -0.2413,  0.9087,  0.4055]],[[ 0.3645, -0.3991, -1.2862,  ..., -0.7078, -0.1457, -1.0457],[ 0.0146, -0.0639, -1.2143,  ..., -0.7865, -0.1270,  0.5623],[ 0.0685, -0.1465, -0.1354,  ...,  0.0738, -0.9769, -1.4295],[ 0.3168,  0.6305, -0.1549,  ...,  1.0969,  1.8775, -0.5154]]],grad_fn=<AddBackward0>)
torch.Size([2, 4, 512])

http://www.ppmy.cn/news/1565341.html

相关文章

WPS PPT中插入实时更新可变的日期

在 WPS 演示&#xff08;WPS Presentation&#xff09;中插入实时可变的日期&#xff0c;可以通过以下步骤实现&#xff1a; 方法一&#xff1a;使用“日期和时间”功能 打开 WPS 演示&#xff0c;进入需要插入日期的幻灯片。 插入日期和时间&#xff1a; 点击顶部菜单栏的 “…

浅谈Java之AJAX

一、基本介绍 在Java开发中&#xff0c;AJAX&#xff08;Asynchronous JavaScript and XML&#xff09;是一种用于创建动态网页的技术&#xff0c;它允许网页在不重新加载整个页面的情况下与服务器进行交互。 二、关键点和示例 1. AJAX的基本原理 AJAX通过JavaScript的XMLHtt…

CentOS 下载软件时报Error: Failed to synchronize cache for repo ‘AppStream‘解决方法

下载软件时出现以下问题 直接把CentOS-AppStream.repo改个名字就行 cd /etc/yum.repos.d/ mv CentOS-AppStream.repo CentOS-AppStream.repo.bak就可以了 解决思路 把AI问遍&#xff0c;无人会&#xff0c;解决法 想要下载软件通通失败了&#xff0c;解决方法当然是问AI&am…

【Unity】ScrollViewContent适配问题(Contentsizefilter不刷新、ContentSizeFilter失效问题)

最近做了一个项目&#xff0c;菜单栏读取数据后自动生成&#xff0c;结果用到了双重布局 父物体 尝试了很多方式&#xff0c;也看过很多大佬的文章&#xff0c;后来自己琢磨了一下&#xff0c;当子物体组件自动生成之后&#xff0c;使用以下以下代码效果会好一些&#xff1a; …

(RAG系列) FastGPT通过API调用工作流问答

FastGPT通过API调用工作流问答 版本使用说明代码模板 版本 fastgpt v4.8.10 使用说明 注意两个参数 stream 是否流式输出 detail 是否体现工作流过程细节 代码模板 import requests import pandas as pddef get_completion(question):# Define the URL and headersurl …

使用 Babylon.js 开发时如何通过 CSS 实现 UI 自适应

本文将介绍如何在 Babylon.js 开发中&#xff0c;通过预先定义的 CSS 文件实现 UI 的自适应布局&#xff0c;确保 UI 能够根据 Canvas 元素的尺寸动态调整。 场景描述 假设我们已经使用 HTML 和 CSS 构建了 Babylon.js 的 UI 界面&#xff0c;并且所有样式都定义在 CSS 文件中…

商汤善惠获金沙江创投领投A轮融资,聚焦零售AI业务

1月20日&#xff0c;商汤善惠宣布完成A轮融资&#xff0c;本轮融资由金沙江创投数千万元领投&#xff0c;微木资本、嘉实基金和金弘基金等知名资管平台和产业资本数千万元跟投&#xff0c;鞍羽资本担任长期财务顾问。 此次融资将重点投向零售AI算法研发创新、海外市场拓展战略…

一文读懂 RocketMQ:从概念到架构与应用原理概述

文章目录 概述架构说明核心组件核心概念 namesvrproducer默认实现producer启动消息发送 broker-mq核心基本模型集群模型内部模型存储机制高可用 consumerpush类型push流程pull类型 概述 随着分布式技术在业内的快速应用&#xff0c;mq&#xff08;消息队列&#xff09;做为不可…