fix some errors and add new chapters
@@ -1,111 +1,227 @@
|
||||
# Tips of Q-learning
|
||||
## Double DQN
|
||||
# PPO
|
||||
## From On-policy to Off-policy
|
||||
在讲 PPO 之前,我们先讲一下 on-policy 和 off-policy 这两种 training 方法的区别。
|
||||
在 reinforcement learning 里面,我们要 learn 的就是一个agent。
|
||||
|
||||
* 如果要 learn 的 agent 跟和环境互动的 agent 是同一个的话, 这个叫做`on-policy(同策略)`。
|
||||
* 如果要 learn 的 agent 跟和环境互动的 agent 不是同一个的话, 那这个叫做`off-policy(异策略)`。
|
||||
|
||||
比较拟人化的讲法是如果要学习的那个 agent,一边跟环境互动,一边做学习这个叫 on-policy。 如果它在旁边看别人玩,通过看别人玩来学习的话,这个叫做 off-policy。
|
||||
|
||||
为什么我们会想要考虑 off-policy ?让我们来想想 policy gradient。Policy gradient 是 on-policy 的做法,因为在做 policy gradient 时,我们需要有一个 agent、一个 policy 和一个 actor。这个 actor 先去跟环境互动去搜集资料,搜集很多的 $\tau$,根据它搜集到的资料,会按照 policy gradient 的式子去 update policy 的参数。所以 policy gradient 是一个 on-policy 的 algorithm。
|
||||
|
||||

|
||||
|
||||
接下来要讲的是 train Q-learning 的一些 tip。第一个 tip 是做 `Double DQN`。那为什么要有 Double DQN 呢?因为在实现上,你会发现 Q value 往往是被高估的。上图来自于 Double DQN 的原始 paper,它想要显示的结果就是 Q value 往往是被高估的。这边有 4 个不同的小游戏,横轴是 training 的时间,红色锯齿状一直在变的线就是 Q-function 对不同的 state estimate 出来的平均 Q value,有很多不同的 state,每个 state 你都 sample 一下,然后算它们的 Q value,把它们平均起来。红色这一条线,它在training 的过程中会改变,但它是不断上升的,为什么它不断上升,因为 Q-function 是 depend on 你的 policy 的。learn 的过程中你的 policy 越来越强,所以你得到 Q value 会越来越大。在同一个state, 你得到 expected reward 会越来越大,所以 general 而言,这个值都是上升的,但这是 Q-network 估测出来的值。
|
||||
PPO 是 policy gradient 的一个变形,它是现在 OpenAI default reinforcement learning 的 algorithm。
|
||||
|
||||
接下来你真地去算它,那怎么真地去算?你有那个policy,然后真的去玩那个游戏。就玩很多次,玩个一百万次。然后就去真地估说,在某一个 state, 你会得到的 Q value 到底有多少。你会得到说在某一个 state,采取某一个 action。你接下来会得到 accumulated reward 是多少。你会发现估测出来的值是远比实际的值大。在每一个游戏都是这样,都大很多。所以今天要 propose Double DQN 的方法,它可以让估测的值跟实际的值是比较接近的。我们先看它的结果,蓝色的锯齿状的线是Double DQN 的 Q-network 所估测出来的Q value,蓝色的无锯齿状的线是真正的Q value,你会发现它们是比较接近的。 用 network 估测出来的就不用管它,比较没有参考价值。用 Double DQN 得出来真正的 accumulated reward,在这 3 个case 都是比原来的DQN 高的,代表 Double DQN learn 出来那个 policy 比较强。所以它实际上得到的reward 是比较大的。虽然一般的 DQN 的 Q-network 高估了自己会得到的reward,但实际上它得到的 reward 是比较低的。
|
||||
$$
|
||||
\nabla \bar{R}_{\theta}=E_{\tau \sim p_{\theta}(\tau)}\left[R(\tau) \nabla \log p_{\theta}(\tau)\right]
|
||||
$$
|
||||
|
||||
问题是上面这个 update 的式子中的 $E_{\tau \sim p_{\theta}(\tau)}$ 应该是你现在的 policy $\theta$ 所 sample 出来的 trajectory $\tau$ 做 expectation。一旦 update 了参数,从 $\theta$ 变成 $\theta'$ ,$p_\theta(\tau)$这个概率就不对了,之前sample 出来的 data 就变的不能用了。所以 policy gradient 是一个会花很多时间来 sample data 的 algorithm,你会发现大多数时间都在 sample data,agent 去跟环境做互动以后,接下来就要 update 参数。你只能 update 参数一次。接下来你就要重新再去 collect data, 然后才能再次update 参数,这显然是非常花时间的。所以我们想要从 on-policy 变成 off-policy。 这样做就可以用另外一个policy, 另外一个actor $\theta'$ 去跟环境做互动。用 $\theta'$ collect 到的data 去训练 $\theta$。假设我们可以用 $\theta'$ collect 到的data 去训练 $\theta$,意味着说我们可以把$\theta'$ collect 到的data 用非常多次。我们可以执行 gradient ascent 好几次,我们可以 update 参数好几次, 都只要用同一笔data 就好了。因为假设 $\theta$ 有能力学习另外一个actor $\theta'$ 所 sample 出来的 data 的话, 那$\theta'$ 就只要sample 一次,也许sample 多一点的data, 让$\theta$ 去update 很多次,这样就会比较有效率。
|
||||

|
||||
|
||||
Q: 为什么 Q value 总是被高估了呢?
|
||||
具体怎么做呢?这边就需要介绍 `important sampling` 的概念。假设你有一个function $f(x)$,你要计算从 p 这个 distribution sample x,再把 x 带到 f 里面,得到$f(x)$。你要该怎么计算这个 $f(x)$ 的期望值?假设你不能对 p 这个distribution 做积分的话,那你可以从 p 这个 distribution 去 sample 一些data $x^i$。把 $x^i$ 代到 $f(x)$ 里面,然后取它的平均值,就可以近似 $f(x)$ 的期望值。
|
||||
|
||||
A: 因为实际上在做的时候,是要让左边这个式子跟右边这个 target 越接近越好。那你会发现说,target 的值很容易一不小心就被设得太高。因为在算这个 target 的时候,我们实际上在做的事情是看哪一个a 可以得到最大的Q value,就把它加上去,就变成我们的target。所以假设有某一个 action 得到的值是被高估的。
|
||||
现在有另外一个问题,我们没有办法从 p 这个 distribution 里面 sample data。假设我们不能从 p sample data,只能从另外一个 distribution q 去 sample data,q 可以是任何 distribution。我们不能够从 p 去sample data,但可以从 q 去 sample $x$。我们从 q 去 sample $x^i$ 的话就不能直接套下面的式子。
|
||||
$$
|
||||
E_{x \sim p}[f(x)] \approx \frac{1}{N} \sum_{i=1}^N f(x^i)
|
||||
$$
|
||||
因为上式是假设你的 $x$ 都是从 p sample 出来的。所以做一个修正,修正是这样子的。期望值$E_{x \sim p}[f(x)]$其实就是$\int f(x) p(x) dx$,我们对其做如下的变换:
|
||||
$$
|
||||
\int f(x) p(x) d x=\int f(x) \frac{p(x)}{q(x)} q(x) d x=E_{x \sim q}[f(x){\frac{p(x)}{q(x)}}]
|
||||
$$
|
||||
我们就可以写成对 q 里面所 sample 出来的 x 取期望值。我们从q 里面 sample x,然后再去计算$f(x) \frac{p(x)}{q(x)}$,再去取期望值。所以就算我们不能从 p 里面去 sample data,只要能够从 q 里面去sample data,然后代入上式,你就可以计算从 p 这个distribution sample x 代入 f 以后所算出来的期望值。
|
||||
|
||||
举例来说, 现在有 4 个 actions,本来其实它们得到的值都是差不多的,它们得到的reward 都是差不多的。但是在estimate 的时候,那毕竟是个network。所以estimate 的时候是有误差的。所以假设今天是第一个action它被高估了,假设绿色的东西代表是被高估的量,它被高估了,那这个target 就会选这个action。然后就会选这个高估的Q value来加上$r_t$,来当作你的target。如果第4 个action 被高估了,那就会选第4 个action 来加上$r_t$ 来当作你的target value。所以你总是会选那个Q value 被高估的,你总是会选那个reward 被高估的action 当作这个max 的结果去加上$r_t$ 当作你的target。所以你的target 总是太大。
|
||||
这边是从 q 做 sample,所以从 q 里 sample 出来的每一笔data,你需要乘上一个 weight 来修正这两个 distribution 的差异,weight 就是$\frac{p(x)}{q(x)}$。$q(x)$ 可以是任何 distribution,唯一的限制就是 $q(x)$ 的概率是 0 的时候,$p(x)$ 的概率不为 0,不然这样会没有定义。假设 $q(x)$ 的概率是 0 的时候,$p(x)$ 的概率也都是 0 的话,那这样 $p(x)$ 除以 $q(x)$是有定义的。所以这个时候你就可以 apply important sampling 这个技巧。你就可以从 p 做 sample 换成从 q 做 sample。
|
||||
|
||||

