(pytorch复现)基于深度强化学习(CNN+dueling network/DQN/DDQN/D3QN/PER)的自适应车间调度(JSP)

为了深入学习各种深度学习网络和强化学习的结合,实现了一下下列文章:

Research on Adaptive Job Shop Scheduling Problems Based on Dueling Double DQN | IEEE Journals & Magazine | IEEE Xplore

状态、动作、奖励函数及实验的简单介绍可参考:

基于深度强化学习的自适应作业车间调度问题研究_松间沙路的博客-CSDN博客_强化学习调度

整体代码复现可见个人Github:Aihong-Sun/DQN-DDQN-Dueling_networ-D3QN-_for_JSP: pytorch implementation of DQN/DDQN/Dueling_networ/D3QN for job shop scheudling problem (github.com)

1 状态特征提取

首先从特征提取开始,原文的状态特征为3个网格矩阵,如下:

于是搭建CNN进行特征提取:

不太了解CNN的可以参考:卷积神经网络(CNN)详解 - 知乎 (zhihu.com)

self.conv1=nn.Sequential(
            nn.Conv2d(
                in_channels=3,  
                out_channels=6,
                kernel_size=3,
                stride=1,
                padding=1,  
            ),      # output shape (3,J_num,O_max_len)
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2,ceil_mode=False)  
        )

 1.1 卷积层

上诉状态可看作是长、宽为工件数、工件最大工序数(若不相等时取最大,但原文涉及的算例都为工序数相等),深度为3的一个图像,于是in_channels=3,out_channels可按自己的需求进行设计,这里我设为6,即有6个卷积核,输出的图像的深度就为6,为保证图片的长宽不变(便于后面针对不同工件数、工序数的全连接层的计算),用0在图像边缘处进行填充,计算方法如下:

假设Jnum=6,O_max_len=6,于是,令卷积核kernel_size=3,stride=1,padding=1,此时,W2=(6-3+2)/1+1=6,H2=(6-3+2)/1+1=6,于是图片大小没变。

1.2 池化层

它的作用是用来逐渐降低数据体的空间尺寸,这样的话就能减少网络中参数的数量,使得计算资源耗费变少,也能有效控制过拟合。

池化层使用 MAX 操作,对输入数据体的每一个深度切片独立进行操作,改变它的空间尺寸。最常见的形式是汇聚层使用尺寸2x2的滤波器,以步长为2来对每个深度切片进行降采样。

这里设置kernel_size=2,即对图像缩小一般,ceil_mode=False,即针对工件为奇数的情况,比如Jnum=7,Omax_len=7,图像缩小边缘的数则不取,于是生成新的图像大小为(3,3),若ceil_mode=False,生成新的图像大小则为(4,4).

2 动作

动作为17条规则,具体可见上诉给出的个人Github

3DQN/DDQN/Dueling Network/D3QN

3.1 DQN与DDQN

下面第一个式子为DQN的目标函数,第二个式子为DDQN的目标函数:

DDQN与DQN大部分都相同,只有一步不同,那就是在选择Q(s_{t+1},a_{t+1})的过程中,DQN总是选择Target Q网络的最大输出值。而DDQN不同,DDQN首先从Q网络中找到最大输出值的那个动作,然后再找到这个动作对应的Target Q网络的输出值。这么做的原因是传统的DQN通常会高估Q值得大小,两者代码差别如下:

        q_eval = self.eval_net(batch_state).gather(1, batch_action) 
        q_next = self.target_net(batch_next_state).detach()
        if self.double:                   #ddqn
            q_next_eval=self.eval_net( batch_next_state).detach()
            q_a=q_next_eval.argmax(dim=1)
            q_a=torch.reshape(q_a,(-1,len(q_a)))
            q_target = batch_reward + self.GAMMA * q_next.gather(1, q_a)
        else:          #dqn
            q_target = batch_reward + self.GAMMA * q_next.max(1)[0]

3.2 DQN 与Dueling Network

Dueling network 是一篇来自2015年的论文,这篇论文提出了一个新的网络架构,这个架构不但提高了最终效果,而且还可以和其他的算法相结合以获取更加优异的表现。

之前的DQN网络在将图片卷积获取特征之后会输入几个全连接层,经过训练直接输出在该state下各个action的价值也就是Q(s,a)。而Dueling network则不同,它在卷积网络之后引出了两个不同的分支,一个分支用于预测state的价值,另一个用于预测每个action的优势。最后将这两个分支的结果合并输出Q(s,a),两者的网络结构如下(上为DQN,下为Dueling network)

代码上的区别:

DQN:

class DQN(nn.Module):
    """docstring for Net"""
    def __init__(self,J_num,O_max_len):
        super(CNN_FNN, self).__init__()
        self.conv1 = nn.Sequential(
            nn.Conv2d(
                in_channels=3,  # input shape (3,J_num,O_max_len)
                out_channels=6,
                kernel_size=3,
                stride=1,
                padding=1,  # 使得出来的图片大小不变P=(3-1)/2,
            ),  # output shape (3,J_num,O_max_len)
            nn.ReLU(),
            # nn.MaxPool2d(kernel_size=2, ceil_mode=True)  # output shape:  (6,int(J_num/2),int(O_max_len/2))
        )
        # summary(self.conv1,(3,6,6))
        self.fc1 = nn.Linear(6*J_num*O_max_len, 258)
       
  • 23
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码丽莲梦露

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值