多階層のニューラルネットワークの勾配法を用いた教師あり学習では、下位層のパラメータは出力までにシグモイド関数が何重にもかかるため、勾配がほぼ0になってしまう問題がある。この問題は、最近ではGradient vanishing「勾配消滅」問題と呼ばれている。意外にも、このGradient vanishing問題を、可視化しているのを本や論文などで見かけたことが無いので、イメージをつかむために、pythonでシグモイド関数を1~4重までプロットしてみた。
1重目は当然ながら普通のシグモイドだが、2重目、3重目、4重目とどんどん潰れていって、4重目は1重目と比較すると平らになる。例えば、グラフの横軸を畳み込みの出力WX+b(W:重みパラメータ、bバイアスパラメータ)だとして、何重にもシグモイドをかけていった場合が縦軸の値だとすると、一層目のパラメータW、bは、どんな値をとろうとも、最終的なネットワークの出力に影響を与えなくなる。つまり、一層目のパラメータW、bは、識別誤差に与える影響がゼロに近くなるため、勾配が消滅するのである。Yann LeCunが1998年に提案したLeNet5では、各convolution層のactivation functionとして、このシグモイド関数を用いているため、LeNet5を多階層にそのまま拡張すると、このgradient vanishingが起こることが想像できる。ちなみに、LeNet5でも、3つのconvlution層があるため、full-connected層も入れると、1つ目のconvolution層のパラメータに対しては、4重にシグモイド関数がかかっていることになる。
ちなみに、Caffeで実装されているLeNetは、各convolution層では、シグモイド関数はかけないで、full-connected層にて、activation functionとして、シグモイド関数の代わりにRectified Linear Unit(ReLU)をかけている。各convolution層でactivation functionをかけなくていいのか、ちょっと疑問?
使ったPythonコードは以下の通り。
import numpy as np def sigmoid(x): y=1/(1+np.exp(-x)) return y # 1st sigmoid x=np.linspace(-10,10,200) y=sigmoid(x) pylab.plot(x,y) # 2nd sigmoid y2=sigmoid(y) pylab.plot(x,y2) # 3rd sigmoid y3=sigmoid(y2) pylab.plot(x,y3) # 4th sigmoid y4=sigmoid(y3) pylab.plot(x,y4) pylab.xlabel('Paramter in 1st layer') pylab.legend(('single sigmoid','double sigmoids','triple sigmoids','quadruple sigmoids'),'lower right') pylab.show()
このgradient vanishing問題を解決する方法として、Rectified Linear Unit(ReLU)が知られている。
ReLUは次のグラフのように、ReLUの出力は、max(0,x)により計算され、xが正の場合には、xに比例する。
シグモイド関数と異なり、出力が[0,1]で抑えられないため、何重にReLUをかけても、値域が小さくならない。
つまり、一層目のパラメータが最終層の出力による識別誤差にそのまま影響を与えることができる
(もちろん、convolutionやpooling層を介した上で)ので、gradient vanishing問題が起こらない。