DataWhale带你入门强化学习

it2023-06-03  79

强化学习讨论的核心是agent(智能体)和environment(环境)间的交互行为。主要是解决agent如何在一个复杂且不确定的environment中去极大化它所获得的奖励。

本篇博文代码部分较少,主要是解释强化学习的概念以及其应用领域。

强化学习和监督学习的对比

监督学习

举个图片分类的例子,我们的数据事先会有标定,如车/飞机/火箭/轮船等等。这些图片都打好了确定的标签。通过训练分类器(如神经网络),把真实的标签告诉分类器(如我告诉这张图片是一个飞机),当训练器做出了错误的判断(如输出了汽车),那我会告诉它预测是错误的,真实的结果应该是一个飞机。这类型的判断错误我们可以写成一个loss function(损失函数),通过反向传播来训练这个分类器。

在监督学习的过程中,有两个假设:

数据服从(或者尽可能服从)i.i.d分布。因为数据若关联性很强不是相互独立的话,往往会干扰模型的训练,分类器没法得到很好的学习数据的标签都是打好了的,这是反向传播的基础,我们需要告诉分类器数据的标签,它才能根据正确的标签来修正自身的预测结果。 这张图片即包含了以上所述:训练数据已经打上了正确的标签。输入一张车的图片,若是神经网络得到的预测结果是飞机,那么就能推断出该预测结果错误,正确的结果是车。

强化学习

区别与监督学习,强化学习既不满足i.i.d分布,数据也没有打好标签。

举个例子,大家都玩过打砖块的游戏:底部控制一块木板,通过左右移动把球反弹到顶部以消除方块。 游戏过程中,我们其实无法立刻获得每一步的反馈。比如,当我们控制木板左移的时候,得到的结果只能是球往上或往右移动,我们没法知道左移之后是否有助于游戏取得更高的分数(即左移这个动作正确与否),这就是强化学习困难的原因,但是我们依然希望agent可以在environment中学习。

如上图展示的那样,模型无法判断每一步是否是正确的,直到游戏结束。 这就涉及到延迟奖励的问题,模型学习变得十分困难。

强化学习下,agent通过不断试错以提高自身能力,其中涉及到两个核心的分支:exploration和exploitation。

exploration指的是探索以及尝试更多新的行为(这些行为有概率会得到更高的奖励,当然也可能使你一无所有);exploitation则是指基于现有已知的行为中,采取最优行为,然后重复执行。 因此,权衡两者在强化学习中是很重要的。

强化学习潜力是非常大的,和机器学习不同,强化学习不需要依据人类给予的标定结果(意味着机器永远无法超越人类),而是可以在环境中自行探索,这就给了它超越人类的机会。比如谷歌的AlphaGo,它正是通过强化学习算法,击败了人类最优秀的棋手。

强化学习的发展

深度强化学习

强化学习其实并不是很新兴的领域,已经发展了有段时间了。只是2012年后,随着卷积神经网络的兴起,我们可以将特征提取和分类两步合并,即训练一个神经网络,从而实现了端到端的训练,保证里面的参数在每一个阶段都能得到极大的优化。这个重大的突破使得深度学习能和强化学习相结合,形成了深度强化学习。(类比于计算机视觉和深度计算机视觉的概念) 强化学习之所以能在近几年取得了如此大的突破,得益于我们拥有了更多的Gpu(更多的计算能力以便更高效地试错),通过深度学习这样一个端到端的训练,我们可以得到更强的决策网络,使得agent在环境中获得更多的信息,得到更大的奖励。

什么是序列决策

agent(智能体)和environment(环境)的关系

强化学习研究agent和environment间的交互。 一开始,agent把它输出的动作给到环境。环境获得动作后,会自然进行下一步,同时将agent下一步的观测和agent上一步是否得到奖励这两个信息同时返回给agent。

通过这样不断的交互,自然产生了很多观测。agent就是通过环境返回的这些观测中学到如何极大化自己获得的奖励,从而制定策略。

rewards(奖励)

奖励是强化学习的灵魂所在,它是由环境反馈给到agent的信号,用来告诉agent:你之前的某一步采取的某个策略是否能得到奖励。

而agent则是为了这个目标(奖励),不断的学习并调整自己的策略,贪婪地极大化自己能获得的奖励,

