强化学习原理python篇07——策略梯度法

强化学习原理python篇07——策略梯度法


本章全篇参考赵世钰老师的教材 Mathmatical-Foundation-of-Reinforcement-Learning Policy Gradient Methods 章节,请各位结合阅读,本合集只专注于数学概念的代码实现。

Average state value

对所有状态值的加权平均
v ˉ = ∑ s ∈ S v π ( s ) = E S − d ( v π ( S ) ) = E S − d ( ∑ a ∈ A q ( s , a ) π ( a ∣ s ) ) \begin {align*} \bar v =& \sum_{s\in S}v_\pi (s)\\ =& E_{S-d}(v_\pi(S))\\ =& E_{S-d}(\sum_{a\in A} q(s,a)\pi(a|s)) \end {align*} vˉ===sSvπ(s)ESd(vπ(S))ESd(aAq(s,a)π(as))

策略函数为 π ( a ∣ s , θ ) \pi(a|s,\theta) π(as,θ)
J ( θ ) = v ˉ J(\theta)=\bar v J(θ)=vˉ
对其求梯度

∇ θ J ( θ ) = E S − d ( ∑ a ∈ A q ( s , a ) ∇ θ π ( a ∣ s , θ ) ) = E S − d ( ∑ a ∈ A q ( s , a ) π ( a ∣ s , θ ) ∇ θ l n π ( a ∣ s , θ ) ) = E S − d [ E a − π ( S , Θ ) [ q ( s , a ) ∇ θ l n π ( a ∣ s , θ ) ] ] = E S − d , a − π ( S , Θ ) [ q ( s , a ) ∇ θ l n π ( a ∣ s , θ ) ] \begin {align*} \nabla_\theta J(\theta) =& E_{S-d}(\sum_{a\in A} q(s,a)\nabla_\theta\pi(a|s,\theta))\\ =& E_{S-d}(\sum_{a\in A} q(s,a)\pi(a|s,\theta) \nabla_\theta ln\pi(a|s,\theta))\\ =& E_{S-d}[E_{a-\pi(S,\Theta)}[q(s,a) \nabla_\theta ln\pi(a|s,\theta)]]\\ =& E_{S-d,a-\pi(S,\Theta)}[q(s,a) \nabla_\theta ln\pi(a|s,\theta)] \end {align*} θJ(θ)====ESd(aAq(s,a)θπ(as,θ))ESd(aAq(s,a)π(as,θ)θl(as,θ))ESd[Eaπ(S,Θ)[q(s,a)θl(as,θ)]]ESd,aπ(S,Θ)[q(s,a)θl(as,θ)]

Average reward

r ˉ = ( 1 − γ ) v ˉ \bar r = (1-\gamma)\bar v rˉ=(1γ)vˉ

Monte Carlo policy gradient (REINFORCE)

为了求 m a x v ˉ = m a x J θ max\bar v=max J_\theta maxvˉ=maxJθ ,则

θ t + 1 = θ t + ∇ θ J ( θ t ) θ_{t+1} = θ_{t} + \nabla _{\theta}J(θ_t) θt+1=θt+θJ(θt)

REINFORCE示例

θ t + 1 = θ t + ∇ θ J ( θ t ) = θ t + ∇ θ E S − d , a − π ( S , Θ ) [ q ( s , a ) ∇ θ l n π ( a ∣ s , θ ) ] \begin {align*} θ_{t+1} =& θ_{t} + \nabla _{\theta}J(θ_t)\\=& θ_{t} + \nabla _{\theta}E_{S-d,a-\pi(S,\Theta)}[q(s,a) \nabla _{\theta}ln\pi(a|s,\theta)] \end {align*} θt+1==θt+θJ(θt)θt+θESd,aπ(S,Θ)[q(s,a)θl(as,θ)]
一般来说, ∇ θ l n π ( a ∣ s , θ ) \nabla _{\theta}ln\pi(a|s,\theta) θl(as,θ)是未知的,可以用随机梯度法来估计,则
θ t + 1 = θ t + ∇ θ J ( θ t ) = θ t + ∇ θ [ q ( s , a ) ∇ θ l n π ( a ∣ s , θ ) ] \begin {align*} θ_{t+1} =& θ_{t} + \nabla _{\theta}J(θ_t)\\=& θ_{t} + \nabla _{\theta}[q(s,a) \nabla _{\theta}ln\pi(a|s,\theta)] \end {align*} θt+1==θt+θJ(θt)θt+θ[q(s,a)θl(as,θ)]

