敞开成长之旅!这是我参与「日新计划 12 月更文挑战」的第3天,点击查看活动详情
前语
昨天无意中翻了翻以前的博文,发现关于强化学习部分的理论部分说的不是很清晰,属于那种懂得都懂,不懂的很难懂的那种。所以的话刚好趁期末有点空温习,那么把这个扼要弥补一下吧。从最根底的当地重新开端讲起吧,那么本文的话也是会将看起来比较复杂的概念进行简化,可是本文傍边仍是会有的,可是你能够挑选性疏忽,或许自行加一个弥补。。
那么本文方针啥呢
- 强化学习的概念
- 强加学习的特征
- 了解马尔科夫决议计划
- bellman方程是啥
- Q-learn
- DQN
大约便是这5个方针吧,可是每一环节是环环相扣的,所以的话需求仔细观看本篇博文哈,OK,这也是可贵写一次这种类型的根底的博文,略有不当,望多多指教。
强化学习概述
在开端疯狂输出前,咱们需求好好了解一下究竟啥是强化学习。这玩意究竟是啥玩意,能够干啥。咱们先来看一下这个玩意的官方一点的概念是啥吧:
强化学习(Reinforcement Learning,RL),又称再励学习、点评学习或增强学习,是机器学习的范式和方法论之一,用于描绘和处理智能体(agent)在与环境的交互进程中经过学习战略以到达报答最大化或完结特定方针的问题 。 强化学习的常见模型是标准的马尔可夫决议计划进程(Markov Decision Process,MDP)。按给定条件,强化学习可分为根据模式的强化学习(model-based RL)和无模式强化学习(model-free RL) ,以及自动强化学习(active RL)和被动强化学习(passive RL)。强化学习的变体包含逆向强化学习、阶层强化学习和部分可观测体系的强化学习。求解强化学习问题所运用的算法可分为战略搜索算法和值函数(value function)算法两类。深度学习模型能够在强化学习中得到运用,形成深度强化学习 。
这么说或许仍是比较笼统,那么咱们来提取一下关键词:再奖赏,方法论,马尔科夫,最优化战略。
OK,这个的话便是咱们整个强化学习的中心,没错便是这几个词,至于其他的,那是一种拓展。万变不离其间,因为强化学习是什么是一种方法论,这个就意味着他是一种思维,就比方web技能,详细的完结你能够运用java能够运用python能够运用go甚至是node.js(go和node.js这个根底的博文咱就不写了,鸽一下,他人写的比咱好,视频讲的都不错,GitHub也有很不错的教程)所以的话其他的什么算法都是完结强化学习的一种计划。
好接下来咱们再根据这几个关键词开端咱们对强化学习的了解。
事例
咱们现在来结合咱们的比较知名的运用场景,事例,在结合咱们的关键词来看看这个玩意现在用来干啥,为什么能够运用强化学习来做这个东西。
alphaGo
说到强化学习,这个玩意是比较有意思的一个事例,没记错的话应该是2016年的时分,那个时分我应该还在初中当帅气的少年。

无人驾驶
这个是咱们近期比较火热的一个论题,它的在这方面的运用十分的广泛。现在的话在咱们的生活傍边用的比较多的是辅佐驾驶,比方自动泊车,巡航之类的。

