价值学习(Value-based Reinforcement Learning)
文章目录前言一、价值学习Value-based Reinforcement Learning1.1 Q-learning算法1.2 Deep Q-NetworkDQN1.3 训练DQN使用的算法1.4 TD learning二、TD Learning algorithms2.1 Sarsa算法2.2 Multi-step TD Target2.3 用于Sarsa算法的One-step TD Target和Multi-step TD Target2.4 用于Q-learning算法的One-step TD Target和Multi-step TD Target三、价值学习代码示例3.1 Q-learning/DQN-离线学习代码3.2 Sarsa在线学习代码总结前言讲完强化学习的基本概念来介绍一下价值学习算法一、价值学习Value-based Reinforcement LearningNotesQ-learning与DQN都是使用TD算法原理上Q-learning与DQN没区别只是DQN用神经网络去近似最优动作价值函数1.1 Q-learning算法1Q-learing算法的表格形式每次观测到一个四元组st,at,rt,st1;然后计算TD target ytQ*st1,a的计算是通过查表格找到状态st1那一行找出最大的元素最大的元素就是Q*st1,a最后把Qπst,at写回表格对应的位置更新了表格里的值2Q-learing算法的神经网络形式跟表格形式的Q-learing算法类似不再赘述3总结Q-learning的目标是学习最优动作价值函数Q*;表格形式的Q适用的条件是状态和动作数量有限Q-learning算法每次更新表格中的一个元素Q-learning算法的神经网络的形式是通过qs,a;w近似QQ-learning算法每次更新参数w1.2 Deep Q-NetworkDQN核心就是用神经网络去近似Q*s,a函数我们把这个神经网络记为Q是Qs,a;w神经网络的参数是w输入是状态s输出是很多数值这些数值是每一个动作对应的分数通过奖励reward学习神经网络使神经网络打分越来越准以打游戏为例强化学习的目标是在游戏结束的时候获得的奖励最大当有Q*s,a函数时就可以告诉我们每个动作的平均回报从而做平均回报最高的动作问题是我们并不知道Q*s,a函数价值学习的想法就是学习一个函数来近似Q*s,a函数例子应用DQN来打游戏观测到当前的状态stDQN把st作为输入给所有的动作打分选出分数最高的动作作为atagent执行动作at后环境会改变状态用状态转移函数p随机抽一个新的状态st1环境同时也告诉我们这一步的奖励rt奖励就是强化学习中的监督信号DQN靠这些奖励来训练同理观测到当前的状态st1DQN把st1作为输入给所有的动作打分选出分数最高的动作作为at1agent执行动作at1后环境改变状态用状态转移函数p随机抽一个新的状态st2环境同时也告诉我们这一步的奖励rt1一直重复这个过程一直到游戏结束1.3 训练DQN使用的算法Temporal Difference LearningTD算法TD算法例子理解Td算法假设现在要开车从纽约到亚特兰大模型QW可以估计开车的时间估计QW估计开车要花1000分钟更新模型参数的过程首先估计开车要花多长时间到达亚特兰大后看一下开车所花的真实时间计算预测时间与真实时间的差距也就是计算损失函数求损失函数对模型参数w的梯度梯度梯度下降更新模型的参数使得估计的时间与真实时间越来越接近问题如果我想在到达亚特兰大之前就更新模型的参数w呢这时候就需要用TD算法了从纽约到亚特兰大要经过DC华盛顿我们可以到华盛顿后估计华盛顿到亚特兰大的时间假设纽约到亚特兰大要300分钟模型估计从纽约到亚特兰大要花1000分钟到华盛顿后发现用了300分钟300分钟是真实的观测模型估计从华盛顿到亚特兰大要花600分钟根据模型新的预测总的时间应该为900分钟新的估计900分钟叫做TD target虽然TD target也是估计值但比原来的1000分钟更可靠因为里面有事实的成分300分钟就是真实值因此当越接近亚特兰大时TD target越准确因此到达华盛顿就可以更新模型参数了损失函数就是最初的估计与TDtarget的差距的平方这个差距叫做TD error然后再做梯度下降更新模型的参数就行了TD算法的优点即使不完成整个旅途也能更新模型的参数改进模型1.4 TD learning应用TD算法到DQN的上个例子要用的公式整个旅途的时间和第二段时间都是模型的估计而第一段时间是真实的时间TD算法必须等式左边有一项右边有两项也右边的两项必须有一项是真实观测到的在深度强化学习中我们要应用的公式为简要证明应用TD算法到DQN上t时刻DQN输出的值Qst,at;w是对Ut作出的估计t1时刻DQN输出的值Qst1,at1;w是对Ut1作出的估计Qst,at;w类似于出发之前预计的时间Qst1,at1;w类似于到达华盛顿后预计的到亚特兰大的时间整个过程二、TD Learning algorithmsNotesSarsa和Q-Learning都是TD算法但是解决的问题不同Sarsa用来训练学习动作价值函数Qπs,aQ-learning用来训练最优动作价值函数Q*s,aQ-learning的TD target和Sarsa的TD target如下图所示Q-learning对Q*s,a求最大化而Sarsa没有最大化2.1 Sarsa算法首先来回顾一下TD算法Ut Rt r * U(t1) Qπst,at是在状态st和动作at下Ut的期望1表格形式的Sarsa算法我们的目标是学习Qπs,a如果状态和动作的数量是有限的那么我们可以画一张表格表中的一行对应一个状态一列对应一个动作表中的每个元素对应一个动作价值我们要做的就是用Sarsa算法来更新表格每次更新一个元素每次观测到一个四元组st,at,rt,st1;用策略函数π来计算下一个动作把下一个动作记为at1然后计算TD target yt这里的Qπst1,at1就是在表格中找到st1再找到动作at1把那个元素取出来该元素就是Qπst1,at1Qπst,at同理最后把Qπst,at写回表格对应的位置更新了表格里的值算法每次用五元组st,at,rt,st1,at1来更新动作价值函数Qπ该五元组首字母缩写就是Sarsa2神经网络形式的Sarsa算法我们的目标就是用神经网络qs,a;w近似Qπs,a跟表格形式的Sarsa算法类似不再赘述3总结Sarsa算法的目标就是学习动作价值函数Qπs,a表格形式的Sarsa算法直接学习Qπs,a条件是状态和动作数量有限神经网络形式的Sarsa算法通过神经网络qs,a;w近似Qπs,a每次通过五元组来更新神经网络的参数w2.2 Multi-step TD Target1One-step 只用一个轨迹去计算TD Target并且来更新动作价值一个轨迹包括(st,at,rt,st1),其中只有一个奖励rt算出的TD Target叫做One-step TD Target下一次用另一个轨迹去更新动作价值一直重复下去Multi-step TD Target使用多个奖励计算TD Target然后对动作价值进行更新比如同时使用两个奖励这样得到的TD Target叫做Multi-step TD Target然后再用后面两个奖励再对动作价值进行更新这样做的效果比One-step TD Target效果要好2Multi-Step Return我们可以让汇报包含两个奖励rt和rt1还可以包含三个奖励rt和rt1以及rt2然后可以递归下去还可以包含m个奖励这个公式叫做Multi-Step Return即多步汇报2.3 用于Sarsa算法的One-step TD Target和Multi-step TD Target用多个奖励值能够把Qπ训练的更好m1就变成了标准的TD Target2.4 用于Q-learning算法的One-step TD Target和Multi-step TD Targetm是一个超参数m大小合适的话多步 TD Target会比一步 TD Target效果更好三、价值学习代码示例3.1 Q-learning/DQN-离线学习代码importnumpyasnpimportrandomimporttorchimporttorch.nnasnnimporttorch.optimasoptimimportgymfromcollectionsimportdeque# 定义Q网络classQNetwork(nn.Module):def__init__(self,state_dim,action_dim,hidden_dim128):super(QNetwork,self).__init__()self.fc1nn.Linear(state_dim,hidden_dim)self.fc2nn.Linear(hidden_dim,hidden_dim)self.fc3nn.Linear(hidden_dim,action_dim)defforward(self,x):xtorch.relu(self.fc1(x))xtorch.relu(self.fc2(x))xself.fc3(x)returnx# 经验回放池classReplayBuffer:def__init__(self,capacity):self.bufferdeque(maxlencapacity)defpush(self,state,action,reward,next_state,done):self.buffer.append((state,action,reward,next_state,done))defsample(self,batch_size):batchrandom.sample(self.buffer,batch_size)state,action,reward,next_state,donemap(np.stack,zip(*batch))returnstate,action,reward,next_state,donedef__len__(self):returnlen(self.buffer)# 实现Q-learning算法使用深度Q网络即DQNdefdqn(env_name,learning_rate0.001,gamma0.99,num_episodes1000,batch_size64,buffer_capacity10000):envgym.make(env_name)state_dimenv.observation_space.shape[0]action_dimenv.action_space.n q_netQNetwork(state_dim,action_dim)target_netQNetwork(state_dim,action_dim)target_net.load_state_dict(q_net.state_dict())optimizeroptim.Adam(q_net.parameters(),lrlearning_rate)bufferReplayBuffer(buffer_capacity)epsilon1.0epsilon_min0.01epsilon_decay0.995forepisodeinrange(num_episodes):stateenv.reset()total_reward0doneFalsewhilenotdone:# ε-贪婪策略选择动作ifrandom.random()epsilon:actionenv.action_space.sample()else:state_tensortorch.FloatTensor(state)q_valuesq_net(state_tensor)actionq_values.argmax().item()next_state,reward,done,_env.step(action)total_rewardrewardbuffer.push(state,action,reward,next_state,done)statenext_state# 当缓冲区有足够数据时开始采样更新iflen(buffer)batch_size:states,actions,rewards,next_states,donesbuffer.sample(batch_size)statestorch.FloatTensor(states)actionstorch.LongTensor(actions)rewardstorch.FloatTensor(rewards)next_statestorch.FloatTensor(next_states)donestorch.BoolTensor(dones)# 计算当前Q值# 假设# q_net(states) 形状: [batch_size, action_dim]# actions 形状: [batch_size]# actions.unsqueeze(1) 形状: [batch_size, 1]# gather(1, actions.unsqueeze(1)) 选择每个样本对应的动作的Q值# 结果形状: [batch_size, 1]# squeeze(1) 形状: [batch_size]current_q_valuesq_net(states).gather(1,actions.unsqueeze(1)).squeeze(1)# 计算目标Q值# target_net(states) 形状: [batch_size, action_dim]# target_net(next_states) 的输出可能是# tensor([[ 1.2, -0.5], # 状态1: 左动作Q1.2, 右动作Q-0.5# [-0.1, 2.3], # 状态2: 左动作Q-0.1, 右动作Q2.3# [ 0.8, 0.6], # 状态3: 左动作Q0.8, 右动作Q0.6# [ 1.5, 1.4]]) # 状态4: 左动作Q1.5, 右动作Q1.4# .max(1) 的结果# values tensor([1.2, 2.3, 0.8, 1.5]) # 每个状态的最大Q值# indices tensor([0, 1, 0, 0]) # 对应最大Q值的动作索引# [0] 取 values# next_q_values tensor([1.2, 2.3, 0.8, 1.5])next_q_valuestarget_net(next_states).max(1)[0]target_q_valuesrewardsgamma*next_q_values*(~dones)lossnn.MSELoss()(current_q_values,target_q_values.detach())optimizer.zero_grad()loss.backward()optimizer.step()# 更新目标网络ifepisode%100:target_net.load_state_dict(q_net.state_dict())# 衰减εepsilonmax(epsilon_min,epsilon*epsilon_decay)ifepisode%1000:print(fEpisode{episode}, Total Reward:{total_reward}, Epsilon:{epsilon})env.close()# 运行DQN# dqn(CartPole-v1)3.2 Sarsa在线学习代码defsarsa(env_name,learning_rate0.001,gamma0.99,num_episodes1000):envgym.make(env_name)state_dimenv.observation_space.shape[0]action_dimenv.action_space.n q_netQNetwork(state_dim,action_dim)optimizeroptim.Adam(q_net.parameters(),lrlearning_rate)epsilon1.0epsilon_min0.01epsilon_decay0.995forepisodeinrange(num_episodes):stateenv.reset()# 根据当前Q网络和ε-贪婪策略选择初始动作state_tensortorch.FloatTensor(state)ifrandom.random()epsilon:actionenv.action_space.sample()else:q_valuesq_net(state_tensor)actionq_values.argmax().item()total_reward0doneFalsewhilenotdone:next_state,reward,done,_env.step(action)total_rewardreward# 选择下一个动作next_state_tensortorch.FloatTensor(next_state)ifrandom.random()epsilon:next_actionenv.action_space.sample()else:next_q_valuesq_net(next_state_tensor)next_actionnext_q_values.argmax().item()# 计算当前Q值和目标Q值# 与DQN算法唯一的区别就是计算下一个q值是不是选择Q值最大的动作别的和DQN差别不大current_qq_net(state_tensor)[action]next_qq_net(next_state_tensor)[next_action]target_qrewardgamma*next_q*(notdone)lossnn.MSELoss()(current_q,target_q.detach())optimizer.zero_grad()loss.backward()optimizer.step()statenext_state actionnext_action state_tensornext_state_tensor# 衰减εepsilonmax(epsilon_min,epsilon*epsilon_decay)ifepisode%1000:print(fEpisode{episode}, Total Reward:{total_reward}, Epsilon:{epsilon})env.close()# 运行SARSA# sarsa(CartPole-v1)总结以上就是今天要讲的内容本文简单介绍了价值学习。