但是,强化学习中,如何极大化奖励并非是个容易的事。因为整个学习过程中,奖励被延迟了。即当下的某一步决策可能要等很久才能直到它产生的影响,比如打砖块游戏,我可能得到游戏结束了以后才能直到我那一步(左移)是否对我游戏胜利更有帮助。又比如下面这个游戏:棕色和绿色两块板需要通过上下移动互相将球击打至对方面,同时要保证自己尽可能多的接到对向的来球。一步上移或下移无法直接获取到游戏能否胜利,往往需要游戏结束后,才能开始分析某一步是否是正确的。

这就是强化学习中近期奖励和远期奖励的概念,同时,保证两者之间的平衡,让agent获得更多的长期奖励是强化学习的问题。

历史

agent和环境交互的过程中,agent会获得很多环境返回的观测。在每一个观测下,agent采取的每个动作都会得到一个奖励(不管是正奖励还是负奖励)。这种观测/行为/奖励的序列,叫做历史。agent采取当前动作的时候会依赖它之前得到的历史,所以我们可以把整个游戏的状态看成是关于这个历史的函数

那么状态又是什么呢?或者说,环境的状态和agent得到的观测之间是什么关系呢?

准确来说,状态(s)是对世界的完整描述,不会隐藏世界的信息;而观测(o)是对状态的部分的描述,可能会遗漏信息。

在深度强化学习中,我们用实值的向量/矩阵或者更加高阶的张量来表示状态和观测。例如,我们用GRB像素值的矩阵表示一个视觉观测,用机器人关节的角度和速度来表示一个机器人的状态。

agent和环境都有状态 当agent的状态和环境的状态等价的时候,我们称这个环境是full observability,即完全可以观测,这也意味这agent能够观察到环境的所有状态。

当然,有完全可以观测,也有部分可观测的。比如agent在看电视游戏的时候,只能观测到某一帧的信息,并没有得到游戏内部里面所有的运作状态。这种情况,强化学习通常被建模成一个POMDP(部分可观测马尔可夫决策过程)问题。POMDP是MDP(马尔可夫决策过程)的泛化,依然具有马尔可夫性质。

POMDP有七个组成部分:S(状态空间-隐变量),A(动作空间),T(s’|s,a,状态转移概率),R(奖励函数),Ω(o|s,a,观测概率),O(观测空间),γ(折扣系数)。 其中,不同的环境下允许不同种类的动作,有效动作的集合即为动作空间。动作空间分为两种,第一种是离散动作空间(动作数量往往有限,如打砖块只有左移和右移);第二种是连续动作空间(就像机器人学习穿衣服)。

agent

对于一个强化学习的agent(智能体),一般有三个组成部分:

policy function(策略函数),agent用这个函数来选取下一步动作;value function(价值函数),用来评估当前状态(进入这个状态可以对后面的收益带来多大的影响)。函数值越大,进入状态就越有利;model(模型),表示agent对环境状态的理解,模型决定这个世界的走向。

policy function

policy决定了agent的行为,本质上是一个把输入的状态变成行为的函数。这里分为两种policy:

stochastic policy(随机性策略),即π函数 π(a|s) = P[At = a|St = s]。输入状态s,输出概率π。然后我们进一步对概率分布进行采样最后得到真实采取的行为。比如概率是70%左移,30%右移,则采样得到action是左移。deterministic policy(确定性策略),即agent尝试最大化奖励的那个动作。

通常情况下,强化学习使用随机性策略。因为这么做一来可以引入一定随机性使agent更好地探索环境,而来随机性策略的动作具有多样性,这点在多个智能体博弈的时候非常重要(你的决策容易被对方agent预测)。

value function

价值函数是一个折扣的未来奖励的加和,即通过某一种行为能够在未来得到多大的奖励

价值函数里discount factor(折现系数),越早得到反馈奖励就更大。本质上,价值函数的定义是一个期望: 上式的角标π就是π函数,意思是我们在已知一个policy function(即输出一个概率π)的时候,我们可以得到多少奖励。

除了这个奖励期望函数,还有一个Q函数。该函数包含了两个变量:状态和动作,即期望取决于当前的状态和当前的动作。当我们获得了Q函数,则表示我们进入了一种状态,那我们进入状态所采取的最优行为就是通过Q函数得到:

model

模型决定了下一个状态的样子,即下一步状态取决于你当前的状态及行为

马尔可夫决策过程的定义

