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

20250225-代码笔记03-class CVRPModel AND other class

文章目录

  • 前言
  • 一、class CVRPModel(nn.Module):__init__(self, **model_params)
    • 函数功能
    • 函数代码
  • 二、class CVRPModel(nn.Module):pre_forward(self, reset_state)
    • 函数功能
    • 函数代码
  • 三、class CVRPModel(nn.Module):forward(self, state)
    • 函数功能
    • 函数代码
  • 四、def _get_encoding(encoded_nodes, node_index_to_pick)
    • 函数功能
    • 函数代码
  • 五、class CVRP_Encoder(nn.Module)
  • 六、class EncoderLayer(nn.Module)
  • 七、CVRP_Decoder(nn.Module)
  • 八、def reshape_by_heads(qkv, head_num)
    • 函数功能
    • 函数代码
  • 九、def multi_head_attention(q, k, v, rank2_ninf_mask=None, rank3_ninf_mask=None)
    • 函数功能
    • 函数代码
  • 十、class AddAndInstanceNormalization(nn.Module):__init__(self, **model_params)
    • 函数功能
    • Batch Normalization (BN) 是什么?
      • Batch Normalization 的具体操作
        • 1. **计算均值和方差**
        • 2. **标准化**
        • 3. **缩放和平移**
      • Batch Normalization 的优势
    • 函数代码
  • 十一、class AddAndInstanceNormalization(nn.Module):forward(self, input1, input2)
    • 函数功能
    • 函数代码
  • 十二、class FeedForward(nn.Module):__init__(self, **model_params)
    • 函数功能
    • 函数代码
  • 十三、class FeedForward(nn.Module):forward(self, input1)
    • 函数功能
    • 函数代码
  • 附录
    • 代码(全)


前言

学习代码:
class CVRPModel(nn.Module):
class CVRP_Encoder(nn.Module):
class EncoderLayer(nn.Module):
class CVRP_Decoder(nn.Module):
class AddAndInstanceNormalization(nn.Module):
class AddAndBatchNormalization(nn.Module):
class FeedForward(nn.Module):

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


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

函数功能

init 是 CVRPModel 类的构造函数,负责初始化模型的各个组件。
主要任务包括:

  • 接收和存储模型的参数(model_params)。
  • 初始化编码器(encoder)和解码器(decoder)子模块。
  • 初始化 encoded_nodes 变量,用于存储经过编码的节点数据。

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

函数代码

    def __init__(self, **model_params):super().__init__()self.model_params = model_paramsself.encoder = CVRP_Encoder(**model_params)self.decoder = CVRP_Decoder(**model_params)self.encoded_nodes = None# shape: (batch, problem+1, EMBEDDING_DIM)

二、class CVRPModel(nn.Module):pre_forward(self, reset_state)

函数功能

pre_forward 是 CVRPModel 类的一个前向传播前的准备函数。它的主要任务是根据给定的初始状态(reset_state)准备和编码数据,为模型的后续前向传播(forward)过程做准备
具体来说,函数的作用是:

  • 提取并处理初始状态的数据。
  • 使用编码器对节点进行编码,得到编码后的节点表示。
  • 为解码器设置额外的嵌入信息,并将编码后的节点与额外的嵌入信息拼接。
  • 设置解码器中的 kv(key-value)信息,为解码过程做准备。

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

函数代码

    def pre_forward(self, reset_state):depot_xy = reset_state.depot_xy# shape: (batch, 1, 2)node_xy = reset_state.node_xy# shape: (batch, problem, 2)node_demand = reset_state.node_demand# shape: (batch, problem)node_xy_demand = torch.cat((node_xy, node_demand[:, :, None]), dim=2)# shape: (batch, problem, 3)encoded_nodes = self.encoder(depot_xy, node_xy_demand)# shape: (batch, problem+1, embedding)_ = self.decoder.regret_embedding[None, None, :].expand(encoded_nodes.size(0), 1,self.decoder.regret_embedding.size(-1))# _ 的shape:(batch,1,embedding)self.encoded_nodes = torch.cat((encoded_nodes, _), dim=1)# self.encoded_nodes的shape:(batch,problem+2,embedding)self.decoder.set_kv(self.encoded_nodes)

三、class CVRPModel(nn.Module):forward(self, state)

函数功能

forward 是 CVRPModel 类的核心前向传播函数,用于根据当前状态(state)生成模型的输出,包括选择的节点(selected)和相关的概率(prob)。
它的主要功能是基于当前的状态和历史选择来决定接下来应该选择哪个节点,并输出相应的概率。

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

函数代码

    def forward(self, state):batch_size = state.BATCH_IDX.size(0)pomo_size = state.BATCH_IDX.size(1)if state.selected_count == 0:  # First Move, depotselected = torch.zeros(size=(batch_size, pomo_size), dtype=torch.long)prob = torch.ones(size=(batch_size, pomo_size))# # Use Averaged encoded nodes for decoder input_1# encoded_nodes_mean = self.encoded_nodes.mean(dim=1, keepdim=True)# # shape: (batch, 1, embedding)# self.decoder.set_q1(encoded_nodes_mean)# Use encoded_depot for decoder input_2encoded_first_node = self.encoded_nodes[:, [0], :]# shape: (batch, 1, embedding)self.decoder.set_q2(encoded_first_node)elif state.selected_count == 1:  # Second Move, POMOselected = torch.arange(start=1, end=pomo_size+1)[None, :].expand(batch_size, pomo_size)prob = torch.ones(size=(batch_size, pomo_size))else:encoded_last_node = _get_encoding(self.encoded_nodes, state.current_node)# shape: (batch, pomo, embedding)probs = self.decoder(encoded_last_node, state.load, ninf_mask=state.ninf_mask)# shape: (batch, pomo, problem+1)if self.training or self.model_params['eval_type'] == 'softmax':while True:  # to fix pytorch.multinomial bug on selecting 0 probability elementswith torch.no_grad():selected = probs.reshape(batch_size * pomo_size, -1).multinomial(1) \.squeeze(dim=1).reshape(batch_size, pomo_size)# shape: (batch, pomo)prob = probs[state.BATCH_IDX, state.POMO_IDX, selected].reshape(batch_size, pomo_size)# shape: (batch, pomo)if (prob != 0).all():breakelse:probs=probs[:,:,:-1]selected = probs.argmax(dim=2)# shape: (batch, pomo)prob = None  # value not needed. Can be anything.return selected, prob