在torch里面编写这段代码

  • 1、用随机权重初始化策略网络
  • 2、运行N个完整的片段,保存其(s,a,r,s’)状态转移
  • 3、对于每个片段k的每一步t,计算后续步的带折扣的总奖励 Q k , t = ∑ i = 0 γ i r i Q_{k,t}=\sum_{i=0}\gamma_ir_i Qk,t=i=0γiri
  • 4、计算所有状态转移的损失函数 L = − ∑ k , t Q k , t l n π ( a k , t ∣ s k , t ) L=-\sum_{k,t}Q_{k,t}ln\pi(a_{k,t}|s_{k,t}) L=k,tQk,tl(ak,tsk,t),由于torch自带的是梯度下降,所以带个负号更新,sum为小批量
  • 5、执行SGD更新权重,以最小化损失
  • 6、从步骤2开始重复,直到收敛

1、用随机权重初始化策略网络

import collections
import copy
import math
import random
import time
from collections import defaultdictimport gym
import gym.spaces
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from gym.envs.toy_text import frozen_lake
from torch.utils.tensorboard import SummaryWriter# 1、用随机权重初始化策略网络
class PolicyNet(nn.Module):def __init__(self, obs_n, hidden_num, act_n):super().__init__()# 动作优势A(s, a)self.net = nn.Sequential(nn.Linear(obs_n, hidden_num),nn.ReLU(),nn.Linear(hidden_num, act_n),nn.Softmax(dim=1),)def forward(self, state):if len(torch.Tensor(state).size()) == 1:state = state.reshape(1, -1)return self.net(state)

2、运行N个完整的片段,保存其(s,a,r,s’)状态转移

def generate_episode(env, n_steps, net, predict=False):episode_history = dict()r_list = []for _ in range(n_steps):episode = []predict_reward = []state, info = env.reset()while True:p = net(torch.Tensor(state)).detach().numpy().reshape(-1)action = np.random.choice(list(range(env.action_space.n)), p=p)next_state, reward, terminated, truncted, info = env.step(action)episode.append([state, action, next_state, reward, terminated])predict_reward.append(reward)state = next_stateif terminated or truncted:episode_history[_] = episoder_list.append(len(episode))episode = []predict_reward = []breakif predict:return np.mean(r_list)return episode_history

3、对于每个片段k的每一步t,计算后续步的带折扣的总奖励

def calculate_t_discount_reward(reward_list, gamma):discount_reward = []total_reward = 0for i in reward_list[::-1]:total_reward = total_reward * gamma + idiscount_reward.append(total_reward)return discount_reward[::-1]

4、计算所有状态转移的损失函数 L = − ∑ k , t Q k , t l n π ( a k , t ∣ s k , t ) L=-\sum_{k,t}Q_{k,t}ln\pi(a_{k,t}|s_{k,t}) L=k,tQk,tl(ak,tsk,t)

def loss(batch, gamma):l = 0for episode in batch.values():reward_list = [reward for state, action, next_state, reward, terminated in episode]state = [state for state, action, next_state, reward, terminated in episode]action = [action for state, action, next_state, reward, terminated in episode]qt = calculate_t_discount_reward(reward_list, gamma)pi = net(torch.Tensor(state))pi = pi.gather(dim=1, index=torch.LongTensor(action).reshape(-1, 1))l += -torch.Tensor(qt) @ torch.log(pi)return l/len(batch.values())

5,6、训练

## 初始化环境
env = gym.make("CartPole-v1", max_episode_steps=1000)
# env = gym.make("CartPole-v1", render_mode = "human")state, info = env.reset()obs_n = env.observation_space.shape[0]
hidden_num = 64
act_n = env.action_space.n
net = PolicyNet(obs_n, hidden_num, act_n)# 定义优化器
opt = optim.Adam(net.parameters(), lr=0.01)# 记录
writer = SummaryWriter(log_dir="logs/PolicyGradient/reinforce", comment="test1")epochs = 1000
batch_size = 200
gamma = 0.9for epoch in range(epochs):batch = generate_episode(env, batch_size, net)l = loss(batch, gamma)# 反向传播opt.zero_grad()l.backward()opt.step()writer.add_scalars("Loss", {"loss": l.item(), "max_steps": generate_episode(env, 10, net, predict=True)}, epoch)print("epoch:{},  Loss: {}, max_steps: {}".format(epoch, l.detach(), generate_episode(env, 10, net, predict=True)))

