20250226-代码笔记05-class CVRP_Decoder

ops/2025/3/4 11:54:38/

文章目录

  • 前言
  • 一、class CVRP_Decoder(nn.Module):__init__(self, **model_params)
    • 函数功能
    • 函数代码
  • 二、class CVRP_Decoder(nn.Module):set_kv(self, encoded_nodes)
    • 函数功能
    • 函数代码
  • 三、class CVRP_Decoder(nn.Module):set_q1(self, encoded_q1)
    • 函数功能
    • 函数代码
  • 四、class CVRP_Decoder(nn.Module):set_q2(self, encoded_q2)
    • 函数功能
    • 函数代码
  • 五、class CVRP_Decoder(nn.Module):forward(self, encoded_last_node, load, ninf_mask)
    • 函数功能
    • 函数代码
  • 附录
    • class CVRP_Decoder代码(全)


前言

class CVRP_DecoderCVRP_Model.py里的类。

/home/tang/RL_exa/NCO_code-main/single_objective/LCH-Regret/Regret-POMO/CVRP/POMO/CVRPModel.py


一、class CVRP_Decoder(nn.Module):init(self, **model_params)

函数功能

init 方法是 CVRP_Decoder 类中的构造函数,主要功能是初始化该类所需的所有网络层、权重矩阵和参数。
该方法设置了用于多头注意力机制的权重、一个用于表示"遗憾"的参数、以及其他必要的操作用于计算注意力权重。

执行流程图链接
在这里插入图片描述

函数代码

    def __init__(self, **model_params):super().__init__()self.model_params = model_paramsembedding_dim = self.model_params['embedding_dim']head_num = self.model_params['head_num']qkv_dim = self.model_params['qkv_dim']# self.Wq_1 = nn.Linear(embedding_dim, head_num * qkv_dim, bias=False)self.Wq_2 = nn.Linear(embedding_dim, head_num * qkv_dim, bias=False)self.Wq_last = nn.Linear(embedding_dim+1, head_num * qkv_dim, bias=False)self.Wk = nn.Linear(embedding_dim, head_num * qkv_dim, bias=False)self.Wv = nn.Linear(embedding_dim, head_num * qkv_dim, bias=False)self.regret_embedding = nn.Parameter(torch.Tensor(embedding_dim))self.regret_embedding.data.uniform_(-1, 1)self.multi_head_combine = nn.Linear(head_num * qkv_dim, embedding_dim)self.k = None  # saved key, for multi-head attentionself.v = None  # saved value, for multi-head_attentionself.single_head_key = None  # saved, for single-head attention# self.q1 = None  # saved q1, for multi-head attentionself.q2 = None  # saved q2, for multi-head attention

二、class CVRP_Decoder(nn.Module):set_kv(self, encoded_nodes)

函数功能

set_kv 方法的功能是将 encoded_nodes 中的节点嵌入转换为多头注意力机制所需的 键(K)值(V),并将它们分别保存为类的属性。
这个方法将输入的节点嵌入通过权重矩阵进行线性变换,得到键和值的表示,并为后续的多头注意力计算做好准备。
执行流程图链接
在这里插入图片描述

函数代码

    def set_kv(self, encoded_nodes):# encoded_nodes.shape: (batch, problem+1, embedding)head_num = self.model_params['head_num']self.k = reshape_by_heads(self.Wk(encoded_nodes), head_num=head_num)self.v = reshape_by_heads(self.Wv(encoded_nodes), head_num=head_num)# shape: (batch, head_num, problem+1, qkv_dim)self.single_head_key = encoded_nodes.transpose(1, 2)# shape: (batch, embedding, problem+1)

三、class CVRP_Decoder(nn.Module):set_q1(self, encoded_q1)

函数功能

set_q1 方法的主要功能是 计算查询(Q) 并将其转换为适用于多头注意力机制的形状。
该方法接受输入的查询张量 encoded_q1,通过线性层 self.Wq_1 映射到一个新的维度,并使用 reshape_by_heads 函数将其调整为适合多头注意力机制计算的形状。计算出的查询会被保存为类的属性 q1,供后续使用。

执行流程图链接
在这里插入图片描述

函数代码

    def set_q1(self, encoded_q1):# encoded_q.shape: (batch, n, embedding)  # n can be 1 or pomohead_num = self.model_params['head_num']self.q1 = reshape_by_heads(self.Wq_1(encoded_q1), head_num=head_num)# shape: (batch, head_num, n, qkv_dim)

四、class CVRP_Decoder(nn.Module):set_q2(self, encoded_q2)

函数功能

set_q2 方法的主要功能是 计算查询(Q) 并将其转换为适用于多头注意力机制的形状。
该方法接收输入的查询张量 encoded_q2,通过线性层 self.Wq_2 映射到一个新的维度,并使用 reshape_by_heads 函数将其调整为适合多头注意力计算的形状。
执行流程图链接
在这里插入图片描述

