强化学习笔记: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:

 

2-1-1.png

 

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的会一直增大 

 

 

 

 

 

 

 

 

 

  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
std::shared_ptr是C++标准库中的一个智能指针类,用于管理动态分配的资源。它具有引用计数机制,可以实现多个指针共享同一个对象的所有权。 在给std::shared_ptr赋值时,有三种方式可以使用: 1) 拷贝赋值:使用一个std::shared_ptr初始化另一个std::shared_ptr,这将导致引用计数加1。 2) 移动赋值:使用std::make_shared或者直接赋值一个临时创建的std::shared_ptr,这将导致原来的std::shared_ptr失去对资源的所有权,引用计数转移。 3) 使用std::move:将一个std::unique_ptr移动给std::shared_ptr,这将导致原来的std::unique_ptr失去对资源的所有权,引用计数转移。 对于std::shared_ptr的成员函数功能,具体可以参考STL的文档或笔记。 关于std::shared_ptr的初始化,当使用裸指针初始化std::shared_ptr时,如果指针为nullptr,则std::shared_ptr的_M_ptr和_M_refcount都将为nullptr;否则,将分配内存并初始化控制块。 所以,std::shared_ptr可以用于管理动态分配的资源,并且可以共享资源的所有权。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [std::shared_ptr 详解](https://blog.csdn.net/baidu_31541363/article/details/95802210)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [[STL] std::shared_ptr笔记](https://blog.csdn.net/weixin_38734472/article/details/126486549)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UQI-LIUWJ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值