运行结果

这是CartPole-v1的步数提升效果。
在这里插入图片描述

改进策略

BaseLine

作为第一个示例,令Q1和Q2都等于某个小的正数,而Q3等于一个大的负数。因此,第一步和第二步的动作得到了一些小的奖励,但是第三步并不是很成功。由这三个步骤所产生的综合梯度将试图使策略远离第三步的动作,而稍微朝第一步和第二步采取的动作靠拢,这是完全合理的。

现在让我们想象一下,假设奖励永远是正的,只有价值不同。这对应于为每个奖励(Q1、Q2和Q3)加上一些常数。在这种情况下,Q1和Q2将变为较大的正数,而Q3为较小的正值。但是,策略更新将有所不同!接下来,我们将努力将策略推向第一步和第二步的动作,并略微将其推向第三步的动作。因此,严格来说,尽管相对奖励是相同的,但我们不再试图避免选择第三步所执行的动作。

策略更新依赖于奖励中所加的常数,这可能会大大减慢训练速度,因为我们可能需要更多样本来平均掉这种策略梯度偏移的影响。甚至更糟的是,由于折扣总奖励随时间变化,随着智能体学着如何表现得越来越好,策略梯度的方差也可能发生变化。

  • 1、用随机权重初始化策略网络
  • 2、运行N个完整的片段,保存其(s,a,r,s’)状态转移
  • 3、对于每个片段k的每一步t,计算后续步的带折扣的总奖励 Q k , t = ∑ i ∈ T γ i r i − 1 n ∑ i ∈ T γ i r i Q_{k,t}=\sum_{i\in T}\gamma_ir_i - \frac{1}{n}\sum_{i\in T}\gamma_ir_i Qk,t=iTγirin1iTγiri
  • 4、计算所有状态转移的损失函数 L = − ∑ k , t Q k , t l n π ( a k , t ∣ s k , t ) L=-\sum_{k,t}Q_{k,t}ln\pi(a_{k,t}|s_{k,t}) L=k,tQk,tl(ak,tsk,t)
  • 5、执行SGD更新权重,以最小化损失
  • 6、从步骤2开始重复,直到收敛

只需要修改第三步

# 对于每个片段k的每一步t,计算后续步的带折扣的总奖励
def calculate_t_discount_reward(reward_list, gamma, baseline=False):discount_reward = []total_reward = 0for i in reward_list[::-1]:total_reward = total_reward * gamma + iif baseline:discount_reward.append(total_reward / np.mean(reward_list))else:discount_reward.append(total_reward)return discount_reward[::-1]

entropy bonus

即使将策略表示为概率分布,智能体也很有可能会收敛到某些局部最优策略并停止探索环境。在DQN中,我们使用ε-greedy动作选择方式解决了这一问题:有epsilon的概率,智能体执行随机动作,而不是当前策略决定的动作。当然,我们可以使用相同的方法,但是策略梯度方法使我们可以采取更好的方法,即熵奖励(entropy bonus)。

在信息论中,熵是某些系统中不确定性的度量。将熵应用到智能体的策略中,它可以显示智能体对执行何种动作的不确定程度。策略的熵可以用数学符号定义为:H(π) = –∑π(a|s)logπ(a|s)。熵的值始终大于零,并且在策略符合平均分布(换句话说,所有动作具有相同的概率)时具有一个最大值。当策略决定某个动作的概率为1而所有其他动作的概率为0时,熵就变得最小,这意味着该智能体完全确定要做什么。为了防止智能体陷入局部最小值,在损失函数中减去熵,以惩罚智能体过于确定要采取的动作

只需要修改Loss函数。

def loss(batch, gamma, entropy_beta):l = 0for episode in batch.values():reward_list = [reward for state, action, next_state, reward, terminated in episode]state = [state for state, action, next_state, reward, terminated in episode]action = [action for state, action, next_state, reward, terminated in episode]qt = calculate_t_discount_reward(reward_list, gamma)pi = net(torch.Tensor(state))entropy_loss = -torch.sum((pi* torch.log(pi)),axis=1).mean() * entropy_betapi = pi.gather(dim=1, index=torch.LongTensor(action).reshape(-1, 1))l_policy = -torch.Tensor(qt) @ torch.log(pi)l += l_policy - entropy_lossreturn l / len(batch.values())

