参考资料:
非常感谢莫烦老师的教程
http://mnemstudio.org/path-finding-q-learning-tutorial.htm
http://www.cnblogs.com/dragonir/p/6224313.html
这篇文章也是用非常简单的说明将 Q-Learning 的过程给讲解清楚了
http://www.cnblogs.com/jinxulin/tag/%E5%A2%9E%E5%BC%BA%E5%AD%A6%E4%B9%A0/
还有感谢这位园友,将增强学习的原理讲解的非常清晰
这篇文章详细描写了 DQN 的演变过程,建议先看看
增强学习(一) ----- 基本概念
机器学习算法大致可以分为三种:
1. 监督学习(如回归,分类)
2. 非监督学习(如聚类,降维)
3. 增强学习
什么是增强学习呢?
增强学习(reinforcementlearning, RL)又叫做强化学习,是近年来机器学习和智能控制领域的主要方法之一。
定义: Reinforcement learning is learning what to do ----how to map situations to actions ---- so as to maximize a numerical reward signal.[1]
也就是说增强学习关注的是智能体(也就是agent)如何在环境中采取一系列行为,从而获得最大的累积回报。
强化学习的学习机制表明它是不断地与环境交互(可以看做是决策系统【采取action的系统】和环境的博弈),以试错的学习方式得到最优策略,是使得决策能力持续获取收益的关键技术。
强化学习以试错的机制与环境进行交互,通过最大化积累奖赏(R)的方式来学习最优策略,最简单的理解就是在训练的过程中,不断地去尝试,错了就惩罚,对了就奖励,由此训练得到各个状态环境当中最好的决策,例如骑车的过程,种瓜的过程。[4]
通过增强学习,一个智能体应该知道在什么状态下应该采取什么行为。RL是从环境状态到动作的映射的学习,我们把这个映射称为策略。
强化学习的问题,通常有如下特点:
- 不同的action产生不同的reward
- reward有延迟性
- 对某个action的reward是基于当前的state的
那么增强学习具体解决哪些问题呢,我们来举一些例子:
例1. flappy bird 是现在很流行的一款小游戏,不了解的同学可以点链接进去玩一会儿。现在我们让小鸟自行进行游戏,但是我们却没有小鸟的动力学模型,也不打算了解它的动力学。要怎么做呢? 这时就可以给它设计一个增强学习算法,然后让小鸟不断的进行游戏,如果小鸟撞到柱子了,那就获得-1的回报,否则获得0回报。通过这样的若干次训练,我们最终可以得到一只飞行技能高超的小鸟,它知道在什么情况下采取什么动作来躲避柱子。
例2. 假设我们要构建一个下国际象棋的机器,这种情况不能使用监督学习,首先,我们本身不是优秀的棋手,而请象棋老师来遍历每个状态下的最佳棋步则代价过于昂贵。其次,每个棋步好坏判断不是孤立的,要依赖于对手的选择和局势的变化。是一系列的棋步组成的策略决定了是否能赢得比赛。下棋过程的唯一的反馈是在最后赢得或是输掉棋局时才产生的。这种情况我们可以采用增强学习算法,通过不断的探索和试错学习,增强学习可以获得某种下棋的策略,并在每个状态下都选择最有可能获胜的棋步。目前这种算法已经在棋类游戏中得到了广泛应用。
可以看到,增强学习和监督学习的区别主要有以下两点:
1. 增强学习是试错学习(Trail-and-error),由于没有直接的指导信息,智能体要以不断与环境进行交互,通过试错的方式来获得最佳策略。
2. 延迟回报,增强学习的指导信息很少,而且往往是在事后(最后一个状态)才给出的,这就导致了一个问题,就是获得正回报或者负回报以后,如何将回报分配给前面的状态。(下面讲的Q-learning例子中,奖励是即时的,)
http://www.cnblogs.com/cjnmy36723/p/7017549.html Deep Q-Network 学习笔记(一)—— Q-Learning
http://www.cnblogs.com/cjnmy36723/p/7018860.html Deep Q-Network 学习笔记(二)—— Q-Learning与神经网络结合使用
Q-learning:
一,Q-learning思路
要解决的问题是:如上图 1.1 中有 5 个房间,分别被标记成 0-4,房间外可以看成是一个大的房间,被标记成 5,现在智能程序 Agent 被随机丢在 0-4 号 5 个房间中的任意 1 个,目标是让它寻找到离开房间的路(即:到达 5 号房间)。
图片描述如下:
图 1.2
给可以直接移动到 5 号房间的动作奖励 100 分,即:图1.2中,4 到 5 、 1 到 5 和 5 到 5 的红线。
在其它几个可移动的房间中移动的动作奖励 0 分。
如下图:
图 1.3
假设 Agent 当前的位置是在 2 号房间,这里就将 Agent 所在的位置做为“状态”,也就是 Agent 当前的状态是 2,当前 Agent 只能移动到 3 号房间,当它移动到 3 号房间的时候,状态就变为了 3,此时得到的奖励是 0 分。
而 Agent 根据箭头的移动则是一个“行为”。
根据状态与行为得到的奖励可以组成以下矩阵。R代表当前奖励
图 1.4
同时,可以使用一个 Q 矩阵,来表示 Agent 学习到的知识,在图 1.4 中,“-1”表示不可移动的位置,比如从 2 号房间移动到 1 号房间,由于根本就没有门,所以没办法过去。
图 1.5
该 Q 矩阵就表示 Agent 在各种状态下,做了某种行为后自己给打的分,也就是将经验数据化,由于 Agent 还没有行动过,所以这里全是 0。
在 Q-Learning 算法中,计算经验得分的公式如下:
Q(state, action) = Q(state, action) + α(R(state, action) + Gamma * Max[Q(next state, all actions)] - Q(state, action))
当 α 的值是 1 时,公式如下:
Q(state, action) = R(state, action) + Gamma * Max[Q(next state, all actions)]
state: 表示 Agent 当前状态。
action: 表示 Agent 在当前状态下要做的行为。
next state: 表示 Agent 在 state 状态下执行了 action 行为后达到的新的状态。
Q(state, action): 表示 Agent 在 state 状态下执行了 action 行为后学习到的经验,也就是经验分数。
R(state, action): 表示 Agent 在 state 状态下做 action 动作后得到的即时奖励分数。(注意是即时奖励,不是经验)
Max[Q(next state, all actions)]: 表示 Agent 在 next state 状态下,自我的经验中,最有价值的行为的经验分数。
Gamma: γ,表示折损率,也就是未来的经验对当前状态执行 action 的重要程度。
二,算法
Agent 通过经验去学习。Agent将会从一个状态到另一个状态这样去探索,直到它到达目标状态。我们称每一次这样的探索为一个场景(episode)。
每个场景就是 Agent 从起始状态到达目标状态的过程。每次 Agent 到达了目标状态,程序就会进入到下一个场景中。
1. 初始化 Q 矩阵,并将初始值设置成 0。
2. 设置好参数 γ 和得分矩阵 R。
3. 循环遍历场景(episode):
(1)随机初始化一个状态 s。
(2)如果未达到目标状态,则循环执行以下几步:
① 在当前状态 s 下,随机选择一个行为 a。
② 执行行为 a 得到下一个状态 s`。
③ 使用 Q(state, action) = R(state, action) + Gamma * Max[Q(next state, all actions)] 公式计算 Q(state, action) 。
④ 将当前状态 s 更新为 s`。
设当前状态 s 是 1, γ =0.8和得分矩阵 R,并初始化 Q 矩阵:
由于在 1 号房间可以走到 3 号房间和 5 号房间,现在随机选一个,选到了 5 号房间。
现在根据公式来计算,Agent 从 1 号房间走到 5 号房间时得到的经验分数 Q(1, 5) :
1.当 Agent 从 1 号房间移动到 5 号房间时,得到了奖励分数 100(即:R(1, 5) = 100)。
2.当 Agent 移动到 5 号房间后,它可以执行的动作有 3 个:移动到 1 号房间(0 分)、移动到 4 号房间(0 分)和移动到 5 号房间(0 分)。注意,这里计算的是经验分数,也就是 Q 矩阵,不是 R 矩阵!
所以,Q(1, 5) = 100 + 0.8 * Max[Q(5, 1), Q(5, 4), Q(5, 5)] = 100 + 0.8 * Max{0, 0, 0} = 100
(已经达到目标状态5,所以进入下一个场景episode)
在次迭代进入下一个episode:
随机选择一个初始状态,这里设 s = 3,由于 3 号房间可以走到 1 号房间、 2 号房间和 4 号房间,现在随机选一个,选到了 1 号房间。
步骤同上得:Q(3, 1) = 0 + 0.8 * Max[Q(1, 3), Q(1, 5)] = 0 + 0.8 * Max{0, 100} = 0 + 0.8 * 100 = 80
即:
三,程序实现
先引入 numpy:
import numpy as np
初始化:
#动作数。
ACTIONS = 6
# 探索次数。
episode = 100
# 目标状态,即:移动到 5 号房间。
target_state = 5
# γ,折损率,取值是 0 到 1 之间。
gamma = 0.8
# 经验矩阵。
q = np.zeros((6, 6))
def create_r():
r = np.array([[-1, -1, -1, -1, 0, -1],
[-1, -1, -1, 0, -1, 100.0],
[-1, -1, -1, 0, -1, -1],
[-1, 0, 0, -1, 0, -1],
[0, -1, -1, 1, -1, 100],
[-1, 0, -1, -1, 0, 100],
])
return r
执行代码:
特别注意红色字体部分,当程序随机到不可移动的位置的时候,直接给于死亡扣分,因为这不是一个正常的操作,比如 从 4 号房间移动到 1 号房间,但这两个房间根本没有门可以直接到。
至于为什么不使用公式来更新,是因为,如果 Q(4, 5)和Q(1, 5)=100分,
当随机到(4, 1)时,Q(4, 1)的经验值不但没有减少,反而当成了一个可移动的房间计算,得到 79 分,即:Q(4, 1) = 79,
当随机到(2, 1)的次数要比(4, 5)多时,就会出现Q(4, 1)的分数要比Q(4, 5)高的情况,这个时候,MaxQ 选择到的就一直是错误的选择。
if __name__ == '__main__':
r = create_r()
print("状态与动作的得分矩阵:")
print(r)
# 搜索次数。
for index in range(episode):
# Agent 的初始位置的状态。
start_room = np.random.randint(0, 5)
# 当前状态。
current_state = start_room
while current_state != target_state:
# 当前状态中的随机选取下一个可执行的动作。
current_action = np.random.randint(0, ACTIONS)
# 执行该动作后的得分。
current_action_point = r[current_state][current_action]
if current_action_point < 0:
q[current_state][current_action] = current_action_point
else:
# 得到下一个状态。
next_state = current_action
# 获得下一个状态中,在自我经验中,也就是 Q 矩阵的最有价值的动作的经验得分。
next_state_max_q = q[next_state].max()
# 当前动作的经验总得分 = 当前动作得分 + γ X 执行该动作后的下一个状态的最大的经验得分
# 即:积累经验 = 动作执行后的即时奖励 + 下一状态根据现有学习经验中最有价值的选择 X 折扣率
q[current_state][current_action] = current_action_point + gamma * next_state_max_q
current_state = next_state
print("经验矩阵:")
print(q)
start_room = np.random.randint(0, 5)
current_state = start_room
step = 0
while current_state != target_state:
next_state = np.argmax(q[current_state])
print("Agent 由", current_state, "号房间移动到了", next_state, "号房间")
current_state = next_state
step += 1
print("Agent 在", start_room, "号房间开始移动了", step, "步到达了目标房间 5")
参考资料:
[1] R.Sutton et al. Reinforcement learning: An introduction , 1998
[2] T.Mitchell. 《机器学习》,2003
[3] Andrew Ng.CS229: Machine learning Lecture notes
[4]深度学习,优化与识别,2017