[PyTorch][chapter 64][强化学习-DQN]

news2024/11/18 13:58:39

前言:

            DQN 就是结合了深度学习和强化学习的一种算法,最初是 DeepMind 在 NIPS 2013年提出,它的核心利润包括马尔科夫决策链以及贝尔曼公式。

            Q-learning的核心在于Q表格,通过建立Q表格来为行动提供指引,但这适用于状态和动作空间是离散且维数不高时,当状态和动作空间是高维连续时Q表格将变得十分巨大,对于维护Q表格和查找都是不现实的。


1: DQN 历史

2:  DQN 网络参数配置

3:DQN 网络模型搭建


一 DQN 历史

     DQN 跟机器学习的时序差分学习里面的Q-Learning 算法相似

    1.1 Q-Learning 算法

在Q Learning 中,我们有个Q table ,记录不同状态下,各个动作的Q 值

我们通过Q table 更新当前的策略

Q table 的作用: 是我们输入S,通过查表返回能够获得最大Q值的动作A.

但是很多场景状态S 并不是离散的,很难去定义

 1.2  DQN 发展史

     Deep network+Q-learning = DQN

     DQN 和 Q-tabel 没有本质区别:

     Q-table: 内部维护 Q Tabel

     DQN:   通过神经网络  a= NN(s), 替代了 Q Tabel

   


二 网络模型

    2.1 DQN 算法

  2.1 模型

模型参数


三  代码实现:

 5.1 main.py

   

# -*- coding: utf-8 -*-
"""
Created on Fri Nov 17 16:53:02 2023

@author: chengxf2
"""

import numpy as np
import torch
import gym
import random 
from Replaybuffer import Replay
from Agent import DQN
import rl_utils
import matplotlib.pyplot as plt
from tqdm import tqdm  #生成进度条

lr = 5e-3
hidden_dim = 128
num_episodes = 500
minimal_size = 500
gamma = 0.98
epsilon =0.01
target_update = 10
buffer_size = 10000
mini_size = 500
batch_size = 64
device = torch.device("cuda") if torch.cuda.is_available() else torch.device(
    "cpu")




if __name__ == "__main__":
    env_name = 'CartPole-v0'
    env = gym.make(env_name)
    random.seed(0)
    np.random.seed(0)
    env.seed(0)
    torch.manual_seed(0)
    replay_buffer = Replay(buffer_size)
    state_dim = env.observation_space.shape[0]
    action_dim = env.action_space.n
    agent = DQN(state_dim, hidden_dim, action_dim, lr, gamma, epsilon,
                target_update, device)
    
    return_list = []
    for i in range(10):
        with tqdm(total=int(num_episodes / 10), desc='Iteration %d' % i) as pbar:
            for i_episode in range(int(num_episodes / 10)):
                
                episode_return = 0
                state = env.reset()
                done = False
                
                while not done:
                    action = agent.take_action(state)
                    next_state, reward, done, _ = env.step(action)
                    replay_buffer.add(state, action, reward, next_state, done)
                    state = next_state
                    episode_return += reward
                    # 当buffer数据的数量超过一定值后,才进行Q网络训练
                    if replay_buffer.size() > minimal_size:
                        b_s, b_a, b_r, b_ns, b_d = replay_buffer.sample(batch_size)
                        transition_dict = {
                            'states': b_s,
                            'actions': b_a,
                            'next_states': b_ns,
                            'rewards': b_r,
                            'dones': b_d
                        }
                        agent.update(transition_dict)
                return_list.append(episode_return)
                if (i_episode + 1) % 10 == 0:
                    pbar.set_postfix({
                        'episode':
                        '%d' % (num_episodes / 10 * i + i_episode + 1),
                        'return':
                        '%.3f' % np.mean(return_list[-10:])
                    })
                pbar.update(1)
                
    episodes_list = list(range(len(return_list)))
    plt.figure(1) 
    plt.subplot(1, 2, 1)  # fig.1是一个一行两列布局的图,且现在画的是左图
    plt.plot(episodes_list, return_list,c='r')
    plt.xlabel('Episodes')
    plt.ylabel('Returns')
    plt.title('DQN on {}'.format(env_name))
   
    plt.figure(1)  # 当前要处理的图为fig.1,而且当前图是fig.1的左图
    plt.subplot(1, 2, 2)  # 当前图变为fig.1的右图
    mv_return = rl_utils.moving_average(return_list, 9)
    plt.plot(episodes_list, mv_return,c='g')
    plt.xlabel('Episodes')
    plt.ylabel('Returns')
    plt.title('DQN on {}'.format(env_name))
    plt.show()