|
||||
Q: 怎么解决这target 总是太大的问题呢?
|
||||
|
||||
A: 在 Double DQN 里面,选 action 的 Q-function 跟算 value 的 Q-function,不是同一个。在原来的DQN 里面,你穷举所有的 a,把每一个a 都带进去, 看哪一个 a 可以给你的 Q value 最高,那你就把那个 Q value 加上$r_t$。但是在 Double DQN 里面,你有两个 Q-network,第一个 Q-network,决定哪一个 action 的 Q value 最大,你用第一个 Q-network 去带入所有的 a,去看看哪一个Q value 最大。然后你决定你的action 以后,你的 Q value 是用 $Q'$ 算出来的,这样子有什么好处呢?为什么这样就可以避免 over estimate 的问题呢?因为今天假设我们有两个 Q-function,假设第一个Q-function 它高估了它现在选出来的action a,那没关系,只要第二个Q-function $Q'$ 没有高估这个action a 的值,那你算出来的,就还是正常的值。假设反过来是 $Q'$ 高估了某一个action 的值,那也没差, 因为反正只要前面这个Q 不要选那个action 出来就没事了。这个就是 Double DQN 神奇的地方。
|
||||
Important sampling 有一些 issue。虽然理论上你可以把 p 换成任何的 q。但是在实现上, p 和 q 不能够差太多。差太多的话,会有一些问题。什么样的问题呢?
|
||||
|
||||
Q: 哪来 Q 跟 $Q'$ 呢?哪来两个 network 呢?
|
||||
$$
|
||||
E_{x \sim p}[f(x)]=E_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]
|
||||
$$
|
||||
虽然上式成立。但上式左边是$f(x)$ 的期望值,它的distribution 是 p,上式右边是$f(x) \frac{p(x)}{q(x)}$ 的期望值,它的distribution 是 q。如果不是算期望值,而是算 variance 的话。这两个variance 是不一样的。两个 random variable 的 mean 一样,并不代表它的 variance 一样。
|
||||
|
||||
A: 在实现上,你有两个 Q-network, 一个是 target 的 Q-network,一个是真正你会 update 的 Q-network。所以在 Double DQN 里面,你的实现方法会是拿你会 update 参数的那个 Q-network 去选action,然后你拿target 的network,那个固定住不动的network 去算value。而 Double DQN 相较于原来的 DQN 的更改是最少的,它几乎没有增加任何的运算量,连新的network 都不用,因为你原来就有两个network 了。你唯一要做的事情只有,本来你在找最大的a 的时候,你在决定这个a 要放哪一个的时候,你是用$Q'$ 来算,你是用target network 来算,现在改成用另外一个会 update 的 Q-network 来算。
|
||||
我们可以代一下方差的公式
|
||||
$$
|
||||
\operatorname{Var}_{x \sim p}[f(x)]=E_{x \sim p}\left[f(x)^{2}\right]-\left(E_{x \sim p}[f(x)]\right)^{2}
|
||||
$$
|
||||
|
||||
假如你今天只选一个tip 的话,正常人都是 implement Double DQN,因为很容易实现。
|
||||
$$
|
||||
\begin{aligned}
|
||||
\operatorname{Var}_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right] &=E_{x \sim q}\left[\left(f(x) \frac{p(x)}{q(x)}\right)^{2}\right]-\left(E_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]\right)^{2} \\
|
||||
&=E_{x \sim p}\left[f(x)^{2} \frac{p(x)}{q(x)}\right]-\left(E_{x \sim p}[f(x)]\right)^{2}
|
||||
\end{aligned}
|
||||
$$
|
||||
|
||||
$\operatorname{Var}_{x \sim p}[f(x)]$ 和 $\operatorname{Var}_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]$ 的差别在第一项是不同的, $\operatorname{Var}_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]$ 的第一项多乘了$\frac{p(x)}{q(x)}$,如果$\frac{p(x)}{q(x)}$ 差距很大的话, $\operatorname{Var}_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]$的 variance 就会很大。所以虽然理论上它们的expectation 一样,也就是说,你只要对 p 这个distribution sample 够多次,q 这个distribution sample 够多,你得到的结果会是一样的。但是假设你sample 的次数不够多,因为它们的variance 差距是很大的,所以你就有可能得到非常大的差别。
|
||||
|
||||
## Dueling DQN
|
||||

