强化学习笔记: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
1 | 38 | |
2 | 22 | |
3 | 9 | |
4 | 5 | |
5 | 7 | |
6 | 5 | |
7 | 5 | |
8 | 5 | |
9 | 5 | |
10 | 5 |
可以发现 left 不会增长,但right的会一直增大
以上是关于强化学习笔记:Q_learning (Q-table)示例举例的主要内容,如果未能解决你的问题,请参考以下文章