QLearning
QLearning并没有直接将这个Q值(q_target是估计值)直接赋予新的Q,而是采用渐进的方式类似梯度下降,朝target迈近一小步,取决于α,这就能够减少估计误差造成的影响。类似随机梯度下降,最后可以收敛到最优的Q值。
1.导入模块
from maze_env import Maze #环境模块
from RL_brain import QLearningTable #思考模块
2.更新迭代
def update():
#---------------------------------------------------------------------------------
#Reapeat(episode):学习100次
for episode in range(100):
#----------------------------------------------------------------------------------
# 初始化 state 的观测值;并开始内循环
observation = env.reset()
while True:
# 更新可视化环境
env.render()
#----------------------------------------------------------------------------------
# 1°Action
action = RL.choose_action(str(observation))
# 2°获得反馈S'(下一步观测值)和R(当前步奖励)和done (是否是掉下地狱或者升上天堂)
observation_, reward, done = env.step(action)
# 3°更新Q表:RL 从这个序列 (state, action, reward, state_) 中学习
RL.learn(str(observation), action, reward, str(observation_))
# 4°S'→state的观测值
observation = observation_
#------------------------------------------------------------------------------------
# 如果掉下地狱或者升上天堂, 这回合就结束了
if done:
break
# 结束游戏并关闭窗口
print('game over')
env.destroy()
if __name__ == "__main__":
# 定义环境 env 和 RL 方式
env = Maze()
RL = QLearningTable(actions=list(range(env.n_actions)))
# 开始可视化环境 env
env.after(100, update)
env.mainloop()
1.思维构架
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):
# 选行为
def choose_action(self, observation):
# 学习更新参数
def learn(self, s, a, r, s_):
# 检测 state 是否存在
def check_state_exist(self, state):
2、函数实现
2.1.初始化
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) # 初始 q_table
2.选行为choose_action
def choose_action(self, observation):
self.check_state_exist(observation) # 检测本 state 是否在 q_table 中存在
# 选择 action
if np.random.uniform() < self.epsilon: # 选择 Q value 最高的 action
state_action = self.q_table.loc[observation, :]
# 同一个 state, 可能会有多个相同的 Q action value, 所以我们乱序一下
action = np.random.choice(state_action[state_action == np.max(state_action)].index)
else: # 随机选择 action
action = np.random.choice(self.actions)
return action
3.学习更新参数(更新Q表)
def learn(self, s, a, r, s_):
self.check_state_exist(s_) # 检测 q_table 中是否存在 s_
q_predict = self.q_table.loc[s, a] # 获取Q预测值
if s_ != 'terminal': # 获取真实值
q_target = r + self.gamma * self.q_table.loc[s_, :].max() # 下个state不是终止符
else:
q_target = r # 下个 state 是终止符
# 更新Q表:更新对应的state-action 值
self.q_table.loc[s, a] += self.lr * (q_target - q_predict)
4.检测Q表中有无当前state—action值
如果还没有当前 state, 那我我们就插入一组全 0 数据, 当做这个 state 的所有 action 初始 values.
def check_state_exist(self, state):
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),
index=self.q_table.columns,
name=state,
)
)