5.2  Agent.py

# -*- coding: utf-8 -*-
"""
Created on Fri Nov 17 16:00:46 2023

@author: chengxf2
"""

import random 
import numpy as np
from   torch import nn
import torch
import torch.nn.functional as F




class QNet(torch.nn.Module):
    
    
    def __init__(self, state_dim, hidden_dim, action_dim):
        
        
        super(QNet, self).__init__()
        
        self.net = nn.Sequential(
            nn.Linear(state_dim, hidden_dim),
            nn.Linear(hidden_dim, action_dim)
            )
    
    def forward(self, state):
        
        qvalue = self.net(state)
        
        return qvalue
    

class  DQN:
    
       def __init__(self,state_dim, hidden_dim, action_dim,learning_rate,
                    discount, epsilon, target_update, device
                    ):
           
           self.action_dim = action_dim
           self.q_net = QNet(state_dim, hidden_dim, action_dim).to(device)
           self.target_q_net = QNet(state_dim, hidden_dim, action_dim).to(device)
           
           #Adam 优化器
           self.optimizer = torch.optim.Adam(self.q_net.parameters(),
                                          lr=learning_rate)
           
           self.gamma = discount #折扣因子
           self.epsilon = epsilon  # e-贪心算法
           self.target_update = target_update  # 目标网络更新频率
           self.device = device
           self.count = 0 #计数器
       
       def  take_action(self, state):
           
           rnd = np.random.random() #产生随机数
           
           if rnd <self.epsilon:
               
               action = np.random.randint(0, self.action_dim)
           
           else:
                state = torch.tensor([state], dtype=torch.float).to(self.device)
                qvalue = self.q_net(state)
                
                action = qvalue.argmax().item()
           return action
       
        
       def update(self, data):
           
           states = torch.tensor(data['states'],
                              dtype=torch.float).to(self.device)
           actions = torch.tensor(data['actions']).view(-1, 1).to(
            self.device)
           rewards = torch.tensor(data['rewards'],
                               dtype=torch.float).view(-1, 1).to(self.device)
           next_states = torch.tensor(data['next_states'],
                                   dtype=torch.float).to(self.device)
           dones = torch.tensor(data['dones'],
                             dtype=torch.float).view(-1, 1).to(self.device)
           #从完整数据中按索引取值[64]
           #print("\n actions ",actions,actions.shape)
           
           q_value = self.q_net(states).gather(1,actions) #Q值
           
           #下一个状态的Q值
           max_next_q_values = self.target_q_net(next_states).max(1)[0].view(-1,1)
           q_targets = rewards + self.gamma * max_next_q_values * (1 - dones)
           
           loss = F.mse_loss(q_value, q_targets)
           loss = torch.mean(loss)
           
           self.optimizer.zero_grad()
           loss.backward()
           self.optimizer.step()
           
           
           if self.count %self.target_update  ==0:
               #更新目标网络
               self.target_q_net.load_state_dict(
                   self.q_net.state_dict()
                   )
           self.count +=1
           
           
    
    

 5.3 Replaybuffer.py

   

# -*- coding: utf-8 -*-
"""
Created on Fri Nov 17 15:50:07 2023

@author: chengxf2
"""

import collections 
import random 
import numpy as np
class Replay:
    
    
    def __init__(self, capacity):
        #双向队列,可以在队列的两端任意添加或删除元素。
        self.buffer = collections.deque(maxlen = capacity)
    
    
    def add(self, state, action ,reward, next_state, done):
        #数据加入buffer
        self.buffer.append((state,action,reward, next_state, done))
        
    
    def sample(self, batch_size):
        #采样数据
        data = random.sample(self.buffer, batch_size)
        
        state,action, reward, next_state,done = zip(*data)
        
        return np.array(state), action, reward, np.array(next_state), done
    
    
    def size(self):
        
        return len(self.buffer)

        

 5.4 rl_utils.py

