Shake Shakeの実装と簡単な解説
前書き
最近画像系コンペに再び参加してみようと思い,既存の分類精度が高いモデルをもう一度調べたいと思ったので,メモ程度に残したいと思います.
Shake Shakeとは
Shake ShakeとはResNetの一種で,中間層でdata augmentationをしており正則化をしています.
shake shakeのモデル図は,以下のように2つに分岐しており分岐しています.
foward時はそれぞれの最後でαi ∈ [0, 1] を乗算しbackward時はαiとは異なる βi ∈ [0, 1] を使用します.またtest時は0.5で固定してやるそうです.
forward時のこれは,画像に含まれる物体の割合が変化してもロバストに識別ができるように学習ができるようです.
backward時は,勾配にノイズを加えると精度が向上するためであり,αiと違う乱数を用いいることでさらに強い正則化効果を持たすことができるようです.
また論文にはThe skip connections represent the identity function except during downsampling where a slightly customized structure consisting of 2 concatenated flows is used. Each of the 2 flows has the following components: 1x1 average pooling with step 2 followed by a 1x1 convolution. The input of one of the two flows is shifted by 1 pixel right and 1 pixel down to make the average pooling sample from a different position. The concatenation of the two flows doubles the width. のような記述があり,skipをダウンサンプリングする場合にはskipをの1つは右に1下に1ずらす必要がありそうです.その後に1x1average pooligと2つの畳み込みをした後にもう1つも同様にpoolingと畳み込みをしたものと結合するようです.
実装
実装はTensorflowで書きました.
Residual Blockの部分を抜粋して載せておきます.
import tensorflow as tf def residual_block(x, a, filter_size, stride): def convolution(x, l): h = tf.nn.relu(x) h = tf.layers.conv2d(h, filter_size, [3,3], [stride, stride], padding="SAME") h = tf.nn.relu(tf.layers.batch_normalization(h)) h = tf.layers.conv2d(h, filter_size, [3,3], padding="SAME") h = tf.layers.batch_normalization(h) return h * (a if l else 1-a) def down_sampling(x): x = tf.nn.relu(x) h1 = tf.layers.average_pooling2d(x, [1,1], [2,2]) h1 = tf.layers.conv2d(h1, filter_size/2, [1,1], padding="SAME") h2 = tf.pad(x[:, 1:, 1:] ,[[0,0], [0,1], [0,1], [0,0]]) h2 = tf.layers.average_pooling2d(h2, [1,1], [2,2]) h2 = tf.layers.conv2d(h2, filter_size/2, [1,1], padding="SAME") return tf.concat([h1, h2], axis=-1) lbranch = convolution(x, True) rbranch = convolution(x, False) branch = lbranch + rbranch if not x.get_shape().as_list()[-1] == filter_size: x = down_sampling(x) else: x = tf.identity(x, name='x') return x + branch
参考文献
Dockerで機械学習環境を整える
## 前置き
複数人で使用するGPUリソースがあるのですが,それぞれ使うライブラリであったり,それを動かすためのCudaのバージョンが違うなどの問題があり,それを解決するための時間を削減するために導入して見ました.
Dockerとは
アプリケーションの依存関係を容易に解決でき,動作が軽やかなため同時に複数のコンテナを動かすことができたり,作成したアプリケーションのデプロイを簡易にしたりすることができます.
Dockerfile
コンテナを作成するためにイメージを作成します.
このイメージを作成するためにDockerfileを記述していきます.
FROM nvidia/cuda:8.0-cudnn5-devel MAINTAINER TrsNium RUN rm /bin/sh && ln -s /bin/bash /bin/sh RUN apt-get -y update RUN apt-get -y upgrade RUN apt-get -y install git build-essential libssl-dev RUN apt-get -y install software-properties-common RUN add-apt-repository -y ppa:neovim-ppa/unstable RUN apt-get -y update RUN apt-get -y install neovim #setup nevoim RUN git clone https://github.com/TrsNium/nvim_config.git ~/nvim_config RUN mkdir ~/.config RUN mv ~/nvim_config/nvim $HOME/.config/ && mv ~/nvim_config/dein ~/.config/ RUN rm -r ~/nvim_config #setup pyenv RUN git clone https://github.com/pyenv/pyenv.git ~/.pyenv RUN echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc RUN echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc RUN echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init -)"\nfi' >> ~/.bashrc
1行目の FROM nvidia/cuda:8.0-cudnn5-devel
はあらかじめCuda環境がセットアップされたイメージをベースに使います.
cuda 8 cudnn5がデフォルトでセットアップされた環境が作成されます.
その下のapt-get -y
でgitや開発環境のneovimを導入します.
-y
オプションを付けないとイメージのビルドに成功しないので気をつけてください.
setup neovim
では僕がいつも使用しているneovimの環境をgitのレポジトリからクローンしてコンフィグファイルに入れいています.
setup pyenv
では好きなpython環境を使用できるようにpyenvを導入しています.
あとは sudo nvidia-docker build -t {お好きなイメージタグ名} --no-cache ./
でビルドが始まりイメージがきます.
コンテナの起動は sudo nvidia-docker run -it -d --name {お好きなコンテナ名} {お好きなイメージタグ名}
.
コンテナに接続するためには sudo docker exec -it {お好きなコンテナ名} /bin/bash
です.