强化学习7-Sarsa
之前讲到时序差分是目前主流强化学习的基本思路,这节就学习一下主流算法之一 Sarsa模型。
Sarsa 是免模型的控制算法,是通过更新状态动作价值函数来得到最优策略的方法。
更新方法 Q(S,A)=Q(S,A)+α(R+γQ(S′,A′)−Q(S,A))
// 回顾一下蒙特卡罗的更新方式 Q(S,A)=Q(S,A)+1/N(S,A)*(R+γQ(S′,A′)−Q(S,A))
// 学习率α不同,目标价值函数R+γQ(S′,A′)不同
Sarsa 算法流程
输入:{S, A, R, α, γ, ε}, 迭代轮数T
输出:所有的状态和动作对应的价值Q
1. 随机初始化所有的状态和动作对应的价值Q. 对于终止状态其Q值初始化为0.
2. for i from 1 to T,进行迭代。
a) 初始化S为当前状态序列的第一个状态。设置A为ε-贪婪法在当前状态S选择的动作。
b) 在状态S执行当前动作A,得到新状态S’和奖励R
c) 用 ε-贪婪法在状态S'选择新的动作A'
d) 更新价值函数Q(S,A)
e) S=S′,A=A′
f) 如果S'是终止状态,当前轮迭代完毕,否则跳转到步骤b)
保障收敛的措施
1. 步长α一般需要随着迭代的进行逐渐变小,这样才能保证动作价值函数Q可以收敛。当Q收敛时,策略ε-贪婪法也就收敛了。
2. ε探索率随着迭代的进行逐渐减小
Sarsa算法实例 Windy GridWorld
下面我们用一个著名的实例Windy GridWorld来研究SARSA算法。
如下图一个10×7的长方形格子世界,标记有一个起始位置 S 和一个终止目标位置 G,格子下方的数字表示对应的列中一定强度的风。当个体进入该列的某个格子时,会按图中箭头所示的方向自动移动数字表示的格数,借此来模拟世界中风的作用。同样格子世界是有边界的,个体任意时刻只能处在世界内部的一个格子中。个体并不清楚这个世界的构造以及有风,也就是说它不知道格子是长方形的,也不知道边界在哪里,也不知道自己在里面移动移步后下一个格子与之前格子的相对位置关系,当然它也不清楚起始位置、终止目标的具体位置。但是个体会记住曾经经过的格子,下次在进入这个格子时,它能准确的辨认出这个格子曾经什么时候来过。格子可以执行的行为是朝上、下、左、右移动一步,每移动一步只要不是进入目标位置都给予一个 -1 的惩罚,直至进入目标位置后获得奖励 0 同时永久停留在该位置。现在要求解的问题是个体应该遵循怎样的策略才能尽快的从起始位置到达目标位置。

# encoding:utf-8
import numpy as np world_size = [7, 10]
world = np.zeros(world_size) start = [3, 0]
end = [3, 7]
# end = [6, 9] actions = [[-1, 0], [1, 0], [0, -1], [0, 1]] # 上下左右
alpha = 0.05
rd = 1 # 衰减因子 q = np.zeros([world_size[0] * world_size[1], len(actions)]) def get_q_x(stat):
# 根据状态找到在q表中的行数
return stat[0] * world_size[1] + stat[1] def R(stat, action):
# 奖励函数
if stat[0] + action[0] == end[0] and stat[1] + action[1] == end[1]:
return 0
else:
return -1 def stat_change(stat, action):
# 无风状态转移
new_stat = []
new_x = stat[0] + action[0]
if new_x < 0:
new_stat.append(0)
elif new_x > world_size[0] - 1:
new_stat.append(world_size[0] - 1)
else:
new_stat.append(new_x) new_y = stat[1] + action[1]
if new_y < 0:
new_stat.append(0)
elif new_y > world_size[1] - 1:
new_stat.append(world_size[1] - 1)
else:
new_stat.append(new_y) return new_stat def stat_change(stat, action):
# 有风状态转移
f = [0, 0, 0, -1, -1, -1, -2, -2, -1, 0]
new_stat = []
new_x = stat[0] + action[0] + f[stat[1]]
if new_x < 0:
new_stat.append(0)
elif new_x > world_size[0] - 1:
new_stat.append(world_size[0] - 1)
else:
new_stat.append(new_x) new_y = stat[1] + action[1]
if new_y < 0:
new_stat.append(0)
elif new_y > world_size[1] - 1:
new_stat.append(world_size[1] - 1)
else:
new_stat.append(new_y) return new_stat def choose_max(stat):
# 选择最大价值
q_stat = q[get_q_x(stat),:].tolist() max_q = max(q_stat)
max_q_count = q_stat.count(max_q)
if max_q_count == 1:
# 最大的q只有一个
action = actions[q_stat.index(max_q)]
return max_q, R(stat, action), stat_change(stat, action), action
else:
# 最大的q不止一个,随机选一个
indexs = [ind for ind, value in enumerate(q_stat) if value == max_q]
index_choose = indexs[np.random.randint(0, len(indexs) - 1)]
return q_stat[index_choose], R(stat, actions[index_choose]), stat_change(stat, actions[index_choose]), actions[index_choose] def choose(stat):
# e贪心策略
if np.random.rand() > 0.3:
maxq, r, stat_, action = choose_max(stat)
else:
index = np.random.randint(0, len(actions) - 1)
q_stat = q[get_q_x(stat),:]
maxq, r, stat_, action = q_stat[index], R(stat, actions[index]), stat_change(stat, actions[index]), actions[index]
return maxq, r, stat_, action for i in range(10000):
# 10000 轮
maxq0, r0, stat_0, action0 = choose(start)
while True:
stat_ = stat_change(start, action0)
if stat_ == end:
start = [3, 0]
break maxq, r, stat__, action = choose(stat_)
q[get_q_x(start), actions.index(action0)] += alpha * (r0 + maxq - q[get_q_x(start), actions.index(action0)])
start = stat_
action0 = action print(q) # 路径
start = [3, 0]
world[start[0], start[1]] = 1
world[end[0], end[1]] = 1 while True:
world[start[0], start[1]] = 1 q_stat = q[get_q_x(start),:].tolist()
act = actions[q_stat.index(max(q_stat))]
stat_ = stat_change(start, act)
start = stat_
if stat_ == end:break print(world)
最优路线图