from tqdm import tqdm
import numpy as np
import torch
import collections
import random

class ReplayBuffer:
    def __init__(self, capacity):
        self.buffer = collections.deque(maxlen=capacity) 

    def add(self, state, action, reward, next_state, done): 
        self.buffer.append((state, action, reward, next_state, done)) 

    def sample(self, batch_size): 
        transitions = random.sample(self.buffer, batch_size)
        state, action, reward, next_state, done = zip(*transitions)
        return np.array(state), action, reward, np.array(next_state), done 

    def size(self): 
        return len(self.buffer)

def moving_average(a, window_size):
    cumulative_sum = np.cumsum(np.insert(a, 0, 0)) 
    middle = (cumulative_sum[window_size:] - cumulative_sum[:-window_size]) / window_size
    r = np.arange(1, window_size-1, 2)
    begin = np.cumsum(a[:window_size-1])[::2] / r
    end = (np.cumsum(a[:-window_size:-1])[::2] / r)[::-1]
    return np.concatenate((begin, middle, end))

def train_on_policy_agent(env, agent, num_episodes):
    return_list = []
    for i in range(10):
        with tqdm(total=int(num_episodes/10), desc='Iteration %d' % i) as pbar:
            for i_episode in range(int(num_episodes/10)):
                episode_return = 0
                transition_dict = {'states': [], 'actions': [], 'next_states': [], 'rewards': [], 'dones': []}
                state = env.reset()
                done = False
                while not done:
                    action = agent.take_action(state)
                    next_state, reward, done, _ = env.step(action)
                    transition_dict['states'].append(state)
                    transition_dict['actions'].append(action)
                    transition_dict['next_states'].append(next_state)
                    transition_dict['rewards'].append(reward)
                    transition_dict['dones'].append(done)
                    state = next_state
                    episode_return += reward
                return_list.append(episode_return)
                agent.update(transition_dict)
                if (i_episode+1) % 10 == 0:
                    pbar.set_postfix({'episode': '%d' % (num_episodes/10 * i + i_episode+1), 'return': '%.3f' % np.mean(return_list[-10:])})
                pbar.update(1)
    return return_list

def train_off_policy_agent(env, agent, num_episodes, replay_buffer, minimal_size, batch_size):
    return_list = []
    for i in range(10):
        with tqdm(total=int(num_episodes/10), desc='Iteration %d' % i) as pbar:
            for i_episode in range(int(num_episodes/10)):
                episode_return = 0
                state = env.reset()
                done = False
                while not done:
                    action = agent.take_action(state)
                    next_state, reward, done, _ = env.step(action)
                    replay_buffer.add(state, action, reward, next_state, done)
                    state = next_state
                    episode_return += reward
                    if replay_buffer.size() > minimal_size:
                        b_s, b_a, b_r, b_ns, b_d = replay_buffer.sample(batch_size)
                        transition_dict = {'states': b_s, 'actions': b_a, 'next_states': b_ns, 'rewards': b_r, 'dones': b_d}
                        agent.update(transition_dict)
                return_list.append(episode_return)
                if (i_episode+1) % 10 == 0:
                    pbar.set_postfix({'episode': '%d' % (num_episodes/10 * i + i_episode+1), 'return': '%.3f' % np.mean(return_list[-10:])})
                pbar.update(1)
    return return_list


def compute_advantage(gamma, lmbda, td_delta):
    td_delta = td_delta.detach().numpy()
    advantage_list = []
    advantage = 0.0
    for delta in td_delta[::-1]:
        advantage = gamma * lmbda * advantage + delta
        advantage_list.append(advantage)
    advantage_list.reverse()
    return torch.tensor(advantage_list, dtype=torch.float)
                

DQN 算法
遇强则强(八):从Q-table到DQN - 知乎使用Pytorch实现强化学习——DQN算法_dqn pytorch-CSDN博客

