实验9:强化学习Q-Learning算法
一:实验目的
1:了解强化学习的基本概念。
2:学习强化学习经典算法——Q-Learing算法。
3:通过Q-Learing算法解决问题。
二:实验内容
2.1 强化学习
强化学习(Reinforcement learning, RL)是机器学习中的一个领域,强调如何基于环境而行动,以取得最大化的预期利益。
核心思想:智能体agent在环境environment中学习,根据环境的状态state(或观测到的observation),执行动作action,并根据环境的反馈reward(奖励)来指导更好的动作。强化学习通过不断的试错探索,吸取经验和教训,持续不断地优化策略,以从环境中拿到更好的反馈。
注意:从环境中获取的状态,有时候叫state,有时候叫observation,它们其实一个代表全局状态,一个代表局部观测值,在多智能体环境里会有差别,但在环境没有那么复杂时,可以先把这两个概念划上等号。
强化学习可以用于:
- 游戏(马里奥、Atari、Alpha Go、星际争霸等)
- 机器人控制(机械臂、机器人、自动驾驶、四轴飞行器等)
- 用户交互(推荐、广告、NLP等)
- 交通(拥堵管理等)
- 资源调度(物流、带宽、功率等)
- 金融(投资组合、股票买卖等)
2.2 GYM库
GYM是强化学习中经典的环境库,它将环境交互接口规范化为:重置环境reset()、交互step()、渲染render()。
2.3 Q-Learing算法
Q-learning学习特定的state下,特定action的价值Q,采用Q表格的方式存储Q值(状态动作价值)。在训练中为了更好的探索环境,采用ε-greedy方式来训练,有一定概率随机选择动作输出。
Q-learning是离线(off-policy)的更新方式,更新learn()时无需获取下一步实际做出的动作next_action,并假设下一步动作是取最大Q值的动作。其具体更新公式如下:
三:实验资源
具体示例代码见百度AIStudio平台:强化学习Q-Learning算法。
四:实验要求
1、阅读示例代码,理解Q-Learning算法。
2、更换场景环境,测试算法结果。
五:实验环境
本实验所使用的环境条件如下表所示。
操作系统 | Windows 10 |
程序语言 | Python(3.11.4) |
运行平台 | Paddle notebook |
第三方依赖 | torch,numpy等 |
六:实验原理
强化学习是一种通过与环境进行交互来学习行为的学习方式。
在这个过程中,智能体(agent)通过执行动作(action)来改变环境的状态(state),并从环境中获得一个奖励(reward)。
智能体的目标是学习一个策略(policy),该策略能够指导智能体在给定状态下选择最优的动作,以最大化累积奖励。
Q-Learning使用一个Q值表来存储每个状态下执行每个动作所获得的预期累积奖励(Q值)。Q值表是一个二维表格,其中行代表不同的状态,列代表不同的动作。Q值表中的每个元素Q(s, a)表示在状态s下执行动作a所获得的预期累积奖励。
在训练过程中,智能体与环境进行交互,根据当前状态选择动作,并观察得到的奖励和新的状态。然后,智能体使用Bellman方程来更新Q值表中的Q值。更新过程不断迭代进行,直到Q值表收敛到一个稳定的状态,此时智能体就学习到了一个最优策略。
在训练完成后,智能体可以使用Q值表来选择动作。对于给定的状态s,智能体选择使Q值最大的动作作为当前的最优动作。由于Q值表已经收敛到最优值,因此这种策略选择方法能够保证智能体在大多数情况下都能获得较高的累积奖励。
七:算法流程
1:初始化Q值函数:对于每个状态-动作对(s,a),初始化其对应的Q值为一个较小的随机数,或者直接初始化为0。这通常构建为一个Q表,其中行代表不同的状态,列代表不同的动作,而表格中的每个元素代表在该状态下执行该动作的预期累积奖励(Q值)。
2:选择动作:从当前状态s开始,按照一种策略选择一个动作a。常用的策略是ε-greedy策略,即以1-ε的概率选择当前Q值最大的动作(即利用已知信息),以ε的概率随机选择一个动作(即探索未知信息)。
3:执行动作和更新Q值:执行选择的动作a,并观察环境反馈的下一个状态s'和奖励r。然后,根据Q值的更新规则更新Q值函数。
4:迭代训练:重复步骤2和步骤3,直到Q值表收敛到一个稳定的状态,或者达到预设的训练次数。在这个过程中,智能体会不断地探索环境,并根据环境反馈的奖励来更新Q值表,从而逐渐学习到最优的策略。
八:实验结果与分析
1:CliffWalking
CliffWalking-v0是一个经典的强化学习任务,模拟了一个人在网格上从一个起点走到一个终点,但有一个悬崖需要避免的场景。
【1】demo
首先执行预定义的动作,在本场景中是0, 1, 1, 2,即'up', 'right', 'right', 'down'。在示例中,CliffWalking-v0生成悬崖环境。
o代表正常可通行路径,x代表受控制的人物,C代表悬崖,T代表目标。如下图所示,在悬崖环境中,目的是寻找最快路径从左下角起点到右下角终点,跌落悬崖会返回起点。
【2】Agent定义
Agent是和环境environment交互的主体。
predict()方法:输入观察值observation(状态state),输出动作值。
sample()方法:在predict()方法基础上使用ε-greedy增加探索。
learn()方法:输入训练数据,完成一轮Q表格的更新。
【3】训练和测试定义
run_episode():agent在一个episode中训练的过程,使用agent.sample()与环境交互,使用agent.learn()训练Q表格。
test_episode():agent在一个episode中测试效果,评估目前的agent能在一个episode中拿到多少总reward。
【4】创建环境和Agent,启动训练
【5】测试算法结果
输出test情况下的行走路径和reward。
路径如下表所示,依次为上——右——右——右——右——右——右——右——右——右——右——右——下。最终的test reward为-13。
o o o o o o o o o o o o o o o o o o o o o o o o x o o o o o o o o o o o o C C C C C C C C C C T o o o o o o o o o o o o o o o o o o o o o o o o o x o o o o o o o o o o o C C C C C C C C C C T o o o o o o o o o o o o o o o o o o o o o o o o o o x o o o o o o o o o o C C C C C C C C C C T o o o o o o o o o o o o o o o o o o o o o o o o o o o x o o o o o o o o o C C C C C C C C C C T o o o o o o o o o o o o o o o o o o o o o o o o o o o o x o o o o o o o o C C C C C C C C C C T o o o o o o o o o o o o o o o o o o o o o o o o o o o o o x o o o o o o o C C C C C C C C C C T o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o x o o o o o o C C C C C C C C C C T o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o x o o o o o C C C C C C C C C C T o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o x o o o o C C C C C C C C C C T o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o x o o o C C C C C C C C C C T o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o x o o C C C C C C C C C C T o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o x o C C C C C C C C C C T o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o C C C C C C C C C C x test reward = -13.0 |
2:FrozenLake-v0
FrozenLake-v0是一个经典的强化学习任务,模拟了一个冰湖环境。智能体需要从起始位置出发,通过冰面上的不同格子,最终到达目标位置。冰面上有安全的格子和危险的格子,智能体需要避开危险格子以避免失败。
【1】demo
首先执行预定义的动作,获得如下结果。
【2】Agent定义
【3】训练和测试定义
【4】创建环境和Agent,启动训练
【5】测试算法结果
路径如下表所示,依次为下——上——不动——不动——不动——下——下——不动——不动——上——上——不动——下——上——下——不动——下——上——下——右——下——不动——右——右。最终的test reward为1。
(Left) SFFF FHFH FFFH HFFG (Left) SFFF FHFH FFFH HFFG (Left) SFFF FHFH FFFH HFFG (Left) SFFF FHFH FFFH HFFG (Left) SFFF FHFH FFFH HFFG (Left) SFFF FHFH FFFH HFFG (Left) SFFF FHFH FFFH HFFG (Up) SFFF FHFH FFFH HFFG (Up) SFFF FHFH FFFH HFFG (Up) SFFF FHFH FFFH HFFG (Left) SFFF FHFH FFFH HFFG (Left) SFFF FHFH FFFH HFFG (Left) SFFF FHFH FFFH HFFG (Left) SFFF FHFH FFFH HFFG (Left) SFFF FHFH FFFH HFFG (Left) SFFF FHFH FFFH HFFG (Left) SFFF FHFH FFFH HFFG (Up) SFFF FHFH FFFH HFFG (Left) SFFF FHFH FFFH HFFG (Up) SFFF FHFH FFFH HFFG (Down) SFFF FHFH FFFH HFFG (Down) SFFF FHFH FFFH HFFG (Down) SFFF FHFH FFFH HFFG (Down) SFFF FHFH FFFH HFFG test reward = 1.0 |
九:实验结论和心得
1:Q-Learning是一种无模型(model-free)的学习方法,不需要知道环境的状态转移概率和奖励函数的具体形式。
2:Q-Learning可以应用于许多实际问题中,例如环境模型难以获取或建模的问题。
3:在FrozenLake实例中,e_greed初始为0.1,则智能体无法到达终点。当调到0.3之后,智能体才能到达终点。
4:在强化学习中,智能体必须能够处理不确定性。因此,需要设计能够鲁棒地应对不确定性的强化学习算法和策略。
5:合适的奖励机制能够引导智能体朝着正确的方向学习。
6:在强化学习中,智能体需要在探索新环境和利用已知信息之间做出权衡。过度的探索可能导致效率低下,而过度的利用则可能导致智能体陷入局部最优解。
十:主要代码
import gym import numpy as np env = gym.make("CliffWalking-v0") env.reset() actiondict = {0: 'up', 1: 'right', 2: 'down', 3: 'left'} for step, action in enumerate((0, 1, 1, 2)): obs, reward, done, info = env.step(action) print('step {}: action {}, obs {}, reward {}, done {}, info {}'.format(\ step, actiondict.get(action), obs, reward, done, info)) env.render() |
import gym import numpy as np class QLearningAgent(object): def __init__(self, obs_n, act_n, learning_rate=0.01, gamma=0.9, e_greed=0.1): self.act_n = act_n # 动作维度,有几个动作可选 self.lr = learning_rate # 学习率 self.gamma = gamma # reward的衰减率 self.epsilon = e_greed # 按一定概率随机选动作 self.Q = np.zeros((obs_n, act_n)) # 根据输入观察值,采样输出的动作值,带探索 def sample(self, obs): if np.random.uniform(0, 1) < (1.0 - self.epsilon): #根据table的Q值选动作 action = self.predict(obs) else: action = np.random.choice(self.act_n) #有一定概率随机探索选取一个动作 return action # 根据输入观察值,预测输出的动作值 def predict(self, obs): Q_list = self.Q[obs, :] maxQ = np.max(Q_list) action_list = np.where(Q_list == maxQ)[0] # maxQ可能对应多个action action = np.random.choice(action_list) return action # 学习方法,也就是更新Q-table的方法 def learn(self, obs, action, reward, next_obs, done): """ off-policy obs: 交互前的obs, s_t action: 本次交互选择的action, a_t reward: 本次动作获得的奖励r next_obs: 本次交互后的obs, s_t+1 done: episode是否结束 """ predict_Q = self.Q[obs, action] if done: target_Q = reward # 没有下一个状态了 else: target_Q = reward + self.gamma * np.max(self.Q[next_obs, :]) # Q-learning self.Q[obs, action] += self.lr * (target_Q - predict_Q) # 修正q # 把 Q表格 的数据保存到文件中 def save(self): npy_file = './q_table.npy' np.save(npy_file, self.Q) print(npy_file + ' saved.')
# 从文件中读取数据到 Q表格 def restore(self, npy_file='./q_table.npy'): self.Q = np.load(npy_file) print(npy_file + ' loaded.') |
def run_episode(env, agent, render=False): total_steps = 0 # 记录每个episode走了多少step total_reward = 0 obs = env.reset() # 重置环境, 重新开一局(即开始新的一个episode) while True: action = agent.sample(obs) # 根据算法选择一个动作 next_obs, reward, done, _ = env.step(action) # 与环境进行一个交互 # 训练 Q-learning算法 agent.learn(obs, action, reward, next_obs, done) obs = next_obs # 存储上一个观察值 total_reward += reward total_steps += 1 # 计算step数 if render: env.render() #渲染新的一帧图形 if done: break return total_reward, total_steps def test_episode(env, agent, render=False): total_reward = 0 obs = env.reset() while True: action = agent.predict(obs) # greedy next_obs, reward, done, _ = env.step(action) total_reward += reward obs = next_obs if render: env.render() if done: break return total_reward |