Q-learning
Q-Learning
Q值
Q值:在当前状态采取某个动作,(最大人生未来幸福度)使t+1时刻折扣未来奖励的最大值(未来每一步都采取最优策略的情况的累计折扣奖励值);
最佳策略
- π就是策略,找到当前状态下使得Q值最大的动作a,作为最佳策略
贝尔曼公式
- 当前状态下采取a动作的Q值=a动作后的奖励+下一个时刻最佳动作的Q值*γ
- 找到最后一刻的Q值就能递推出之前所有状态的Q值
off-policy 的 Q learning 如何决策和学习优化决策
根据 Q 表的估计, s1 中a2 的值比较大, 在 s1 采取了 a2, 并到达 s2, 这时开始更新用于决策的 Q 表, 接着并没有在实际中采取任何行为, 而是再想象自己在 s2 上采取了每种行为, 分别看看两种行为哪一个的 Q 值大, 比如说 Q(s2, a2) 的值比 Q(s2, a1) 的大, 所以我们把大的 Q(s2, a2) 乘上一个衰减值 γ(比如是0.9) 并加上到达s2时所获取的奖励 R (这里奖励为 0), 因为会获取实实在在的奖励 R ,将这个作为我现实中 Q(s1, a2) 的值, 但是之前是根据 Q 表估计 Q(s1, a2)值. 所以有了现实和估计值, 就能更新Q(s1, a2) , 根据 估计与现实的差距, 将这个差距乘以一个学习效率 α累加上老的 Q(s1, a2) 的值 变成新的值.
- α学习效率来决定这次的误差有多少是要被学习的,是一个小于1 的数
- 虽然用MaxQ(s2)估计下一个s2状态,但还没在s2做出任何行为,决策部分要等更新完了后再另外做
- Q(s1,a2)的现实中也包含了Q(s2)的最大估计; 将对下一步的衰减的最大估计和当前所得到的奖励当成这一步的现实
- Epsilon greedy用在决策上的一种策略, 比如 epsilon = 0.9 时, 就说明有90% 的情况我会按照 Q 表的最优值选择行为, 10%时间使用随机选行为
实例(一维)
例子的环境是一个一维世界, 在世界的右边有宝藏,T为探索者
-o---T
# T 就是宝藏的位置, o 是探索者的位置
- Q-learning 是一种记录行为值 (Q value) 的方法, 每种在一定状态的行为都会有一个值 Q(s, a), 就是说 行为 a
在 s 状态的值是 Q(s, a). s 在上面的探索者游戏中, 就是 o 所在的地点了. 而每一个地点探索者都能做出两个行为
left/right, 这就是探索者的所有可行的 a - 如果在某个地点 s1, 探索者计算了他能有的两个行为, a1/a2=left/right, 计算结果是 Q(s1, a1) > Q(s1,
a2), 那么探索者就会选择 left 这个行为. 这就是 Q learning 的行为选择简单规则.
预设值
import numpy as np
import pandas as pd
import time#控制探索者移动速度有多快
np.random.seed(2)#伪随机序列 虽然随机但每次产生的效果都是一样的
N_STATES = 6 # 一开始的距离离宝藏有多少步 一维的宽度
ACTIONS = ['left', 'right'] # 探索者的可用动作
EPSILON = 0.9 # 贪婪度 greedy
ALPHA = 0.1 # 学习率
GAMMA = 0.9 # 奖励递减值
MAX_EPISODES = 13 # 最大回合数
FRESH_TIME = 0.3 # 移动间隔时间
Q表
所有的 Q values (行为值) 放在 q_table 中, 更新 q_table 也是在更新他的行为准则.
#纵轴STATES s1,s2,s3…横轴左边右边
def build_q_table(n_states, actions):
table = pd.DataFrame(#建表
np.zeros((n_states, len(actions))), # q_table 全 0 初始
# columns=actions, # columns 对应的是行为名称
)
return table
···
0 1
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
定义动作
90% 的时间是选择最优策略,
10% 的时间来探索.
def choose_action(state, q_table):
state_actions = q_table.iloc[state, :] # 选出这个 state 的所有 action 值 iloc函数:通过行号来取行数据
if (np.random.uniform() > EPSILON) or (state_actions.all() == 0): # 非贪婪 or 或者这个 state 还没有探索过(初始化时)
action_name = np.random.choice(ACTIONS)#随机选择action里的动作
else:
action_name = state_actions.argmax() # 贪婪模式(选择最大的)argmax()获取数据最大的index
return action_name
环境反馈 S_, R
做出行为后, 环境也要给我们的行为一个反馈, 反馈出下个 state (S_) 和 在上个 state (S) 做出 action (A) 所得到的 reward ®.
这里定义的规则就是, 只有当 o 移动到了 T, 探索者才会得到唯一的一个奖励, 奖励值 R=1, 其他情况都没有奖励.
#环境反馈
def get_env_feedback(S, A):
if A == 'right': # move right
if S == N_STATES - 2: # terminate
S_ = 'terminal'
R = 1
else:
S_ = S + 1
R = 0
else: # move left
R = 0
if S == 0:
S_ = S # reach the wall
else:
S_ = S - 1
return S_, R
环境更新
def update_env(S, episode, step_counter):
# ‘-----------T’怎样在环境中移动
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)
强化学习主循环
#主循环
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) # 选行为
S_, R = get_env_feedback(S, A) # 实施行为并得到环境的反馈
q_predict = q_table.loc[S, A] # 估算的(状态-行为)值
if S_ != 'terminal':
q_target = R + GAMMA * q_table.iloc[S_, :].max() # 真实的(状态-行为)值 (回合没结束)
else:#回合终止
q_target = R # 真实的(状态-行为)值 (回合结束)
is_terminated = True # 终止断开while循环,直接回到for循环下一个回合
q_table.loc[S, A] += ALPHA * (q_target - q_predict) # q_table 更新 新的Q值=老的Q值+ALPHA * 误差值
S = S_ # 探索者移动到下一个 state
update_env(S, episode, step_counter+1) # 环境更新
step_counter += 1
return q_table
if __name__ == "__main__":
q_table = rl()#学习好后的qtable
print('\r\nQ-table:\n')
print(q_table)
···
Q-table:
left right
0 0.000001 0.005728
1 0.000271 0.032612
2 0.002454 0.111724
3 0.000073 0.343331
4 0.000810 0.745813
5 0.000000 0.000000