四、def _get_encoding(encoded_nodes, node_index_to_pick)

函数功能

_get_encoding 的作用是从 encoded_nodes 中按照 node_index_to_pick 选择相应的编码,并返回选中的编码信息。

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

函数代码

def _get_encoding(encoded_nodes, node_index_to_pick):# encoded_nodes.shape: (batch, problem, embedding)# node_index_to_pick.shape: (batch, pomo)batch_size = node_index_to_pick.size(0)pomo_size = node_index_to_pick.size(1)embedding_dim = encoded_nodes.size(2)gathering_index = node_index_to_pick[:, :, None].expand(batch_size, pomo_size, embedding_dim)# shape: (batch, pomo, embedding)picked_nodes = encoded_nodes.gather(dim=1, index=gathering_index)# shape: (batch, pomo, embedding)return picked_nodes

五、class CVRP_Encoder(nn.Module)

笔记:20250226-代码笔记04-class CVRP_Encoder AND class EncoderLayer


六、class EncoderLayer(nn.Module)

笔记:20250226-代码笔记04-class CVRP_Encoder AND class EncoderLayer


七、CVRP_Decoder(nn.Module)

笔记:20250226-代码笔记05-class CVRP_Decoder


八、def reshape_by_heads(qkv, head_num)

函数功能

reshape_by_heads 函数的功能是将输入的张量(如查询 q, 键 k, 或值 v)从一个紧凑的多头结构 (batch, n, head_num * key_dim) 转换为适合多头注意力机制计算的结构 (batch, head_num, n, key_dim)
此操作将多个注意力头的维度进行拆分,并将其调整为每个头独立计算的格式。
执行流程图链接
在这里插入图片描述

函数代码

def reshape_by_heads(qkv, head_num):# q.shape: (batch, n, head_num*key_dim)   : n can be either 1 or PROBLEM_SIZEbatch_s = qkv.size(0)n = qkv.size(1)q_reshaped = qkv.reshape(batch_s, n, head_num, -1)# shape: (batch, n, head_num, key_dim)q_transposed = q_reshaped.transpose(1, 2)# shape: (batch, head_num, n, key_dim)return q_transposed

九、def multi_head_attention(q, k, v, rank2_ninf_mask=None, rank3_ninf_mask=None)

函数功能

multi_head_attention 函数的主要功能是实现 多头注意力机制。该函数接收查询(Q)、键(K)和值(V),并计算多头注意力输出。它通过计算查询与键之间的相似度,生成加权值的结果,并结合所有头的输出生成最终的注意力表示。
执行流程图链接
在这里插入图片描述

函数代码

def multi_head_attention(q, k, v, rank2_ninf_mask=None, rank3_ninf_mask=None):# q shape: (batch, head_num, n, key_dim)   : n can be either 1 or PROBLEM_SIZE# k,v shape: (batch, head_num, problem, key_dim)# rank2_ninf_mask.shape: (batch, problem)# rank3_ninf_mask.shape: (batch, group, problem)batch_s = q.size(0)head_num = q.size(1)n = q.size(2)key_dim = q.size(3)input_s = k.size(2)score = torch.matmul(q, k.transpose(2, 3))# shape: (batch, head_num, n, problem)score_scaled = score / torch.sqrt(torch.tensor(key_dim, dtype=torch.float))if rank2_ninf_mask is not None:score_scaled = score_scaled + rank2_ninf_mask[:, None, None, :].expand(batch_s, head_num, n, input_s)if rank3_ninf_mask is not None:score_scaled = score_scaled + rank3_ninf_mask[:, None, :, :].expand(batch_s, head_num, n, input_s)weights = nn.Softmax(dim=3)(score_scaled)# shape: (batch, head_num, n, problem)out = torch.matmul(weights, v)# shape: (batch, head_num, n, key_dim)out_transposed = out.transpose(1, 2)# shape: (batch, n, head_num, key_dim)out_concat = out_transposed.reshape(batch_s, n, head_num * key_dim)# shape: (batch, n, head_num*key_dim)return out_concat

十、class AddAndInstanceNormalization(nn.Module):init(self, **model_params)

函数功能

对输入数据进行基于嵌入维度的批量标准化操作,从而使得模型在训练过程中能够更好地收敛和提高稳定性。

Batch Normalization (BN) 是什么?

Batch Normalization (BN) 是一种在训练深度神经网络时常用的技术,它的目的是提高网络的训练速度、稳定性,并帮助避免梯度消失或爆炸问题。
Batch Normalization 操作的核心思想是对每一层的输入数据进行标准化,使得输入数据的均值接近 0,方差接近 1。这样可以避免激活函数输出过大或过小的问题,帮助优化过程更加稳定。

Batch Normalization 的具体操作

1. 计算均值和方差