|
||||
第二个 tip 是 `Dueling DQN`。其实 Dueling DQN 也蛮好做的,相较于原来的DQN。它唯一的差别是改了network 的架构,Dueling DQN 唯一做的事情是改network 的架构。Q-network 就是input state,output 就是每一个action 的Q value。dueling DQN 唯一做的事情,是改了network 的架构,其它的算法,你都不要去动它。
|
||||
|
||||
Q: Dueling DQN 是怎么改了network 的架构呢?
|
||||
举个例子,当 $p(x)$ 和 $q(x)$ 差距很大的时候,会发生什么样的问题。假设蓝线是 $p(x)$ 的distribution,绿线是 $q(x)$ 的 distribution,红线是 $f(x)$。如果我们要计算$f(x)$的期望值,从 $p(x)$ 这个distribution 做 sample 的话,那显然 $E_{x \sim p}[f(x)]$ 是负的,因为左边那块区域 $p(x)$ 的概率很高,所以要 sample 的话,都会 sample 到这个地方,而 $f(x)$ 在这个区域是负的, 所以理论上这一项算出来会是负。
|
||||
|
||||
A: 本来的DQN 就是直接output Q value 的值。现在这个dueling 的DQN,就是下面这个network 的架构。它不直接output Q value 的值,它分成两条path 去运算,第一个path,它算出一个scalar,这个scalar 我们叫做$V(s)$。因为它跟input s 是有关系,所以叫做$V(s)$,$V(s)$ 是一个scalar。下面这个会output 一个vector,这个vector 叫做$A(s,a)$。下面这个vector,它是每一个action 都有一个value。然后你再把这两个东西加起来,就得到你的Q value。
|
||||
接下来我们改成从 $q(x)$ 这边做 sample,因为 $q(x)$ 在右边这边的概率比较高,所以如果你sample 的点不够的话,那你可能都只sample 到右侧。如果你都只 sample 到右侧的话,你会发现说,算 $E_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]$这一项,搞不好还应该是正的。你这边sample 到这些点,然后你去计算它们的$f(x) \frac{p(x)}{q(x)}$都是正的,所以你sample 到这些点都是正的。 你取期望值以后,也都是正的。为什么会这样,因为你 sample 的次数不够多,因为假设你sample 次数很少,你只能sample 到右边这边。左边这边虽然概率很低,但也不是没有可能被 sample 到。假设你今天好不容易 sample 到左边的点,因为左边的点,$p(x)$ 和 $q(x)$ 是差很多的, 这边 $p(x)$ 很小,$q(x)$ 很大。今天 $f(x)$ 好不容易终于 sample 到一个负的,这个负的就会被乘上一个非常大的 weight ,这样就可以平衡掉刚才那边一直 sample 到 positive 的 value 的情况。最终你算出这一项的期望值,终究还是负的。但前提是你要sample 够多次,这件事情才会发生。但有可能sample 不够,$E_{x \sim p}[f(x)]$跟$E_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]$就有可能有很大的差距。这就是 importance sampling 的问题。
|
||||
|
||||

|
||||
|
||||
Q: 这么改有什么好处?
|
||||
现在要做的事情就是把 importance sampling 用在 off-policy 的 case。把 on-policy training 的algorithm 改成 off-policy training 的 algorithm。怎么改呢,之前我们是拿 $\theta$ 这个policy 去跟环境做互动,sample 出trajectory $\tau$,然后计算$R(\tau) \nabla \log p_{\theta}(\tau)$。
|
||||
|
||||
A : 那我们假设说,原来的$Q(s,a)$ 就是一个table。我们假设 state 是discrete 的,实际上state 不是discrete 的。那为了说明方便,我们假设就是只有4 个不同的state,只有3 个不同的action,所以$Q(s,a)$ 你可以看作是一个table。
|
||||
现在我们不用$\theta$ 去跟环境做互动,假设有另外一个 policy $\theta'$,它就是另外一个actor。它的工作是他要去做demonstration,$\theta'$ 的工作是要去示范给$\theta$ 看。它去跟环境做互动,告诉 $\theta$ 说,它跟环境做互动会发生什么事。然后,借此来训练$\theta$。我们要训练的是$\theta$ ,$\theta'$ 只是负责做 demo,负责跟环境做互动。
|
||||
|
||||
我们知道:
|
||||
$$
|
||||
Q(s,a) = V(s) + A(s,a)
|
||||
$$
|
||||
我们现在的$\tau$ 是从 $\theta'$ sample 出来的,是拿 $\theta'$ 去跟环境做互动。所以sample 出来的 $\tau$ 是从 $\theta'$ sample 出来的,这两个distribution 不一样。但没有关系,假设你本来是从 p 做sample,但你发现你不能够从 p 做sample,所以我们不拿$\theta$ 去跟环境做互动。你可以把 p 换 q,然后在后面这边补上一个 importance weight。现在的状况就是一样,把 $\theta$ 换成 $\theta'$ 后,要补上一个importance weight $\frac{p_{\theta}(\tau)}{p_{\theta^{\prime}}(\tau)}$。这个 importance weight 就是某一个 trajectory $\tau$ 用 $\theta$ 算出来的概率除以这个 trajectory $\tau$,用$\theta'$ 算出来的概率。这一项是很重要的,因为今天你要learn 的是actor $\theta$ 和 $\theta'$ 是不太一样的。$\theta'$ 会见到的情形跟 $\theta$ 见到的情形不见得是一样的,所以中间要做一个修正的项。
|
||||
|
||||
其中
|
||||
|
||||
* $V(s)$ 是对不同的state 它都有一个值。
|
||||
* $A(s,a)$ 它是对不同的state,不同的action都有一个值。
|
||||
|
||||
你把这个 V 的值加到 A 的每一个 column 就会得到Q 的值。把 2+1,2+(-1),2+0,就得到 3,1,2,以此类推。
|
||||
|
||||
如上图所示,假设说你在train network 的时候,target 是希望这一个值变成 4,这一个值变成 0。但是你实际上能更改的并不是Q 的值,你的network 更改的是V 跟A 的值。根据network 的参数,V 跟A 的值output 以后,就直接把它们加起来,所以其实不是更动Q 的值。然后在learn network 的时候,假设你希望这边的值,这个3 增加1 变成 4,这个-1 增加1 变成 0。最后你在train network 的时候,network 可能会说,我们就不要动这个 A 的值,就动 V 的值,把 V 的值从0 变成 1。把0 变成1 有什么好处呢?你会发现说,本来你只想动这两个东西的值,那你会发现说,这个第三个值也动了,-2 变成 -1。所以有可能说你在某一个state,你明明只sample 到这2 个action,你没sample 到第三个action,但是你其实也可以更改第三个action 的Q value。这样的好处就是你不需要把所有的 state-action pair 都sample 过,你可以用比较efficient 的方式去 estimate Q value 出来。因为有时候你update 的时候,不一定是update 下面这个table。而是只update 了$V(s)$,但update $V(s)$ 的时候,只要一改所有的值就会跟着改。这是一个比较有效率的方法,去使用你的data,这个是Dueling DQN 可以带给我们的好处。
|
||||
|
||||
那可是接下来有人就会问说会不会最后learn 出来的结果是说,反正machine 就学到 V 永远都是 0,然后反正A 就等于 Q,那你就没有得到任何 Dueling DQN 可以带给你的好处, 就变成跟原来的DQN 一模一样。为了避免这个问题,实际上你要给 A 一些constrain,让update A 其实比较麻烦,让network 倾向于会想要去用V 来解问题。
|
||||
|
||||
举例来说,你可以看原始的文献,它有不同的constrain 。那一个最直觉的constrain 是你必须要让这个A 的每一个column 的和都是 0,所以看我这边举的例子,我的column 的和都是 0。那如果这边column 的和都是 0,这边这个V 的值,你就可以想成是上面 Q 的每一个column 的平均值。这个平均值,加上这些值才会变成是Q 的value。所以今天假设你发现说你在update 参数的时候,你是要让整个row 一起被update。你就不会想要update 这边,因为你不会想要update A这个matrix。因为 A 这个matrix 的每一个column 的和都要是 0,所以你没有办法说,让这边的值,通通都+1,这件事是做不到的。因为它的constrain 就是你的和永远都是要 0。所以不可以都+1,这时候就会强迫network 去update V 的值,然后让你可以用比较有效率的方法,去使用你的data。
|
||||
现在的data 不是从$\theta$ sample 出来,是从 $\theta'$ sample 出来的。从$\theta$ 换成$\theta'$ 有什么好处呢?因为现在跟环境做互动是$\theta'$ 而不是$\theta$。所以 sample 出来的东西跟 $\theta$ 本身是没有关系的。所以你就可以让 $\theta'$ 做互动 sample 一大堆的data,$\theta$ 可以update 参数很多次。然后一直到 $\theta$ train 到一定的程度,update 很多次以后,$\theta'$ 再重新去做sample,这就是on-policy 换成off-policy 的妙用。
|
||||
|
||||

