【强化学习】 之 算法范式

!!!图片和代码不全 完整内容请参考链接https://f01anvir4t.feishu.cn/docx/P6skdqvU2oSneAxmVuIcwk8BnYf?from=from_copylink

强化学习笔记(一)cr.白狮山

日期:2023年11月22日

参考:

  1. Datawhale人工智能培养方案V2.0

  2.JoyRL Book

  3.https://chat.openai.com

基础概念

  1. 智能体(Agent)的实现

在代码中,智能体负责制定策略并采取动作。智能体可能基于不同的算法和方法实现,比如Q-Learning、深度Q网络(DQN)、策略梯度方法等。这些方法会影响智能体如何选择动作和更新策略。

  1. 环境(Environment)

环境模拟了智能体所处的场景,包括状态空间、动作空间和奖励机制。在强化学习中,环境是智能体与之交互的场所。不同的问题领域会有不同的环境设置。

  1. 训练过程

在训练过程中,智能体与环境进行交互,并根据交互结果进行学习更新。

  1. 关键概念

  • 策略(Policy):智能体选择动作的方式,可以是确定性的(给定状态选择一个确定的动作)或是随机的(按概率分布选择动作)。

  • 经验池(Experience Replay):用于存储智能体与环境交互获得的经验,以供后续学习使用。

  • 价值函数(Value Function):评估状态或动作的价值,帮助智能体决定在给定状态下采取最优的动作。

  • 探索与利用(Exploration vs Exploitation):在学习过程中,智能体需要在探索未知领域和利用已知信息之间取得平衡。

定义训练

回顾一下伪代码的第二行到最后一行,我们会发现一个强化学习训练的通用模式,首先我们会迭代很多个(M)回合,在每回合中,首先重置环境回到初始化的状态,智能体根据状态选择动作,然后环境反馈中下一个状态和对应的奖励,同时智能体会更新策略,直到回合结束。这其实就是马尔可夫决策过程中智能体与环境互动的过程,写成一段通用的代码如下:

 

for i_ep in range(train_eps): # 遍历每个回合 # 重置环境,获取初始状态 state = env.reset() # 重置环境,即开始新的回合 while True: # 对于比较复杂的游戏可以设置每回合最大的步长,例如while ep_step<100,即最大步长为100。 # 智能体根据策略采样动作 action = agent.sample_action(state) # 根据算法采样一个动作 # 与环境进行一次交互,得到下一个状态和奖励 next_state, reward, terminated, _ = env.step(action) # 智能体将样本记录到经验池中 agent.memory.push(state, action, reward, next_state, terminated) # 智能体更新策略 agent.update(state, action, reward, next_state, terminated) # 更新状态 state = next_state # 如果终止则本回合结束 if terminated: break

  • 环境重置与回合开始:state = env.reset() 重置环境为初始状态,获取初始状态开始新的回合。

  • 回合内交互:while True 循环内部,智能体与环境交互直至回合结束。

    • 智能体根据策略选择动作:action = agent.sample_action(state)

    • 通过 env.step(action) 与环境交互,获取下一个状态 next_state、奖励 reward 和终止标志 terminated

    • 将经验存储到经验池中:agent.memory.push(state, action, reward, next_state, terminated)

    • 智能体根据经验更新策略:agent.update(state, action, reward, next_state, terminated)

    • 更新状态为下一个状态:state = next_state

  • 回合结束:如果达到终止条件,例如游戏结束或达到最大步长,if terminated: break 结束当前回合。

定义算法(采样、预测、更新)

sample_action(state) 采样动作
  • self.sample_count:用于跟踪采样次数,用来逐渐降低探索率 ε

  • self.epsilon:探索率,通过指数衰减函数逐渐减小,这里采用了指数递减。

  • ε-greedy策略:以 1 - ε 的概率选择当前最优的动作(基于Q值),以 ε 的概率随机选择动作。

      np.random.uniform(0, 1)生成一个0到1之间的随机数。

      如果这个随机数大于self.epsilon,也就是落在[self.epsilon, 1)区间内,智能体会选择当前状态下Q值最高的动作,即action = np.argmax(self.Q_table[str(state)])

      如果生成的随机数小于等于self.epsilon,也就是落在[0, self.epsilon]区间内,智能体会以随机选择的方式挑选动作,即action = np.random.choice(self.n_actions),其中self.n_actions表示可行动作的数量。

class Agent:# 为智能体写个类 def __init__():# 写个构造函数(可以传递参数给构造函数,从而初始化对象的属性) pass def sample_action(self, state): ''' 采样动作,训练时用 ''' self.sample_count += 1 # epsilon是会递减的,这里选择指数递减 self.epsilon = self.epsilon_end + (self.epsilon_start - self.epsilon_end) * math.exp(- self.sample_count / self.epsilon_decay) # e-greedy 策略 if np.random.uniform(0, 1) > self.epsilon: action = np.argmax(self.Q_table[str(state)]) # 选择Q(s,a)最大对应的动作 else: action = np.random.choice(self.n_actions) # 随机选择动作 return action