有了policy function,value function和model,我们就形成了一个MDP(马尔可夫决策过程)。MDP可视化了状态之间的转移以及agent采取的行为。

agent的类型

我们可以把agent分为下面三类: 1.基于value function的agent,这一类agent显式地学习的是value function,隐式地学习了它的策略(policy)。因为策略是通过value function推算而出的; 2.基于policy function的agent,这一类agent直接学习policy,通过给policy function输入状态,从而输出动作行为的概率。这里,agent不会学习到它的value function; 3.两者结合的agent。结合了value funciton和policy function,有了Actor-Critic agent,这是两者的权衡。

实践环节

我这里简单地跟了两个openai中gym的小环境的例子,具体的代码应该要等task2再深入了,以下是代码:

# !/usr/bin/env python # -*- coding:utf-8 -*- # Author:TreeFei # Create_time: # Software: Pycharm import gym from gym import envs ''' OpenAI Gym 是一个环境仿真库,里面包含了很多现有的环境,针对不同的场景可以选择不同的环境 1.离散控制场景(输出的动作是可数的,比如Pong游戏中输出的向上或向下动作);一般使用Atari环境评估 2.连续控制场景(输出的动作是不可数的,比如机器人走路时不仅有方向,还有角度,角度就不可数,是一个连续的量);一般使用mujoco环境评估 Gym Retro 是对Gym环境的进一步扩展,包含了更多的一些游戏 ''' # 调入Taxi-v3的环境 env = gym.make('Taxi-v3') # 初始化环境 observation = env.reset() env.render() ''' 在强化学习算法中,智能体需要一次次地尝试,累积经验,然后从经验中学到好的动作。 一次尝试我们称之为一条轨迹或一个episode. 每次尝试都要到达终止状态. 一次尝试结束后,智能体需要从头开始. 这就需要智能体具有重新初始化的功能。 ''' # agent = load_agent() - 这行代码不知道什么意思 ''' for step in range(100): action = agent(observation) observation, reward, done, info = env.step(action) ''' # 看一下CartPole环境,这个环境有两个动作,Cart往左移或往右移。 ''' 这个环境得到的观测有: 1.当前的位置 2.当前左移或右移的速度 3.杆的角度 4.杆的最高点的速度 observation(观测)越详细,就可以更好地描述当前的所有状态。 这里有reward(奖励)的定义:如果能多保留一步,就会等到一个奖励;所以需要在尽可能多的时间存活来得到更多的奖励。 当杆的角度大于某一个角度(没能保持平衡)或者这个车已经出界的时候,游戏就结束了。 所以这个agent的目的就是为了控制木棍,让它尽可能保持在这个环境的中央 ''' # 构建实验环境(CartPole) env = gym.make('CartPole-v0') # 初始化环境 env.reset() for _ in range(1000): '''显示图形界面''' env.render() '''从动作空间中随机选取一个动作''' action = env.action_space.sample() ''' 打印 env.action_space.sample()的返回指 env.action_space.sample()的含义是:在该游戏的所有动作空间里随机选择一个作为输出 这个例子里动作只有两个:0和1,一左一右 ''' print(env.action_space.sample()) ''' 提交动作,参数是具体的动作 env.step()的作用不止于此,它还有四个返回值:observation, reward, done, info observation(object) - 状态信息,是在游戏中观测到的屏幕像素值或者盘面状态描述信息 reward(float) - 奖励值,即action提交以后能够获得的奖励值,原则是对游戏有帮助的动作会获得较高奖励值 done(boolean) - 表示游戏是否已经完成,如果完成了,就需要重置游戏并开始新的一轮 info(dict) - 比较原始的用于诊断和调试的信息,或许对训练有帮助 ''' env.step(action) # 关闭环境 env.close() # 每个训练中都要使用的返回值有observation, reward, done,但observation的结构会随游戏的不同而发生变化 '''以CartPole-v0为例,看看observation''' env = gym.make('CartPole-v0') env.reset() for _ in range(1000): env.render() action = env.action_space.sample() observation, reward, done, info = env.step(action) print(observation) env.close() '''从输出,可以看出是一个四维空间的observation,其他的游戏中会有维度很多的情况''' # 看Gym库注册了哪些环境 env_specs = envs.registry.all() env_ids = [env_spec.id for env_spec in env_specs] print(env_ids)

等待Task2,嘿嘿~

最新回复(0)