强化学习之路1——Q-learning

it2022-05-05  115

Q-learning算法

最近在学强化学习,看了不少的教程,还是觉得莫烦大神的强化学习教程写的不错。所以,特意仔细研究莫烦的RL代码。在这贴上自己的理解。 莫烦RL教程:https://morvanzhou.github.io/tutorials/machine-learning/reinforcement-learning/ 代码:https://github.com/MorvanZhou/Reinforcement-learning-with-tensorflow/tree/master/contents

1.Q-learning算法的决策

Q-learning算法是如何决策的呢? 原来Q-learning算法会生成一个Q表,agent每一次要采取的action,都会根据当前agent的state去Q表中查找奖励(reward)最高的动作。 就这样,agent每次采取动作都去Q表中查找.以此来决策agent的下一步的action。

2.Q-learning算法的更新

假如有如下的Q表

-a1a2s1-21s2-42

现在agent在s1状态,根据前文说的算法决策方法Q(s1,a1) < Q(s1,a2),所以接下来会采取a2这个动作,并到达s2状态。 我们来更新Q表。接下来的我们没有在实际中采取任何动作,而是想想自己在S2状态下采取的动作,分别看看在S2状态下哪个动作的Q值最大。 比如说Q(s2,a2) > Q(s2,a1),所以把大的Q(s2,a2)乘一个gamma并加上到达s2时的奖励R,把这个作为现实中Q(s1,a2)的值。也就是 ‘Q现实’。 Q现实 = R + γ*maxQ(s2) 之前的根据Q表得到的Q(s1,a2)是Q表估计的值,也就是‘Q估计’。 Q估计 = Q(s1,a2) 有了 Q现实 和 Q估计,就可以更新Q(s1,a2)。

Q(s1,a2) = Q(s1,a2) + α * (Q现实 - Q估计)

但时刻记住, 我们虽然用 maxQ(s2) 估算了一下 s2 状态, 但还没有在 s2 做出任何的行为, s2 的行为决策要等到更新完了以后再重新另外做. 这就是 off-policy 的 Q learning 是如何决策和学习优化决策的过程.

3.Q-learning整体算法

[站外图片上传中…(image-6af5ac-1563434302631)] 这一张图概括了我们之前所有的内容. 这也是 Q learning 的算法, 每次更新我们都用到了 Q 现实和 Q 估计, 而且 Q learning 的迷人之处就是 在 Q(s1, a2) 现实 中, 也包含了一个 Q(s2) 的最大估计值, 将对下一步的衰减的最大估计和当前所得到的奖励当成这一步的现实, 很奇妙吧. 最后我们来说说这套算法中一些参数的意义. Epsilon greedy 是用在决策上的一种策略, 比如 epsilon = 0.9 时, 就说明有90% 的情况我会按照 Q 表的最优值选择行为, 10% 的时间使用随机选行为. alpha是学习率, 来决定这次的误差有多少是要被学习的, alpha是一个小于1 的数. gamma 是对未来 reward 的衰减值。

4.探索者小游戏——代码实现

会用 tabular Q-learning 的方法实现一个小例子, 例子的环境是一个一维世界, 在世界的右边有宝藏, 探索者只要得到宝藏尝到了甜头, 然后以后就记住了得到宝藏的方法, 这就是他用强化学习所学习到的行为.

-o---T # T 就是宝藏的位置, o 是探索者的位置

4.1模块和参数

import numpy as np import pandas as pd import time N_STATES = 6 # 1维世界的宽度 -o---T ACTIONS = ['left', 'right'] # 动作列表 EPSILON = 0.9 # 贪婪度 ALPHA = 0.1 # 学习率 GAMMA = 0.9 # 奖励衰减值 MAX_EPISODES = 13 # 训练次数(回合数)/游戏运行次数 FRESH_TIME = 0.3 # 移动间隔时间

4.2创建Q表

## 创建Q表 def build_q_table(n_states, actions): table = pd.DataFrame( np.zeros((n_states, len(actions))), # 初始化Q表,值为0 columns=actions, # 列的名字为动作的名称 ) #print(table) # show table return table

4.3动作的选择

## 在某状态时,选择动作 def choose_action(state, q_table): # iloc 选择state行的 动作的值,类型还是 Dataframe state_actions = q_table.iloc[state, :] ''' np.random.uniform(low=0.0, high=1.0, size=None) 随机数''' # 大于贪婪度 or 这个 state 未探索过, 则随机选择一个动作 if (np.random.uniform() > EPSILON) or ((state_actions == 0).all()): action_name = np.random.choice(ACTIONS) else: # 否则采取贪婪模式 action_name = state_actions.idxmax() return action_name

4.4环境的反馈