这个策略的目的是在探索与利用之间寻找一个平衡。在训练早期,self.epsilon的值通常比较大,会使得智能体更多地进行随机探索,以便发现更多的状态和动作。随着训练的进行,self.epsilon会逐渐减小,智能体会更多地倾向于根据已学习到的Q值来选择动作,以利用已有的经验。

predict_action(self,state)

此外对于每个智能体在训练中和在测试中采取动作的方式一般是不一样的,因为在训练中需要增加额外的探索策略,而在测试中只需要输出Q值对应最大的动作即可,如下采用贪婪(greedy)策略,直接选择当前状态下Q值最高的动作。

解释如下:

  • state 是当前智能体所处的状态。

  • self.Q_table[str(state)] 用于访问Q表中与当前状态对应的Q值。

  • np.argmax() 会返回Q值数组中最大值所在的索引,即对应于当前状态下Q值最高的动作。

  • action = np.argmax(self.Q_table[str(state)]) 将选择得到的最优动作作为预测的动作。

  • 最后,predict_action 方法返回预测的动作 action

这个方法适用于测试阶段,当智能体已经通过训练学习到了Q值,并希望在给定状态下选择最优的动作以执行。

 

class Agent: def __init__(): pass def predict_action(self,state): ''' 预测或选择动作,测试时用 ''' action = np.argmax(self.Q_table[str(state)]) return actionCopy to clipboardErrorCopied

update

所有强化学习算法的采样动作和预测动作方式几乎是比较固定的,对于每个智能体来说最核心的还是更新网络的方式,在 Q-learning 算法中的更新方式较为简单,而且不需要经验回放(具体会在 DQN 算法中展开),如下:

  • Q_predict = self.Q_table[str(state)][action]:获取当前状态下采取特定动作的Q值。

  • if terminated: Q_target = reward:如果当前状态是终止状态(terminated),则目标Q值等于当前的即时奖励(reward),因为在终止状态下不存在后续的奖励。

  • else: Q_target = reward + self.gamma * np.max(self.Q_table[str(next_state)]):如果当前状态不是终止状态,则目标Q值为当前即时奖励加上未来预期最大Q值的折扣self.gamma 是折扣因子,用于平衡即时奖励和未来奖励的重要性。

  • self.Q_table[str(state)][action] += self.lr * (Q_target - Q_predict):利用Q-learning更新规则,以学习率 self.lr 来调整当前Q值,以使其逐步趋近于目标Q值。

    • self.Q_table[str(state)][action]:这部分代码访问了Q表中特定状态下特定动作的Q值。这个Q值表示了在当前状态下采取该动作的预期长期回报。

    • self.lr:这是一个称为学习率(learning rate)的超参数。学习率控制了每次更新时,新的信息对Q值的影响程度。它决定了更新的步长大小,过大的学习率可能导致不稳定性,而过小的学习率可能导致学习过于缓慢。

    • (Q_target - Q_predict):这部分代表了Q-learning更新中的“误差”或“差异”。Q_target 是我们希望Q值逐步收敛到的目标值,而 Q_predict 是当前Q值的预测值。这个差值代表了当前估计值与我们希望的目标值之间的差异。

    • self.Q_table[str(state)][action] += self.lr * (Q_target - Q_predict):这个表达式实际上是一个更新规则,它将当前的Q值根据计算出的误差进行调整。通过乘以学习率,我们控制了这个误差对Q值的调整程度。这个调整过程是基于误差的大小和学习率的设定,它使得当前的Q值向着我们期望的目标Q值(即 Q_target)移动。

这个更新方法是Q-learning算法中的基础,它帮助智能体通过不断地与环境交互,根据即时奖励和预期未来奖励来更新状态-动作对的Q值。在实际应用中,这个过程会不断迭代,通过与环境的交互来逐步提升智能体的策略。

 

def update(self, state, action, reward, next_state, terminated): Q_predict = self.Q_table[str(state)][action] if terminated: # 终止状态 Q_target = reward else: Q_target = reward + self.gamma * np.max(self.Q_table[str(next_state)]) self.Q_table[str(state)][action] += self.lr * (Q_target - Q_predict)Copy to clipboardErrorCopied

定义环境

CliffWalking-v0 是 OpenAI Gym 中的一个经典离散动作空间的强化学习环境之一,通常用于测试和验证强化学习算法。这个环境是一个10x4的网格世界,代表了一个遍布悬崖的地形。

  • 状态空间:网格世界上的每个格子都代表一个状态。状态空间是离散的,总共有40个状态(10行 x 4列)。

  • 动作空间:智能体可以执行上、下、左、右四种离散动作,移动到相邻的格子。动作空间是离散的。

  • 奖励:智能体在移动时会收到不同的奖励。移动到普通的地面格子上会得到-1的奖励,当智能体移动到悬崖(标记为C)上时会得到-100的奖励并被重置到起始位置,移动到目标(标记为G)上会得到一个较高的奖励(通常是+50)。

  • 终止状态:终点是网格世界的右下角,到达这个位置表示完成一个任务,智能体到达这个位置后会停止并重置到起始位置。

