运行有问题或需要源码请点赞关注收藏后评论区留下QQ~~~
一、时序差分预测
时序差分法(TD)TD方法将DP的自举性和MC的采样性相结合,学习时间间隔产生的差分数据,并通过迭代更新来求解未知环境模型的MDP问题
在时序差分预测中,每前进一步或N步,就可以直接计算状态值函数,接下来我们讨论单步情况TD(0)下的时序差分算法
TD(0)算法适用于小批量状态的更新方法,其中0表示向前行动一步,它的核心思想是向前行动一步后,使用得到的立即奖赏和下一状态的状态值函数的估计值来进行更新,这也是TD0被称为单步TD算法的原因
表格型TD(0)算法如下
二、时序差分控制
TD控制算法和MC控制算法一样,都遵循GPI,且评估的目标都是状态-动作对的最优动作值函数,为了平衡探索与利用,TD控制算法分为基于策略迭代的同策略Sarsa算法和基于值迭代的异策略Q-Learning算法,它们两个算法都属于TD(0)算法 它们的收敛性同样遵循MC增量式中的随机近似条件
三、扫地机器人实战
使用Sarsa算法解决确定环境扫地机器人的问题,将动作值函数设置为24×4的二维数组,这样当Sarsa算法使用具有贪心性质的策略时也会逐渐变得贪心。
运行结果可以看到,当迭代到20000个情节时,迭代已经收敛。
扫地机器人环境的搭建以及背景条件可参考如下链接
开始迭代时
迭代完成后输出如下
代码如下
from 扫地机器人gym环境 import GridWorldEnv import numpy as np np.random.seed(1) env = GridWorldEnv() #有效动作空间 def vilid_action_space(s): action_sacpe = [] if s % 5 != 0:#左 action_sacpe.append(0) if s % 5 != 4:#右 action_sacpe.append(1) if s <= 19:#上 action_sacpe.append(2) if s >= 5:#下 action_sacpe.append(3) return action_sacpe def policy_epsilon_greedy(s, Q, epsilon):#ε贪心策略 Q_s = Q[s] action = vilid_action_space(s) if np.random.rand() < epsilon: a = np.random.choice(action) else: index_a = np.argmax([Q_s[i] for i in action]) a = action[index_a] return a def print_dd(s, a, next_s, next_a, print_len, episode_i, Q,e_k,a_k): for i in range(1): if episode_i == int(print_len * (0.1 * i + 1)): if s == 21 and a == 1 and next_s == 22 and next_a == 1: print("*********************************单步的计算过程**************************************") print("alpha:"+str(a_k)) print("epsilon:"+str(e_k)) print("state:" + str(int(print_len * (0.1 * i + 1)))) print(Q[s][a]) print(Q[next_s][a]) print("update:"+str(Q[s, a] + a_k * (0.8 * Q[next_s, next_a] - Q[s, a]))) print("************************************************************************************") def trans(Q_S):#因为环境中动作顺序是左右上下,文章建模的动作顺序是上下左右,所以转换为文章中的顺序(上下左右)进行输出,并保存3位小数 new_Q = [] new_Q.append(round(Q_S[2],3)) new_Q.append(round(Q_S[3],3)) new_Q.append(round(Q_S[0],3)) new_Q.append(round(Q_S[1],3)) return new_Q def print_ff(list_q, Q, episode_i,epsilon_k,alpha_k): list_s = range(0,25) for em in list_q: if em == episode_i: print("*******************************情节数:%s*******************************"%(str(em))) for state in list_s: print("Q(%d,*) "%(state) + str(trans(Q[state]))) action = vilid_action_space(state) len_a = len(action) e_p = epsilon_k / float(len_a) prob = [] index_a = np.argmax([Q[state][i] for i in action]) for i in range(4):#计算epsilon if i not in action: prob.append(0.0) else: if i == action[index_a]: prob.append(1 - epsilon_k + e_p) else: prob.append(e_p) print('概率值:' + str(trans(prob))) print("epsilon_k: {}".format(epsilon_k)) print("alpha_k:{}".format(alpha_k)) def Attenuation(epsilon,alpha,episode_sum,episode):#epsilon和alpha衰减函数 epsilon = (float(episode_sum) - float(episode)) / float(episode_sum) * epsilon alpha = (float(episode_sum) - float(episode)) / float(episode_sum) * alpha return epsilon, alpha tate epsilon_k, alpha_k = Attenuation(epsilon,alpha,episode_num,episode_i) A = policy_epsilon_greedy(S, Q, epsilon_k) done = False print_ff(list_q,Q,episode_i,epsilon_k,alpha_k) while not done: next_S, R, done, _ = env.step(A) next_A = policy_epsilon_greedy(next_S, Q, epsilon_k) print_dd(S,A,next_S,next_A,3000,episode_i,Q,epsilon_k,alpha_k) Q[S, A] = Q[S,
创作不易 觉得有帮助请点赞关注收藏~~~