函数代码

    def set_q2(self, encoded_q2):# encoded_q.shape: (batch, n, embedding)  # n can be 1 or pomohead_num = self.model_params['head_num']self.q2 = reshape_by_heads(self.Wq_2(encoded_q2), head_num=head_num)# shape: (batch, head_num, n, qkv_dim)

五、class CVRP_Decoder(nn.Module):forward(self, encoded_last_node, load, ninf_mask)

函数功能

forward 方法是 CVRP_Decoder 类中的前向传播函数,主要功能是执行 多头自注意力机制 和 单头注意力计算,并最终输出每个可能节点的选择概率(probs)。
该方法通过多头注意力计算、前馈神经网络处理,以及概率计算来进行节点选择。

执行流程图链接
在这里插入图片描述

函数代码

    def forward(self, encoded_last_node, load, ninf_mask):# encoded_last_node.shape: (batch, pomo, embedding)# load.shape: (batch, pomo)# ninf_mask.shape: (batch, pomo, problem)head_num = self.model_params['head_num']#  Multi-Head Attention#######################################################input_cat = torch.cat((encoded_last_node, load[:, :, None]), dim=2)# shape = (batch, group, EMBEDDING_DIM+1)q_last = reshape_by_heads(self.Wq_last(input_cat), head_num=head_num)# shape: (batch, head_num, pomo, qkv_dim)# q = self.q1 + self.q2 + q_last# # shape: (batch, head_num, pomo, qkv_dim)# q = q_last# shape: (batch, head_num, pomo, qkv_dim)q = self.q2 + q_last# # shape: (batch, head_num, pomo, qkv_dim)out_concat = multi_head_attention(q, self.k, self.v, rank3_ninf_mask=ninf_mask)# shape: (batch, pomo, head_num*qkv_dim)mh_atten_out = self.multi_head_combine(out_concat)# shape: (batch, pomo, embedding)#  Single-Head Attention, for probability calculation#######################################################score = torch.matmul(mh_atten_out, self.single_head_key)# shape: (batch, pomo, problem)sqrt_embedding_dim = self.model_params['sqrt_embedding_dim']logit_clipping = self.model_params['logit_clipping']score_scaled = score / sqrt_embedding_dim# shape: (batch, pomo, problem)score_clipped = logit_clipping * torch.tanh(score_scaled)score_masked = score_clipped + ninf_maskprobs = F.softmax(score_masked, dim=2)# shape: (batch, pomo, problem)return probs

附录

class CVRP_Decoder代码(全)

class CVRP_Decoder(nn.Module):def __init__(self, **model_params):super().__init__()self.model_params = model_paramsembedding_dim = self.model_params['embedding_dim']head_num = self.model_params['head_num']qkv_dim = self.model_params['qkv_dim']# self.Wq_1 = nn.Linear(embedding_dim, head_num * qkv_dim, bias=False)self.Wq_2 = nn.Linear(embedding_dim, head_num * qkv_dim, bias=False)self.Wq_last = nn.Linear(embedding_dim+1, head_num * qkv_dim, bias=False)self.Wk = nn.Linear(embedding_dim, head_num * qkv_dim, bias=False)self.Wv = nn.Linear(embedding_dim, head_num * qkv_dim, bias=False)self.regret_embedding = nn.Parameter(torch.Tensor(embedding_dim))self.regret_embedding.data.uniform_(-1, 1)self.multi_head_combine = nn.Linear(head_num * qkv_dim, embedding_dim)self.k = None  # saved key, for multi-head attentionself.v = None  # saved value, for multi-head_attentionself.single_head_key = None  # saved, for single-head attention# self.q1 = None  # saved q1, for multi-head attentionself.q2 = None  # saved q2, for multi-head attentiondef set_kv(self, encoded_nodes):# encoded_nodes.shape: (batch, problem+1, embedding)head_num = self.model_params['head_num']self.k = reshape_by_heads(self.Wk(encoded_nodes), head_num=head_num)self.v = reshape_by_heads(self.Wv(encoded_nodes), head_num=head_num)# shape: (batch, head_num, problem+1, qkv_dim)self.single_head_key = encoded_nodes.transpose(1, 2)# shape: (batch, embedding, problem+1)def set_q1(self, encoded_q1):# encoded_q.shape: (batch, n, embedding)  # n can be 1 or pomohead_num = self.model_params['head_num']self.q1 = reshape_by_heads(self.Wq_1(encoded_q1), head_num=head_num)# shape: (batch, head_num, n, qkv_dim)def set_q2(self, encoded_q2):# encoded_q.shape: (batch, n, embedding)  # n can be 1 or pomohead_num = self.model_params['head_num']self.q2 = reshape_by_heads(self.Wq_2(encoded_q2), head_num=head_num)# shape: (batch, head_num, n, qkv_dim)def forward(self, encoded_last_node, load, ninf_mask):# encoded_last_node.shape: (batch, pomo, embedding)# load.shape: (batch, pomo)# ninf_mask.shape: (batch, pomo, problem)head_num = self.model_params['head_num']#  Multi-Head Attention#######################################################input_cat = torch.cat((encoded_last_node, load[:, :, None]), dim=2)# shape = (batch, group, EMBEDDING_DIM+1)q_last = reshape_by_heads(self.Wq_last(input_cat), head_num=head_num)# shape: (batch, head_num, pomo, qkv_dim)# q = self.q1 + self.q2 + q_last# # shape: (batch, head_num, pomo, qkv_dim)# q = q_last# shape: (batch, head_num, pomo, qkv_dim)q = self.q2 + q_last# # shape: (batch, head_num, pomo, qkv_dim)out_concat = multi_head_attention(q, self.k, self.v, rank3_ninf_mask=ninf_mask)# shape: (batch, pomo, head_num*qkv_dim)mh_atten_out = self.multi_head_combine(out_concat)# shape: (batch, pomo, embedding)#  Single-Head Attention, for probability calculation#######################################################score = torch.matmul(mh_atten_out, self.single_head_key)# shape: (batch, pomo, problem)sqrt_embedding_dim = self.model_params['sqrt_embedding_dim']logit_clipping = self.model_params['logit_clipping']score_scaled = score / sqrt_embedding_dim# shape: (batch, pomo, problem)score_clipped = logit_clipping * torch.tanh(score_scaled)score_masked = score_clipped + ninf_maskprobs = F.softmax(score_masked, dim=2)# shape: (batch, pomo, problem)return probs