why
事例的话,咱们就拿这几个就够了,总而言之,言而总归经过强化学习,咱们能够让一个东西,具有一种相似于人类相同的决议计划思维,来完结某一种需求实时进行调整的任务。那么问题来了,凭什么强化学习能够做到这些工作,非她不可?!那么现在咱们来说说为啥。
首要咱们回到一开端咱们关于前面提取的关键词:再奖赏,方法论,马尔科夫,最优化战略。
首要咱们来解读解读啥是战略,战略便是一种进程,一种履行的计划是吧,就比方咱们下棋的时分一步一步下,一步一步怎样下,这个下的方法便是咱们的一种战略。那么咱们下棋的时分肯定是期望咱们能够找到最好的一种计划去做。而且每一次咱们做了之后,都会得到一个及时的反应,比方你下了一步,你的对手也会下一步给你进行一个及时反应。那么相同的咱们无人驾驶开车也是相同的,咱们一步一步操作,确保车开的稳,又快又稳。
所以的话咱们发现因为强化学习他能够做最优化战略,所以的话咱们能够用这玩意来完结咱们的这种操作,当咱们需求进行一些决议计划任务的时分,咱们就能够挑选强化学习方法来完结这个功能。
强化学习特色
ok,说完了前面强化学习的根本的一个概述之后,我想你关于强化学习应该有了根本的形象。而且咱们现在能够对这个玩意儿下一简略的界说:这个东西是一个用于寻觅到最优决议计划的一种优化方法论。而且为了完结这个方法论,咱们衍生出了许多详细的算法用于完结她。
所以咱们再给强化学习RL下一个界说,这玩意便是一个优化算法。仅仅优化的成果是咱们的战略,是咱们每一个进程的操作,而且咱们的操作是一次一次拿出来的。也便是和咱们的其他算法,例如遗传算法其实是相似的,仅仅说咱们的方针不太相同,怎样不相同呢遗传算法是求取详细的某一个函数的值或许是说咱们的一个组合问题的成果。那么问题来了,强化学习的思路是怎样样的?有啥不太相同的嘛?
那么在这儿的话,请记住咱们现在找到的RL的特色,那便是:决议计划+最优化
。
根本理论部分
首要咱们来搞清楚强化学习究竟是怎样工作的。咱们现已知道了她的特色那便是决议计划+最优化。那么咱们这儿就需求搞清楚两个问题,什么是决议计划,她这儿的决议计划是指的啥,最优化怎样最优化,最优化的是谁。搞清楚这个那么咱们离搞清楚RL就不远了,那么在这儿咱们先来搞清楚决议计划。
刚刚咱们拿下棋的比方阐明晰决议计划便是一步一步怎样个走法对吧。每一步怎样走的其实便是一个决议计划进程,那么这个便是决议计划,而且在咱们下达决议计划之后,咱们这边马上就能够得到外界给咱们的一个反应。例如你在此刻挑选向一个妹子表达,那么你很快就能够收到被回绝的消息,得到一个反应(这儿不评论成功的状况)。那么这个进程咱们将怎样表明呢。
ok,这儿咱们就能够对咱们的决议计划进行一个简略的了解,决议计划便是在一个状况下做出一个行为,而且当行为做出之后,会得到一个及时的反应,也便是会改动一个状况,比方你的心态,或许那个妹子的心态,总归会有一个状况的改动。例如你被回绝了,所以你发扬蹈厉,终究完结:“今天你对我爱答不理,明日我让你高攀不起”的一个方针。那么此刻你的状况是有一个改动的。
根本概念
咱们总是拿下棋,表达被拒这种事例来阐明咱们这个高大上的概念实在是不当,不符合我RL的规范。所以咱们决议对咱们刚刚的那些东西就行提出一些简略的概念。所以咱们提取出了这些东西:
智能体
强化学习的本体,作为学习者或许决议计划者。也便是此刻下棋的你
环境
强化学习智能体以外的悉数,主要由状况调集组成。此刻下棋的环境,比方咱们下象棋有一系列的规程。
状况
一个表明环境的数据,状况集则是环境中悉数或许的状况。
动作
智能体能够做出的动作,动作集则是智能体能够做出的悉数动作。
奖赏
智能体在履行一个动作后,取得的正/负反应信号,奖赏集则是智能体能够取得的悉数反应信息。例如下棋赢了之类的。
战略
强化学习是从环境状况到动作的映射学习,称该映射关系为战略。浅显的了解,即智能体怎样挑选动作的考虑进程称为战略。
方针
智能体自动寻觅在接连时间序列里的最优战略,而最优战略通常指最大化长时间累积奖赏。
因而,强化学习实践上是智能体在与环境进行交互的进程中,学会最佳决议计划序列。这个不便是咱们最优化的方针嘛
马尔可夫模型
那么刚刚的那个玩意怎样用数学进行表明呢。我知道这个时分有人或许要问了,为什么要把那么苦楚的工作(举例中的表达失败)用数学来表明呢。原因很简略咱们要做最优化问题,假如不能转为为数学模型,那么怎样进行优化呀?!不懂得“反思”很难搞的呀。所以咱们有这么一个玩意叫做马尔可夫模型来表明。
那么关于这个马尔科模型的,还有许多相关的概念,这儿的话咱们就先不提了,咱们只挑选咱们需求了解的部分。毕竟博文不是专业图书,加上博主能力也有限,有些东西很难说清楚。
ok,好咱们现在现已找到了一个模型,这个模型能够表明刚刚咱们下棋,或许追女孩子被拒的一个状况。相同的,这个马尔可夫模型呢和俺们的强化学习相似,她也是一个大约念或许叫方法论吧。说不是人话便是:从模型的界说和性质来看,具有马尔可夫性质、并以随机进程为根底模型的随机进程/随机模型被统称为马尔可夫模型。
其间包含马尔可夫链、马尔可夫决议计划进程、隐马尔可夫链(HMM)等随机进程/随机模型。
什么上来就放大招有那么一点带点不理会解是吧,没事咱们慢慢来,咱们先来简略说说:马尔可夫链、马尔可夫决议计划进程,至于HMM,这个说清楚前面两个这个第三个就大约了解了是什么意思(老粉或许知道了,这玩意又能够被我水一篇博文出来了)仍是那句话嘛,俺们重在了解,了解了去推倒数学公式不是有手就行。
马尔可夫链
(俄国数学家 Andrey Andreyevich Markov 研究并提出一个用数学方法就能解释自然改变的一般规则模型,被命名为马尔科夫链(Markov Chain)。马尔科夫链为状况空间中经过从一个状况到另一个状况的转换的随机进程,该进程要求具有“无记忆性 ”,即下一状况的概率分布只能由当时状况决议,在时间序列中它前面的事情均与之无关。这种特定类型的“无记忆性 ”称作马尔可夫性质。马尔科夫链以为曩昔悉数的信息都被保存在了现在的状况下了 。比方这样一串数列 1 - 2 - 3 - 4 - 5 - 6,在马尔科夫链看来,6 的状况只与 5 有关,与前面的其它进程无关。)
ok,咱们先来说一下,那便是咱们的马尔可夫链是什么东西,这儿的话咱们回到刚刚那个你被回绝然后发愤图强的事例来(下棋的事例不好画图)
咱们把时间先拉回到表达被回绝的时间点:
所以你将迎来如下或许的状况的改动:

例如,你挑选了图强,所以你挑选去给博主来个三连,然后好好学习天天向上,终究到达人身巅峰。 状况由:s0-s1-s2-s3。因为咱们刚刚在强化学习的时分也说过嘛,包含事例咱们都是接连的一个进程,比方开车,你总不或许方向盘拧一下就完事了吧。那么这个有一系列的状况的改动终究串联出来的一系列的状况进程就组成了一个链嘛。
咱们在用形象一点的图来表明便是这样的:

在这儿咱们简略解释一下这张图哈(没找到合适的图,又不好画只能先这样了)
S表明的便是咱们的一个状况,在刚刚的比方的话刚好便是有4个状况是吧。而且咱们每一个时间都只能有一种状况,总不能既堕落又图强吧,搁着叠加是吧。那么咱们四个状况确认下来组成的序列,比方咱们四个时间,每一个时间确认一个状况,而且咱们的状况不重复,那么得到一个状况的进程例如 s1-s2-s3-s0 或许 s2-s3-s0-s1(假定这个的S的下标不是时间t,而是单纯表明状况的序号)那么这个组成的链状结构的话便是咱们的这个马尔科夫链。
P,说完了S,咱们在来说说这个P是啥,这个P的话其实是咱们状况的搬运矩阵,什么意思,当你此刻决议图强的时分,下一个时间仍是不是图强是纷歧定的,例如某些人,阶段性发愤图强,持续性混吃等死。因而还有一个这个搬运矩阵。
所以咱们给出的那个图完好版是这样的:

那么此刻我想你对马尔科夫链应该是有一点了解了的。因为这玩意说白了其实便是算:由初始化状况经过N进程之后到达终究状况的一个概率。
事例
OK,这儿的话咱再举个比方吧,只需求运用到高中的数学仅仅即可。
咱们有这样的一个状况和对应的一个状况搬运的概率

现在咱们求取从A开端两次之后还在A的概率。
经过高中的常识,咱们能够这样算出成果:
P = 0.3 * 0.3 + 0.7 * 0.9 = 0.72 假定A—>A —>A 假定A—>B—>A 那么这个那两条链子便是马尔科夫链。好家伙,合着废了半天这个便是马尔科夫链呀,那问题来了我知道这个玩意有啥用呀。诶呀,咱们图强的方针是什么,是不是为了走上人身巅峰,咱们知道每到一个阶段是不是说会得到一下东西,比方咱们好好学习,是不是能够变得优异为以后打下根底,那么咱们能够对自己扼要的打个分对这个状况,当自己表现杰出的时分,这样一来,当咱们走向人身巅峰的时分,没有状况得到的评分之和都是十分高的。等等,这个不便是刚刚说到的这个嘛:

那么问题来了,是什么东西导致咱们能够到达那个状况呢?!从前咱们是怎样说的,咱们是怎样到达那个状况的来着?便是你为啥要决议发愤图强的来着的?哦,是因为你表达被回绝了是吧(狗头)那么表达便是一种战略便是一种行为嘛。因为这激动的行为导致了你将处于某一种状况。那么此刻咱们仅仅知道了表层。咱们还需求知道你究竟是为啥会做出这样的行为对吧。
马尔科夫决议计划进程
书接上回,咱们还需求知道你为啥要做出这样的行为,而且咱们还需求运用数学模型来表明你为啥要这样。之后咱们就能够知道在这种状况下做出这个行为决议计划的原因,经过不断调整你的决议计划,终究让咱们的马尔科夫链的奖赏最大。那么这个做决议计划的进程就和咱们正常考虑的进程很像了。那么这个时分咱们拿下棋的比方来举比方吧。老是那啥表达被拒被拒的太伤感了,搞得博主被拒过相同那么了解这个心太的改变(虽然是存在这种或许的)
来说点不是人话的东西:

所以一句话俺们经过上面的界说能够知道,其实便是加一点点细节,在咱们状况搬运的根底上加上决议计划。每次咱们刚刚一向着重的事例,其实便是咱们的决议计划进程,便是你怎样下棋,你怎样表达而且被回绝的一个进程。 前面介绍这个马尔科夫链仅仅为了咱们这个部分便于了解。
累计报答
OK,咱们现在来试想一下,回到咱们刚刚下棋的事例,咱们现在知道了这几个东西:
- 奖赏
- 状况
- 反应
- 环境
- 奖赏
而且咱们发现咱们的状况,和反应其实都是有环境进行反应的。也便是说咱们的环境包含了状况和反应。那么反应的是啥呢,咱们要做最优化,那么反应的应该是能够用来评判好坏的东西,而且咱们不是不是一步到位需求一步一步慢慢来,因而每一步都需求有个东西来点评。那么这个东西是啥,显着便是前面说到的reward。
所以说,咱们在下棋的时分,是不是能够这样,咱们假定在当时的状况下,也便是在当时这一步,咱们猜想一下假如下在这儿会怎样,下在那里会怎样样,而且下在那里的时分咱们给一个评价,那么也便是reward,那么这个时分你或许会说了,我挑选当时能够得到最大的reward的当地然后把棋子放下去不就好了嘛。好像是能够,可是每一步最优必定是全局最优嘛?显现纷歧定吧,你下棋的时分也不或许只看这一步吧,而是看好几下,假定下到这儿咋样,假如下到那里了后边又会咋样吧。
因而咱们需求知道的不仅仅是咱们下在那个当地之后能够得到的奖赏吧,咱们还要尽或许知道去猜想后边能够的大的奖赏吧。那么这个便是咱们累计报答的意思。
那么公式便是这样的:

在举个比方便是,在当时t时间,我猜想接下来的状况搬运是这样的(马尔科夫链)

可是呢,记住一点便是,咱们这个都是猜想,实践上需求实时的更新。大白话便是我猜的,纷歧定准。
所以说,在现在下棋的时分,我此刻此刻,我有好几个方位能够落子,可是我需求挑选累计报答最高的那个来落子。
概念及其求取流程
OK,又到了最OK的根底概念时间了。现在咱们来回忆一下,关于马尔科夫,强化学习,以及咱们从前说到的比方,咱们现在现已扯到的东西。
首要是咱们的一个概率搬运矩阵是吧。这个搬运矩阵便是咱们由状况1到状况2的一个概率。
之后是咱们说到的马尔科夫链,这个和咱们的状况矩阵是一起的
然后是咱们说到的累计报答,咱们的累计报答的表明方法
呢刚刚那个公式
而且在当时的一个状况的时分,咱们有许多挑选,每一个挑选对应一种举动,也便是对应一种战略。每一个战略的成果便是能够帮助咱们搬运到下一个状况。而且此刻都对应一个奖赏。
当咱们挑选下一个举动或许说战略的时分,咱们经过累计报答来挑选。
所以此刻咱们能够发现便是说,咱们比较重要的是啥咧: 挑选战略-那么怎样挑选-经过累计报答-累计报答怎样算呢。少年你问到点子上了!
其实这个咱们早就给出答案了。便是从前的那个算两次回到A那个方位的比方傍边,咱们说咱们有一个马尔科夫链,而且知道状况搬运矩阵,以及那个状况对应的reward。然后咱们概率相乘做累加不就得到了一个累计奖赏了嘛。
OK,现在咱们来开端用数学言语来表达,可是咱们先把咱们从前一向说到的概念进行数学化表达;
战略:
强化学习的方针便是给定一个马尔可夫决议计划进程,去寻觅最优的战略;
咱们能够把策胳了解为在状况s下挑选某一个动作的概率;
战略通常用符号来表明: 数学形式表明为:(a|s)含义为;
战略在每个状况s指定一个每个动作的发生概率;
假如战略是确认的,那么战略在每个状况下的每个动作的概率都是确认的。
然后咱们再提取出一个概念叫做值函数。这个东西是啥呢。首要函数这个概念大家应该都知道输入一个值,得到另一个值。假如咱们把刚刚得到的累计状况存储起来,以后你输入一个状况,我就把那个状况对应的累计报答给你那么,咱们存储这个累计报答值的玩意,便是一个值函数。寄存累计报答值的玩意的函数咱们叫做“状况-值函数
”
公式是这样的:

此外咱们还有一个玩意叫做““状况-行为值函数”
”,这个是啥呢,便是在当时的这个状况下我做了一个动作能够得到的累计报答。因为在当时的状况的咱们能够有许多个动作,上面那个值函数其实便是说把咱们的这个悉数对应的动作的累计报答进行求和。那么这个函数的公式是这样的:

那么他们之间的关系呢就能够用下面的图表明:


状况-值函数能够这样表明
”

事例
OK,这个时分有点笼统,咱们举个比方吧,咱们举比方,这个比方是十分经典的比方。 来看到这个图:

状况-值函数
”V(s4) 的值
直接这样算:

之后的话是到宣布这个节点,有0.5的概率,可是宣布的话接下来有三个状况,结合上面的公式,咱们只需求在算 0.2x-1.3+0.4×2.7+0.4×7.4 就能够了。
这个时分你或许需求问了,咱们的公式是这样的:

咱们要算出一条链路的值呀,为什么事例仅仅算到0.2x-1.3+0.4x2.7+0.4x7.4就不算了,难道不应该继续算下去嘛,直到终究睡觉的一个状况嘛。OK,咱们回到一开端对应马尔科夫的阐明,他是当时状况之和上一个状况相关对吧。那么咱们求取0.2x-1.3...这个值的时分咱们是求取下一步的状况,咱们的那个-1.3,2.7,7.4是怎样来的,这个东西是不是也是求取它的下一步的报答得到的,它的下一步的下一步也是经过下一步,下一步的下一步的下一步来的吧,那么我直接求下一步也便是那个式子是不是便是相当于直接把后边的一条链路直到终究状况都求到了,OK,这个便是看公式假如不看界说比较容易搞错的当地。
算法意图
OK,现在咱们现已知道了咱们的马尔科夫模型了。 咱们知道了咱们的一些值函数,咱们也知道了怎样求,咱们能够经过这些值函数来决议咱们的操作,终究改动一个状况完结一个方针。
因而咱们不难发现,咱们的强化学习算法其实意图便是:

可是别着急呀,咱们操作的时分,咱们其实依照这个

状况-行为值函数
”就能够去决议咱们的一个战略,咱们挑选最大的就好了嘛。可是这个玩意咱们一开端是压根就不知道的呀。只要咱们不断去尝试才干够去知道的呀,不断试探才干知道底线嘛(狗头)可是只要咱们能够得到或许求取出这个玩意,咱们就能够无敌了,咱们只需求不断去尝试就好了,因为咱们又不是量子一次性就能够知道每一个动作能够得到的累计报答,咱们只能知道当时的,那么咱们就能够经过直接尝试,结合咱们的当时的奖赏去不断尝试猜想,终究越来越准就好了。
Q-Leaning
OK,现在咱们的问题定位到怎样找到这个Q(s,a)函数。那么咱们的Q-Learning就诞生了。咱们首要直接看到伪代码。

实在值与猜想值
其实咱们前面一向在着重,那便是咱们的这些值函数,其实都是一个猜想,经过马可夫模型进行猜想的,咱们经过猜想的这些值来到达咱们最优的一个战略。只要咱们尽或许确保咱们猜想的“状况-行为值函数
”愈加准确咱们才有或许更好地得到咱们的这个战略,也便是,咱们的这个Q(s,a)相当于一份棋谱,这玩意都禁绝,棋怎样或许能够下好呢。所以为了能够让咱们的这个准一点,咱们搞出实在值和猜想值这样的概念,那么这个值是啥呢,显着便是对应的累计报答嘛。
可是问题来了,猜想值咱们知道呀,猜想嘛,尝试呗,可是你说,实在值我上哪知道去?每次咱们确实是不知道的,可是咱们能够知道的便是跟着咱们不断尝试,咱们的猜想应该是越来越准的,因为咱们把更多的或许性给走出来了,而且咱们能够知道,结合公式一开端咱们说到的这个公式:

那么实在和猜想别离表明啥呢,便是这个:

事例
ok,又到了咱们的事例部分了,这儿的话咱们举一个(以前的比方)咱们让咱们的强化学习Q算法来玩一个游戏,规则是这样的:

咱们具象化咱们的Q(s,a)是这样的:

首要在回忆一下咱们最开端说到的概念:
智能体
强化学习的本体,作为学习者或许决议计划者。也便是此刻下棋的你
环境
强化学习智能体以外的悉数,主要由状况调集组成。此刻下棋的环境,比方咱们下象棋有一系列的规程。
状况
一个表明环境的数据,状况集则是环境中悉数或许的状况。
动作
智能体能够做出的动作,动作集则是智能体能够做出的悉数动作。
奖赏
智能体在履行一个动作后,取得的正/负反应信号,奖赏集则是智能体能够取得的悉数反应信息。例如下棋赢了之类的。
战略
强化学习是从环境状况到动作的映射学习,称该映射关系为战略。浅显的了解,即智能体怎样挑选动作的考虑进程称为战略。
方针
智能体自动寻觅在接连时间序列里的最优战略,而最优战略通常指最大化长时间累积奖赏。
因而,强化学习实践上是智能体在与环境进行交互的进程中,学会最佳决议计划序列。这个不便是咱们最优化的方针嘛
现在方针是走到要点,智能体是小人。此外咱们还有对应的环境,那么这个环境其实便是咱们拟定的游戏。咱们还要编写出这个游戏。
这部分的话咱们直接看到代码就好了都有注释哈:
import numpy as np
import pandas as pd
import time
np.random.seed(2)
#作用和pytorch的那个相同
N_STATES = 6
ACTIONS = ['left','right']
EPSILON = 0.9 #greedy
ALPHA = 0.1 #学习速率
GAMMER = 0.9
ECPHOS = 10 #轮数
FRESH_TIME = 0.01 #演示作用用的
def Init(n_states,actions):
#初始化
table = pd.DataFrame(
np.zeros((n_states-1,len(actions))),
columns=actions
)
return table
def ChoseAction(state:int,QTable:pd.DataFrame):
state_actions = QTable.iloc[state,:]
# 大于0.9 也便是0.1部分随便挑选
gailv = np.random.uniform()
if(gailv>EPSILON or state_actions.all(0)==0):
action = np.random.choice(ACTIONS)
else:
action = state_actions.idxmax()
return action
def GetReward(S,A):
#我觉得这个有点相似与一个丢失函数,仅仅这个丢失函数很特别
#这个是模拟游戏环境,同时也是假定假如我挑选了a1 我会得到的R和下一步对应的步数是几
if (A=="right"):
if(S==N_STATES-2):
#咱们是假定往右走的
S_= 'win'
R = 1
else:
S_ = S+1
R = 0
else:
R = 0
if S==0:
S_ = S
else:
S_ = S-1
return S_,R
def updateEnvShow(S,ecpho,step_counter):
#在终端可视化显现行走的进程
env_list = ['-'] * (N_STATES-1) +['F']
if(S=='win'):
interaction = "当时练习轮数 %s: 成功时走的步数= %s "%(ecpho+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)
def QLearning():
QTable = Init(N_STATES, ACTIONS)
for ecpho in range(ECPHOS):
step_counter = 0
S = 0
# 是否回合完毕
isWin = False
updateEnvShow(S, ecpho, step_counter)
while not isWin:
#挑选行为
A = ChoseAction(S, QTable)
# 得到当时行为会得到的Reward,以及下一步的状况
S_, R = GetReward(S, A)
# 预算的(状况-行为)值
q_predict = QTable.loc[S, A]
if S_ != 'win':
# 实践的(状况-行为)值 这个便是相似与G1
q_target = R + GAMMER * QTable.iloc[S_, :].max()
else:
# 实践的(状况-行为)值 (回合完毕)
q_target = R
isWin = True
QTable.loc[S, A] += ALPHA * (q_target - q_predict) # QTable 更新
S = S_ # 探索者移动到下一个 state
# 环境更新显现
updateEnvShow(S, ecpho, step_counter+1)
step_counter += 1
return QTable
if __name__ == '__main__':
QTable = QLearning()
print("\r\nQ-table:\n")
print(QTable)
代码仍是十分简略的。公式的完结咱们也有哈。
离线学习Sarsa
之后的话咱们在刚刚的话咱们还留意到一点,那便是咱们这个:

这个算法其实和QLearning很像

区别在哪,或许说为什么要有这个算法咧?
挑选动作函数
其实区别就在于挑选下一步的战略。 咱们能够要点看到这个函数:

咱们返回的动作有必定概率不是奖赏最大的动作。
关于QLearning来说,他每一次都会现在新的动作,也便是每一次都有概率不是挑选最优的动作。
可是Sarsa不是呀,它下一个动作便是挑选下一步傍边奖赏最大的。
换一句话说QLearning 胆子大,Sarsa保存。有着不同的收敛性,相对而言QL会想着找到更好的路,Sarsa比较保存,走“稳路”。
代码
代码也是相似的,只需求修正一个函数
def SARSA():
QTable = Init(N_STATES, ACTIONS)
for ecpho in range(ECPHOS):
step_counter = 0
S = 0
# 是否回合完毕
isWin = False
updateEnvShow(S, ecpho, step_counter)
A = ChoseAction(S, QTable) # 先初始化挑选行为
while not isWin:
S_, R = GetReward(S, A)
try:
A_ = ChoseAction(S_, QTable)
except:
# 这儿阐明现已到了结尾(假如报错)
pass
q_predict = QTable.loc[S, A]
if S_ != 'win':
q_target = R + GAMMER * QTable.iloc[S_, :].max()
else:
q_target = R
isWin = True
QTable.loc[S, A] += ALPHA * (q_target - q_predict) # QTable 更新
S = S_
A = A_
updateEnvShow(S, ecpho, step_counter+1)
step_counter += 1
return QTable
DQN
前面咱们说了这个Q-Leaning,咱们现已知道了根本的一个强化学习算法了,可是呢,这个玩意是不是无敌了?OK,咱们现在仍是下棋,咱们说,咱们这个Q(s,a)是棋谱对吧,可是呢,就比方咱们下围棋吧,这个或许是许多的呀,咱们不或许也很难直接把悉数的S和 A都存进去吧,存进去了也很难检索呀,数据量很大呀。
所以有什么方法能够优化呢。
咱们本来说 Q(s,a) 是什么东西,是一个“状况-行为值函数
”
是一个函数呀,既然如此,我为什么不能去直接运用一种函数呢,你只需求输入当时的State然后我就能告诉你对应的action 的值

那么咱们怎样才干找到这样的函数呀? 什么东西能够到达这样的作用咧?
当然是神经网络呀!这玩意不是能够“拟合”出任何我想要的函数嘛!!! 所以咱们运用神经网络来替代了咱们的Q表
流程
此刻咱们的流程也发生了改变。 这儿的话咱们是有两个版别的一个是2013年的


这儿多引入了一个记忆库的玩意,原因是为了打破本来数据之间的连贯性,也便是数据之间的强相关性。
本来咱们的数据和上一步或许上几步之间是紧密相连的,换一句话来说,关于相邻的数据之间的相关性较高,这个就会导致一个问题,例如咱们在做拟合的时分,就会导致局部拟合作用很好可是全局作用差,也便是两个图画部分贴合可是整体贴合度差。(还好老子玩过数学建模)
所以为了下降这玩意,这儿挑选了存储必定进程的数据,然后随机挑选一部分,然后去练习,你拟合,这样就能够下降练习数据之间的相关性。
你能够这样了解。假如我的输入是接连的,不是打乱的,此刻我在做拟合,那么,为了拟合当时的这一端,我或许就会破坏另一端,终究当我拟合完毕后,或许只要一端是贴合的。现在我数据大散,那么我的拟合的点在图画上是均匀的,那么总体上贴合就会比较好。
那么流程如下:

预估“表”与实践“表”
此外还有一个细节。在咱们本来的时分

可是现在的话,因为咱们是直接运用了这种“函数”所以咱们能够单独运用两个神经网络去别离代表实践和估量(猜想)



编码
坑点
在开端之前先来说说我踩到的坑。 第一个:

第二个:

环境修正
现在俺们仿造一下gym,咱们自己把刚刚的那个“走棋” 给做成环境出来。
咱们封装一下:
import time
"""
这个环境是这样的,
每一步的observer只要一个,
到要点总共是5步,往右走总共6个格子,所以结尾的下标是4
"""
class Env(object):
def __init__(self):
self.N_STATES = 6
self.Actions = ['left','right']
self.FRESH_TIME = 0.001
self.Win = 'win'
def updateEnvShow(self,S, ecpho, step_counter):
# 在终端可视化显现行走的进程
env_list = ['-'] * (self.N_STATES - 1) + ['F']
if (S == self.Win):
interaction = "当时练习轮数 %s: 成功时走的步数= %s " % (ecpho + 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{ins}:当时练习轮数:{ec},当时步数{st}".format(ins=interaction,ec=ecpho+1,st=step_counter),end="")
time.sleep(self.FRESH_TIME)
def getStatus(self):
return 1
def getActions(self):
return self.Actions
def GetReward(self,S, A):
# 我觉得这个有点相似与一个丢失函数,仅仅这个丢失函数很特别
# 这个是模拟游戏环境,同时也是假定假如我挑选了a1 我会得到的R和下一步对应的步数是几
if (A == 1):
if (S == - 2):
# 咱们是假定往右走的
S_ = self.Win
R = 1
else:
S_ = S + 1
R = 0
else:
R = 0
if S == 0:
S_ = S
else:
S_ = S - 1
return S_, R
def reset(self):
#开端
self.updateEnvShow(0,0,0)
return 0
运转代码
现在咱们开端进行完好的编码
import torch
from torch.nn import *
from torch import nn
from DQNNetWork.Env import Env
import numpy as np
import torch.nn.functional as F
#初始化运转环境
env = Env()
N_Status= env.getStatus()
HIDDEN_NUMBERS = 5
ACTIONS = env.getActions()
ACTIONSLEN = len(ACTIONS)
MEMORY_CAPACITY = 30
LR = 0.01
EPSILON = 0.9
BATCH_SIZE = 2
TARGET_REPLACE_ITER = 10
GAMMA = 0.9
ECPHOS = 50
class NetWork(nn.Module):
#替代表格Q的神经网络
def __init__(self, ):
super(NetWork, self).__init__()
self.fc1 = nn.Linear(N_Status, 50)
self.fc1.weight.data.normal_(0, 0.1) # initialization
self.out = nn.Linear(50, ACTIONSLEN)
self.out.weight.data.normal_(0, 0.1) # initialization
def forward(self, x):
x = self.fc1(x)
x = F.relu(x)
actions_value = self.out(x)
return actions_value
class DQN(object):
def __init__(self):
#在咱们运用表格的时分,咱们需求的是一个实践核算的V,和一个估量的
#可是实践上咱们做的时分其实仅仅把上一轮的作为预估的表然后更新下一轮
#那么现在咱们直接运用两个神经网络一个便是实践的“表”一个是预估的表
#还有一个好处,本来用一个表是预估和实践的步长只要1,现在我能够随意设置
#所以这个进程就变成了两个网络彼此学习的进程
self.eval_net, self.target_net = NetWork(), NetWork()
self.LearnStepCount = 0
self.MemoryCount = 0 # 记录了几条记忆
self.Memory= np.zeros((MEMORY_CAPACITY, N_Status * 2 + 2)) # 初始化记忆
self.optimizer = torch.optim.Adam(self.eval_net.parameters(), lr=LR)
self.loss_func = nn.MSELoss()
#咱们的Status是只要一个状况的
def ChooseAction(self,s):
s = torch.FloatTensor([s])
if np.random.uniform() < EPSILON: # greedy
actions_value = self.eval_net.forward(s)
#因为咱们是1x2的所以咱们是0
action = torch.max(actions_value, 0)[1].data.numpy()
#挑选出咱们value最大对应的下标0,1
else:
action = np.random.randint(0, ACTIONSLEN)
return action
def Remember(self, s, a, r, s_):
#这个是咱们的记忆体
transition = np.hstack((s, [a, r], s_))
index = self.MemoryCount % MEMORY_CAPACITY
self.Memory[index, :] = transition
self.MemoryCount += 1
def Learn(self):
# 到达必定的练习步数后,咱们更新咱们的target网络
#咱们的这个函数的意图只要一个得到俺们的Q表,Q神经网络
if self.LearnStepCount % TARGET_REPLACE_ITER == 0:
self.target_net.load_state_dict(self.eval_net.state_dict())
self.LearnStepCount += 1
# sample batch transitions
SelectMemory = np.random.choice(MEMORY_CAPACITY, BATCH_SIZE)
selectM = self.Memory[SelectMemory, :]
S_s = torch.FloatTensor(selectM[:, :N_Status])
S_a = torch.LongTensor(selectM[:, N_Status:N_Status+1].astype(int))
S_r = torch.FloatTensor(selectM[:, N_Status+1:N_Status+2])
S_s_ = torch.FloatTensor(selectM[:, -N_Status:])
#这一步得到了咱们一个batch_size的最佳值(最佳)
q_eval = self.eval_net(S_s)
q_eval = q_eval.gather(1, S_a)
#这个是下一步动作对应的值
q_next = self.target_net(S_s_).detach()
#更新咱们的G
# shape (batch, 1)
q_target = S_r + GAMMA * q_next.max(1)[0].view(BATCH_SIZE, 1)
loss = self.loss_func(q_eval, q_target)
self.optimizer.zero_grad()
loss.backward()
self.optimizer.step()
if __name__ == '__main__':
Dqn = DQN()
for ecpho in range(ECPHOS):
s = env.reset()
e_step = 0
isWin = False
while not isWin:
if(s >=env.N_STATES-2):
env.updateEnvShow(s, ecpho, e_step)
isWin = True
print("")
env.updateEnvShow(s,ecpho,e_step)
a = Dqn.ChooseAction(s)
s_,r = env.GetReward(s,a)
Dqn.Remember(s,a,r,s_)
#更新咱们的Q表,准确来说是咱们的Q神经网络
#可是咱们不是立即更新,咱们先随便试一下,然后从里边去寻觅最优值
if(Dqn.MemoryCount>MEMORY_CAPACITY):
Dqn.Learn()
e_step+=1
s=s_
运转作用

总结
又水了一篇博文~