【Python强化学习】时序差分法Sarsa算法和Qlearning算法在冰湖问题中实战(附源码)

女爷i 2023-09-30 18:17 145阅读 0赞

需要源码请点赞关注收藏后评论区留言私信~~~

时序差分算法

时序差分法在一步采样之后就更新动作值函数Q(s,a),而不是等轨迹的采样全部完成后再更新动作值函数。

在时序差分法中,对轨迹中的当前步的(s,a)的累积折扣回报G,用立即回报和下一步的(s^′,a^′)的折扣动作值函数之和r+γQ(s^′,a^′)来计算,即:

G=r+γQ(s^′,a^′)

在递增计算动作值函数时,用一个[0,1]之间的步长α来代替1/N(s,a)。动作值函数Q(s,a)的递增计算式为:

245d5f018d8247f0ba14ebd215c14d3e.png

Sarsa算法与Qlearning算法

在蒙特卡罗法中,当前状态s下,对动作的采样是完全依据Q(s,a)来进行的,选中a的概率与对应的Q(s,a)的大小成正比。在时序差分法中,对动作的采样采用ε-贪心策略,Q(s,a)最大的动作被选择的概率为ε/|A|+1−ε,其他动作被选择的概率为ε/|A|,|A|是动作空间的大小。

Sarsa算法的采样和改进都采用了ε-贪心策略,是同策略的算法。

Qlearning算法对动作的采样采用的是ε-贪心策略,而对动作值函数Q(s,a)的更新采用的是贪心策略,因此,它是异策略的算法:

2c2c399c522e45dea337a6bb1eb38b77.png

算法流程图如下

3fda6c0742cd48d480fe24356c6ab2cb.png

算法在冰湖问题中求解结果如下

b5f2fa265cdf4925a1454fda158a81c3.png

23169e0a97ad41cca9763d2c1ebe15b6.png

要注意的是,时序差分法也存在方差大,不稳定的问题,每次实验的得分可能会相差较大

部分代码如下

  1. # 基于贪心策略,根据当前状态s的所有动作值函数,采样输出动作值
  2. def greedy_sample(Q_s):
  3. # Q_s:状态s的所有动作值函数,一维数组
  4. max_Q = np.max( Q_s )
  5. action_list = np.where( max_Q == Q_s )[0] # 最大动作值函数可能有多个action对应
  6. a = np.random.choice( action_list )
  7. return a
  8. # 基于e-gredy贪心策略,根据当前状态s的所有动作值函数,采样输出动作值
  9. def epsilon_greedy_sample(Q_s, n_actions, epsilon):
  10. # Q_s:状态s的所有动作值函数,一维数组
  11. # <时表示利用,否则为探索
  12. if np.random.uniform(0,1) <= 1-epsilon:
  13. a = greedy_sample(Q_s)
  14. else:
  15. a = np.random.choice(n_actions)
  16. return a
  17. # 时序差分算法
  18. def TD(env, gamma=1.0, alpha=0.01, epsilon=0.1, n_episodes=10000, algorithm="Qlearning"):
  19. Q = np.zeros([env.observation_space.n, env.action_space.n]) # 用数组来存储动作值函数
  20. n_actions = env.action_space.n
  21. for i in range(n_episodes):
  22. # 开始一次尝试
  23. sum_rewards = 0
  24. steps = 0
  25. s = env.reset() # 获取初始s
  26. a = epsilon_greedy_sample(Q[s], n_actions, epsilon)
  27. # 逐步推进
  28. while(True):
  29. next_s, r, done, _ = env.step(a) # 执行动作a
  30. # e-gredy贪心策略得到下一动作a'
  31. next_a = epsilon_greedy_sample( Q[next_s], n_actions, epsilon )
  32. # 更新动作值函数
  33. if(done):
  34. Q[s, a] = Q[s, a] + alpha * ( r - Q[s, a] )
  35. else:
  36. if algorithm == "Qlearning":
  37. Q[s, a] = Q[s, a] + alpha * ( r + gamma * np.max(Q[next_s]) - Q[s, a] )
  38. else:
  39. Q[s, a] = Q[s, a] + alpha * ( r + gamma*Q[next_s, next_a] - Q[s, a] )
  40. # 更新当前s,a
  41. s = next_s
  42. a = next_a
  43. sum_rewards += r * gamma**steps
  44. steps += 1
  45. if(done):
  46. break
  47. #print('尝试次:%s: 共运行步数:%s, 本次累积折扣回报:%.1f' % (i+1, steps, sum_rewards))
  48. pi = []
  49. for s in range(env.observation_space.n):
  50. a = greedy_sample( Q[s] )
  51. pi.append(a)
  52. return pi

创作不易 觉得有帮助请点赞关注收藏~~~

发表评论

表情:
评论列表 (有 0 条评论,145人围观)

还没有评论,来说两句吧...

相关阅读