https://www.cnblogs.com/xiaohuiduan/p/12993691.html

https://www.cnblogs.com/xiaohuiduan/p/12945449.html

强化学习第五节(DQN)【个人知识分享】_哔哩哔哩_bilibili

CSDN

组会讲解强化学习的DQN算法_哔哩哔哩_bilibili

3-ε-greedy_ReplayBuffer_FixedQ-targets_哔哩哔哩_bilibili

4-代码实战DQN_Agent和Env整体交互_哔哩哔哩_bilibili

DQN基本概念和算法流程(附Pytorch代码) - 知乎

CSDN

DQN 算法

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

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

相关文章

现货黄金区间交易的两个要点

在现货黄金市场中&#xff0c;我们常碰到横盘区间行情。有区间&#xff0c;就终究会出现突破&#xff0c;因为金价不可能缺乏方向而一直在区间内运行。那既然要突破&#xff0c;我们又应当如何应对和交易呢&#xff1f;下面我们就来讨论一下。 切忌在突破发生时马上跟随突破方向…

EI期刊完整程序:MEA-BP思维进化法优化BP神经网络的回归预测算法,可作为对比预测模型,丰富内容,直接运行,免费

适用平台&#xff1a;Matlab 2020及以上 本程序参考中文EI期刊《基于MEA⁃BP神经网络的建筑能耗预测模型》&#xff0c;程序注释清晰&#xff0c;干货满满&#xff0c;下面对文章和程序做简要介绍。 适用领域&#xff1a;风速预测、光伏功率预测、发电功率预测、碳价预测等多…

leetcode刷题详解三

2. 两数相加 思路&#xff1a;直接加&#xff0c;注意进位条件不要用if&#xff0c;核心代码在于sum l1->val l2->val carry; ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {ListNode* dummy new ListNode();ListNode* dummy_head dummy;int carry 0;int …

OSG编程指南<十>:OSG几何体的绘制

1、场景基本绘图类 在 OSG 中创建几何体的方法比较简单&#xff0c;通常有 3 种处理几何体的手段&#xff1a; 使用松散封装的OpenGL 绘图基元&#xff1b;使用 OSG 中的基本几何体&#xff1b;从文件中导入场景模型。 使用松散封装的OpenGL 绘图基元绘制几何体具有很强的灵活…

完美解决:vue.js:6 TypeError: Cannot read properties of undefined (reading ‘0‘)

Vue项目出现以下报错&#xff1a; 原因&#xff1a; 在渲染的时候&#xff0c;不满足某个条件而报错&#xff0c;或者某个属性丢失或后台没传过来导致 我这里出现的原因是后台给我传递过来的数组中&#xff0c;其中有一条少传了一个我在渲染时需要用的属性&#xff0c;没让后台…

毅速:3D打印随形透气钢为解决模具困气提供了新助力

在模具行业中&#xff0c;困气是一个较常见的问题。解决困气问题的方法有很多&#xff0c;透气钢就是其一。传统的制造的透气钢往往存在一些不足&#xff0c;如加工难度大、无法满足复杂形状的需求等。随着3D打印技术的发展&#xff0c;一种新型的随形透气钢技术逐渐崭露头角&a…

HBase数据模型杂谈

1.概述 HBase是一个稀疏、多维度、排序的映射表&#xff0c;这张表的索引是行键、列族、列限定符和时间戳。 每个值是一个未经解释的字符串&#xff0c;没有数据类型。用户在表中存储数据&#xff0c;每一行都有一个可排序的行键和任意多的列。表在水平方向由一个或者多个列族…

【Jenkins】jenkins发送邮件报错:Not sent to the following valid addresses:

jenkins报错未能发送邮件到指定邮箱 注意&#xff1a;这是在系统配置中修改 在系统配置》邮件通知中添加配置信息 注意&#xff1a;这个是在项目的配置下修改 配置完成后&#xff0c;重新执行发送邮件成功&#xff01;&#xff01;&#xff01;

AI动画制作 StableDiffusion