对于一批输入样本(batch),在每个特征维度上计算均值和方差:

  • 均值
    μ B = 1 m ∑ i = 1 m x i \mu_B = \frac{1}{m} \sum_{i=1}^{m} x_i μB=m1i=1mxi

  • 方差
    σ B 2 = 1 m ∑ i = 1 m ( x i − μ B ) 2 \sigma_B^2 = \frac{1}{m} \sum_{i=1}^{m} (x_i - \mu_B)^2 σB2=m1i=1m(xiμB)2

其中, m m m 是一个批次中的样本数, x i x_i xi是每个样本的输入值。

2. 标准化

使用计算出的均值和方差将输入数据标准化,使得每个特征的均值为 0,方差为 1:

x ^ i = x i − μ B σ B 2 + ϵ \hat{x}_i = \frac{x_i - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}} x^i=σB2+ϵ xiμB

这里 ϵ \epsilon ϵ是一个非常小的数值,用来防止除以零的情况。

3. 缩放和平移

由于标准化可能会影响到模型的表达能力,Batch Normalization 还会引入两个可学习的参数 γ \gamma γ(缩放参数)和 β \beta β(平移参数),它们允许模型重新调整标准化后的数据:

y i = γ x ^ i + β y_i = \gamma \hat{x}_i + \beta yi=γx^i+β

其中, γ \gamma γ β \beta β是学习的参数,通常会通过反向传播进行优化。

Batch Normalization 的优势

  • 加速训练:Batch Normalization 通过减少输入数据的偏移(internal covariate shift),使得每一层的输入分布更加稳定,从而加速了网络的训练过程。
  • 提高稳定性:由于它通过标准化输入避免了梯度爆炸或梯度消失问题,使得训练更加稳定。
  • 缓解过拟合:在一些情况下,Batch Normalization 也可以起到正则化的作用,减少了模型对训练数据的过拟合。
  • 减少对初始化的依赖:Batch Normalization 可以在一定程度上缓解对权重初始化的敏感性。

函数代码

    def __init__(self, **model_params):super().__init__()embedding_dim = model_params['embedding_dim']self.norm = nn.InstanceNorm1d(embedding_dim, affine=True, track_running_stats=False)

十一、class AddAndInstanceNormalization(nn.Module):forward(self, input1, input2)

函数功能

forward 方法,它执行了加法和批量归一化操作。
forward 方法的主要功能是:

  • 加法操作:将两个输入张量 input1input2 相加。
  • 批量归一化:将加法结果进行批量归一化(Batch Normalization),标准化其特征维度。
  • 形状恢复:批量归一化后,将张量的形状恢复到原来的维度。

执行流程:

函数代码

  1. 获取输入张量的维度:
batch_s = input1.size(0)
problem_s = input1.size(1)
embedding_dim = input1.size(2)
  • batch_s 表示批次大小,problem_s 表示问题的大小(特征的数量),embedding_dim 表示嵌入的维度。
  • 这些维度来自输入张量input1,并且假设 input2 具有相同的形状。
  1. 加法操作:
added = input1 + input2
  • input1 nput2 进行逐元素加法。此时,added 张量的形状与 input1input2 相同,仍为 (batch_s, problem_s, embedding_dim)
  1. 批量归一化:
normalized = self.norm_by_EMB(added.reshape(batch_s * problem_s, embedding_dim))
  • added 张量的形状重塑为 (batch_s * problem_s, embedding_dim),将批次维度和问题维度合并,以便进行批量归一化操作。这样就对每个特征维度(embedding_dim)做了批量标准化。
  • self.norm_by_EMB 是一个 BatchNorm1d 层,它会对每个特征维度执行标准化,使得每个特征的均值接近 0,方差接近 1。
  1. 恢复形状:
back_trans = normalized.reshape(batch_s, problem_s, embedding_dim)
  • 批量归一化后,将 normalized 张量的形状恢复回 (batch_s, problem_s, embedding_dim),即恢复原本的输入形状。
  1. 返回结果:
return back_trans
  • 返回经过批量归一化的张量 back_trans,它的形状与输入相同,并且每个特征维度已经经过标准化。
    def forward(self, input1, input2):# input.shape: (batch, problem, embedding)added = input1 + input2# shape: (batch, problem, embedding)transposed = added.transpose(1, 2)# shape: (batch, embedding, problem)normalized = self.norm(transposed)# shape: (batch, embedding, problem)back_trans = normalized.transpose(1, 2)# shape: (batch, problem, embedding)return back_trans

十二、class FeedForward(nn.Module):init(self, **model_params)

函数功能

FeedForward 的类,它是一个典型的前馈神经网络(Feedforward Neural Network)模块,实现了一个简单的两层神经网络。

  • __init__ 方法是类的构造函数,用来初始化网络的层和超参数。
  • embedding_dim ff_hidden_dim 是通过 model_params 传递的超参数,分别表示嵌入维度和前馈神经网络隐藏层的维度。
    • embedding_dim 是输入和输出的维度。
    • ff_hidden_dim 是隐藏层的维度,即在网络的中间层。
  • self.W1 self.W2是两个全连接层nn.Linear):
    • self.W1 将输入的 embedding_dim 维度的向量转换为 ff_hidden_dim 维度的向量。
    • self.W2 ff_hidden_dim 维度的向量转换回 embedding_dim 维度的向量。

函数代码

    def __init__(self, **model_params):super().__init__()embedding_dim = model_params['embedding_dim']ff_hidden_dim = model_params['ff_hidden_dim']self.W1 = nn.Linear(embedding_dim, ff_hidden_dim)self.W2 = nn.Linear(ff_hidden_dim, embedding_dim)

十三、class FeedForward(nn.Module):forward(self, input1)

