强化学习原理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.rhkb.cn/news/249344.html

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

相关文章

Web中的转发与重定向

转发与重定向 一、转发和重定向的概念1.转发2.重定向 二、JavaWeb 中的转发和重定向三、SpringMVC 中的转发和重定向1.转发(1) 默认的方式(2) 完整的方式 2.重定向 四、总结 一、转发和重定向的概念 在 Web 应用中,转发和重定向都是用于将请求从一个页面传递到另一…

故障诊断 | 一文解决,CNN卷积神经网络故障诊断(Matlab)

文章目录 效果一览文章概述专栏介绍源码设计参考资料效果一览 文章概述 故障诊断 | 一文解决,CNN卷积神经网络故障诊断(Matlab) 专栏介绍 订阅【故障诊断】专栏,不定期更新机器学习和深度学习在故障诊断中的应用;订阅

外星人入侵(python)

前言 代码来源《python编程从入门到实践》Eric Matthes 署 袁国忠 译 使用软件:PyCharm Community Editor 2022 目的:记录一下按照书上敲的代码 alien_invasion.py 游戏的一些初始化设置,调用已经封装好的函数方法,一个函数的…

【React】前端项目引入阿里图标

【React】前端项目引入阿里图标 方式11、登录自己的iconfont-阿里巴巴矢量图标库,把需要的图标加入到自己的项目中去;2、加入并进入到项目中去选择Font class 并下载到本地3、得到的文件夹如下4. 把红框中的部分粘贴到自己的项目中(public 文…

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

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

更改MAC终端样式(美化、易用的提示等)

1. 前言 之前用 Ubuntu、Elementary OS 时觉得其终端既漂亮又好用,购买的云服务器的默认终端也好看,一些牛人的桌面终端也配置得挺好看。虽然 Mac 的默认终端配置已经比 Windows 好看好用很多了,但还是觉得不够。于是灵机一动,想…

springboot139华强北商城二手手机管理系统

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计,课程设计参考与学习用途。仅供学习参考, 不得用于商业或者非法用途,否则,一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

idea docker 内网应用实践

文章目录 前言一、服务器端1.1 离线安装docker1.2 开启docker远程访问1.3 制作对应jdk镜像1.3.1 下载jdk171.3.2 Dockerfile 制作jdk17镜像1.3.3 镜像导出1.3.4 服务器引入镜像 二、Idea 配置2.1 Dockerfile2.2 pom 引入docker插件2.3 idea docker插件配置2.4 打包镜像上传2.5 …

第17次修改了可删除可持久保存的前端html备忘录:增加年月日星期,增加倒计时,更改保存区名称可以多个备忘录保存不一样的信息,匹配背景主题:现代深色

第17次修改了可删除可持久保存的前端html备忘录&#xff1a;增加年月日星期&#xff0c;增加倒计时&#xff0c;更改保存区名称可以多个备忘录保存不一样的信息&#xff0c;匹配背景主题&#xff1a;现代深色 备忘录代码&#xff1a; <!DOCTYPE html> <html lang&quo…

前端常见的栈溢出报错

什么是栈溢出&#xff1f; 在前端开发中&#xff0c;栈溢出是指JavaScript引擎执行代码时&#xff0c;调用栈&#xff08;call stack&#xff09;变得太大&#xff0c;超过了浏览器或JavaScript引擎所分配的栈空间&#xff0c;从而导致栈溢出错误。调用栈是一种数据结构&#x…

【Spark系列2】Spark编程模型RDD

RDD概述 RDD最初的概述来源于一片论文-伯克利实验室的Resilient Distributed Datasets&#xff1a;A Fault-Tolerant Abstraction for In-Memory Cluster Computing。这篇论文奠定了RDD基本功能的思想 RDD实际为Resilient Distribution Datasets的简称&#xff0c;意为弹性分…

git clone常见问题一览及解决方法

在使用Ubuntu下&#xff0c;终端运行git clone命令时会遇见许多问题&#xff0c;本文主要针对一些常见的问题进行整理。关于换源问题&#xff0c;推荐使用小鱼的一键换源。 1.git clone 速度过慢 1.1 魔法 这个方法不做过多赘述&#xff0c;ubuntu下个人使用发现体验良好&am…

matlab中的图窗属性和坐标轴的属性

图窗的Position和Outerposition Position 指定窗口的尺寸和窗口在屏幕中的位置。 Outerposition 指定窗口外轮廓的大小和位置。 两者都是用一个4维向量来定义&#xff0c;格式为[左 底 宽 高]。 可通过set函数修改Position和Outerposition&#xff0c;如下&#xff1a;在屏幕左…

【2024全网最详细】Google 搜索命令终极指南

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 你是否尝试过使用 Google 搜索作为免费的 SEO …

Flink 读取 Kafka 消息写入 Hudi 表无报错但没有写入任何记录的解决方法

博主历时三年精心创作的《大数据平台架构与原型实现:数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行,点击《重磅推荐:建大数据平台太难了!给我发个工程原型吧!》了解图书详情,京东购书链接:https://item.jd.com/12677623.html,扫描左侧二维…

设计一个支持并发的前端缓存接口

文章目录 一、概述二、并发缓存2.1、问题2.2、思考2.3、优化 三、总结四、最后 一、概述 缓存池不过就是一个map&#xff0c;存储接口数据的地方&#xff0c;将接口的路径和参数拼到一块作为key&#xff0c;数据作为value存起来罢了&#xff0c;这个咱谁都会。 const cacheMa…

pnpm tauri icon 一键转换 icon

在使用 Electron、Tauri 等框架开发桌面应用时&#xff0c;需要为应用生成不同平台的图标&#xff0c;如&#xff1a;MacOS 中的 icon.icns、Windows 中的 icon.ico、Linux 中的 *.png 等类型图标&#xff0c;这里介绍一种简单快捷一键转换图标的方法。 准备工作 nodejs 环境n…

ElasticSearch 应用实践 笔记

概述 介绍 ES 是一个开源的高扩展的分布式全文搜索引擎&#xff0c;是整个Elastic Stack技术栈的核心。它可以近乎实时的存储&#xff0c;检索数据&#xff1b;本身扩展性很好&#xff0c;可以扩展到上百台服务器&#xff0c;处理PB级别的数据。ElasticSearch的底层是开源库Lu…

c JPEG ZRL (15,0) 的问题

问题&#xff1a;如果量化表全为64个1&#xff0c;编码图片显示非常乱。如果用压缩比较大的量化表&#xff0c;显示基本正常。如果编码过程中不处理ZRL&#xff0c;图片正常。此问题一直没有排除。 下图为两张量化表全为64个1的情况下加了&#xff08;15,0&#xff09;后的不正…

[Bug] [OpenAI] [TypeError: fetch failed] { cause: [Error: AggregateError] }

[Bug] [OpenAI] [TypeError: fetch failed] { cause: [Error: AggregateError] } ubuntu20 win10 edge浏览器访问 服务器部署 页面打开后想使用chatgpt报错了 rootcoal-pasi1cmp:/www/wwwroot/ChatGPT-Next-Web# PORT3000 yarn start yarn run v1.22.19 warning package.json:…