我一直在阅读关于Q-learning和神经网络的内容。我认为我已经掌握了正确的概念,但是我想请教一下关于我的神经网络代码和使用Q值更新的部分是否正确。
我已经在MatLab中实现了山地车问题和我的神经网络,我使用了神经网络工具箱来处理神经网络部分。
这个网络有2个输入,5到20个隐藏层(用于实验),以及3个输出(对应于山地车中的动作)。
隐藏单元设置为tansig,输出为purelin,训练函数是traingdm。
这些步骤是否正确?
- 获取初始状态 s -> [-0.5; 0.0]
- 运行网络,Qs=net(s),这会给我一个1×3的矩阵,包含初始状态 s 下的每个动作的Q值。
- 使用ε-贪婪选择来选择动作 a
- 模拟山地车并获取 s’(执行动作 a 后的新状态)
- 运行网络,Qs_prime=net(s’),获取 s’ 的另一个Q值矩阵
现在,我不确定这部分是否正确,因为我需要弄清楚如何正确地更新神经网络的权重。
- 计算QTarget,即 = 奖励 + gamma * s’ 的最大Q值?
- 创建一个包含初始 s 的Q值的Targets矩阵(1×3),并将执行的动作 a 对应的Q值更改为QTarget
- 使用 net=Train(net,s,Targets) 来更新神经网络中的权重
- s=s’
- 对新的 s 重复上述所有步骤
示例:
actions 1 2 3Qs = 1.3346 -1.9000 0.2371selected action 3(corresponding to move mountain car forward)Qs' = 1.3328 -1.8997 0.2463QTarget=reward+gamma*max(Qs') = -1+1.0*1.3328 = 0.3328s= [-5.0; 0.0] and Targets = 1.3346 -1.9000 0.3328Or I have this wrong and the Targets are 0 0 0.3328 since we don't know how good the other actions are..
这是我的MatLab代码(我使用的是R2011版本和神经网络工具箱)
%create a neural networknum_hidden=5num_actions=3net= newff([-1.2 0.6; -0.07 0.07;], [num_hidden,num_actions], {'tansig', 'purelin'},'traingdm');%network weight and bias initalizationnet= init(net);%turn off the training windownet.trainParam.showWindow = false;%neural network training parametersnet.trainParam.lr=0.01;net.trainParam.mc=0.1;net.trainParam.epochs=100%parameters for q learningepsilon=0.9;gamma=1.0;%parameters for Mountain car taskmaxEpisodes =10;maxSteps=5000;reset=false;inital_pos=-0.5;inital_vel=0.0;%construct the inital states=[inital_pos;inital_vel];Qs=zeros(1,3);Qs_prime=zeros(1,3);%training for maxEpisodesfor i=1:maxEpisodes %each episode is maxSteps long for j = 1:maxSteps %run the network and get Q values for current state Qs-> vector of %current Q values for state s at time t Q(s_t) Qs=net(s); %select an action if (rand() <= epsilon) %returns max Q value over all actions [Qs_value a]=max(Qs); else %return a random number between 1 and 3(inclusive) a = randint(1,1,3)+1; end %simulate a step of Mountain Car [s_prime, action, reward, reset] = SimulateMC(s,a); %get new Q values for S_prime -> Q(s_t+1) Qs_prime=net(s_prime); %Compute Qtarget for weight updates given by r+y*max Q(s_t+1) over all %actions Q_target = reward+gamma*max(Qs_prime); %Create a Targets matrix with the orginal state s q-values Targets=Qs; %change q-value of the original action to the QTarget Targets(a)=Q_target; % update the network for input state s and targets [net TR]=train(net,s,Targets); %update the state for next step s=s_prime; %display exactly where the car is to user the NN learns if this output reaches -0.45 disp(s(1)) if reset==true bestSteps=j break end end %reset for new episode reset=false; s=[inital_pos;inital_vel];end%test the network%reset state s=[inital_pos;inital_vel]; for i=1:maxEpisodes for j=1:maxSteps %run the network and get Q values for current state Qs=net(s); %select the max action always [Qs_value a]=max(Qs); %simulate a step of Mountain Car [s_prime, action, reward, reset] = SimulateMC(s,a); s=s_prime; disp(s(1)) end s=[inital_pos;inital_vel]; end
谢谢
回答:
问题表示
使用神经网络来表示动作-值函数是一个好主意。已证明这在许多应用中效果很好。然而,对于Q函数来说,更自然的表示方法是接收组合状态-动作向量作为输入,并输出标量值的网络。但只要动作数量是有限且较少的,就应该可以像你那样做。只是要记住,严格来说,你不是在学习Q(s,a),而是多个共享相同权重的值函数V(s)(每个动作一个),除了最后一层之外。
测试
这是对Q函数的直接贪婪利用。应该是正确的。
学习
这里有几个需要考虑的陷阱。第一个是缩放。对于神经网络学习,你真的需要将输入缩放到相同的范围。如果你在输出层使用了S形激活函数,你可能还需要缩放目标值。
数据效率是另一个需要考虑的问题。你可以用每个转换样本多次更新网络。学习会更快,但你需要将每个转换样本存储在内存中。
在线与批量:如果你存储你的样本,你可以进行批量学习,避免最近的样本破坏已经学习的部分问题。
文献
你应该看看