## 游戏环境给我们的行为一个反馈(环境) 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: # 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

4.5游戏环境更新

## 游戏环境更新(环境) def update_env(S, episode, step_counter): # This is how environment be updated env_list = ['-']*(N_STATES-1) + ['T'] # '---------T' our environment 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)

4.6Q-learning算法核心

## tabular Q learning 算法的核心 def rl(): # main part of RL loop q_table = build_q_table(N_STATES, ACTIONS) # 创建Q表 for episode in range(MAX_EPISODES): # 游戏运行次数 step_counter = 0 # 步数计数 S = 0 # agent 现在的 state is_terminated = False # 游戏是否结束的 flag update_env(S, episode, step_counter) # 更新游戏环境 while not is_terminated: # 只要游戏未结束 A = choose_action(S, q_table) # 根据现在的state 和 Q表 选择下一步的动作 # 根据State 和 Action,来获得环境的反馈(下一步的State,奖励) S_, R = get_env_feedback(S, A) q_predict = q_table.loc[S, A] # Q估计——也就是之前储存在Q表中的Q(s,a)值 if S_ != 'terminal': # 接下来的state不是terminal,也就是游戏未结束 q_target = R + GAMMA * q_table.iloc[S_, :].max() # Q现实值,见Q-learning算法 else: q_target = R # S_接下来的state为terminal,也就是游戏结束,Q现实 = R is_terminated = True # 游戏结束,flag置1 q_table.loc[S, A] += ALPHA * (q_target - q_predict) # 更新Q表的值 S = S_ # state变为 下一步的state update_env(S, episode, step_counter+1) # 更新游戏环境 step_counter += 1 # 游戏步数计数 return q_table

4.7主函数

if __name__ == "__main__": q_table = rl() print('\r\nQ-table:\n') print(q_table)

5.迷宫小游戏——代码实现

说说一个更具体的例子. 让探索者学会走迷宫. 黄色的是天堂 (reward 1), 黑色的地狱 (reward -1). 大多数 RL 是由 reward 导向的, 所以定义 reward 是 RL 中比较重要的一点.

[站外图片上传中…(image-fd9598-1563434302632)]

5.1Q-learning算法实现

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 # 动作列表 self.lr = learning_rate # 学习率 self.gamma = reward_decay # self.epsilon = e_greedy #贪婪度 self.q_table = pd.DataFrame(columns=self.actions, dtype=np.float64) #Q表 # 选择activate def choose_action(self, observation): self.check_state_exist(observation) # 选择动作 if np.random.uniform() < self.epsilon: # 选择最佳动作 state_action = self.q_table.loc[observation, :] ''' 这一行不好理解。np.max(state_action) 选出state_action中的最大值。 state_action == np.max(state_action) 对应数据是否与max相等,返回bool值。True or False state_action[state_action == np.max(state_action) 筛选出最大值,可能是一个,也可能是两个 之后随机挑选最大值的动作。(只有一个则就是它,如果max有多个数值相同,则随机挑选) ''' action = np.random.choice(state_action[state_action == np.max(state_action)].index) else: # 贪婪 随机选择动作 action = np.random.choice(self.actions) return action def learn(self, s, a, r, s_): # 检测S_是否存在 self.check_state_exist(s_) # Q估计(Q表中存储的值) q_predict = self.q_table.loc[s, a] # Q现实(对下一状态的最大估计) 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 # 更新Q(s,a) self.q_table.loc[s, a] += self.lr * (q_target - q_predict) # update 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), # 添加 动作数 个[0],初始 0 0 index=self.q_table.columns, # Series的index也就是 DataFrame 的columns,也就是index 对应action name=state, # 设置q_table的index名称 ) )

这一段把Q-learning算法整合为一个类。

5.2主函数

from maze_env import Maze from RL_brain import QLearningTable def update(): # 游戏运行次数 for episode in range(100): # 初始化游戏环境 observation = env.reset() # 时间步 while True: # 更新游戏界面 env.render() # 根据observation选择动作,这里的observation也就是state(位置坐标) action = RL.choose_action(str(observation)) # agent采取这个action,并返回state、raward和游戏结束flag observation_, reward, done = env.step(action) # 根据经历(S,A,R,S_)更新Q表 RL.learn(str(observation), action, reward, str(observation_)) # 交换state,state进入下一循环 observation = observation_ # 如果游戏结束,则本回合结束 if done: break # 结束游戏并关闭窗口 print('game over') env.destroy() if __name__ == "__main__": env = Maze() # 建造游戏环境 RL = QLearningTable(actions=list(range(env.n_actions))) # 使用0~3代表迷宫游戏的四个动作 # 开始可视化环境 env env.after(100, update) env.mainloop()

最新回复(0)