最近抽时间把第三章和第四章看完了,可以说这两章算是进入本书的正题了。正如本书第二页说的那样,本书适用于有深度学习基础的读者,如果不会Python,不会Pytorch,也没怎么学习过深度学习基本数学原理的,感觉还是挺难啃的,因为书里面代码的注释都是给一些核心的,如果完全没接触过pytorch或者numpy这两个库,很多代码估计完全看不懂。
这两章主要介绍了深度 Q 网络(Deep Q-Network, DQN)和随机策略梯度法(Stochastic Policy Gradient Methods),然后给出两个案例一个是类似走迷宫的游戏,另一个是基于Openai Gym的平衡车。总的来说,这两个方法都是深度强化学习领域中的重要方法,用于解决不同类型的强化学习问题。
DQN 适用于值函数估计的任务,如 Q-Learning。它基于 Q-learning 算法,使用神经网络来近似 Q 值函数,将状态动作对映射到它们的预期累积奖励。DQN 的关键创新是使用经验回放(Experience Replay)和利用目标网络(Fixed Target Network)来提高训练的稳定性和收敛性。经验回放允许存储和重用之前的经验样本,固定目标网络用于稳定目标 Q 值的更新。DQN 可以用于解决各种基于值函数的强化学习问题,包括在游戏中的控制问题,如深度强化学习代理在 Atari 游戏中的表现。而随机策略梯度法是一种用于解决强化学习问题的方法,它专注于直接学习策略(即动作选择策略)的参数,而不是值函数。这些方法试图优化策略,以最大化期望回报,通过沿着策略梯度的方向更新策略参数。随机策略梯度法包括 REINFORCE、Proximal Policy Optimization(PPO)、Actor-Critic 等,它们可以用于连续动作和离散动作的问题。这些方法在处理高维、连续动作空间或具有随机性的环境时非常有用,因为它们不需要像值函数方法那样离散化动作空间或明确建模价值函数。
最后,我也跑了一下P57页的Q-Learning的网络训练案例,顺便把注释写的更详细了一点,供大家一起学习。
案例代码在本书的GitHub仓库中,直达链接:
三个文件都要下载,Ch3_book.ipynb 是Jupyter笔记本文件,GridBoard.py Gridworld.py是用到的两个库,和前面的文件放在一起就好,或者可以直接运行以下代码,亲测库装全了可用
import numpy as np #导入相关的库
import torch
from Gridworld import Gridworld
from IPython.display import clear_output
import random
from matplotlib import pylab as plt
#定义每层神经网络的神经元个数
l1 = 64 #第一层设置64个神经元,以此类推
l2 = 150
l3 = 100
l4 = 4
model = torch.nn.Sequential( #pytorch的一个容器,用于设置神经网络层,运行时会按照从上到下的顺序依次运行
torch.nn.Linear(l1, l2), #全连接层,第一个参数为输入的Tensor个数,第二个为输出的个数
torch.nn.ReLU(), #激活函数层,Relu中文名是线性整流函数,表达式f(x)=max(0,x)
torch.nn.Linear(l2, l3),
torch.nn.ReLU(),
torch.nn.Linear(l3,l4)
)
loss_fn = torch.nn.MSELoss()#定义损失函数为均方差
learning_rate = 1e-3 # 学习率
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)#使用adam优化器
gamma = 0.9 #表示在未来奖励的累积衰减程度
epsilon = 1.0#用于平衡探索和利用
action_set = {0: 'u',1: 'd',2: 'l',3: 'r'}
#书上有注释
epochs = 1000
losses = [] #A
for i in range(epochs): #B
game = Gridworld(size=4, mode='static') #C
#reshape用了改变数据的形状,例如这里是将4x4x4的数据打平为(1,64)
state_ = game.board.render_np().reshape(1,64) + np.random.rand(1,64)/10.0 #D
state1 = torch.from_numpy(state_).float() #E 将numpy的数组转为tensor
#仓库中的代码这个位置有错误,需要将state改为state1
status = 1 #F
while(status == 1): #G
qval = model(state1) #H #送数据进入前面定义的网络
qval_ = qval.data.numpy()
if (random.random() < epsilon): #I
action_ = np.random.randint(0,4)
else:
action_ = np.argmax(qval_)
action = action_set[action_] #J
game.makeMove(action) #K
state2_ = game.board.render_np().reshape(1,64) + np.random.rand(1,64)/10.0
state2 = torch.from_numpy(state2_).float() #L
reward = game.reward()
with torch.no_grad():
newQ = model(state2.reshape(1,64))
maxQ = torch.max(newQ) #M
if reward == -1: #N
Y = reward + (gamma * maxQ)
else:
Y = reward
Y = torch.Tensor([Y]).detach()
X = qval.squeeze()[action_] #O
loss = loss_fn(X, Y) #P #计算mse误差
print(i, loss.item())
clear_output(wait=True)
optimizer.zero_grad()
loss.backward() #神经网络反向传播计算梯度
losses.append(loss.item())
optimizer.step()#根据梯度更新权重
state1 = state2
if reward != -1: #Q
status = 0
if epsilon > 0.1: #R
epsilon -= (1/epochs)
结果:
|