Q-Learning 算法学习心得

写在前面的话: 留给以后的自己,先通俗的弄懂这个算法具体的效果,每一步怎么实现的,每一步的含义,然后实现这个算法,也可以仿写别人的例子,但是一定得写,这样我们就能从中得到一个正向反馈,才会更有动力,最后再去看算法对应的公式,也许就能看懂了呢~

1 Q-learning算法是智能体(agent)通过与环境进行不停的交互,并从环境中得到行为反馈,最终生成一个状态-行为的奖励表(Q table)。而我们的智能体(agent),根据这个q table来进行决策,完成人类交给她的各种任务的。

例如:一个agent为O,在一个二维的直线上,从左边移动到右边的目标点T处,即完成任务。

O_________________T

   对于以上的例子,O有从起始点到终点T这条线段长度状态(State    s),并且每个状态有左(left)、右(right)两种行为(Action    a),当O移动到T时,训练结束给予1的反馈(Reward    R),否则认为这次行为不是有益的,给予R 为 0	。
   根据上述例子描述,可以初始化一个Q表:(假设起始位置到T的长度仅为6)

q table:

S\A(Q(s,a))LR
000
100
200
300
400
500
600
    表格中列表示为状态State    ,行表示行为action,他们之间对应的值Q(s,a)得含义为:在状态s下,采取行为a,环境给出的反馈值。如当前表,Q(s|1, a|L) = 0表示目前环境给出的反馈值为0,当然 ,这是因为在初始化的时候我们的“O”还没有和环境进行交互,所以还没有从环境中学习到任何宝贵的经验。

下面我们通过下面的算法来更新我们的Q表中的每一个值:
这张图片来自莫烦Python
Q Table 更新清单:

  1. 首先我们有epsilon的概率(贪婪度greedy)去选择最大Q值的action,否则随机选择一个action;
  2. 我们执行这个a,通过和环境进行交互,它会给我们一个反馈r 和通过这个a智能体到达的下一个状态s_;
  3. 计算出Q(s,a)的估计值(也有说法叫做旧值),这个估计值是我们通过s和a在Q 表中查到的值;
  4. 计算出Q(s,a)的现实值(新值),这个现实值是指,环境给我们的反馈r,以及加上在新的状态s_下,我们采取最优的行为所得到的最大反馈乘以一个折扣因子。即,将下一步的衰减最大估计和当前的奖励当做当前步的现实奖励。个人理解为,当前状态s下采取的行为a对下一个状态s_的行为有影响,但是又不能将下一步行为得到的奖励全部归功于上一个状态s下选择的行为,所以会乘上一个衰减因子(折扣因子,一个意思)gamma,将二者之和作为当前状态s选择行为a的现实奖励;
  5. Q现实和Q估计(或者说是Q新值和Q旧值)做差,即得到一个误差。误差乘上学习因子(学习效率)alpha,再加上q表中原来s、a对应的值(Q估计/Q旧值),最后将计算得到的新的奖励值更新到Q表中;
  6. 将当前状态更新为s_,因为我们已经执行过a,到达s_的状态了。
    根据上面的更新步骤,我们可以进行Q  Table的更新,但是更新的步骤只进行一次(“O”进行一次探索到达“T”)可能无法完全的更新所有的Q值,所以我们会需要进行多次的迭代,来尽可能多的更新Q table中的值。

一次完整的算法清单:

开始迭代,迭代次数为完成目标次数
1 初始化环境env
2 从环境中获取初始状态
3 开始执行Q Table更新清单步骤:行为选择、行为实施、更新Q值、转移当前状态为最新状态
4 如果当前状态为完成目标的状态,即完成此次迭代

代码示例:

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@Author  :   
@Contact :   907177955@qq.com
@Time    :   2020/3/4 23:36 
@Desc    :
'''

import numpy as np
import pandas as pd
import time

np.random.seed(2)

N_STATE = 6  # the length of the 1 dimensional world
ACTIONS = ['left', 'right']  # available cations
EPSILON = 0.9  # greedy policies
ALPHA = 0.1  # learning rate
LAMBDA = 0.9  # discount factor
MAX_EPISODES = 13  # maximum episodes => training steps
FRESH_TIME = 0.3  # fresh time for one move, the cost of time to move for each step


def build_q_table(nstates, actions):
    table = pd.DataFrame(
        np.zeros((nstates, len(actions))),  # q_table initial values
        columns=actions  # action's name
    )
    print(table)  # show table
    return table


def choose_action(state, q_table):
    # This is how to choose an action
    state_actions = q_table.iloc[state, :]
    if np.random.uniform() > EPSILON or (state_actions.all() == 0):
        #
        action_name = np.random.choice(ACTIONS)
    else:  # act greedy(贪婪的,贪心的)
        action_name = state_actions.idxmax()
    return action_name


def get_env_feedback(S, A):
    # this is how agent will interact with the environment
    if A == 'right':  # move right
        if S == N_STATE - 2: # reach to the terminal
            S_ = 'terminal'
            R = 1
        else:
            S_ = S + 1
            R = 0
    else:  # move left
        R = 0
        if S == 0:  # reach the wall
            S_ = S
        else:
            S_ = S - 1
    return S_, R


def update_env(S, episode, step_counter):
    env_list = ['-'] * (N_STATE - 1) + ['T']
    if S == 'terminal':
        interaction = 'Episode %s: total steps = %s' % (episode+1, step_counter)
        print('\r{}'.format(interaction), end='')
        time.sleep(2)
        print('\r                  ', end='')
    else:
        env_list[S] = 'o'
        interaction = ''.join(env_list)
        print('\r{}'.format(interaction), end='')
        time.sleep(FRESH_TIME)


def rl():
    q_table = build_q_table(N_STATE, ACTIONS)
    for episode in range(MAX_EPISODES):
        step_counter = 0
        S = 0
        is_terminated = False
        update_env(S, episode, step_counter)
        while not is_terminated:
            # 真实的行为,有一定概率随机选择行为,否则选择反馈最大的行为
            A = choose_action(S, q_table)
            S_, R = get_env_feedback(S, A)
            # q 估计,指只选择q表中的反馈最大的action
            q_predict = q_table.ix[S, A]  # ix 既可以通过标签进行索引,也可以通过整数进行索引
            if S_ != 'terminal':
                # q 现实
                q_target = R + LAMBDA * q_table.iloc[S_, :].max()
            else:
                q_target = R
                is_terminated = True
            # 更新q表
            q_table.ix[S, A] += ALPHA * (q_target - q_predict)
            S = S_

            update_env(S, episode, step_counter+1)
            step_counter += 1
    return q_table


if __name__ == '__main__':
    q_table = rl()
    print(q_table)


运行结果:
在这里插入图片描述

参考

莫烦的教程

其他博客:
https://www.cnblogs.com/yifdu25/p/8169226.html
https://zhuanlan.zhihu.com/p/29213893

推荐一篇写的很好的文章:
https://blog.csdn.net/songrotek/article/details/50580904

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值