|
||||
|
||||
实现时,你要给这个 A 一个 constrain。举个例子,假设你有 3 个actions,然后在这边 output 的 vector 是7 3 2,你在把这个 A 跟这个 V 加起来之前,先加一个normalization,就好像做那个layer normalization 一样。加一个normalization,这个normalization 做的事情就是把 7+3+2 加起来等于 12,12/3 = 4。然后把这边通通减掉 4,变成 3, -1, 2。再把 3, -1, 2 加上 1.0,得到最后的Q value。这个normalization 的 step 就是 network 的其中一部分,在train 的时候,你从这边也是一路 back propagate 回来的,只是 normalization 是没有参数的,它只是一个normalization 的operation。把它可以放到network 里面,跟network 的其他部分 jointly trained,这样 A 就会有比较大的 constrain。这样network 就会给它一些benefit, 倾向于去update V 的值,这个是Dueling DQN。
|
||||
实际在做 policy gradient 的时候,我们并不是给整个 trajectory $\tau$ 都一样的分数,而是每一个state-action 的pair 会分开来计算。实际上 update gradient 的时候,我们的式子是长这样子的。
|
||||
$$
|
||||
=E_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta}}\left[A^{\theta}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right]
|
||||
$$
|
||||
|
||||
我们用 $\theta$ 这个actor 去sample 出$s_t$ 跟$a_t$,sample 出state 跟action 的pair,我们会计算这个state 跟action pair 它的advantage, 就是它有多好。$A^{\theta}\left(s_{t}, a_{t}\right)$就是 accumulated 的 reward 减掉 bias,这一项就是估测出来的。它要估测的是,在state $s_t$ 采取action $a_t$ 是好的,还是不好的。那接下来后面会乘上$\nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)$,也就是说如果$A^{\theta}\left(s_{t}, a_{t}\right)$是正的,就要增加概率, 如果是负的,就要减少概率。
|
||||
|
||||
那现在用了 importance sampling 的技术把 on-policy 变成 off-policy,就从 $\theta$ 变成 $\theta'$。所以现在$s_t$、$a_t$ 是$\theta'$ ,另外一个actor 跟环境互动以后所 sample 到的data。 但是拿来训练要调整参数是 model $\theta$。因为 $\theta'$ 跟 $\theta$ 是不同的model,所以你要做一个修正的项。这项修正的项,就是用 importance sampling 的技术,把$s_t$、$a_t$ 用 $\theta$ sample 出来的概率除掉$s_t$、$a_t$ 用 $\theta'$ sample 出来的概率。
|
||||
|
||||
$$
|
||||
=E_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{P_{\theta}\left(s_{t}, a_{t}\right)}{P_{\theta^{\prime}}\left(s_{t}, a_{t}\right)} A^{\theta}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right]
|
||||
$$
|
||||
|
||||
这边 $A^{\theta}(s_t,a_t)$ 有一个上标 $\theta$,$\theta$ 代表说这个是 actor $\theta$ 跟环境互动的时候所计算出来的 A。但是实际上从 $\theta$ 换到 $\theta'$ 的时候,$A^{\theta}(s_t,a_t)$ 应该改成 $A^{\theta'}(s_t,a_t)$,为什么?A 这一项是想要估测说现在在某一个 state 采取某一个 action,接下来会得到 accumulated reward 的值减掉base line 。你怎么估 A 这一项,你就会看在 state $s_t$,采取 action $a_t$,接下来会得到的reward 的总和,再减掉baseline。之前是 $\theta$ 在跟环境做互动,所以你观察到的是 $\theta$ 可以得到的reward。但现在是 $\theta'$ 在跟环境做互动,所以你得到的这个advantage, 其实是根据 $\theta'$ 所estimate 出来的advantage。但我们现在先不要管那么多, 我们就假设这两项可能是差不多的。
|
||||
|
||||
那接下来,我们可以拆解 $p_{\theta}\left(s_{t}, a_{t}\right)$ 和 $p_{\theta'}\left(s_{t}, a_{t}\right)$,即
|
||||
$$
|
||||
\begin{aligned}
|
||||
p_{\theta}\left(s_{t}, a_{t}\right)&=p_{\theta}\left(a_{t}|s_{t}\right) p_{\theta}(s_t) \\
|
||||
p_{\theta'}\left(s_{t}, a_{t}\right)&=p_{\theta'}\left(a_{t}|s_{t}\right) p_{\theta'}(s_t)
|
||||
\end{aligned}
|
||||
$$
|
||||
于是我们得到下式:
|
||||
$$
|
||||
=E_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} \frac{p_{\theta}\left(s_{t}\right)}{p_{\theta^{\prime}}\left(s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right]
|
||||
$$
|
||||
|
||||
|
||||
## Prioritized Experience Replay
|
||||
然后这边需要做一件事情是,假设 model 是 $\theta$ 的时候,你看到$s_t$ 的概率,跟 model 是$\theta'$ 的时候,你看到$s_t$ 的概率是差不多的,即$p_{\theta}(s_t)=p_{\theta'}(s_t)$。因为它们是一样的,所以你可以把它删掉,即
|
||||
$$
|
||||
=E_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right] \quad(1)
|
||||
$$
|
||||
|
||||
为什么可以假设它是差不多的。举例来说,会看到什么state 往往跟你会采取什么样的action 是没有太大的关系的。比如说你玩不同的 Atari 的游戏,其实你看到的游戏画面都是差不多的,所以也许不同的 $\theta$ 对 $s_t$ 是没有影响的。但是有一个更直觉的理由就是这一项到时候真的要你算,你会算吗?因为想想看这项要怎么算,这一项你还要说我有一个参数$\theta$,然后拿$\theta$ 去跟环境做互动,算$s_t$ 出现的概率,这个你根本很难算。尤其是你如果 input 是image 的话, 同样的 $s_t$ 根本就不会出现第二次。你根本没有办法估这一项, 所以干脆就无视这个问题。
|
||||
|
||||
但是 $p_{\theta}(a_t|s_t)$很好算。你手上有$\theta$ 这个参数,它就是个network。你就把$s_t$ 带进去,$s_t$ 就是游戏画面,你把游戏画面带进去,它就会告诉你某一个state 的 $a_t$ 概率是多少。我们其实有个 policy 的network,把 $s_t$ 带进去,它会告诉我们每一个 $a_t$ 的概率是多少。所以
|
||||
$\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)}$ 这一项,你只要知道$\theta$ 和 $\theta'$ 的参数就可以算。
|
||||
|
||||
现在我们得到一个新的objective function。
|
||||
|
||||
$$
|
||||
J^{\theta^{\prime}}(\theta)=E_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right)\right]
|
||||
$$
|
||||
|
||||
|
||||
式(1)是 gradient,其实我们可以从 gradient 去反推原来的 objective function。这边有一个公式
|
||||
|
||||
$$
|
||||
\nabla f(x)=f(x) \nabla \log f(x)
|
||||
$$
|
||||
|
||||
我们可以用这个公式来反推objective function,要注意一点,对 $\theta$ 求梯度时,$p_{\theta^{\prime}}(a_{t} | s_{t})$ 和 $A^{\theta^{\prime}}\left(s_{t}, a_{t}\right)$ 都是常数。
|
||||
|
||||
|
||||
所以实际上,当我们apply importance sampling 的时候,要去optimize 的那一个objective function 就长这样子,我们把它写作$J^{\theta^{\prime}}(\theta)$。为什么写成$J^{\theta^{\prime}}(\theta)$ 呢,这个括号里面那个$\theta$ 代表我们要去optimize 的那个参数。$\theta'$ 是说我们拿 $\theta'$ 去做demonstration,就是现在真正在跟环境互动的是$\theta'$。因为 $\theta$ 不跟环境做互动,是 $\theta'$ 在跟环境互动。
|
||||
|
||||
然后你用$\theta'$ 去跟环境做互动,sample 出$s_t$、$a_t$ 以后,你要去计算$s_t$ 跟$a_t$ 的advantage,然后你再去把它乘上$\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)}$。$\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)}$是好算的,$A^{\theta^{\prime}}\left(s_{t}, a_{t}\right)$ 可以从这个 sample 的结果里面去估测出来的,所以 $J^{\theta^{\prime}}(\theta)$ 是可以算的。实际上在 update 参数的时候,就是按照式(1) 来 update 参数。
|
||||
|
||||
|
||||
|
||||
## PPO
|
||||
|
||||

