先从最简单的开始入门吧
主要参考:
主要改动:
- 因为原代码使用Categorical,训练效果不佳,改成了比较简单的动作选择,效果改善了。
- 添加一部分函数的说明[Categorical, gather, clamp]
强化学习
类似巴普洛夫的狗
环境=>观测=>动作=>环境改变=>观测
通过奖励,训练模型采取更好的策略。
倒立摆
在倒立摆中,环境的观测值就是
- 小车在轨道上的位置
- 杆子与竖直方向的夹角
- 小车速度
- 角度变化率
动作为:
- 0 左
- 1 右
训练模型,让其学会左右移动,使得杆子与数值方向夹角为0
代码
#导入gym和torch相关包
import gym
import random
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.distributions import Categorical
超参数设置
#Hyperparameters
learning_rate = 0.0005 #学习率
gamma = 0.98 #
lmbda = 0.95 #
eps_clip = 0.1 #
K_epoch = 3 #
T_horizon = 20 #
1.定义PPO架构
class PPO(nn.Module):
def __init__(self):
super(PPO, self).__init__()
self.data = [] #用来存储交互数据
self.fc1 = nn.Linear(4, 256) #由于倒立摆环境简单,这里仅用一个线性变换来训练数据
self.fc_pi = nn.Linear(256, 2) #policy函数, 动作只有左和右,因此输出是2
self.fc_v = nn.Linear(256, 1) #value函数(输出v),值只有1,因此输出为1
self.optimizer = optim.Adam(self.parameters(), lr=learning_rate) #优化器
#policy函数
#输入观测值x
#输出动作空间概率,从而选择最优action
def pi(self, x, softmax_dim=0):
x = F.relu(self.fc1(x))
x = self.fc_pi(x)
prob = F.softmax(x, dim=softmax_dim)
# x形状20*2
# 这里的dim取0,代表获取同一样本的动作空间softmax
# 概率越大代表选择的可能性越大,在每次观测时,95%选择概率更大的动作,5%选择概率更小的动作。
# 下面有个地方dim取1,代表获取一个批次(例如20次尝试)的softmax,不同状态时的动作概率
return prob
#value函数
#输入观测值x
#输出x状态下value的预测值(reward),提供给policy函数作为参考值
def v(self, x):
x = F.relu(self.fc1(x))
v = self.fc_v(x)
return v
#把交互数据存入buffer
def put_data(self, transition):
self.data.append