与Sarsa算法类似,Q Learning算法基于∈-贪婪算法进行选择,然后以如下方式迭代更新Q函数,但是与Sarsa算法不同的是,Q Learning算法在计算Q值时使用了贪婪算法,即选择使Q值最大的动作对应的Q值。
其中,表示学习率,表示衰减因子。st 和at 分别表示当前的状态以及采取的动作,st+1 表示下一个的状态,rt+1 表示当前状态采取动作后得到的奖励。
Q Learning算法的实现过程使用伪码描述如下:
初始化Q函数 while 没有达到设置的学习次数 { 初始化状态s0为随机值 根据∈-贪婪算法选择状态s0对应的动作a0 while 没有达到设置的学习步长并且s0不是结束状态 { 执行行为a0转移到状态s1,得到回报r 根据∈-贪婪算法选择状态s1对应的动作a1 更新Q(s0,a0) s0=s1 a0=a1 } }
我们可以发现Q Learning算法与Sarsa算法非常类似,区别就是更新Q值的方法不同,两者更新Q值的公式推导过程已经超出了本文的范围,有兴趣的读者可以参考由机械工业出版社出版的《多智能体机器学习:强化学习方法》。
我们尝试使用Q Learning算法来处理上一案例的金币问题,本例代码在本书对应的GitHub的code/qlearn-gold.py文件。
Q Learning算法处理金币问题的代码与Sarsa算法非常接近,我们重点介绍不同的地方。
我们同样设置一个学习周期内学习步长为20:
for t in range(20):
使用a0作用于环境,转移到状态s1,得到奖励值reward:
observation, reward, done, info = env.step(a0) s1=observation
根据贪婪算法获得s1对应的动作a1,注意这里使用的是贪婪算法而不是∈-贪婪算法:
a1 = greedy(Q,s1)
更新Q函数:
key0="%d_%s" % (s0, a0) key1="%d_%s" % (s1, a1) #更新Q函数 Q[key0] = Q[key0] + alpha * (reward + gamma * Q[key1] - Q[key0])
根据∈-贪婪算法获得s1对应的动作a1,并重新设置s0和a0。可以看出Q Learning算法最终选择执行的操作还是根据∈-贪婪算法,但是更新Q值使用的是贪婪算法对应的值:
a1 = epsilon_greedy(Q,s1,epsilon) a0=a1 s0=s1
运行程序,发现999次学习过程,拿到金币的次数为712次,其中121次是初始状态就在7,即一开始就拿到金币了,另外有273次初始状态为6或者8,即一开始就结束了,真正玩死的次数为14,代码如下:
Get Gold 994th Episode finished after 3 timesteps Get Gold 996th Episode finished after 2 timesteps Get Gold 998th Episode finished after 2 timesteps Get Gold 999th Episode finished after 1 timesteps episode:999 get gold:591 bad luck:273 good luck:121 lose:14