entropy_beta&baseline

同时加入两种方式,再次修改loss函数

def loss(batch, gamma, entropy_beta=False, baseline=False):l = 0for episode in batch.values():reward_list = [reward for state, action, next_state, reward, terminated in episode]state = [state for state, action, next_state, reward, terminated in episode]action = [action for state, action, next_state, reward, terminated in episode]qt = calculate_t_discount_reward(reward_list, gamma, baseline)pi = net(torch.Tensor(state))entropy_loss = -torch.sum((pi * torch.log(pi)), axis=1).mean() * entropy_betapi = pi.gather(dim=1, index=torch.LongTensor(action).reshape(-1, 1))l_policy = -torch.Tensor(qt) @ torch.log(pi)if entropy_beta:l += l_policy - entropy_losselse:l += l_policyreturn l / len(batch.values())

训练

## 初始化环境
env = gym.make("CartPole-v1", max_episode_steps=200)
# env = gym.make("CartPole-v1", render_mode = "human")state, info = env.reset()obs_n = env.observation_space.shape[0]
hidden_num = 64
act_n = env.action_space.n
net = PolicyNet(obs_n, hidden_num, act_n)# 定义优化器
opt = optim.Adam(net.parameters(), lr=0.01)# 记录
writer = SummaryWriter(log_dir="logs/PolicyGradient/reinforce-entropy-bonus&baseline", comment="test1"
)epochs = 200
batch_size = 20
gamma = 0.9
entropy_beta= 0.01
baseline=Truefor epoch in range(epochs):batch = generate_episode(env, batch_size, net)l = loss(batch, gamma, entropy_beta, baseline)# 反向传播opt.zero_grad()l.backward()opt.step()writer.add_scalars("Loss",{"loss": l.item(), "max_steps": generate_episode(env, 10, net, predict=True)},epoch,)print("epoch:{},  Loss: {}, max_steps: {}".format(epoch, l.detach(), generate_episode(env, 10, net, predict=True)))

对比结果如下

在这里插入图片描述
加入entropy_beta可以解决局部最优点问题
baseline可以优化收敛方向。

Ref

[1] Mathematical Foundations of Reinforcement Learning,Shiyu Zhao
[2] 深度学习强化学习实践(第二版),Maxim Lapan

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

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

相关文章

RocketMQ—RocketMQ安装

RocketMQ—RocketMQ安装 在安装RocketMQ之前需要先安装Jdk,并配置JAVA_HOME环境变量。 在安装之前我们要先下载RocketMQ的安装包。 下载 到RocketMQ的官网https://rocketmq.apache.org/ 选择Download。 本文使用4.9.2版本。 将下载页面拉到最后面,有…

外星人入侵(python)

前言 代码来源《python编程从入门到实践》Eric Matthes 署 袁国忠 译 使用软件:PyCharm Community Editor 2022 目的:记录一下按照书上敲的代码 alien_invasion.py 游戏的一些初始化设置,界面的大小,标题 import sys import …

【Tomcat与网络10】Tomcat I/O和线程池的并发调优

前面我们看了提高Tomcat启动速度的措施,这里我们看一下如何提高Tomcat的性能。 Tomcat 的调优涉及 I/O 模型和线程池调优、JVM 内存调优以及网络优化等,今天我们来聊聊 I/O 模型和线程池调优,由于 Web 应用程序跑在 Tomcat 的工作线程中&…

075:vue+mapbox 利用高德地址逆转换,点击地图,弹出地址信息

第075个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中利用高德逆地理编码,点击地图,弹出某点坐标和地址信息。这里要仔细阅读高德地图的逆编码API,同时要注意的是,这种转换在中国很好用,到了欧美国家就不好使了。同时这个底图是天地图的图像和标记。 直接…

Elasticsearch:构建自定义分析器指南

在本博客中,我们将介绍不同的内置字符过滤器、分词器和分词过滤器,以及如何创建适合我们需求的自定义分析器。更多关于分析器的知识,请详细阅读文章: 开始使用 Elasticsearch (3) Elasticsearch: analyzer…

MYSQL的配置和安装

