探索者学会走迷宫. 黄色的是天堂 (reward 1),
黑色的地狱 (reward -1).
算法
整个算法就是一直不断更新 Q table 里的值, 然后再根据新的值来判断要在某个 state 采取怎样的 action.
Qlearning 是一个 off-policy 的算法, 因为里面的 max action 让 Q table 的更新可以不基于正在经历的经验(可以是现在学习着很久以前的经验,甚至是学习他人的经验).
不过这一次的例子, 我们没有运用到 off-policy, 而是把 Qlearning 用在了 on-policy 上, 也就是现学现卖, 将现在经历的直接当场学习并运用.
代码形式
三个py文件。 maze_env 环境模块(python 自带的简单 GUI 模块 tkinter 来编写虚拟环境.教程),RL_brain如何决策,run_this# 如何提升循环
Qlearning 迭代更新部分
# 如何提升循环
from maze_eny import Maze
from RL_brain import QLearningTable
def update():
for episode in range(100):#100个回合
observation = env.reset()#环境给出的观测值(红点坐标(1,1),(1,2)。。)
while True:#,每个episode回合里
env.render()#环境重新刷新(要跟环境互动就要进行刷新)
action = RL.choose_action(str(observation))#基于观测值挑选动作 用str方式放在table中可以当做索引
observation_, reward, done = env.step(action)#在env中施加动作返回下一个状态 done代表跳到黑的部分回
# 合结束跳出while循环进入下个episode
RL.learn(str(observation), action, reward, str(observation_))#从(第一个observation,第一个observation
#施加的动作,施加动作得到的reward和跳到下一个状态)进行强化学习
observation = observation_
# break while loop when end of this episode
if done:
break
# end of game
print('game over')
env.destroy()
if __name__ == "__main__":
env = Maze()
RL = QLearningTable(actions=list(range(env.n_actions)))
env.after(100, update)
env.mainloop()
思维决策
代码主结构
class QLearningTable:
# 初始化
def __init__(self, actions, learning_rate=0.01, reward_decay=0.9, e_greedy=0.9):
# 选行为
def choose_action(self, observation):
# 更新Q表值
def learn(self, s, a, r, s_):
# 检测 state 是否存在
def check_state_exist(self, state):
# QLearning如何决策
import numpy as np
import pandas as pd
class QLearningTable:
def __init__(self, actions, learning_rate=0.01, reward_decay=0.9, e_greedy=0.9):
self.actions = actions # a list
self.lr = learning_rate
self.gamma = reward_decay
self.epsilon = e_greedy
self.q_table = pd.DataFrame(columns=self.actions, dtype=np.float64)#纵轴是有多少个state横轴标签是可用action
#初始化qtable是一个空的dataframe
def choose_action(self, observation):
self.check_state_exist(observation)#检验传入的observation中有没有在qtable中
if np.random.uniform() < self.epsilon:
# 根据最优选action
state_action = self.q_table.loc[observation, :]
action = np.random.choice(state_action[state_action == np.max(state_action)].index)#打乱action的位置
#因为选最优相同时永远选第一个位置上的
else:
# 随机选择action
action = np.random.choice(self.actions)
return action
def learn(self, s, a, r, s_):
self.check_state_exist(s_)#多了s_检验是否在qtable当中
q_predict = self.q_table.loc[s, a]
if s_ != 'terminal':
q_target = r + self.gamma * self.q_table.loc[s_, :].max() # next state is not terminal
else:
q_target = r # next state is terminal
self.q_table.loc[s, a] += self.lr * (q_target - q_predict) # 要修改的值
def check_state_exist(self, state):#检验下一个经历的state是不是之前已经经过的或者是从没经历过的state
#如果从来没有经历过state放到table中去
if state not in self.q_table.index:
# append new state to q table
self.q_table = self.q_table.append(#若不存在加入
pd.Series(
[0] * len(self.actions),#state在任何时候都是全0的
index=self.q_table.columns,
name=state,
)
)