|
||||
有一个技巧叫做 `Prioritized Experience Replay`。Prioritized Experience Replay 是什么意思呢?
|
||||
|
||||
我们原来在 sample data 去 train 你的 Q-network 的时候,你是 uniformly 从 experience buffer 里面去 sample data。那这样不见得是最好的, 因为也许有一些 data 比较重要。假设有一些 data,你之前有 sample 过。你发现这些 data 的 TD error 特别大(TD error 就是 network 的 output 跟 target 之间的差距),那这些 data 代表说你在 train network 的时候, 你是比较 train 不好的。那既然比较 train 不好, 那你就应该给它比较大的概率被 sample 到,即给它 `priority`。这样在 training 的时候才会多考虑那些 train 不好的 training data。实际上在做 prioritized experience replay 的时候,你不仅会更改 sampling 的 process,你还会因为更改了 sampling 的 process,更改 update 参数的方法。所以 prioritized experience replay 不仅改变了 sample data 的 distribution,还改变了 training process。
|
||||
## Balance between MC and TD
|
||||
我们可以把 on-policy 换成 off-policy,但 importance sampling 有一个 issue,如果 $p_{\theta}\left(a_{t} | s_{t}\right)$ 跟 $p_{\theta'}\left(a_{t} | s_{t}\right)$ 差太多的话,这两个 distribution 差太多的话,importance sampling 的结果就会不好。怎么避免它差太多呢?这个就是 `Proximal Policy Optimization (PPO) ` 在做的事情。它实际上做的事情就是这样,在 off-policy 的方法里要optimize 的是 $J^{\theta^{\prime}}(\theta)$。但是这个 objective function 又牵涉到 importance sampling。在做 importance sampling 的时候,$p_{\theta}\left(a_{t} | s_{t}\right)$ 不能跟 $p_{\theta'}\left(a_{t} | s_{t}\right)$差太多。你做 demonstration 的 model 不能够跟真正的 model 差太多,差太多的话 importance sampling 的结果就会不好。我们在 training 的时候,多加一个 constrain。这个constrain 是 $\theta$ 跟 $\theta'$ output 的 action 的 KL divergence,简单来说,这一项的意思就是要衡量说 $\theta$ 跟 $\theta'$ 有多像。
|
||||
|
||||
然后我们希望在 training 的过程中,learn 出来的 $\theta$ 跟 $\theta'$ 越像越好。因为如果 $\theta$ 跟 $\theta'$ 不像的话,最后的结果就会不好。所以在 PPO 里面有两个式子,一方面是 optimize 本来要 optimize 的东西,但再加一个 constrain。这个 constrain 就好像那个 regularization 的 term 一样,在做 machine learning 的时候不是有 L1/L2 的regularization。这一项也很像 regularization,这样 regularization 做的事情就是希望最后 learn 出来的 $\theta$ 不要跟 $\theta'$ 太不一样。
|
||||
|
||||
PPO 有一个前身叫做TRPO,TRPO 的式子如下式所示。
|
||||
$$
|
||||
\begin{aligned}
|
||||
J_{T R P O}^{\theta^{\prime}}(\theta)=E_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right)\right] \\ \\
|
||||
\mathrm{KL}\left(\theta, \theta^{\prime}\right)<\delta
|
||||
\end{aligned}
|
||||
$$
|
||||
|
||||
它与PPO不一样的地方 是 constrain 摆的位置不一样,PPO是直接把 constrain 放到你要 optimize 的那个式子里面,然后你就可以用 gradient ascent 的方法去 maximize 这个式子。但 TRPO 是把 KL divergence 当作constrain,它希望 $\theta$ 跟 $\theta'$ 的 KL divergence 小于一个$\delta$。如果你是用 gradient based optimization 时,有 constrain 是很难处理的。
|
||||
|
||||
PPO是很难处理的,因为它是把 KL divergence constrain 当做一个额外的 constrain,没有放 objective 里面,所以它很难算。所以不想搬石头砸自己的脚的话, 你就用PPO 不要用TRPO。看文献上的结果是,PPO 跟TRPO 可能 performance 差不多,但 PPO 在实现上比 TRPO 容易的多。
|
||||
|
||||
KL divergence 到底指的是什么?这边我是直接把 KL divergence 当做一个 function,input 是 $\theta$ 跟 $\theta'$,但我的意思并不是说把 $\theta$ 或 $\theta'$ 当做一个distribution,算这两个distribution 之间的距离,我不是这个意思。所谓的 $\theta$ 跟 $\theta'$ 的距离并不是参数上的距离,而是 behavior 上的距离。
|
||||
|
||||
假设你有一个model,有一个actor 它是$\theta$,你有另外一个actor 的参数是$\theta'$ ,所谓参数上的距离就是你算这两组参数有多像。我今天所讲的不是参数上的距离, 而是它们行为上的距离。就是你先带进去一个state s,它会对这个 action 的 space output 一个 distribution。假设你有 3 个actions,3 个可能的 actions 就 output 3 个值。那今天所指的 distance 是behavior distance。也就是说,给同样的 state 的时候,输出 action 之间的差距。这两个 actions 的 distribution 都是一个概率分布。所以就可以计算这两个概率分布的 KL divergence。把不同的 state output 的这两个 distribution 的KL divergence 平均起来才是我这边所指的两个 actor 间的 KL divergence。你可能说怎么不直接算这个 $\theta$ 或 $\theta'$ 之间的距离,甚至不要用KL divergence 算,L1 跟 L2 的 norm 也可以保证 $\theta$ 跟 $\theta'$ 很接近啊。在做reinforcement learning 的时候,之所以我们考虑的不是参数上的距离,而是 action 上的距离,是因为很有可能对 actor 来说,参数的变化跟 action 的变化不一定是完全一致的。有时候你参数小小变了一下,它可能 output 的行为就差很多。或是参数变很多,但 output 的行为可能没什么改变。**所以我们真正在意的是这个actor 它的行为上的差距,而不是它们参数上的差距。**所以在做PPO 的时候,所谓的 KL divergence 并不是参数的距离,而是action 的距离。
|
||||
|
||||