下载安装 打开官网 MYSQL官网 点击DOWNLOADS 滑到最低下点击:MYSQL Community(GPL) Downlads 点击Download Archives 点击MySQL Community Server进入网站 选择相应版本下载,这里选择的是5.7.24版本,x86 64位【按需选择】 下载解压 配置文件…

Node.js Express 框架 2024版 笔记

1.0 操作命令 Node.js express 框架 https://www.expressjs.com.cn/ npm install -g express-generator expressexpress --pug --git // --pug 添加对 pug 模板引擎的支持 // --git 添加 .gitignore 代码仓库排除 //无法直接安装新版pug模板 npm i npm …

uniApp开发小程序自定义tabBar底部导航栏+tabBar中间凸起自定义样式实现

先看效果是否可以满足你们,如果可以满足你只要一步一步照着做绝对没有错。 本人技术不佳,研究了一整天,全网的大佬们写的博客看的晕头转向,避免大伙再走弯路,跟着我以下步骤一点一点来绝对可以实现。 最终效果图&#…

万兆电口模块10GBase-T:提升网络性能的利器

随着数字化时代的到来,数据传输速度已经成为各行各业不可或缺的一项需求。而在数据中心和企业网络中,网络设备也正面临着越来越高的带宽需求。在满足这一需求的过程中,万兆电口模块10GBase-T成为了一种重要的解决方案。本文将围绕万兆电口模块…

工作七年,对消息推送使用的一些经验和总结

前言:不管是APP还是WEB端都离不开消息推送,尤其是APP端,push消息,小信箱消息;WEB端的代办消息等。因在项目中多次使用消息推送且也是很多项目必不可少的组成部分,故此总结下供自己参考。 一、什么是消息推…

最短路径 ( floyd) 算法

Floyd算法又称为插点法,是一种用于寻找给定的加权图中多源点之间最短路径的算法。 算法思想: https://upimg.baike.so.com/doc/5450540-5688910.html 图演示: 代码实现: public void floyd() {int[] vertex graph.getVertex();int[][] edges graph.getEdges()…

<网络安全>《12 数据库安全审计系统》

1 概念 数据库安全审计系统通过对用户访问数据库行为的记录、分析和汇报,来帮助用户事后生成合规报告、事故追根溯源,同时通过大数据搜索技术提供高效查询审计报告,定位事件原因,以便日后查询、分析、过滤,实现加强内…

【算法】拦截导弹(线性DP)

题目 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。 但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。 某天,雷达捕捉到敌国的导弹来袭。 由于该系…

VUE3+elementPlus 之 Form表单校验器 之 字符长度校验

需求:校验字符长度,超过后仍可输入,error提示录入字符数与限制字符数 校验字符长度: /*** 检验文字输入区的长度* param {*} rule 输入框的rule 对象,field:字段名称* param {*} value …

【百度Apollo】本地调试仿真:加速自动驾驶系统开发的利器

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《linux深造日志》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! ⛳️ 推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下…

Unity | 资源热更(YooAsset AB)

目录 一、AssetBundle 1. 插件AssetBundle Browser 打AB包 (1)Unity(我用的版本是2020.3.8)导入AssetBundle Browser (2)设置Prefab (3)AssetBundleBrowser面板 2. 代码打AB包…

nodejs历史版本下载

Node.js — Previous Releases下载地址 .msi 是安装包(windows),下载安装包即可

关于最小系统板PCB设计后的一些反思

简介 趁着刚刚画完板子寄回来,在这里做一些记录。 板子状况 这里打烊了5块PCB,但是没有进行SMT贴片,后续如果有芯片可以焊接上去进行后续验证。 封装问题 这里可以看到,我这里两侧的排针都是焊盘,不是通孔&#…

Unity_Timeline使用说明

Unity_Timeline使用说明 首先要找到工具吧?Unity2023.1.19f1c1打开如下: (团结引擎没找见哪儿打开,可能是引擎问题吧?有知道的同学可以告诉我在哪儿打开) Timelime使用流程: 打开之后会提示您…

ClickHouse为什么这么快(二)SSE指令优化

上一篇 ClickHouse为什么这么快(一)减少数据扫描范围 我们说到了ClickHouse中使用列存储,每个列都单独存储为一个文件,每个文件都是由一个或多个数据块组成,也就是说:每个文件由一个或多个数组组成&#xf…