极简Qlearning入门教程
在当前的机器学习中,主流方向为有监督学习、无监督学习以及强化学习,今天我想介绍的就是强化学习的一个小入门Qleaning算法。
回想我们小时候在妈妈的教育下进行学习,首先我们是什么都不会,但是在父母的教育下,慢慢地开始学习起来,比如看见猫,第一次见到不知道这是什么物种,于是妈妈告诉你这是猫,下次见到就知道了,这就是监督学习,当我们做出一个动作,立即得到反馈,而强化学习则不然,当我们做出动作的时候,却不会有立即的反馈,只能到结束才能知道效果,因此本人在学习的过程中,将网上的资料收集了一下,发现这篇文章是特别棒的http://mnemstudio.org/path-finding-q-learning-tutorial.htm
假设有这样的房间
这样看,我们可以将其进行建模:
这就是房间对应的图。我们首先将agent(机器人)处于任何一个位置,让他自己走动,直到走到5房间,表示成功。为了能够走出去,我们将每个节点之间设置一定的权重,能够直接到达5的边设置为100,其他不能的设置为0,这样网络的图为:
Qlearning中,最重要的就是“状态”和“动作”,状态表示处于图中的哪个节点,比如2节点,3节点等等,而动作则表示从一个节点到另一个节点的操作。
首先我们生成一个奖赏矩阵:
-1表示不可以通过
0表示可以通过
100表示直接到达终点
总结就是:R矩阵中非负的表示节点之间是可以相通的。
同时,我们创建一个Q表,表示学习到的经验,与R表同阶,初始化为0矩阵。
根据Q-learning转移方程:
S表示当前的状态
a表示当前的动作
s~表示下一个状态
a~表示下一个动作
λ为贪婪因子,0
下面就是Qlearning的学习步骤:
当Q表学习完以后,就可以根据Q表来选择路径。
看一个实际的例子
首先设定λ=0.8,R:
Q:
随机选择一个状态,比如1,查看状态1所对应的R表,也就是1可以到达3或5,随机地,我们选择5,根据转移方程:
于是,Q表为:
这样,到达目标,一次尝试结束。
接下来再选择一个随机状态,比如3,3对应的下一个状态有(1,2,4都是状态3对应的非负状态),随机地,我们选择1,这样根据算法更新:
这样,Q表为
到达1状态以后,可以直接到达5,这样一次训练也完成了。
这样,我们将上面的解答转换为代码,采用Python编写。
import numpy as np
import random
# 建立 Q 表
q = np.zeros((6, 6))
q = np.matrix(q)
# 建立 R 表
r = np.array([[-1, -1, -1, -1, 0, -1], [-1, -1, -1, 0, -1, 100], [-1, -1, -1, 0, -1, -1], [-1, 0, 0, -1, 0, -1],
[0, -1, -1, 0, -1, 100], [-1, 0, -1, -1, 0, 100]])
r = np.matrix(r)
# 贪婪指数
gamma = 0.8
开始训练:
for i in range(1000):
# 对每一个训练,随机选择一种状态
state = random.randint(0, 5)
while state != 5:
# 选择r表中非负的值的动作
r_pos_action = []
for action in range(6):
if r[state, action] >= 0:
r_pos_action.append(action)
next_state = r_pos_action[random.randint(0, len(r_pos_action) - 1)]
q[state, next_state] = r[state, next_state] + gamma * q[next_state].max()
state = next_state
经过训练后,Q表为
当我们的Q表训练好,就可以根据Q表来进行路径选择。
选择算法如下:
这样,对应的代码如下:
state = random.randint(0, 5)
print('机器人处于{}'.format(state))
count = 0
while state != 5:
if count > 20: # 如果尝试次数大于20次,表示失败
print('fail')
break
# 选择最大的q_max
q_max = q[state].max()
q_max_action = []
for action in range(6):
if q[state, action] == q_max: # 选择可行的下一个动作
q_max_action.append(action)
# 随机选择一个可行的动作
next_state = q_max_action[random.randint(0, len(q_max_action) - 1)]
print("the robot goes to " + str(next_state) + '.')
state = next_state
这样,整个训练效果就是这样。,整体代码如下:
import numpy as np
import random
# 建立 Q 表
q = np.zeros((6, 6))
q = np.matrix(q)
# 建立 R 表
r = np.array([[-1, -1, -1, -1, 0, -1], [-1, -1, -1, 0, -1, 100], [-1, -1, -1, 0, -1, -1], [-1, 0, 0, -1, 0, -1],
[0, -1, -1, 0, -1, 100], [-1, 0, -1, -1, 0, 100]])
r = np.matrix(r)
# 贪婪指数
gamma = 0.8
# 训练
for i in range(1000):
# 对每一个训练,随机选择一种状态
state = random.randint(0, 5)
while state != 5:
# 选择r表中非负的值的动作
r_pos_action = []
for action in range(6):
if r[state, action] >= 0:
r_pos_action.append(action)
next_state = r_pos_action[random.randint(0, len(r_pos_action) - 1)]
q[state, next_state] = r[state, next_state] + gamma * q[next_state].max()
state = next_state
print(q)
# 验证
for i in range(10):
print("第{}次验证".format(i + 1))
state = random.randint(0, 5)
print('机器人处于{}'.format(state))
count = 0
while state != 5:
if count > 20:
print('fail')
break
# 选择最大的q_max
q_max = q[state].max()
q_max_action = []
for action in range(6):
if q[state, action] == q_max:
q_max_action.append(action)
next_state = q_max_action[random.randint(0, len(q_max_action) - 1)]
print("the robot goes to " + str(next_state) + '.')
state = next_state
count += 1
输出效果:
如果觉得这篇文章有用,请留言,谢谢。