极简Qlearning教程(附Python源码)

极简Qlearning教程(附Python源码)

极简Qlearning入门教程


在当前的机器学习中,主流方向为有监督学习、无监督学习以及强化学习,今天我想介绍的就是强化学习的一个小入门Qleaning算法。

回想我们小时候在妈妈的教育下进行学习,首先我们是什么都不会,但是在父母的教育下,慢慢地开始学习起来,比如看见猫,第一次见到不知道这是什么物种,于是妈妈告诉你这是猫,下次见到就知道了,这就是监督学习,当我们做出一个动作,立即得到反馈,而强化学习则不然,当我们做出动作的时候,却不会有立即的反馈,只能到结束才能知道效果,因此本人在学习的过程中,将网上的资料收集了一下,发现这篇文章是特别棒的mnemstudio.org/path-fin



假设有这样的房间


这样看,我们可以将其进行建模:



这就是房间对应的图。我们首先将agent(机器人)处于任何一个位置,让他自己走动,直到走到5房间,表示成功。为了能够走出去,我们将每个节点之间设置一定的权重,能够直接到达5的边设置为100,其他不能的设置为0,这样网络的图为:




Qlearning中,最重要的就是“状态”和“动作”,状态表示处于图中的哪个节点,比如2节点,3节点等等,而动作则表示从一个节点到另一个节点的操作。


首先我们生成一个奖赏矩阵:


  1. -1表示不可以通过
  2. 0表示可以通过
  3. 100表示直接到达终点

总结就是:R矩阵中非负的表示节点之间是可以相通的。


同时,我们创建一个Q表,表示学习到的经验,与R表同阶,初始化为0矩阵。


根据Q-learning转移方程:



  1. S表示当前的状态
  2. a表示当前的动作
  3. s~表示下一个状态
  4. a~表示下一个动作
  5. λ为贪婪因子,0<λ<1,一般设置为0.8

下面就是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

输出效果:





如果觉得这篇文章有用,请留言,谢谢。

发布于 2017-09-10 17:54