强化学习从基础到进阶--案例与实践[7.1]:深度确定性策略梯度DDPG算法、双延迟深度确定性策略梯度TD3算法详解项目实战

news2024/11/18 8:10:42

在这里插入图片描述
【强化学习原理+项目专栏】必看系列:单智能体、多智能体算法原理+项目实战、相关技巧(调参、画图等、趣味项目实现、学术应用项目实现

在这里插入图片描述
专栏详细介绍:【强化学习原理+项目专栏】必看系列:单智能体、多智能体算法原理+项目实战、相关技巧(调参、画图等、趣味项目实现、学术应用项目实现

对于深度强化学习这块规划为:

  • 基础单智能算法教学(gym环境为主)
  • 主流多智能算法教学(gym环境为主)
    • 主流算法:DDPG、DQN、TD3、SAC、PPO、RainbowDQN、QLearning、A2C等算法项目实战
  • 一些趣味项目(超级玛丽、下五子棋、斗地主、各种游戏上应用)
  • 单智能多智能题实战(论文复现偏业务如:无人机优化调度、电力资源调度等项目应用)

本专栏主要方便入门同学快速掌握强化学习单智能体|多智能体算法原理+项目实战。后续会持续把深度学习涉及知识原理分析给大家,让大家在项目实操的同时也能知识储备,知其然、知其所以然、知何由以知其所以然。

声明:部分项目为网络经典项目方便大家快速学习,后续会不断增添实战环节(比赛、论文、现实应用等)

  • 专栏订阅(个性化选择):

    • 强化学习原理+项目专栏大合集-《推荐订阅☆☆☆☆☆》

    • 强化学习单智能体算法原理+项目实战《推荐订阅☆☆☆☆》

    • 强化学习多智能体原理+项目实战《推荐订阅☆☆☆☆☆》

    • 强化学习相关技巧(调参、画图等《推荐订阅☆☆☆》)

    • tensorflow_gym-强化学习:免费《推荐订阅☆☆☆☆》

    • 强化学习从基础到进阶-案例与实践:免费《推荐订阅☆☆☆☆☆》

强化学习从基础到进阶–案例与实践[7.1]:深度确定性策略梯度DDPG算法、双延迟深度确定性策略梯度TD3算法详解项目实战

项目链接fork一下直接运行

https://www.heywhale.com/mw/project/649afec770567260f8b79b26

全系列代码包见文章顶部

1、定义算法

1.1 定义模型

!pip uninstall -y parl
!pip install parl
import parl
import paddle
import paddle.nn as nn
import paddle.nn.functional as F
class Actor(parl.Model):
    def __init__(self, n_states, n_actions):
        super(Actor, self).__init__()

        self.l1 = nn.Linear(n_states, 400)
        self.l2 = nn.Linear(400, 300)
        self.l3 = nn.Linear(300, n_actions)

    def forward(self, state):
        x = F.relu(self.l1(state))
        x = F.relu(self.l2(x))
        return paddle.tanh(self.l3(x))

class Critic(parl.Model):
    def __init__(self, n_states, n_actions):
        super(Critic, self).__init__()

        self.l1 = nn.Linear(n_states, 400)
        self.l2 = nn.Linear(400 + n_actions, 300)
        self.l3 = nn.Linear(300, 1)

    def forward(self, state, action):
        x = F.relu(self.l1(state))
        x = F.relu(self.l2(paddle.concat([x, action], 1)))
        return self.l3(x)
class ActorCritic(parl.Model):
    def __init__(self, n_states, n_actions):
        super(ActorCritic, self).__init__()
        self.actor_model = Actor(n_states, n_actions)
        self.critic_model = Critic(n_states, n_actions)

    def policy(self, state):
        return self.actor_model(state)

    def value(self, state, action):
        return self.critic_model(state, action)

    def get_actor_params(self):
        return self.actor_model.parameters()

    def get_critic_params(self):
        return self.critic_model.parameters()

1.2 定义经验回放

from collections import deque
import random
class ReplayBuffer:
    def __init__(self, capacity: int) -> None:
        self.capacity = capacity
        self.buffer = deque(maxlen=self.capacity)
    def push(self,transitions):
        '''_summary_
        Args:
            trainsitions (tuple): _description_
        '''
        self.buffer.append(transitions)
    def sample(self, batch_size: int, sequential: bool = False):
        if batch_size > len(self.buffer):
            batch_size = len(self.buffer)
        if sequential: # sequential sampling
            rand = random.randint(0, len(self.buffer) - batch_size)
            batch = [self.buffer[i] for i in range(rand, rand + batch_size)]
            return zip(*batch)
        else:
            batch = random.sample(self.buffer, batch_size)
            return zip(*batch)
    def clear(self):
        self.buffer.clear()
    def __len__(self):
        return len(self.buffer)

1.3 定义智能体

import parl
import paddle
import numpy as np


class DDPGAgent(parl.Agent):
    def __init__(self, algorithm,memory,cfg):
        super(DDPGAgent, self).__init__(algorithm)
        self.n_actions = cfg['n_actions']
        self.expl_noise = cfg['expl_noise']
        self.batch_size = cfg['batch_size'] 
        self.memory = memory
        self.alg.sync_target(decay=0)

    def sample_action(self, state):
        action_numpy = self.predict_action(state)
        action_noise = np.random.normal(0, self.expl_noise, size=self.n_actions)
        action = (action_numpy + action_noise).clip(-1, 1)
        return action

    def predict_action(self, state):
        state = paddle.to_tensor(state.reshape(1, -1), dtype='float32')
        action = self.alg.predict(state)
        action_numpy = action.cpu().numpy()[0]
        return action_numpy

    def update(self):
        if len(self.memory) < self.batch_size: 
            return
        state_batch, action_batch, reward_batch, next_state_batch, done_batch = self.memory.sample(
            self.batch_size)
        done_batch = np.expand_dims(done_batch , -1)
        reward_batch = np.expand_dims(reward_batch, -1)
        state_batch = paddle.to_tensor(state_batch, dtype='float32')
        action_batch = paddle.to_tensor(action_batch, dtype='float32')
        reward_batch = paddle.to_tensor(reward_batch, dtype='float32')
        next_state_batch = paddle.to_tensor(next_state_batch, dtype='float32')
        done_batch = paddle.to_tensor(done_batch, dtype='float32')
        critic_loss, actor_loss = self.alg.learn(state_batch, action_batch, reward_batch, next_state_batch,
                                                 done_batch)

2. 定义训练

def train(cfg, env, agent):
    ''' 训练
    '''
    print(f"开始训练!")
    rewards = []  # 记录所有回合的奖励
    for i_ep in range(cfg["train_eps"]):
        ep_reward = 0  
        state = env.reset()  
        for i_step in range(cfg['max_steps']):
            action = agent.sample_action(state) # 采样动作
            next_state, reward, done, _ = env.step(action)  
            agent.memory.push((state, action, reward,next_state, done)) 
            state = next_state  
            agent.update()  
            ep_reward += reward  
            if done:
                break
        rewards.append(ep_reward)
        if (i_ep + 1) % 10 == 0:
            print(f"回合:{i_ep+1}/{cfg['train_eps']},奖励:{ep_reward:.2f}")
    print("完成训练!")
    env.close()
    res_dic = {'episodes':range(len(rewards)),'rewards':rewards}
    return res_dic

def test(cfg, env, agent):
    print("开始测试!")
    rewards = []  # 记录所有回合的奖励
    for i_ep in range(cfg['test_eps']):
        ep_reward = 0  
        state = env.reset()  
        for i_step in range(cfg['max_steps']):
            action = agent.predict_action(state) 
            next_state, reward, done, _ = env.step(action)  
            state = next_state  
            ep_reward += reward 
            if done:
                break
        rewards.append(ep_reward)
        print(f"回合:{i_ep+1}/{cfg['test_eps']},奖励:{ep_reward:.2f}")
    print("完成测试!")
    env.close()
    return {'episodes':range(len(rewards)),'rewards':rewards}

3、定义环境

OpenAI Gym中其实集成了很多强化学习环境,足够大家学习了,但是在做强化学习的应用中免不了要自己创建环境,比如在本项目中其实不太好找到Qlearning能学出来的环境,Qlearning实在是太弱了,需要足够简单的环境才行,因此本项目写了一个环境,大家感兴趣的话可以看一下,一般环境接口最关键的部分即使reset和step。

import gym
import os
import paddle
import numpy as np
import random
from parl.algorithms import DDPG
class NormalizedActions(gym.ActionWrapper):
    ''' 将action范围重定在[0.1]之间
    '''
    def action(self, action):
        low_bound   = self.action_space.low
        upper_bound = self.action_space.high
        action = low_bound + (action + 1.0) * 0.5 * (upper_bound - low_bound)
        action = np.clip(action, low_bound, upper_bound)
        return action

    def reverse_action(self, action):
        low_bound   = self.action_space.low
        upper_bound = self.action_space.high
        action = 2 * (action - low_bound) / (upper_bound - low_bound) - 1
        action = np.clip(action, low_bound, upper_bound)
        return action
def all_seed(env,seed = 1):
    ''' 万能的seed函数
    '''
    env.seed(seed) # env config
    np.random.seed(seed)
    random.seed(seed)
    paddle.seed(seed)
def env_agent_config(cfg):
    env = NormalizedActions(gym.make(cfg['env_name'])) # 装饰action噪声
    if cfg['seed'] !=0:
        all_seed(env,seed=cfg['seed'])
    n_states = env.observation_space.shape[0]
    n_actions = env.action_space.shape[0]
    print(f"状态维度:{n_states},动作维度:{n_actions}")
    cfg.update({"n_states":n_states,"n_actions":n_actions}) # 更新n_states和n_actions到cfg参数中
    memory = ReplayBuffer(cfg['memory_capacity'])
    model = ActorCritic(n_states, n_actions)
    algorithm = DDPG(model, gamma=cfg['gamma'], tau=cfg['tau'], actor_lr=cfg['actor_lr'], critic_lr=cfg['critic_lr'])
    agent = DDPGAgent(algorithm,memory,cfg)
    return env,agent

4、设置参数

到这里所有qlearning模块就算完成了,下面需要设置一些参数,方便大家“炼丹”,其中默认的是笔者已经调好的~。另外为了定义了一个画图函数,用来描述奖励的变化。

import argparse
import matplotlib.pyplot as plt
import seaborn as sns
def get_args():
    """ 超参数
    """
    parser = argparse.ArgumentParser(description="hyperparameters")      
    parser.add_argument('--algo_name',default='DDPG',type=str,help="name of algorithm")
    parser.add_argument('--env_name',default='Pendulum-v0',type=str,help="name of environment")
    parser.add_argument('--train_eps',default=200,type=int,help="episodes of training")
    parser.add_argument('--test_eps',default=20,type=int,help="episodes of testing")
    parser.add_argument('--max_steps',default=100000,type=int,help="steps per episode, much larger value can simulate infinite steps")
    parser.add_argument('--gamma',default=0.99,type=float,help="discounted factor")
    parser.add_argument('--critic_lr',default=1e-3,type=float,help="learning rate of critic")
    parser.add_argument('--actor_lr',default=1e-4,type=float,help="learning rate of actor")
    parser.add_argument('--memory_capacity',default=80000,type=int,help="memory capacity")
    parser.add_argument('--expl_noise',default=0.1,type=float)
    parser.add_argument('--batch_size',default=128,type=int)
    parser.add_argument('--target_update',default=2,type=int)
    parser.add_argument('--tau',default=1e-2,type=float)
    parser.add_argument('--critic_hidden_dim',default=256,type=int)
    parser.add_argument('--actor_hidden_dim',default=256,type=int)
    parser.add_argument('--device',default='cpu',type=str,help="cpu or cuda")  
    parser.add_argument('--seed',default=1,type=int,help="random seed")
    args = parser.parse_args([])    
    args = {**vars(args)} # 将args转换为字典  
    # 打印参数
    print("训练参数如下:")
    print(''.join(['=']*80))
    tplt = "{:^20}\t{:^20}\t{:^20}"
    print(tplt.format("参数名","参数值","参数类型"))
    for k,v in args.items():
        print(tplt.format(k,v,str(type(v))))   
    print(''.join(['=']*80))                  
    return args
def smooth(data, weight=0.9):  
    '''用于平滑曲线,类似于Tensorboard中的smooth

    Args:
        data (List):输入数据
        weight (Float): 平滑权重,处于0-1之间,数值越高说明越平滑,一般取0.9

    Returns:
        smoothed (List): 平滑后的数据
    '''
    last = data[0]  # First value in the plot (first timestep)
    smoothed = list()
    for point in data:
        smoothed_val = last * weight + (1 - weight) * point  # 计算平滑值
        smoothed.append(smoothed_val)                    
        last = smoothed_val                                
    return smoothed

def plot_rewards(rewards,cfg,path=None,tag='train'):
    sns.set()
    plt.figure()  # 创建一个图形实例,方便同时多画几个图
    plt.title(f"{tag}ing curve on {cfg['device']} of {cfg['algo_name']} for {cfg['env_name']}")
    plt.xlabel('epsiodes')
    plt.plot(rewards, label='rewards')
    plt.plot(smooth(rewards), label='smoothed')
    plt.legend()

5、训练

# 获取参数
cfg = get_args() 
# 训练
env, agent = env_agent_config(cfg)
res_dic = train(cfg, env, agent)
 
plot_rewards(res_dic['rewards'], cfg, tag="train")  
# 测试
res_dic = test(cfg, env, agent)
plot_rewards(res_dic['rewards'], cfg, tag="test")  # 画出结果
训练参数如下:
================================================================================
        参数名         	        参数值         	        参数类型        
     algo_name      	        DDPG        	   <class 'str'>    
      env_name      	    Pendulum-v0     	   <class 'str'>    
     train_eps      	        200         	   <class 'int'>    
      test_eps      	         20         	   <class 'int'>    
     max_steps      	       100000       	   <class 'int'>    
       gamma        	        0.99        	  <class 'float'>   
     critic_lr      	       0.001        	  <class 'float'>   
      actor_lr      	       0.0001       	  <class 'float'>   
  memory_capacity   	       80000        	   <class 'int'>    
     expl_noise     	        0.1         	  <class 'float'>   
     batch_size     	        128         	   <class 'int'>    
   target_update    	         2          	   <class 'int'>    
        tau         	        0.01        	  <class 'float'>   
 critic_hidden_dim  	        256         	   <class 'int'>    
  actor_hidden_dim  	        256         	   <class 'int'>    
       device       	        cpu         	   <class 'str'>    
        seed        	         1          	   <class 'int'>    
================================================================================
状态维度:3,动作维度:1
开始训练!
回合:10/200,奖励:-922.80
回合:20/200,奖励:-390.80
回合:30/200,奖励:-125.50
回合:40/200,奖励:-822.66
回合:50/200,奖励:-384.92
回合:60/200,奖励:-132.26
回合:70/200,奖励:-240.20
回合:80/200,奖励:-242.37
回合:90/200,奖励:-127.13
回合:100/200,奖励:-365.29
回合:110/200,奖励:-126.27
回合:120/200,奖励:-231.47
回合:130/200,奖励:-1.98
回合:140/200,奖励:-223.84
回合:150/200,奖励:-123.29
回合:160/200,奖励:-362.06
回合:170/200,奖励:-126.93
回合:180/200,奖励:-119.77
回合:190/200,奖励:-114.72
回合:200/200,奖励:-116.01
完成训练!
开始测试!
回合:1/20,奖励:-125.61
回合:2/20,奖励:-0.97
回合:3/20,奖励:-130.02
回合:4/20,奖励:-117.46
回合:5/20,奖励:-128.45
回合:6/20,奖励:-124.48
回合:7/20,奖励:-118.31
回合:8/20,奖励:-127.18
回合:9/20,奖励:-118.09
回合:10/20,奖励:-0.55
回合:11/20,奖励:-117.72
回合:12/20,奖励:-1.08
回合:13/20,奖励:-124.74
回合:14/20,奖励:-133.55
回合:15/20,奖励:-234.81
回合:16/20,奖励:-126.93
回合:17/20,奖励:-128.20
回合:18/20,奖励:-124.76
回合:19/20,奖励:-119.91
回合:20/20,奖励:-287.89
完成测试!

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

项目链接fork一下直接运行

https://www.heywhale.com/mw/project/649afec770567260f8b79b26

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

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

相关文章

计算机网络—数据链路层

文章目录 数据链路层服务差错编码多路访问协议信道划分随机访问MAC协议 数据链路层服务 该层中的帧数据结构&#xff1a; 帧头部会因为不同的局域网协议而不同&#xff0c;因此会在另一篇博文中继续介绍不同的帧数据报&#xff0c;不在本博文介绍。&#xff08;不过除了PPP协…

Docker学习笔记11

Docker容器镜像&#xff1a; 1&#xff09;docker client 向docker daemon发起创建容器的请求&#xff1b; 2&#xff09;docker daemon查找本地有客户端需要的镜像&#xff1b; 3&#xff09;如无&#xff0c;docker daemon则到容器的镜像仓库中下载客户端需要的镜像&#…

线性代数基础--向量

目录 向量的概念 基本概念 抽象概念 向量的意义 几何意义 物理意义 欧式空间 特点和性质 行向量与列向量 行向量 列向量 两者的关系 向量的基本运算与范数 向量的基本运算 向量的加法 数乘运算&#xff08;实数与向量相乘&#xff09; 转置 向量的范数 向量…

echart 设置柱状图y轴最大刻度

start 最近接到需求希望柱状图 y轴最大高度可以略高一些&#xff1b;柱状图的数据能展示在柱状图的上方 记录一下相关配置项 解决方案 官方文档说明 https://echarts.apache.org/zh/option.html#xAxis.max 效果 代码 {key: business,title: {text: 业务领域分类,textSt…

DAY32:回溯算法(七)全排列+全排列Ⅱ(排列问题)

文章目录 46.全排列思路树形图used数组的作用 伪代码完整版时间复杂度总结 47.全排列Ⅱ思路树形图 完整版时间复杂度总结 46.全排列 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xf…

C#和LABVIEW的对决:哪种上位机编程语言更适合你?

今天&#xff0c;我们将谈论主流的上位机编程语言。你听说过C#和LABVIEW吗&#xff1f;它们是的上位机编程语言&#xff0c;C#作为自动化主流编程语言特别受欢迎&#xff0c;LABVIEW用于自动化测试&#xff0c; 首先&#xff0c;我们来了解C#语言。C#是一种文本语言&#xff0c…

2023年江西省研究生数模竞赛植物的多样性

2023年江西省研究生数模竞赛 植物的多样性 原题再现 植物作为食物链中的生产者&#xff0c;通过光合作用吸收二氧化碳&#xff0c;制造氧气&#xff0c;同时为其他生物提供食物和栖息地&#xff0c;支持它们的生存。植物在生态系统中还起到防止水土流失、缓解温室效应等作用。…

新手小白编程利器!Debug 断点调试工具IDEA

前言 很多新手小白在学习的时候总会遇到一个问题&#xff1a; 我们一运行程序&#xff0c;只能看到程序最后的结果&#xff0c;但是这个程序究竟是怎么一步步运行出这样的结果呢&#xff1f;如果有一个工具能够让我们看到我们程序的执行流程该有多好~ 这就需要用到新手小白编程…

modbus转MQTT网关支持自定义JSON格式

在工业自动化系统中&#xff0c;Modbus是一种非常常见的通信协议&#xff0c;而OPC UA则是近年来兴起的一种新型通信协议。由于各种设备之间使用的通信协议不尽相同&#xff0c;因此需要一种能够实现多种协议转换的网关产品。BL110网关就是一款能够实现Modbus到OPC UA转换的产品…

硬件设计-PLL篇(下)

目录 概要 整体架构流程 技术名词解释 技术细节 1.环路滤波器采用有源滤波器还是无源滤波器&#xff1f;、 2.如何设计 VCO 输出功率分配器&#xff1f;、 3.如何设置电荷泵的极性&#xff1f; 4.锁定指示电路如何设计&#xff1f; 小结 概要 提示&#xff1a;这里可以添加技术…

学习Spring的补充

《JavaEE 框架整合开发入门到实践 》这本书还是太浅了 &#xff0c;需要补充一些基本的知识。 首先修改一下快捷键&#xff0c;使得可以像eclipse一样使用alt/ 快速补全代码。 参考博客&#xff1a; (33条消息) IDEA 设置代码提示或自动补全的快捷键_idea补全提示_thirty.st…

【Java核心技术】面向对象编程

面向对象编程 1、面向过程与面向对象面向过程(POP)与面向对象(OOP)面向对象的三大特征面向对象的思想概述 2、Java语言基本元素&#xff1a;类和对象类和对象类和对象的使用&#xff08;面向对象思想落地的实现&#xff09;对象的创建和使用&#xff1a;内存解析 3、类的成员之…

【瑞萨RA6系列】CoreMark移植完全指南——UART输出和SysTick计时

一、CoreMark简介 什么是CoreMark&#xff1f; 来自CoreMark首页的解释是&#xff1a; CoreMark is a simple, yet sophisticated benchmark that is designed specifically to test the functionality of a processor core. Running CoreMark produces a single-number scor…

tomcat进程注入

跟随上一篇《java进程注入》 这里使用memShell https://github.com/rebeyond/memShell 将agent.jar和inject.jar放到tomcta的web目录下 然后输入命令注入 效果&#xff1a; 注入成功后 可以看到agent.jar文件为了防止发现&#xff0c;自动清除&#xff0c;而且重启电脑之后&…

【Python数据分析】Python中axis的理解

axis用来为超过一维的数组定义属性。 理解时从数据变化的方向入手&#xff01; 以二维数据为例&#xff0c;在二维数据中&#xff0c;1表示横轴&#xff0c;方向从左到右&#xff1b;0表示纵轴&#xff0c;方向从上到下从数轴的方向入手&#xff0c;理解数据变化&#xff0c;a…

测试这碗饭,你还拿得稳吗?

今年测试行业格外寒冷&#xff0c;大部分人为了糊口饭吃&#xff0c;紧紧地捂住了本来已经很嫌弃的饭碗&#xff0c;以便挺过寒冬迎接春天。 公司天天加班&#xff0c;新出了各种扣款制度&#xff0c;为了上老下小我忍了。 2022年度的绩效&#xff0c;2023年都要过完了&#xf…

Windows同时安装两个版本JDK,并实现动态切换

1、载安装两个版本的JDK 安装后&#xff0c;默认路径C:\Program Files\Java。 实际上JDK8有两个包一个jdk1.8.0_311&#xff0c;一个jre1.8.0_311。 JDK11只有一个jdk-11.0.16.1。 2、系统环境配置 设置JAVA_HOME 在环境变量中选中Path&#xff0c;点击编辑 点击新建&…

DARAZ使用虚拟信用卡购物教程

Daraz为阿里巴巴南亚电商平台&#xff0c;市场覆盖巴基斯坦、孟加拉、斯里兰卡、尼泊尔和缅甸超过5亿人口级别市场&#xff0c;是南亚地区最受欢迎的在线购物网站&#xff0c;购物APP NO.1。 注册一个DARAZ的买家账号。 找到需要购买的商品&#xff0c;点击Buy Now进行购买 填…

Sip通话,qq通话,微信通话,普通的通话的条件和过程描述

SiP通话 SIP电话是基于SIP&#xff08;Session Initiation Protocol&#xff0c;会话初始化协议&#xff09;协议实现的通信。SIP是一种应用层协议&#xff0c;用于建立、修改和终止多媒体会话&#xff0c;如语音通话、视频通话等。SIP电话通过SIP协议进行信令交换和媒体流传输…

【MySQL学习笔记】(二)MySQL操作库基础

库的操作 1 创建数据库2 关于字符集和校验规则2.1 查看系统字符集以及校验规则2.2 查看数据支持的字符集2.3 查看数据库支持的字符集校验规则3 删除数据库4 查看并使用数据库5 修改数据库6 查看连接情况7 备份和恢复 1 创建数据库 1&#xff09;创建数据库 在学习笔记&#xf…