備忘録とか日常とか

学んだこととかを書きます。

theanoでLocal Response Normalization(LRN)を使う

Deeplearning Tutorialでtheanoによる実装、アルゴリズムを勉強中。
前回のLCNに引き続いて、LRNの正規化についても試す。

今回はpylearn2内のコードがそのまま流用できるので、新しくコードを書いたりする必要はない。

参考元は以下
pylearn2/normalize.py at master · lisa-lab/pylearn2 · GitHub
MIRU2014 tutorial deeplearning


pylearn2内のコードではLocalResponseNormalizationではなくCrossChannelNormalizationという名前になっている。LCNとごっちゃになるのを避けてるのかもしれない。

LRNが最初に世に知られたのが、Imagenetの論文である。オーバーラッププーリングや活性化関数のReLUなどと並べて説明されており、このCNNの性能の要になっているように思える。

LRNは端的に述べると、「同一位置(ピクセル)において複数の特徴マップ間で正規化する」ということだそうだ。元の論文にも書いてあるが、LRNは"brightness normalization"であり、LCNのように輝度の平均を減算して0にしないことがミソらしい。
式で書くと以下のようになる(論文の式そのままです)


{\displaystyle
b^i_{x,y}=a^i_{x,y}/ \left( k+\alpha \sum^{min(N-1,i+\frac{n}{2})}_{j=max(0,i-\frac{n}{2})} (a^j_{x,y})^2 \right)^\beta
}


k, n, {\alpha}, {\beta}がパラメータである。{a^i_{x,y}}はi番目の特徴マップの(x,y)のピクセルを、Nは特徴マップの総数を表す。
summationの部分は、「i番目の特徴マップに対して、n近傍の特徴マップの二乗和をとる」という意味である。
下みたいなイメージ
f:id:may46onez:20160109161610p:plain


端っこの特徴マップに関しては片側だけ和をとる。

この処理をCNN内の1層として組み込む。Imagenetの論文では畳みこみ層の直後にLRNを配置しているが、Caffeで用意されているモデルではプーリングの直後に配置されていた。岡谷先生の[asin:4061529021:title]でもそのモデルが紹介されていたので、どっちでもいいのかもしれない。


実際に使うのはすごく簡単。
pylearn2からnormalize.pyのCrossChannelNormalizationを引っ張ってくる。
Deeplearning Tutorialでは画像データの扱いは[batch_size, channel, row, column](bc01)となっていたので、それにあったものをインポートする。

from pylearn2.expr.normalize import CrossChannelNormalizationBC01 as Normalize
# Normalizeは引数にalpha, k, beta, nが指定できる。
# デフォルトでは alpha=1e-4, k=2, beta=0.75, n=5
Normlayer = Normalize()

名前は適当に決めた。
あとはconvolutionかpoolingの出力をNormlayerに入れるだけである。
以前の記事に載せてあるConvLayerを使って書くと、

layerC0 = ConvLayer(...)
inputP0 = Normlayer(layerC0.output)
layerP0 = PoolLayer(inputP0, ...)

これでおけ。


theanoじゃなくてpylearn2をそのまま使いたいところだけど、pylearn2でCNN使ったら11epochで止まっちゃって学習できなかった。
同じ症状の人も結構いるっぽいけど直し方がよくわからないし・・・ドキュメント全然更新されてないし・・・
そのうちchainerとかtensorflowとかも触ってみようかな。