1.brew -v 2.安装爬虫项目包所必需的python和git等系列系统支持部件 brew install cmake protobuf rust python3.10 git wget pod --version brew link --overwrite cocoapods 3.从github网站克隆stable-diffusion-webui爬虫项目包至本地 ssh-add /Users/haijunyan/.ssh/id_rs…

API 设计:使用 Node.js 和 Express.js 的综合教程

API&#xff08;应用程序编程接口&#xff09;设计涉及创建一个高效而强大的接口&#xff0c;允许不同的软件应用程序相互交互。 说明 本教程将指导您使用 Node.js 和 Express.js 作为核心技术来规划、设计和构建 API。但是&#xff0c;这些原则可以应用于任何语言或框架。我们…

NX二次开发UF_CURVE_ask_curve_inflections 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_ask_curve_inflections Defined in: uf_curve.h int UF_CURVE_ask_curve_inflections(tag_t curve_eid, double proj_matrx [ 9 ] , double range [ 2 ] , int * num_infpt…

手写一个简单版的Spring

1. 创建一个工程及初始化 创建Java工程 创建对应的包 config&#xff1a;为配置类包 service&#xff1a;定义的将要被自己写的Spring容器管理的组件bean spring&#xff1a;里面定义自己写的Spring的类文件&#xff0c;包含子包anno注解包 test&#xff1a;定义测试类 2.…

生物识别访问面临风险

安全公司 Blackwing Intelligence 发现了多个允许您绕过Windows Hello 身份验证的漏洞。 戴尔 Inspiron 灵越 15、联想 ThinkPad T14 和 Microsoft Surface Pro X笔记本电脑上会出现这种情况&#xff0c;原因是设备中集成了来自Goodix、Synaptics 和 ELAN的指纹传感器。 所有…

C#,数值计算——插值和外推,Powvargram的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// Functor for variogram v(r)ar^b, /// where b is specified, a is fitted from the data. /// </summary> public class Powvargram { private do…

情感对话机器人的任务体系

人类在处理对话中的情感时&#xff0c;需要先根据对话场景中的蛛丝马迹判断出对方的情感&#xff0c;继而根据对话的主题等信息思考自身用什么情感进行回复&#xff0c;最后结合推理出的情感形成恰当的回复。受人类处理情感对话的启发&#xff0c;情感对话机器人需要完成以下几…

在新疆乌鲁木齐的汽车托运

在新疆乌鲁木齐要托运的宝! 看过来了 找汽车托运公司了 连夜吐血给你们整理了攻略!! ⬇️以下&#xff1a; 1 网上搜索 可以在搜索引擎或专业的货运平台上搜索相关的汽车托运公司信息。在网站上可以了解到公司的服务范围、托运价格、运输时效等信息&#xff0c;也可以参考其他车…

Ubuntu中安装搜狗输入法教程(详细图文教程)

习惯了使用搜狗输入法&#xff0c;这里总结了Ubuntu系统下安装搜狗输入法的详细教程&#xff0c;每个步骤都很详细&#xff0c;耐心安装。 搜狗输入法是一款功能强大、使用方便的输入法&#xff0c;能够有效提升用户在Ubuntu系统中的输入体验。 目录 一、下载搜狗安装包1.1 搜…

SpringCloud原理-OpenFeign篇(四、请求原理)

文章目录 前言正文一、书接上回&#xff0c;从代理对象入手二、ReflectiveFeign.FeignInvocationHandler#invoke()三、SynchronousMethodHandler#invoke(...) 的实现原理3.1 invoke(...)源码3.2 executeAndDecode(...) 执行请求并解码 四、如何更换client 的实现 附录附1&#…

【精选】框架初探篇之——MyBatis的CRUD及配置文件

MyBatis增删改查 MyBatis新增 新增用户 持久层接口添加方法 void add(User user);映射文件添加标签 <insert id"add" parameterType"com.mybatis.pojo.User">insert into user(username,sex,address) values(# {username},# {sex},# {address}) <…

NX二次开发UF_CURVE_ask_joined_parms 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_ask_joined_parms Defined in: uf_curve.h int UF_CURVE_ask_joined_parms(tag_t joined_curve_feature, UF_STRING_p_t uf_curve_string, int * creation_method, double …