本文内容以及图片均源自李宏毅老师2017机器学习课程
RNN-based is always not easy to learn
一般而言,你在做training的时候,你会希望,你的learning curve是像蓝色这条线,纵轴是total loss,横轴是epoch的数目,你会希望:随着epoch的增加,参数的不断update,loss会慢慢下降最后趋于收敛。但不幸的是,在训练RNN的时候,有时会看到这条绿色的线
我们分析下RNN的性质,看看RNN的error surface的变化
假设你从橙色的点当作初始点($w_1=-2.2,w_2=4.6$),利用Gradient Descent更新参数,有一种情况是你一脚蹬上了悬崖,loss暴涨。另一种更惨的情况是你一脚踩到了悬崖边上(从右往左数第三个橙色的点),此时当前这个点的Gradient很大,导致整个参数飞出去了
解决办法相当粗暴,clipping。具体来说就是当Gradient大于某个设定的阈时,让Gradient直接等于这个阈值,所以就算踩在这个悬崖边上,也不会飞出去,而是飞到一个比较近的地方,这样你还可以继续做RNN的training
思考:为什么RNN会有这种奇怪的特性?有人认为,是不是因为activation function用的是sigmoid从而导致了Gradient Vanish,其实并不是,如果真是这个问题,你换成ReLU去解决是不是就行了?然而事实是,使用ReLU会导致RNN performance更差,所以activation function其实并不是关键点
举个很简单的例子,只有一个neuron,这个neuron是Linear的。input没有bias,weight是1。output的weight也是1,transition的weight是$w$,也就是说memory接到neuron的input weight是$w$
现在假设input是[1,0,0,0,...,0],那这个neural network在最后一个时间点(1000)的output值就是$w^{999}$。假设$w$是我们要learn的参数,我们想知道它的Gradient,所以我们观察一下当$w$改变的而时候,对neural的output有多大的影响。假设$w=1$,那么$y^{1000}=1$;假设$w=1.01$,那么$y^{1000}\approx 20000$,这就跟蝴蝶效应一样,$w$有一点小小的变化,就会对output产生非常大的影响,但是我们可以通过把learning rate设小一点。但如果假设$w=0.99$,那么$y^{1000}\approx 0$,也就是说这时候需要一个很大的learning rate。所以,一会儿你又要很小的learning rate,一会儿又要很大的learning rate,这就很麻烦了。RNN training的问题其实来自于它把同样的东西在transition的时候反复使用,所以这个$w$只要一有变化,造成的影响都是天崩地裂级别的