函数功能

  • forward 方法定义了数据流通过网络的方式,也就是前向传播过程。
  • 输入 input1 的形状为 (batch, problem, embedding),即批次大小 batch、问题数量 problem和每个问题的嵌入维度embedding
  • 执行的步骤如下:
    • 1.第一层线性变换(self.W1:输入通过 self.W1 进行线性变换,将输入的嵌入维度转换为隐藏层的维度(ff_hidden_dim)。变换公式为:
      在这里插入图片描述
      其中 x 是输入,W1 是权重矩阵,b1 是偏置。

    • 2.激活函数(ReLU):对 self.W1 的输出应用 ReLU 激活函数,ReLU 将负值归零,保留正值。公式为:
      在这里插入图片描述

    • 3.第二层线性变换(self.W2:通过 self.W2 进行线性变换,将隐藏层的输出转换回原始的嵌入维度(embedding_dim)。变换公式为:
      在这里插入图片描述

  • 最终输出是经过两层线性变换和 ReLU 激活函数处理的结果,形状仍然是 (batch, problem, embedding)。

函数代码

    def forward(self, input1):# input.shape: (batch, problem, embedding)return self.W2(F.relu(self.W1(input1)))

附录

代码(全)


import torch
import torch.nn as nn
import torch.nn.functional as Fclass CVRPModel(nn.Module):def __init__(self, **model_params):super().__init__()self.model_params = model_paramsself.encoder = CVRP_Encoder(**model_params)self.decoder = CVRP_Decoder(**model_params)self.encoded_nodes = None# shape: (batch, problem+1, EMBEDDING_DIM)def pre_forward(self, reset_state):depot_xy = reset_state.depot_xy# shape: (batch, 1, 2)node_xy = reset_state.node_xy# shape: (batch, problem, 2)node_demand = reset_state.node_demand# shape: (batch, problem)node_xy_demand = torch.cat((node_xy, node_demand[:, :, None]), dim=2)# shape: (batch, problem, 3)encoded_nodes = self.encoder(depot_xy, node_xy_demand)# shape: (batch, problem+1, embedding)_ = self.decoder.regret_embedding[None, None, :].expand(encoded_nodes.size(0), 1,self.decoder.regret_embedding.size(-1))# _ 的shape:(batch,1,embedding)self.encoded_nodes = torch.cat((encoded_nodes, _), dim=1)# self.encoded_nodes的shape:(batch,problem+2,embedding)self.decoder.set_kv(self.encoded_nodes)def forward(self, state):batch_size = state.BATCH_IDX.size(0)pomo_size = state.BATCH_IDX.size(1)if state.selected_count == 0:  # First Move, depotselected = torch.zeros(size=(batch_size, pomo_size), dtype=torch.long)prob = torch.ones(size=(batch_size, pomo_size))# # Use Averaged encoded nodes for decoder input_1# encoded_nodes_mean = self.encoded_nodes.mean(dim=1, keepdim=True)# # shape: (batch, 1, embedding)# self.decoder.set_q1(encoded_nodes_mean)# Use encoded_depot for decoder input_2encoded_first_node = self.encoded_nodes[:, [0], :]# shape: (batch, 1, embedding)self.decoder.set_q2(encoded_first_node)elif state.selected_count == 1:  # Second Move, POMOselected = torch.arange(start=1, end=pomo_size+1)[None, :].expand(batch_size, pomo_size)prob = torch.ones(size=(batch_size, pomo_size))else:encoded_last_node = _get_encoding(self.encoded_nodes, state.current_node)# shape: (batch, pomo, embedding)probs = self.decoder(encoded_last_node, state.load, ninf_mask=state.ninf_mask)# shape: (batch, pomo, problem+1)if self.training or self.model_params['eval_type'] == 'softmax':while True:  # to fix pytorch.multinomial bug on selecting 0 probability elementswith torch.no_grad():selected = probs.reshape(batch_size * pomo_size, -1).multinomial(1) \.squeeze(dim=1).reshape(batch_size, pomo_size)# shape: (batch, pomo)prob = probs[state.BATCH_IDX, state.POMO_IDX, selected].reshape(batch_size, pomo_size)# shape: (batch, pomo)if (prob != 0).all():breakelse:probs=probs[:,:,:-1]selected = probs.argmax(dim=2)# shape: (batch, pomo)prob = None  # value not needed. Can be anything.return selected, probdef _get_encoding(encoded_nodes, node_index_to_pick):# encoded_nodes.shape: (batch, problem, embedding)# node_index_to_pick.shape: (batch, pomo)batch_size = node_index_to_pick.size(0)pomo_size = node_index_to_pick.size(1)embedding_dim = encoded_nodes.size(2)gathering_index = node_index_to_pick[:, :, None].expand(batch_size, pomo_size, embedding_dim)# shape: (batch, pomo, embedding)picked_nodes = encoded_nodes.gather(dim=1, index=gathering_index)# shape: (batch, pomo, embedding)return picked_nodes########################################
# ENCODER
########################################class CVRP_Encoder(nn.Module):def __init__(self, **model_params):super().__init__()self.model_params = model_paramsembedding_dim = self.model_params['embedding_dim']encoder_layer_num = self.model_params['encoder_layer_num']self.embedding_depot = nn.Linear(2, embedding_dim)self.embedding_node = nn.Linear(3, embedding_dim)self.layers = nn.ModuleList([EncoderLayer(**model_params) for _ in range(encoder_layer_num)])def forward(self, depot_xy, node_xy_demand):# depot_xy.shape: (batch, 1, 2)# node_xy_demand.shape: (batch, problem, 3)embedded_depot = self.embedding_depot(depot_xy)# shape: (batch, 1, embedding)embedded_node = self.embedding_node(node_xy_demand)# shape: (batch, problem, embedding)out = torch.cat((embedded_depot, embedded_node), dim=1)# shape: (batch, problem+1, embedding)for layer in self.layers:out = layer(out)return out# shape: (batch, problem+1, embedding)class EncoderLayer(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 = nn.Linear(embedding_dim, 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.multi_head_combine = nn.Linear(head_num * qkv_dim, embedding_dim)self.add_n_normalization_1 = AddAndInstanceNormalization(**model_params)self.feed_forward = FeedForward(**model_params)self.add_n_normalization_2 = AddAndInstanceNormalization(**model_params)def forward(self, input1):# input1.shape: (batch, problem+1, embedding)head_num = self.model_params['head_num']q = reshape_by_heads(self.Wq(input1), head_num=head_num)k = reshape_by_heads(self.Wk(input1), head_num=head_num)v = reshape_by_heads(self.Wv(input1), head_num=head_num)# qkv shape: (batch, head_num, problem, qkv_dim)out_concat = multi_head_attention(q, k, v)# shape: (batch, problem, head_num*qkv_dim)multi_head_out = self.multi_head_combine(out_concat)# shape: (batch, problem, embedding)out1 = self.add_n_normalization_1(input1, multi_head_out)out2 = self.feed_forward(out1)out3 = self.add_n_normalization_2(out1, out2)return out3# shape: (batch, problem, embedding)########################################
# 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########################################
# NN SUB CLASS / FUNCTIONS
########################################def reshape_by_heads(qkv, head_num):# q.shape: (batch, n, head_num*key_dim)   : n can be either 1 or PROBLEM_SIZEbatch_s = qkv.size(0)n = qkv.size(1)q_reshaped = qkv.reshape(batch_s, n, head_num, -1)# shape: (batch, n, head_num, key_dim)q_transposed = q_reshaped.transpose(1, 2)# shape: (batch, head_num, n, key_dim)return q_transposeddef multi_head_attention(q, k, v, rank2_ninf_mask=None, rank3_ninf_mask=None):# q shape: (batch, head_num, n, key_dim)   : n can be either 1 or PROBLEM_SIZE# k,v shape: (batch, head_num, problem, key_dim)# rank2_ninf_mask.shape: (batch, problem)# rank3_ninf_mask.shape: (batch, group, problem)batch_s = q.size(0)head_num = q.size(1)n = q.size(2)key_dim = q.size(3)input_s = k.size(2)score = torch.matmul(q, k.transpose(2, 3))# shape: (batch, head_num, n, problem)score_scaled = score / torch.sqrt(torch.tensor(key_dim, dtype=torch.float))if rank2_ninf_mask is not None:score_scaled = score_scaled + rank2_ninf_mask[:, None, None, :].expand(batch_s, head_num, n, input_s)if rank3_ninf_mask is not None:score_scaled = score_scaled + rank3_ninf_mask[:, None, :, :].expand(batch_s, head_num, n, input_s)weights = nn.Softmax(dim=3)(score_scaled)# shape: (batch, head_num, n, problem)out = torch.matmul(weights, v)# shape: (batch, head_num, n, key_dim)out_transposed = out.transpose(1, 2)# shape: (batch, n, head_num, key_dim)out_concat = out_transposed.reshape(batch_s, n, head_num * key_dim)# shape: (batch, n, head_num*key_dim)return out_concatclass AddAndInstanceNormalization(nn.Module):def __init__(self, **model_params):super().__init__()embedding_dim = model_params['embedding_dim']self.norm = nn.InstanceNorm1d(embedding_dim, affine=True, track_running_stats=False)def forward(self, input1, input2):# input.shape: (batch, problem, embedding)added = input1 + input2# shape: (batch, problem, embedding)transposed = added.transpose(1, 2)# shape: (batch, embedding, problem)normalized = self.norm(transposed)# shape: (batch, embedding, problem)back_trans = normalized.transpose(1, 2)# shape: (batch, problem, embedding)return back_transclass AddAndBatchNormalization(nn.Module):def __init__(self, **model_params):super().__init__()embedding_dim = model_params['embedding_dim']self.norm_by_EMB = nn.BatchNorm1d(embedding_dim, affine=True)# 'Funny' Batch_Norm, as it will normalized by EMB dimdef forward(self, input1, input2):# input.shape: (batch, problem, embedding)batch_s = input1.size(0)problem_s = input1.size(1)embedding_dim = input1.size(2)added = input1 + input2normalized = self.norm_by_EMB(added.reshape(batch_s * problem_s, embedding_dim))back_trans = normalized.reshape(batch_s, problem_s, embedding_dim)return back_transclass FeedForward(nn.Module):def __init__(self, **model_params):super().__init__()embedding_dim = model_params['embedding_dim']ff_hidden_dim = model_params['ff_hidden_dim']self.W1 = nn.Linear(embedding_dim, ff_hidden_dim)self.W2 = nn.Linear(ff_hidden_dim, embedding_dim)def forward(self, input1):# input.shape: (batch, problem, embedding)return self.W2(F.relu(self.W1(input1)))

相关文章:

20250225-代码笔记03-class CVRPModel AND other class

文章目录 前言一、class CVRPModel(nn.Module):__init__(self, **model_params)函数功能函数代码 二、class CVRPModel(nn.Module):pre_forward(self, reset_state)函数功能函数代码 三、class CVRPModel(nn.Module):forward(self, state)函数功能函数代码 四、def _get_encodi…...

京准电钟快讯:NTP时钟同步服务在智造行业应用

京准电钟快讯:NTP时钟同步服务在智造行业应用 京准电钟快讯:NTP时钟同步服务在智造行业应用 一、NTP技术概述 基本原理 NTP(Network Time Protocol)是一种用于同步计算机系统时间的网络协议,通过分层时钟源&#xff…...

【Qt】详细介绍如何在Visual Studio Code中编译、运行Qt项目

Visual Studio Code一只用的顺手,写Qt的时候也能用VS Code开发就方便多了。 理论上也不算困难,毕竟Qt项目其实就是CMake(QMake的情况这里就暂不考虑了)项目,VS Code在编译、运行CMake项目还是比较成熟的。 这里笔者打…...

jsherp importItemExcel接口存在SQL注入

一、漏洞简介 很多人说管伊佳ERP(原名:华夏ERP,英文名:jshERP)是目前人气领先的国产ERP系统虽然目前只有进销存财务生产的功能,但后面将会推出ERP的全部功能,有兴趣请帮点一下 二、漏洞影响 …...

Node.js, Bun, Deno 比较概述

以下是 Node.js、Bun 和 Deno 的对比分析 概览 对比维度Node.jsDenoBun首次发布200920202022创始人Ryan DahlRyan Dahl(Node.js 原作者)Jarred Sumner运行时引擎V8(Chrome)V8(Chrome)JavaScriptCore&#…...

大白话跨域问题怎么破,解决方法有啥?

大白话跨域问题怎么破,解决方法有啥? 啥是跨域问题 咱先说说啥是跨域。你可以把每个网站想象成一个独立的小房子,每个房子都有自己的地址(也就是域名)。正常情况下,一个房子里的东西只能在这个房子里用&a…...

DeepSeek R1满血+火山引擎详细教程

DeepSeek R1满血火山引擎详细教程 一、安装Cherry Studio。 Cherry Studio AI 是一款强大的多模型 AI 助手,支持 iOS、macOS 和 Windows 平台。可以快速切换多个先进的 LLM 模型,提升工作学习效率。下载地址 https://cherry-ai.com/ 认准官网,无强制注册。 这…...

Pytorch中的ebmedding到底怎么理解?

在 PyTorch 中,nn.Embedding 是一个用于处理离散符号映射到连续向量空间的模块。它通常用于自然语言处理(NLP)任务(如词嵌入)、处理分类特征,或任何需要将离散索引转换为密集向量的场景。 核心理解 功能&am…...

【JAVA面试题】什么是面向对象?谈谈你对面向对象的理解。

【JAVA面试题】什么是面向对象?谈谈你对面向对象的理解 在 Java 面试中,面向对象 是一个高频考点。它不仅是一种编程思想,更是现代软件开发的核心方法论。本文将从 面向对象的概念、与面向过程的对比、以及 面向对象的三大特性(封…...

【C】链式二叉树算法题1 -- 单值二叉树

leetcode链接https://leetcode.cn/problems/univalued-binary-tree/description/ 1 题目描述 如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。只有给定的树是单值二叉树时,才返回 true;否则返回 false。 示例 1&#xff1…...

基于单片机的GPS定位系统设计

1 系统硬件 1.1单片机模块 单片机的种类和型号可以说是有成百上千种,很多大的公司和企业都生产开发自己的单片机芯片,并且广泛应用于各种产品。Intel、 philips、 摩托罗拉、凌阳、宏晶等等种类繁多。大体上可以分为51系列单片机和非51系列单片机。 其…...

[React]Render Props、自定义Hooks和Context API优化详解

关于React中的Render Props、自定义Hooks和Context API优化的详解。我需要根据我搜索到的资料来综合回答这三个部分。首先,我需要分别理解每个概念的定义、用途以及优化方法。 首先看Render Props。根据Render Props是一种通过传递函数作为prop来共享组件间逻辑的技…...

关于大型语言模型的结构修剪

本文介绍了一种名为 **LLM-Pruner** 的方法,用于对大型语言模型(LLMs)进行结构化剪枝,以减少模型大小和计算需求,同时保留其多任务解决和语言生成能力。LLM-Pruner 通过依赖检测和重要性估计实现高效剪枝,并…...

【语法】C++中string类中的两个问题及解答

贴主在学习string类时遇到过两个困扰我的问题,今天拿出来给大家分享一下我是如何解决的 一、扩容时capacity的增长问题 在string的capacity()接口中,调用的是这个string对象的容量(可以存多少个有效字符),而size()是调用的string对象现在有…...

Linux(centOS) 命令提示符格式修改(PS1)

1. 命令提示符的组成 命令提示符(PS1)通常由以下部分组成: 部分示例说明[ 和 ][...]提示符的开头和结尾,用于视觉分隔。用户名root 或 tianjiajie当前登录的用户。root 是超级用户,普通用户可能是其他名称。分隔用户…...

QwenVL 2.5-本地安装编译布署全教程

开篇 DeepSeek开源后我国又开源了一个震撼大模型,QwenVL2.5,这是一个多模态的模形,它可以认图、识图、更能作图,还能读懂video。 Qwen2.5-VL 的主要特点如下所示: 感知更丰富的世界:Qwen2.5-VL 不仅擅长识别常见物体,如花、鸟、鱼和昆虫,还能够分析图像中的文本、图表…...

Hutool - JWT:轻松玩转 JSON Web Token

各位开发者朋友们,在现代的前后端分离开发模式里,身份验证和授权可是至关重要的环节。JSON Web Token(JWT)作为一种轻量级的身份验证和授权机制,在很多项目中都得到了广泛应用。它可以在客户端和服务器之间安全地传输信…...

2024年第十五届蓝桥杯大赛软件赛省赛Python大学A组真题解析《更新中》

文章目录 试题A: 拼正方形(本题总分:5 分)解析答案试题B: 召唤数学精灵(本题总分:5 分)解析答案试题C: 数字诗意解析答案试题D:回文数组试题A: 拼正方形(本题总分:5 分) 【问题描述】 小蓝正在玩拼图游戏,他有7385137888721 个2 2 的方块和10470245 个1 1 的方块,他需…...

【2025年2月28日稳定版】小米路由器4C刷机Immortalwrt 23.05.4系统搭载mentohust 0.3.1插件全记录

小米路由器4C刷机Immortalwrt系统搭载mentohust插件全记录 首先将路由器按住后面的reset,用一个针插进去然后等待5s左右,松开,即可重置路由器。 然后要用物理网线物理连接路由器Lan口和电脑,并将路由器WAN口连接至网口。确保电脑…...

W3C标准和ES规范之一文通

W3C标准和ES规范之一文通 以下是关于W3C标准和ES规范的透彻解析,通过结构化对比和生活化类比帮助理解和记忆: 一、核心概念对比(总览) 维度W3C标准ES规范(ECMAScript)定位Web技术的建筑蓝图JavaScript的语…...

Linux:应用层协议

协议是一种 "约定". socket api的接口, 在读写数据时, 都是按 "字符串" 的方式来发送接收的. 如果我们要传输一些"结构化的数据" 怎么办呢? 无论我们采用什么方案, 只要保证, 一端发送时构造的数据, 在另一端能够正确的进行解析, 就是ok的. 这种…...

深度学习五大模型:CNN、Transformer、BERT、RNN、GAN详细解析

# 深度学习五虎将:当CNN遇见Transformer的奇幻漂流 ## 序章:AI江湖的兵器谱排行 2012年,多伦多大学的厨房里,Hinton的学生们用GPU煎了个"AlexNet"荷包蛋,从此开启了深度学习的热兵器时代。如今五大模型各显…...

微服务组件详解——sentinel

1.启动sentinel: 下载jar sentinel-dashboard-1.8.0.jar 使用以下命令直接运行 jar 包(JDK 版本必须≥ 1.8): java -Dserver.port9999 -jar D:\sentinel-dashboard-1.8.0.jar 控制台访问地址:http://localhost:9999…...

波导阵列天线 学习笔记11双极化全金属垂直公共馈电平板波导槽阵列天线

摘要: 本communicaition提出了一种双极化全金属垂直公共馈电平板波导槽阵列天线。最初提出了一种公共馈电的单层槽平板波导来实现双极化阵列。此设计消除了传统背腔公共馈电的复杂腔体边缘的必要性,提供了一种更简单的天线结构。在2x2子阵列种发展了宽十…...

swift 开发效率提升工具

安装github copliot for xcode github/CopilotForXcode brew install --cask github-copilot-for-xcode安装swiftformat for xcode brew install swiftformatXcode Swift File代码格式化-SwiftFormat...

3-5 WPS JS宏 工作表的移动与复制学习笔记

************************************************************************************************************** 点击进入 -我要自学网-国内领先的专业视频教程学习网站 *******************************************************************************************…...

Centos7部署k8s(单master节点安装)

单master节点部署k8s集群(Centos) 一、安装前准备 1、修改主机名 按照资源准备修改即可 # master01 hostnamectl set-hostname master01 ; bash # node1 hostnamectl set-hostname node1 ; bash # node2 hostnamectl set-hostname node2 ; bash2、修改hosts文件 以下命令所…...

Tomcat

1.Tomcat是什么? Tomcat 是一个开源的、轻量级的 Servlet 容器,也被称为 Web 服务器,由 Apache 软件基金会的 Jakarta 项目开发,在 Java Web 开发领域应用广泛。 1)Servlet 容器:Servlet 是 Java 语言编写…...

基于SpringBoot+Vue的电影订票及评论网站的设计与实现(源码+SQL脚本+LW+部署讲解等)

专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...

地基简识Spring MVC 组件

Spring MVC 是一个基于 MVC 设计模式的框架,其核心组件协同工作以处理 HTTP 请求并生成响应。以下是各组件的详细说明及其协作流程: 一、​核心组件 ​DispatcherServlet(前端控制器)​ ​作用:接收所有请求并协调其他…...

如何通过Python网络爬虫技术应对复杂的反爬机制?

要使用Python网络爬虫技术绕过复杂的反爬虫机制,可以采取以下几种策略: 设置User-Agent:通过设置不同的User-Agent,模拟正常用户的浏览器访问,避免被网站识别为爬虫。可以使用fake_useragent库来随机生成User-Agent。…...

深入浅出:Spring AI 集成 DeepSeek 构建智能应用

Spring AI 作为 Java 生态中备受瞩目的 AI 应用开发框架,凭借其简洁的 API 设计和强大的功能,为开发者提供了构建智能应用的强大工具。与此同时,DeepSeek 作为领先的 AI 模型服务提供商,在自然语言处理、计算机视觉等领域展现了卓…...

Node.js二:第一个Node.js应用

精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 创建的时候我们需要用到VS code编写代码 我们先了解下 Node.js 应用是由哪几部分组成的: 1.引入 required 模块:我们可以使用 requi…...

【HarmonyOS Next】鸿蒙状态管理装饰器V1和V2混用方案

【HarmonyOS Next】鸿蒙状态管理装饰器V1和V2混用方案 一、V1和V2为什么需要混用 自从api7开始,一直到api10。V1的实际使用中,开发人员发现Observed和ObjectLink 监听实现多层级嵌套对象的更新的方案,太过于臃肿。当需要监听处理更新的多层…...

【技海登峰】Kafka漫谈系列(三)详解Kafka的数据结构与存储机制

【技海登峰】Kafka漫谈系列(三)详解Kafka的数据结构与存储机制 Kafka 使用消息日志(Log)机制来持久化保存数据,我们知道Kafka实际是以Partition分区为单位进行负载均衡和资源分配,每个Partition又由多个Replica副本组成,副本之间分布于不同的Broker上来保证高可用,因此…...

PyCharm接入本地部署DeepSeek 实现AI编程!【支持windows与linux】

今天尝试在pycharm上接入了本地部署的deepseek,实现了AI编程,体验还是很棒的。下面详细叙述整个安装过程。 本次搭建的框架组合是 DeepSeek-r1:1.5b/7b Pycharm专业版或者社区版 Proxy AI(CodeGPT) 首先了解不同版本的deepsee…...

腾讯云扩容记录

腾讯云扩容: sudo yum install -y cloud-utils-growpart 安装扩容工具 sudo file -s /dev/vda1 有数据 sudo LC_ALLen_US.UTF-8 growpart /dev/vda 1 sudo resize2fs /dev/vda1 df -Th 完毕 以下是对执行的命令的详细解释以及背后的原理: 1. 安装 cloud…...

计算机毕业设计Hadoop+Spark+DeepSeek-R1大模型音乐推荐系统 音乐数据分析 音乐可视化 音乐爬虫 知识图谱 大数据毕业设计

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...

本地部署大语言模型-DeepSeek

DeepSeek 是国内顶尖 AI 团队「深度求索」开发的多模态大模型,具备数学推理、代码生成等深度能力,堪称"AI界的六边形战士"。 Hostease AMD 9950X/96G/3.84T NVMe/1G/5IP/RTX4090 GPU服务器提供多种计费模式。 DeepSeek-R1-32B配置 配置项 规…...

Windows逆向工程入门之MASM数据结构使用

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 第一章:MASM数据定义体系精要 1.1 基础数据类型全景 1.1.1 整型数据规范 1.1.2 浮点数据编码 1.2 复合数据结构 1.2.1 多维数组定义 1.2.2 复杂结构体 第二章&#xf…...

python 之协程笔记

协程 协程的本质是用户态线程,由程序自行控制切换时机,无需操作系统介入。与线程相比,协程的三大核心优势: 资源占用极低:一个协程仅需KB级内存,可轻松创建数万个切换效率惊人:上下文切换在用户…...

使用 REINFORCE 算法强化梯度策略

一、整体概述 此代码利用 REINFORCE 算法(一种基于策略梯度的强化学习算法)来解决 OpenAI Gym 中的 CartPole-v1 环境问题。CartPole-v1 环境的任务是控制一个小车,使连接在小车上的杆子保持平衡。代码通过构建一个神经网络作为策略网络&…...

【C++并发编程实战】第1章 你好,C++的并发世界!

文章目录 1. 何谓并发2. 为什么使用并发?3. 什么时候不使用并发4. C多线程历史5. 第一个并发程序 1. 何谓并发 最简单和最基本的并发,是指两个或更多独立的活动同时发生。计算机领域的并发指的是在单个系统里同时执行多个独立的任务,而非顺序的进行一些…...

【QT线程】子线程阻塞主线程的一次网络api请求案例

阻塞源码赏析 这是最近一次项目遇到的问题,原因是我觉得子线程里俩次请求间隔太短了,会引起服务器屏蔽我的api因此,我故作聪明加多了一个延时函数,欢迎各位鉴赏代码。 // 并行发起双请求 QNetworkRequest liveRequest(liveUrl);…...

DockerでOracle Database 23ai FreeをセットアップしMAX_STRING_SIZEを拡張する手順

DockerでOracle Database 23ai FreeをセットアップしMAX_STRING_SIZEを拡張する手順 はじめに環境準備ディレクトリ作成Dockerコンテナ起動 データベース設定変更コンテナ内でSQL*Plus起動PDB操作と文字列サイズ拡張設定検証 管理者ユーザー作成注意事項まとめ 中文版请访问这里…...

【计算机网络入门】初学计算机网络(五)

目录 1.编码&解码、调制&解调 2.常用编码方法 2.1 不归零编码(NRZ) 2.2 归零编码(RZ) 2.3 反向非归零编码(NRZI) 2.4 曼彻斯特编码 2.5 差分曼彻斯特编码 3. 各种编码的特点 4.调制 5.有线传输介质 5.1 双绞线 5.2 同轴电缆 5.3 光…...

unity学习60: 滑动条 和 滚动条 滚动区域

目录 1 滚动条 scrollbar 1.1 创建滚动条 1.2 scrollbar的子物体 1.3 scrollbar的属性 2 滚动视图 scroll View 2.1 创建1个scroll View 2.1.1 实际类比,网页就是一个 scroll view吧 2.2 子物体构成 2.3 核心component : Scroll Rect 3 可视区域 view p…...

【Linux网络-HTTP协议】HTTP基础概念+构建HTTP

代码定位:南毅c/Linux - Gitee.com HTTP协议 介绍 虽然我们说,应用层协议是我们程序猿自己定的.但实际上,已经有大佬们定义了一些现成的,又非常好用的应用层协议,供我们直接参考使用。HTTP(超文本传输协议)就是其中之一。 在互联网世界中&#xff0c…...

2025年企业网络安全实战指南:常见漏洞解析与全方位防御策略

2025年企业网络安全实战指南:常见漏洞解析与全方位防御策略 作者: 网络安全专家 日期: 2025-02-27 分类: [网络安全] 标签: [漏洞防护, 信息安全, 企业安全] 引言:漏洞是攻击者的入口,防御是安全的基石 2025年,网络安全威胁持续升级。根据Gartner最新报告,全球企业因漏洞…...

一个py文件搞定mysql查询+Json转换+表数据提取+根据数据条件生成excel文件+打包运行一条龙

import os import argparse import pymssql import json import pandas as pd from datetime import datetime from pandas.io.formats.excel import ExcelFormatter import openpyxl# 投注类型映射字典 BET_MAPPING {1: WIN, 2: PLA, 3: QIN, 4: QPL,5: DBL, 6: TCE, 7: QTT,…...