Sarsa(λ)
Sarsa(λ)对应多步TD(λ),它也有前向和后向两种价值迭代的方式,当然也是等价的。
在控制算法中,常用后向迭代的方式,数据学习完即可丢弃,因此 Sarsa(λ)算法默认都是基于反向来进行价值函数迭代。
Sarsa(λ)算法流程
输入:{S A R π γ ε} , 迭代轮数T,α衰减因子, ε衰减因子
输出:q表
1. 随机初始化所有的状态和动作对应的价值Q. 对于终止状态其Q值初始化为0.
2. for i from 1 to T,进行迭代。
a) 初始化所有状态动作的效用迹E为0,初始化S为当前状态序列的第一个状态。设置A为ϵ−贪婪法在当前状态S选择的动作。
b) 在状态S执行当前动作A,得到新状态S’和奖励R
c) 用ε-贪婪法在状态S’选择新的动作A'
d) 更新效用迹函数E(S,A)和TD误差δ:
e) 对当前序列所有出现的状态s和对应动作a, 更新价值函数Q(s,a)和效用迹函数E(s,a):
f) S=S′,A=A′
g) 如果S'是终止状态,当前轮迭代完毕,否则跳转到步骤b)
保障收敛的措施
1.步长α一般需要随着迭代的进行逐渐变小,这样才能保证动作价值函数Q可以收敛。当Q收敛时,策略ε-贪婪法也就收敛了。
2.ε 探索率随着迭代的进行逐渐减小
3. Sarsa(λ)尤其要注意,如果不采取措施,真的可能无法收敛
上述实例的Sarsa(λ)方法
def choose(stat, echo):
# e贪心策略
if np.random.rand() > 0.3 - echo * rd: # 探索率衰减
maxq, r, stat_, action = choose_max(stat)
else:
index = np.random.randint(0, len(actions) - 1)
q_stat = q[get_q_x(stat),:]
maxq, r, stat_, action = q_stat[index], R(stat, actions[index]), stat_change(stat, actions[index]), actions[index]
return maxq, r, stat_, action for i in range(10000):
# 10000 轮
es = np.zeros([world_size[0] * world_size[1], len(actions)])
maxq0, r0, stat_0, action0 = choose(start, i)
while True:
stat_ = stat_change(start, action0)
es[get_q_x(start), actions.index(action0)] += 1 maxq, r, stat__, action = choose(stat_, i)
delta = r0 + maxq - q[get_q_x(start), actions.index(action0)] if stat_ == end:
start = [3, 0]
break q += (alpha - i * 0.0000001) * delta * es # alpha 衰减
es[get_q_x(start), actions.index(action0)] *= 0.5 * rd start = stat_
action0 = action
效果同Sarsa
总结
优点:Sarsa非常灵活,不需要状态转移矩阵,不需要完整序列,在传统强化学习中应用广泛
缺点:不能处理非常复杂的问题,因为通过q表来存储数据,如果sa太大,内存将无法承受
强化学习7-Sarsa的更多相关文章
- 强化学习 - Q-learning Sarsa 和 DQN 的理解
本文用于基本入门理解. 强化学习的基本理论 : R, S, A 这些就不说了. 先设想两个场景: 一. 1个 5x5 的 格子图, 里面有一个目标点, 2个死亡点二. 一个迷宫, 一个出发点, ...
- 强化学习之Sarsa (时间差分学习)
上篇文章讲到Q-learning, Sarsa与Q-learning的在决策上是完全相同的,不同之处在于学习的方式上 这次我们用openai gym的Taxi来做演示 Taxi是一个出租车的游戏,把顾 ...
- 强化学习(六)时序差分在线控制算法SARSA
在强化学习(五)用时序差分法(TD)求解中,我们讨论了用时序差分来求解强化学习预测问题的方法,但是对控制算法的求解过程没有深入,本文我们就对时序差分的在线控制算法SARSA做详细的讨论. SARSA这 ...
- 强化学习(三)—— 时序差分法(SARSA和Q-Learning)
1.时序差分法基本概念 虽然蒙特卡洛方法可以在不知道状态转移概率矩阵的前提下,灵活地求解强化学习问题,但是蒙特卡洛方法需要所有的采样序列都是完整的状态序列.如果我们没有完整的状态序列就无法用蒙特卡洛方 ...
- 【转载】 强化学习(六)时序差分在线控制算法SARSA
原文地址: https://www.cnblogs.com/pinard/p/9614290.html ------------------------------------------------ ...
- 爬格子问题(经典强化学习问题) Sarsa 与 Q-Learning 的区别
SARSA v.s. Q-learning 爬格子问题,是典型的经典强化学习问题. 动作是上下左右的走,每走一步就会有一个-1的奖赏.从初始状态走到最终的状态,要走最短的路才能使奖赏最大.图中有一个悬 ...
- 【强化学习RL】model-free的prediction和control —— MC,TD(λ),SARSA,Q-learning等
本系列强化学习内容来源自对David Silver课程的学习 课程链接http://www0.cs.ucl.ac.uk/staff/D.Silver/web/Teaching.html 本文介绍了在m ...
- 强化学习中的无模型 基于值函数的 Q-Learning 和 Sarsa 学习
强化学习基础: 注: 在强化学习中 奖励函数和状态转移函数都是未知的,之所以有已知模型的强化学习解法是指使用采样估计的方式估计出奖励函数和状态转移函数,然后将强化学习问题转换为可以使用动态规划求解的 ...
- 强化学习读书笔记 - 06~07 - 时序差分学习(Temporal-Difference Learning)
强化学习读书笔记 - 06~07 - 时序差分学习(Temporal-Difference Learning) 学习笔记: Reinforcement Learning: An Introductio ...
- 强化学习(十七) 基于模型的强化学习与Dyna算法框架
在前面我们讨论了基于价值的强化学习(Value Based RL)和基于策略的强化学习模型(Policy Based RL),本篇我们讨论最后一种强化学习流派,基于模型的强化学习(Model Base ...
随机推荐
- 暂时关闭 windows 病毒防护
- 串的模式匹配算法 ------ KMP算法
//KMP串的模式匹配算法 #include <stdio.h> #include <stdlib.h> #include <string.h> int* get_ ...
- Python记录_day21 模块
引入模块的方式: 1. import 模块 2. from xxx import 模块 一.collections 模块 1.Counter() counter是一个计数器,主要用来计数,计算一个字符 ...
- 『计算机视觉』经典RCNN_其一:从RCNN到Faster-RCNN
RCNN介绍 目标检测-RCNN系列 一文读懂Faster RCNN 一.目标检测 1.两个任务 目标检测可以拆分成两个任务:识别和定位 图像识别(classification)输入:图片输出:物体的 ...
- java多线程wait()方法必须放在while循环里面的原因探析
1.写一个包子生产消费案例:一次生产或消费一个包子,有包子就消费,没有就生产.(部分代码参考传智播客刘意2015Java基础视频讲义) 1.1 写一个Baozi.class,包含main()方法,用来 ...
- Spring boot(六)优雅使用mybatis
orm框架的本质是简化编程中操作数据库的编码,发展到现在基本上就剩两家了,一个是宣称可以不用写一句SQL的hibernate,一个是可以灵活调试动态sql的mybatis,两者各有特点,在企业级系统开 ...
- 【CSS】【1】让DIV中的文字换行显示
<div style="white-space:normal;word-break:break-all;word-wrap:break-word;">data</ ...
- Hash应用例子
八.Hash应用例子搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节.假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复 ...
- Leetcode 117
if(root == NULL) return; queue<TreeLinkNode *> que; que.push(root); while(!empty(que)){ int le ...
- js浮点数相加、减、乘、除精确计算
js 浮点数计算时 ,无缘无辜 后边冒出一堆 小数点………… 貌似js本身的问题,类型不定?????? 只能自己写函数处理.. http://blog.csdn.net/w4bobo/article ...