|
||||
另外一个可以做的方法是,你可以balance MC 跟TD。MC 跟 TD 的方法各自有各自的优劣。我们怎么在MC 跟TD 里面取得一个平衡呢?我们的做法是这样,在TD 里面,在某一个state $s_t$采取某一个action $a_t$ 得到 reward $r_t$,接下来跳到那一个state $s_{t+1}$。但是我们可以不要只存一个step 的data,我们存 N 个step 的data。
|
||||
|
||||
我们记录在$s_t$ 采取$a_t$,得到$r_t$,会跳到什么样$s_t$。一直纪录到在第N 个step 以后,在$s_{t+N}$采取$a_{t+N}$得到 reward $r_{t+N}$,跳到$s_{t+N+1}$的这个经验,通通把它存下来。实际上你今天在做update 的时候, 在做你 Q-network learning 的时候,你的learning 的方法会是这样,你learning 的时候,要让 $Q(s_t,a_t)$ 跟你的target value 越接近越好。$\hat{Q}$ 所计算的不是$s_{t+1}$,而是$s_{t+N+1}$的。你会把 N 个step 以后的state 丢进来,去计算 N 个step 以后,你会得到的reward。要算 target value 的话,要再加上multi-step 的reward $\sum_{t^{\prime}=t}^{t+N} r_{t^{\prime}}$ ,multi-step 的 reward 是从时间 t 一直到 t+N 的 N 个reward 的和。然后希望你的 $Q(s_t,a_t)$ 和 target value 越接近越好。
|
||||
我们来看一下PPO1 的algorithm。它先initial 一个policy 的参数$\theta^0$。然后在每一个iteration 里面呢,你要用参数$\theta^k$,$\theta^k$ 就是你在前一个training 的iteration得到的actor 的参数,你用$\theta^k$ 去跟环境做互动,sample 到一大堆 state-action 的pair。
|
||||
|
||||
你会发现说这个方法就是 MC 跟 TD 的结合。因此它就有 MC 的好处跟坏处,也有 TD 的好处跟坏处。如果看它的这个好处的话,因为我们现在 sample 了比较多的step,之前是只sample 了一个step, 所以某一个step 得到的data 是real 的,接下来都是Q value 估测出来的。现在sample 比较多step,sample N 个step 才估测value,所以估测的部分所造成的影响就会比小。当然它的坏处就跟MC 的坏处一样,因为你的 r 比较多项,你把 N 项的 r 加起来,你的variance 就会比较大。但是你可以去调这个N 的值,去在variance 跟不精确的 Q 之间取得一个平衡。N 就是一个hyper parameter,你要调这个N 到底是多少,你是要多 sample 三步,还是多 sample 五步。
|
||||
然后你根据$\theta^k$ 互动的结果,估测一下$A^{\theta^{k}}\left(s_{t}, a_{t}\right)$。然后你就 apply PPO 的 optimization 的 formulation。但跟原来的policy gradient 不一样,原来的 policy gradient 只能 update 一次参数,update 完以后,你就要重新 sample data。但是现在不用,你拿 $\theta^k$ 去跟环境做互动,sample 到这组 data 以后,你可以让 $\theta$ update 很多次,想办法去 maximize objective function。这边 $\theta$ update 很多次没有关系,因为我们已经有做 importance sampling,所以这些experience,这些 state-action 的 pair 是从 $\theta^k$ sample 出来的没有关系。$\theta$ 可以 update 很多次,它跟 $\theta^k$ 变得不太一样也没有关系,你还是可以照样训练 $\theta$。
|
||||
|
||||
## Noisy Net
|
||||

|
||||
有一个技术是要improve 这个exploration 这件事,我们之前讲的Epsilon Greedy 这样的 exploration 是在action 的space 上面加noise,但是有另外一个更好的方法叫做`Noisy Net`,它是在参数的space 上面加noise。Noisy Net 的意思是说,每一次在一个episode 开始的时候,在你要跟环境互动的时候,你就把你的Q-function 拿出来,Q-function 里面其实就是一个network ,就变成你把那个network 拿出来,在network 的每一个参数上面加上一个Gaussian noise。那你就把原来的Q-function 变成$\tilde{Q}$ 。因为$\hat{Q}$ 已经用过,$\hat{Q}$ 是那个target network,我们用 $\tilde{Q}$ 来代表一个`Noisy Q-function`。我们把每一个参数都可能都加上一个Gaussian noise,就得到一个新的network 叫做$\tilde{Q}$。这边要注意在每个episode 开始的时候,开始跟环境互动之前,我们就 sample network。接下来你就会用这个固定住的 noisy network 去玩这个游戏,直到游戏结束,你才重新再去sample 新的noise。OpenAI 跟 Deep mind 又在同时间 propose 一模一样的方法,通通都publish 在ICLR 2018,两篇paper 的方法就是一样的。不一样的地方是,他们用不同的方法,去加noise。OpenAI 加的方法好像比较简单,他就直接加一个 Gaussian noise 就结束了,就你把每一个参数,每一个weight都加一个Gaussian noise 就结束了。Deep mind 做比较复杂,他们的noise 是由一组参数控制的,也就是说 network 可以自己决定说它那个noise 要加多大,但是概念就是一样的。总之就是把你的Q-function的里面的那个network 加上一些noise,把它变得有点不一样,跟原来的Q-function 不一样,然后拿去跟环境做互动。两篇paper 里面都有强调说,你这个参数虽然会加noise,但在同一个episode 里面你的参数就是固定的,你是在换episode, 玩第二场新的游戏的时候,你才会重新sample noise,在同一场游戏里面就是同一个noisy Q-network 在玩那一场游戏,这件事非常重要。为什么这件事非常重要呢?因为这是导致了Noisy Net 跟原来的Epsilon Greedy 或其它在action 做sample 方法的本质上的差异。
|
||||
|
||||
在PPO 的paper 里面还有一个 `adaptive KL divergence`,这边会遇到一个问题就是 $\beta$ 要设多少,它就跟那个regularization 一样。regularization 前面也要乘一个weight,所以这个 KL divergence 前面也要乘一个 weight,但 $\beta$ 要设多少呢?所以有个动态调整 $\beta$ 的方法。在这个方法里面呢,你先设一个 KL divergence,你可以接受的最大值。然后假设你发现说你 optimize 完这个式子以后,KL divergence 的项太大,那就代表说后面这个 penalize 的 term 没有发挥作用,那就把 $\beta$ 调大。那另外你定一个 KL divergence 的最小值。如果发现 optimize 完上面这个式子以后,KL divergence 比最小值还要小,那代表后面这一项的效果太强了,你怕他只弄后面这一项,那$\theta$ 跟$\theta^k$ 都一样,这不是你要的,所以你这个时候你叫要减少 $\beta$。所以 $\beta$ 是可以动态调整的。这个叫做 adaptive KL penalty。
|
||||
|
||||

