强化学习笔记:Q_learning (Q-table)示例举例

Posted UQI-LIUWJ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了强化学习笔记:Q_learning (Q-table)示例举例相关的知识,希望对你有一定的参考价值。

1 示例介绍

在右侧有宝藏,探险者到达宝藏所在的位置,就可以获得奖励

比如某一时刻的状态是这个样子的:“-o---T”

 T 就是宝藏的位置, o 是探索者的位置

如果在某个地点 s1, 探索者计算了他能有的两个行为, Q(s1, a1) > Q(s1, a2), 那么探索者就会选择 left 这个行为. 否则就是right

参考内容:小例子 - 强化学习 (Reinforcement Learning) | 莫烦Python (mofanpy.com)

2  导入库& 超参数设定

import numpy as np
import pandas as pd
import time

np.random.seed(2)  
# 随机种子

N_STATES = 6   
# 探宝者可能在的位置

ACTIONS = ['left', 'right']     
# 探索者的可用动作

EPSILON = 0.9   
# 贪婪度 greedy 
#0.9的概率选择最大的Q对应的action
#0.1的概率随机选action

ALPHA = 0.1     
# 学习率

GAMMA = 0.9    
# 奖励递减值

MAX_EPISODES = 13   
# 最大回合数

FRESH_TIME = 0.3    
# 移动间隔时间

3 创建Q-table

这是一个DataFrame

python 库整理:pandas_UQI-LIUWJ的博客-CSDN博客

index是目前探宝者的位置,columns是对应的动作
 

def build_q_table(n_states, actions):
    table = pd.DataFrame(
        np.zeros((n_states, len(actions))),     
        # q_table 初始状态全0
        columns=actions,    
        # columns 对应的是action名称
    )
    return table

#对于我们这个示例来说,出来的Q-table将会是
# q_table:
"""
   left  right
0   0.0    0.0
1   0.0    0.0
2   0.0    0.0
3   0.0    0.0
4   0.0    0.0
5   0.0    0.0
"""

4 定义动作

定义探宝者如何挑选行为的

这里我们使用ε-greedy

强化学习笔记: generalized policy iteration with MC_UQI-LIUWJ的博客-CSDN博客

# 在某个 state 地点, 选择行为
def choose_action(state, q_table):
    state_actions = q_table.iloc[state, :]  
    # 选出这个 state 的所有 action 值(把这一行挑出来 pd.Series)
    if (np.random.uniform() > EPSILON) or (state_actions.all() == 0): 
        # 非贪婪的10% , 或者这个 state 还没有探索过
        action_name = np.random.choice(ACTIONS)
        #exploration 探索
    else:
        action_name = state_actions.idxmax()    
        # 贪婪模式的90% 
        # exploitation 利用
    return action_name

5 设置状态转换和奖励reward

        做出行为后, 环境也要给我们的行为一个反馈, 反馈出下个 state (S_) 和 在上个 state (S) 做出 action (A) 所得到的 reward (R).

        这里定义的规则就是, 只有 移动到了 T, 探宝者才会得到唯一的一个奖励, 奖励值 R=1, 其他情况都没有奖励.

def get_env_feedback(S, A):
    # This is how agent will interact with the environment
    if A == 'right':    
        # move right
        if S == N_STATES - 2:   
            #现在在位置4,再往右1格是5,也就是宝藏所在的位置
            S_ = 'terminal'
            R = 1
        else:
            S_ = S + 1
            R = 0
    else:   
        # move left
        R = 0
        if S == 0:
            S_ = S  
            # 在最右侧,碰壁了,所以不变状态
        else:
            S_ = S - 1
    return S_, R

6 环境更新可视化

def update_env(S, episode, step_counter):
    env_list = ['-']*(N_STATES-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)
        #探宝者所在的位置替换为o

7 Q-learning

使用的是TD:

 

 

def rl():
    q_table = build_q_table(N_STATES, ACTIONS)  
    # 创建初始 q table

    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)   
            # 选行为(ε-greedy)

            S_, R = get_env_feedback(S, A)  
            # 实施行为并得到环境的反馈
            
            q_predict = q_table.loc[S, A]    # 估算的(状态-行为)值
            #Q(s,a)

            if S_ != 'terminal':
                q_target = R + GAMMA * q_table.iloc[S_, :].max()   
            #  实际的(状态-行为)值 (回合没结束)
            # q_table.iloc[S_, :].max()  ——>  max Q(s',a') 
            else:
                q_target = R     
                #  实际的(状态-行为)值 (回合结束)
                #没有后续状态了,所以也不用加那一项
                #当然get_env_feedback 当遇到terminal 的时候,直接返回'terminal' ,也算不出它的max Q(s',a') 
                is_terminated = True    
                # 此时已经到达terminal了
            
            #if-else的作用就是计算q-target,也就是TD更新里面 减号之前的部分

            q_table.loc[S, A] += ALPHA * (q_target - q_predict)  
            #  q_table 更新(TD)
            S = S_  
            # 探索者移动到下一个状态

            update_env(S, episode, step_counter+1)  
            # 环境更新
            '''
            如果在终点,那么输出这一回合的一些信息
            如果非重点,那么输出当前探宝者所在的状态
            '''

            step_counter += 1

            #一致循环,直到拿到宝藏为止
          print(q_table)

        return q_table

8 训练

直接调用函数即可

q_table = rl()
print(q_table)

在上面的实现中,命令行一次只会出现一行状态(这个是在update_env里面设置的('\\r'+end=''))

​​​​​​python笔记 print+‘\\r‘ (打印新内容时删除打印的旧内容)_UQI-LIUWJ的博客-CSDN博客

如果不加这个限制,我们看一个episode:

然后我们综合考量下每个episode之后的Q-table

138
222
39
45
57
65
75
85
95
105

可以发现 left  不会增长,但right的会一直增大 

 

 

 

 

 

 

 

 

 

以上是关于强化学习笔记:Q_learning (Q-table)示例举例的主要内容,如果未能解决你的问题,请参考以下文章

DQN

强化学习目录

强化学习笔记-01强化学习介绍

强化学习笔记-01强化学习介绍

强化学习笔记1:强化学习概述

强化学习笔记:强化学习的约束