env = gym.make('CliffWalking-v0') 这行代码使用了 OpenAI Gym 库中的 gym.make() 函数来创建一个名为 'CliffWalking-v0' 的强化学习环境,并将其赋值给变量 env

大多数情况下需要根据需求建立我们自己的环境【暂时没学到抱歉】

 

n_states = env.observation_space.n # 状态数 n_actions = env.action_space.n # 动作数 print(f"状态数:{n_states}, 动作数:{n_actions}")

  • env.observation_space.n:这里 observation_space 属性代表了环境的观察空间(也就是状态空间)。env.observation_space.n 表示状态空间的大小,即环境中可能的状态数量。

  • env.action_space.naction_space 属性表示了环境的动作空间。env.action_space.n 表示动作空间的大小,即智能体可以执行的动作的数量。

设置参数

Q-learning 算法的超参数(需要人工调整的参数)比较少,其中 (折扣因子)比较固定,设置在 0.9 到 0.999 之间,一般设置成 0.99 即可。而学习率在本章节中设置的比较大,为 0.1,实际更复杂的环境和算法中学习率是小于 0.01,因为太大很容易发生过拟和的问题,只是本节的环境和算法都比较简单,为了收敛得更快点所以设置得比较大。此外由于我们探索策略中的 探索率 ε是会随着采样步数衰减的,在实践过程中既不能让它衰减得太快也不能让它衰减得太慢,因此需要合理设置如下参数:

 

self.epsilon_start = 0.95 # e-greedy策略中epsilon的初始值 self.epsilon_end = 0.01 # e-greedy策略中epsilon的最终值 self.epsilon_decay = 200 # e-greedy策略中epsilon的衰减率

训练情况

曲线横坐标表示回合数(episode),纵坐标表示每回合获得的总奖励,可以看出曲线其实从大约 50 个回合的时候就开始收敛了,也就是我们的智能体学到了一个最优策略。

 

... 回合:280/300,奖励:-13.0,Epsilon:0.010 回合:300/300,奖励:-13.0,Epsilon:0.010

收敛值约在 −13 左右波动,波动的原因是因为此时还存在 0.01 的概率做随机探索。

拿训好的策略去测试,测试的过程跟训练的过程差别不大,其一是智能体在测试的时候直接用模型预测的动作输出就行,即在训练中是采样动作(带探索),测试中就是预测动作,其二是训练过程中不需要更新策略,因为已经收敛了。测试了 10 个回合,发现每回合获得的奖励都是 −13 左右,说明我们学到的策略是比较稳定的。

消融实验

为了进一步探究ε是随着采样步数衰减更好些,还是恒定不变更好,我们做了一个消融( Ablation )实验,即将 ε设置为恒定的 0.1,将初始值和最终值设置为一样

 

# 将初始值和最终值设置为一样,这样 epsilon 就不会衰减 self.epsilon_start = 0.1 # e-greedy策略中epsilon的初始值 self.epsilon_end = 0.1 # e-greedy策略中epsilon的最终值 self.epsilon_decay = 200 # e-greedy策略中epsilon的衰减率

然后重新训练和测试

不难发现,虽然最后也能收敛,但是相对来说没有那么稳定,在更复杂的环境中ε随着采样步数衰减的好处会体现得更加明显。

总结

Q-learning和SARSA两种算法范式

  • Q-learning算法:它属于一种基于价值迭代的算法,通过估计每个状态-动作对的价值(Q值)来学习最优策略。在每个时间步骤,它会选择当前状态下具有最大Q值的动作,并根据更新规则(利用当前奖励和预期未来奖励)来更新Q值。Q-learning算法是一种离策略off-policy学习算法,因为它更新Q值时会选择最优的动作,而不受当前策略的影响。

  • SARSA算法:与Q-learning类似,它也是基于值迭代的算法,用于学习最优策略。不同之处在于,SARSA算法在更新Q值时采用的是当前策略下的动作(即当前状态下采取的动作),并根据这个动作和后续的动作-值对来更新Q值。因此,SARSA算法是一种在策略下学习on-policy的算法。

这两种算法在传统的强化学习中被广泛使用,它们提供了理解强化学习基础原理的重要途径。虽然在实践中可能会有更先进的算法(比如基于深度学习的DQN等),但理解Q-learning和SARSA对于深入探索强化学习的进阶算法仍然至关重要。https://f01anvir4t.feishu.cn/docx/P6skdqvU2oSneAxmVuIcwk8BnYf?from=from_copylink

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值