|
||||
|
||||
有什么样本质上的差异呢?在原来sample 的方法,比如说Epsilon Greedy 里面,就算是给同样的state,你的agent 采取的action 也不一定是一样的。因为你是用sample 决定的,given 同一个state,要根据 Q-function 的network,你会得到一个action,你 sample 到random,你会采取另外一个action。所以 given 同样的state,如果你今天是用Epsilon Greedy 的方法,它得到的 action 是不一样的。但实际上你的policy 并不是这样运作的啊。在一个真实世界的policy,给同样的state,他应该会有同样的回应。而不是给同样的state,它其实有时候吃 Q-function,然后有时候又是随机的,所以这是一个不正常的action,是在真实的情况下不会出现的action。但是如果你是在Q-function 上面去加noise 的话, 就不会有这个情形。因为如果你今天在Q-function 上加 noise,在Q-function 的network 的参数上加noise,那在整个互动的过程中,在同一个episode 里面,它的network 的参数总是固定的,所以看到同样的state,或是相似的state,就会采取同样的action,那这个是比较正常的。在paper 里面有说,这个叫做 `state-dependent exploration`,也就是说你虽然会做 explore 这件事, 但是你的explore 是跟state 有关系的,看到同样的state, 你就会采取同样的exploration 的方式,而 noisy 的 action 只是随机乱试。但如果你是在参数下加noise,那在同一个episode 里面,里面你的参数是固定的。那你就是有系统地在尝试,每次会试说,在某一个state,我都向左试试看。然后再下一次在玩这个同样游戏的时候,看到同样的state,你就说我再向右试试看,你是有系统地在explore 这个环境。
|
||||
如果你觉得算 KL divergence 很复杂。有一个PPO2。PPO2 要去 maximize 的 objective function 如下式所示,它的式子里面就没有 KL divergence 。
|
||||
$$
|
||||
\begin{aligned}
|
||||
J_{P P O 2}^{\theta^{k}}(\theta) \approx \sum_{\left(s_{t}, a_{t}\right)} \min &\left(\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)} A^{\theta^{k}}\left(s_{t}, a_{t}\right),\right.\\
|
||||
&\left.\operatorname{clip}\left(\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}, 1-\varepsilon, 1+\varepsilon\right) A^{\theta^{k}}\left(s_{t}, a_{t}\right)\right)
|
||||
\end{aligned}
|
||||
$$
|
||||
这个式子看起来有点复杂,但实际 implement 就很简单。我们来实际看一下说这个式子到底是什么意思。
|
||||
min 这个 operator 做的事情是第一项跟第二项里面选比较小的那个。第二项前面有个clip function,clip 这个function 的意思是说,在括号里面有3 项,如果第一项小于第二项的话,那就output $1-\varepsilon$ 。第一项如果大于第三项的话,那就output $1+\varepsilon$。 $\varepsilon$ 是一个 hyper parameter,你要tune 的,你可以设成 0.1 或 设 0.2 。
|
||||
假设这边设0.2 的话,如下式所示
|
||||
$$
|
||||
\operatorname{clip}\left(\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}, 0.8, 1.2\right)
|
||||
$$
|
||||
|
||||
如果$\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}$算出来小于0.8,那就当作0.8。如果算出来大于1.2,那就当作1.2。
|
||||
|
||||
我们先看一下下面这项这个算出来到底是什么的东西。
|
||||
$$
|
||||
\operatorname{clip}\left(\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}, 1-\varepsilon, 1+\varepsilon\right)
|
||||
$$
|
||||
|
||||
## Distributional Q-function
|
||||

|
||||
|
||||
还有一个技巧叫做 Distributional Q-function。我们不讲它的细节,只告诉你大致的概念。Distributional Q-function 还蛮有道理的, 但是它没有红起来。你就发现说没有太多人真的在实现的时候用这个技术,可能一个原因就是它不好实现。它的意思是什么?Q-function 到底是什么意思啊,Q-function 是 accumulated reward 的期望值,所以我们算出来的这个Q value 其实是一个期望值。因为环境是有随机性的,在某一个state 采取某一个action 的时候,我们把所有的reward 玩到游戏结束的时候所有的 reward 进行一个统计,你其实得到的是一个distribution。也许在reward 得到0 的机率很高,在-10 的概率比较低,在+10 的概率比较低,但是它是一个distribution。我们对这一个distribution 算它的mean才是这个Q value,我们算出来是 expected accumulated reward。所以这accumulated reward 是一个distribution,对它取expectation,对它取mean,你得到了Q value。但不同的distribution,它们其实可以有同样的mean。也许真正的distribution 是右边的distribution,它算出来的 mean 跟左边的 distribution 算出来的mean 其实是一样的,但它们背后所代表的distribution 其实是不一样的。假设我们只用一个 expected 的 Q value 来代表整个reward 的话,其实可能会丢失一些 information,你没有办法 model reward 的distribution。
|
||||
上图的横轴是 $\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}$,纵轴是 clip function 实际的输出。
|
||||
|
||||
* 如果 $\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}$ 大于$1+\varepsilon$,输出就是$1+\varepsilon$。
|
||||
* 如果小于 $1-\varepsilon$, 它输出就是 $1-\varepsilon$。
|
||||
* 如果介于 $1+\varepsilon$ 跟 $1-\varepsilon$ 之间, 就是输入等于输出。
|
||||
|
||||

|
||||
|
||||
Distributional Q-function 它想要做的事情是model distribution,怎么做呢?在原来的 Q-function 里面,假设你只能够采取 $a_1$, $a_2$, $a_3$, 3 个actions,那你就是input 一个state,output 3 个values。3 个values 分别代表3 个actions 的Q value,但是这个 Q value 是一个distribution 的期望值。所以 Distributional Q-function 的想法就是何不直接output 那个 distribution。但是要直接output 一个distribution 也不知道怎么做嘛。实际上的做法是说, 假设 distribution 的值就分布在某一个 range 里面,比如说-10 到10,那把-10 到10 中间拆成一个一个的bin,拆成一个一个的长条图。举例来说,在这个例子里面,每一个action 的 reward 的space 就拆成 5 个bin。假设reward 可以拆成5 个bin 的话,今天你的Q-function 的output 是要预测说,你在某一个 state,采取某一个action,你得到的reward,落在某一个bin 里面的概率。所以其实这边的概率的和,这些绿色的bar 的和应该是 1,它的高度代表说,在某一个state,采取某一个action 的时候,它落在某一个bin 的机率。这边绿色的代表action 1,红色的代表action 2,蓝色的代表action 3。所以今天你就可以真的用Q-function 去 estimate $a_1$ 的distribution,$a_2$ 的distribution,$a_3$ 的distribution。那实际上在做testing 的时候, 我们还是要选某一个action去执行嘛,那选哪一个action 呢?实际上在做的时候,还是选这个mean 最大的那个action 去执行。但假设我们今天可以 model distribution 的话,除了选mean 最大的以外,也许在未来你可以有更多其他的运用。举例来说,你可以考虑它的distribution 长什么样子。若distribution variance 很大,代表说采取这个action 虽然mean 可能平均而言很不错,但也许风险很高,你可以train一个network 它是可以规避风险的。就在 2 个action mean 都差不多的情况下,也许可以选一个风险比较小的 action 来执行,这是 Distributional Q-function 的好处。关于怎么train 这样的 Q-network 的细节,我们就不讲,你只要记得说 Q-network 有办法output 一个distribution 就对了。我们可以不只是估测得到的期望reward mean 的值。我们其实是可以估测一个distribution 的。
|
||||
|
||||
## Rainbow
|
||||
$\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}$ 是绿色的线,$\operatorname{clip}\left(\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}, 1-\varepsilon, 1+\varepsilon\right)$ 是蓝色的线。在绿色的线跟蓝色的线中间,我们要取一个最小的。假设前面乘上的这个 term A,它是大于0 的话,取最小的结果,就是红色的这一条线。
|
||||
|
||||

