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

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
完成测试!

更多优质内容请关注公号:汀丶人工智能

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

  1. 强化学习入门基础-马尔可夫决策过程(MDP)

    作者:YJLAugus 博客: https://www.cnblogs.com/yjlaugus 项目地址:https://github.com/YJLAugus/Reinforcement-Lear ...

  2. 【算法总结】强化学习部分基础算法总结(Q-learning DQN PG AC DDPG TD3)

    总结回顾一下近期学习的RL算法,并给部分实现算法整理了流程图.贴了代码. 1. value-based 基于价值的算法 基于价值算法是通过对agent所属的environment的状态或者状态动作对进 ...

  3. [原创]java WEB学习笔记21:MVC案例完整实践(part 2)---DAO层设计

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  4. [原创]java WEB学习笔记20:MVC案例完整实践(part 1)---MVC架构分析

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  5. MySQL学习笔记——基础与进阶篇

    目录 一.###MySQL登录和退出 二.###MySQL常用命令 三.###MySQL语法规范 四.###基础查询 五.###条件查询 六.###排序查询 七.###常见函数的学习 八.###分组查 ...

  6. [原创]java WEB学习笔记26:MVC案例完整实践(part 7)---修改的设计和实现

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  7. [原创]java WEB学习笔记25:MVC案例完整实践(part 6)---新增操作的设计与实现

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  8. [原创]java WEB学习笔记24:MVC案例完整实践(part 5)---删除操作的设计与实现

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  9. [原创]java WEB学习笔记23:MVC案例完整实践(part 4)---模糊查询的设计与实现

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  10. [原创]java WEB学习笔记22:MVC案例完整实践(part 3)---多个请求对应一个Servlet解析

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

随机推荐

  1. MySQL 创建存储过程注意项

    MySQL server version for the  right syntax to use near 'IF' MySQL server version for the right synta ...

  2. redis之列表 redis之hash redis其他操作 redis管道 django中使用redis celery介绍和安装 celery快速使用 celery包结构

    目录 昨日回顾 今日内容 1 redis之列表 2 redis之hash 3 redis其他操作 4 redis 管道 5 django中使用redis 6 celery介绍和安装 7 celery快 ...

  3. MMSC 扩充物料库存地点

    当涉及到物料的库存地点时,系统通常会做校验,该物料是否扩充了库存地点,没有扩充则报错.为了不使这样的错误干扰到程序逻辑,通常会在涉及时,先查询MARD表,判断是否存在对应的库存地点.如果没有存在,则直 ...

  4. POJ 2484博弈——对称法

    题目链接:http://poj.org/problem?id=2484 题意:Alice和Bob玩游戏,从一堆圆环形排列的硬币中拿硬币,每次可以拿一个或者两个,但必须拿连续的(两个中间有空位也视为不连 ...

  5. Codeforces Round #715 (Div. 2) (A~D 补题记录)

    补题链接:Here 经典手速场 1509A. Average Height 题意:要找出最大不平衡对序列 先输出奇数,然后输出偶数 void solve() { int n; cin >> ...

  6. 人人都会Kubernetes(二):使用KRM实现快速部署服务,并且通过域名发布

    1. 上节回顾 上一小节<人人都会Kubernetes(一):告别手写K8s yaml,运维效率提升500%>介绍了KRM的一些常用功能,并且使用KRM的DEMO环境,无需安装就可以很方便 ...

  7. wireshark 抓包使用

    本文为博主原创,转载请注明出处: 在项目开发过程当中,尤其在联调和测试功能的使用,经常会用到抓包,用抓包进行问题的定位. 所以记录一下wireshark的使用,如何抓包,分析,保存等. wiresha ...

  8. windows mysql安装及常用命令

    安装windows版本mysql只是为本地代码调试,不建议用于生产.觉得步骤麻烦也可以直接下载集成环境(如xampp),一键安装即可用.之前本地测试都用一键安装,今天换个方法玩玩,安装步骤如下: my ...

  9. 6. 配置项:relabel_config

    6.1relabel_config的位置 6.2 relabel_config参数详解 1.replace 2. keep 3.drop 6.labelkeep 7.hashmod 6.3 正则表达式 ...

  10. SV interface and Program3

    时钟域的理解 在仿真过程中,时钟跳变的一瞬间,CPU将时间域划分为不同的时钟域执行不同的代码 信号在芯片中都是金属丝,在进行跳变的时候都是电容的充放电过程,通常使用时钟上升沿进行模拟,而不使用时钟下降 ...