http://www.ppmy.cn/ops/162500.html

相关文章

MySQL 存储过程详解

文章目录 1. 存储过程定义1.1 基本概念1.2 核心特点1.3 存储过程 vs 函数 2. 工作原理与示意图2.1 执行流程2.2 示意图 3. 使用场景3.1 复杂业务逻辑3.2 批量数据处理3.3 权限控制3.4 性能优化 4. 示例与说明4.1 基础示例:创建存储过程4.2 带输出参数的存储过程4.3 …

智能合约安全指南 [特殊字符]️

智能合约安全指南 🛡️ 1. 安全基础 1.1 常见漏洞类型 重入攻击整数溢出权限控制缺陷随机数漏洞前后运行攻击签名重放 1.2 安全开发原则 最小权限原则检查-生效-交互模式状态机安全失败保护机制 2. 重入攻击防护 2.1 基本防护模式 contract ReentrancyGuarde…

使用 Polars 进行人工智能医疗数据分析(ICU数据基本测试篇)

引言 在医疗领域,数据就是生命的密码,每一个数据点都可能蕴含着拯救生命的关键信息。特别是在 ICU 这样的重症监护场景中,医生需要实时、准确地了解患者的病情变化,以便做出及时有效的治疗决策。而随着医疗技术的飞速发展&#x…

vue3:四嵌套路由的实现

一、前言 1、嵌套路由的含义 嵌套路由的核心思想是&#xff1a;在某个路由的组件内部&#xff0c;可以定义子路由&#xff0c;这些子路由会渲染在父路由组件的特定位置&#xff08;通常是 <router-view> 标签所在的位置&#xff09;。通过嵌套路由&#xff0c;你可以实…

MySQL DBA技能指南

1. MySQL 安装与配置 安装和部署&#xff1a;掌握 MySQL 在不同操作系统上的安装方法&#xff08;Linux、Windows、Docker 等&#xff09;。配置管理&#xff1a;熟悉 MySQL 配置文件&#xff08;my.cnf 或 my.ini&#xff09;的设置与优化&#xff0c;了解常见的配置参数&…

Spring Boot 日志配置与常见问题解析(详解)

目录 Spring Boot 日志配置与常见问题解析引言什么是日志&#xff1f;日志的重要性日志使用打印日志 日志框架介绍日志格式的说明⽇志级别日志级别的分类日志级别的使用 Spring Boot 日志配置1. 设置日志级别和格式2. 配置日志收集器3. 查看和分析日志4.日志的持久化5.设置日志…

AI编程界的集大成者——通义灵码AI程序员

一、引言 随着软件行业的快速发展和技术的进步&#xff0c;人工智能&#xff08;AI&#xff09;正在成为软件开发领域的一个重要组成部分。近年来&#xff0c;越来越多的AI辅助工具被引入到开发流程中&#xff0c;旨在提高效率、减少错误并加速创新。在这样的背景下&#xff0…

nz-upload 手动上传 PDF预览

<nz-upload [(nzFileList)]"fileList" [nzBeforeUpload]"beforeUpload" ><button nz-button><i nz-icon nzType"upload"></i>上传材料</button> </nz-upload>/**编辑的对象 */editingItem: ReportMaterialD…