|
||||
|
||||
最后一个技巧叫做 rainbow 。Rainbow 就是把刚才所有的方法都综合起来就变成 rainbow 。因为刚才每一个方法,就是有一种自己的颜色,把所有的颜色通通都合起来,就变成rainbow,它把原来的DQN 也算是一种方法,故有 7 色。
|
||||
如果 A 小于0 的话,取最小的以后,就得到红色的这一条线。
|
||||
这一个式子虽然看起来有点复杂,implement 起来是蛮简单的,因为这个式子想要做的事情就是希望 $p_{\theta}(a_{t} | s_{t})$ 跟$p_{\theta^k}(a_{t} | s_{t})$,也就是你拿来做 demonstration 的那个model, 跟你实际上 learn 的 model,在optimize 以后不要差距太大。那你要怎么让它做到不要差距太大呢?
|
||||
|
||||
那我们来看看这些不同的方法。横轴是 training process,纵轴是玩了10 几个 Atari 小游戏的平均的分数的和,但它取的是median 的分数,为什么是取 median 不是直接取平均呢?因为它说每一个小游戏的分数,其实差很多。如果你取平均的话,到时候某几个游戏就dominate 你的结果,所以它取median 的值。
|
||||
如果 A 大于 0,也就是某一个 state-action 的pair 是好的。那我们希望增加这个state-action pair 的概率。也就是说,我们想要让 $p_{\theta}(a_{t} | s_{t})$ 越大越好,但它跟 $p_{\theta^k}(a_{t} | s_{t})$ 的比值不可以超过 $1+\varepsilon$。如果超过$1+\varepsilon$ 的话,就没有benefit 了。红色的线就是我们的objective function,我们希望objective 越大越好,我们希望 $p_{\theta}(a_{t} | s_{t})$ 越大越好。但是$\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}$只要大过 $1+\varepsilon$,就没有benefit 了。
|
||||
|
||||
所以今天在train 的时候,当$p_{\theta}(a_{t} | s_{t})$ 被 train 到$\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}$大于 $1+\varepsilon$ 时,它就会停止。
|
||||
|
||||
假设 $p_{\theta}(a_{t} | s_{t})$ 比 $p_{\theta^k}(a_{t} | s_{t})$ 还要小,那我们的目标是要让 $p_{\theta}(a_{t} | s_{t})$ 越大越好。
|
||||
|
||||
* 假设这个 advantage 是正的,我们希望$p_{\theta}(a_{t} | s_{t})$ 越大越好。假设这个 action 是好的,我们当然希望这个 action 被采取的概率越大越好。所以假设 $p_{\theta}(a_{t} | s_{t})$ 还比 $p_{\theta^k}(a_{t} | s_{t})$ 小,那就尽量把它挪大,但只要大到$1+\varepsilon$ 就好。
|
||||
* 负的时候也是一样,如果某一个state-action pair 是不好的,我们希望把 $p_{\theta}(a_{t} | s_{t})$ 减小。如果 $p_{\theta}(a_{t} | s_{t})$ 比$p_{\theta^k}(a_{t} | s_{t})$ 还大,那你就尽量把它压小,压到$\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}$是$1-\epsilon$ 的时候就停了,就不要再压得更小。
|
||||
|
||||
这样的好处就是, 你不会让 $p_{\theta}(a_{t} | s_{t})$ 跟 $p_{\theta^k}(a_{t} | s_{t})$ 差距太大。要 implement 这个东西,很简单。
|
||||
|
||||
如果你是一般的DQN,就灰色这一条线,就没有很强。那如果是你换noisy DQN,就强很多。如果这边每一个单一颜色的线是代表说只用某一个方法,那紫色这一条线是DDQN(Double DQN),DDQN 还蛮有效的。然后 Prioritized DDQN、Dueling DDQN 和 Distributional DQN 都蛮强的,它们都差不多很强的。A3C 其实是 Actor-Critic 的方法。单纯的 A3C 看起来是比DQN 强的。这边怎么没有 multi-step 的方法,multi-step 的方法就是 balance TD 跟MC,我猜是因为 A3C 本身内部就有做 multi-step 的方法,所以他可能觉得说有 implement A3C 就算是有 implement multi-step 的方法。所以可以把这个 A3C 的结果想成是 multi-step 方法的结果。其实这些方法他们本身之间是没有冲突的,所以全部都用上去就变成七彩的一个方法,就叫做rainbow,然后它很高。
|
||||
|
||||

|
||||
上图是 PPO 跟其它方法的比较。Actor-Critic 和 A2C+Trust Region 方法是actor-critic based 的方法。PPO 是紫色线的方法,这边每张图就是某一个RL 的任务,你会发现说在多数的cases 里面,PPO 都是不错的,不是最好的,就是第二好的。
|
||||
|
||||
上图是说,在rainbow 这个方法里面, 如果我们每次拿掉其中一个技术,到底差多少。因为现在是把所有的方法都加在一起,发现说进步很多,但会不会有些方法其实是没用的。所以看看说, 每一个方法哪些方法特别有用,哪些方法特别没用。这边的虚线就是拿掉某一种方法以后的结果,你会发现说,黄色的虚线,拿掉 multi-step 掉很多。Rainbow 是彩色这一条,拿掉 multi-step 会掉下来。拿掉 Prioritized Experience Replay 后也马上就掉下来。拿掉这个distribution,它也掉下来。
|
||||
|
||||
这边有一个有趣的地方是说,在开始的时候,distribution 训练的方法跟其他方法速度差不多。但是如果你拿掉distribution 的时候,你的训练不会变慢,但是 performance 最后会收敛在比较差的地方。拿掉 Noisy Net 后performance 也是差一点。拿掉Dueling 也是差一点。拿掉 Double 没什么差,所以看来全部合在一起的时候,Double 是比较没有影响的。其实在paper 里面有给一个make sense 的解释,其实当你有用 Distributional DQN的 时候,本质上就不会over estimate 你的reward。我们是为了避免over estimate reward 才加了Double DQN。那在paper 里面有讲说,如果有做 Distributional DQN,就比较不会有over estimate 的结果。 事实上他有真的算了一下发现说,其实多数的状况是 under estimate reward 的,所以会变成Double DQN 没有用。那为什么做 Distributional DQN,不会over estimate reward,反而会under estimate reward 呢?因为这个 distributional DQN 的 output 的是一个distribution 的range,output 的 range 不可能是无限宽的,你一定是设一个range, 比如说我最大output range 就是从-10 到10。假设今天得到的reward 超过10 怎么办?是100 怎么办,就当作没看到这件事。所以 reward 很极端的值,很大的值其实是会被丢掉的, 所以用 Distributional DQN 的时候,你不会有over estimate 的现象,反而会 under estimate。
|
||||
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 188 KiB |
|
Before Width: | Height: | Size: 961 KiB After Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 802 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 617 KiB After Width: | Height: | Size: 197 KiB |
|
Before Width: | Height: | Size: 1.8 MiB After Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 645 KiB |
|
Before Width: | Height: | Size: 613 KiB After Width: | Height: | Size: 241 KiB |
|
Before Width: | Height: | Size: 1001 KiB After Width: | Height: | Size: 227 KiB |
|
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 268 KiB |
|
Before Width: | Height: | Size: 862 KiB After Width: | Height: | Size: 208 KiB |
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 283 KiB |
|
Before Width: | Height: | Size: 405 KiB After Width: | Height: | Size: 222 KiB |
|
Before Width: | Height: | Size: 920 KiB After Width: | Height: | Size: 195 KiB |
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 451 KiB |