Cutout / Random Erasing

Cutout / Random Erasing

Cutout7は2017年8月15日に、Random Erasing8は2017年8月16日と、ほぼ同時期にarXivに論文が公開されたほぼ同一の手法(!)で、モデルの正則化を目的とした新しいdata augmentationを提案しています。

同じく正則化を目的としたDropoutは全結合層には効果がありますが、CNNに対しては元々パラメータが少ないため効果が限定的でした。より重要な観点として、CNNの入力である画像は隣接画素に相関があるので、ランダムにdropしたとしてもその周りのピクセルで補間できてしまうため、正則化の効果が限定的でした。
これに対し、Cutout/Random Erasingでは入力画像をランダムなマスクで欠落させることで、より強い正則化の効果を作り出すことを狙いとしています。

上図の左がCutout、右がRandom Erasingにおけるdata augmentation結果例です(画像はそれぞれの論文から引用)。

 Cutout

Cutoutでは、マスクの形よりもサイズが重要であるとの主張から、マスクの形状は単純なサイズ固定の正方形を利用し、そのマスクを画像のランダムな位置にかけて、その値を(データセットの?)平均値にしてしまいます。
より詳細には、マスクの中心位置を画像中のランダムな位置に設定し、その周りをマスクします。これにより、マスクの一部が画像からはみ出すケースが発生し、このようなあまりマスクをしすぎないケースが存在することも重要だと主張しています。
より明示的には、一定の確率でマスクを掛けないケースを許容することも考えられると記載されています(後述のRandom Erasingではそうなっています)。

Cutoutの効果は上図(縦軸精度、横軸マスクのサイズ)のようにマスクのサイズに依存し、データセットとタスクによって最適なサイズが違うことが予想されます。

 Random Erasing

Random Erasingでは、まず各画像に対しマスクを行うか行わないかをランダムに決定します。
マスクを行う場合には、まず画像中の何%をマスクするかを予め決められた範囲内からランダムに決定します。次に、同じく予め決められた範囲内でマスクのアスペクト比を決定します。最後にマスクの場所をランダムに決定し、マスク内の画素を0から255のランダムな値に変更します。
上記をベースとし、物体検出のように認識対象のBounding Boxが与えられるケースでは、それぞれの物体に対し、個別にRandom Erasingを行うことも提案しています。

具体的なパラメータとしては、実験的に、マスクをする確率を0.5、マスクの割合を2%〜40%、アスペクト比を0.3〜1/0.3とすることが推奨されています。
また、マスクでどのように画素を変更するかについて、ランダム、平均(Cutoutと同じ)、0、255の4種類のアプローチを比較しており、ランダムが一番良かったと報告されています(平均もほぼ同じ)。
Cutoutでは画像分類タスクのみでしか評価されていませんでしたが、Random Erasingの論文では、画像分類に加えて物体検出と人物照合タスクについても有効性が確認されています。

参考

https://qiita.com/yu4u/items/a9fc529c85534eca11e5

 

Shake-Shake

Shake-Shake4 5はResNetをベースとし、テンソルに対するdata augmentationを行うことで、正則化を実現する手法です。通常data augmentationは画像に対して行われますが、中間層の出力テンソル(特徴ベクトル)に対してもdata augmentationを行うことが有効であろうというのが基本的なアイディアになります。

下記にShake-Shakeで利用されるl番目のresidual unitの構成を示します。

上記のようにShake-Shakeでは、residual unit内の畳み込みを2つに分岐させ、それらを一様乱数αl[0,1]によって混ぜ合わせるということを行います。直感的には、画像ドメインに対するdata augmentationにおいてランダムクロッピングを行うことで、その画像内に含まれている物体の割合が変動してもロバストな認識ができるように学習ができるように、特徴レベルにおいても各特徴の割合が変動してもロバストな認識ができるようにしていると解釈することができます。
興味深いのは、backward時には、forward時の乱数αとは異なる一様乱数βl[0,1]を利用するということです。テスト時には、乱数の期待値である0.5を固定で利用してforwardを行います。
論文中では、上記αlβlを、0.5固定にしたり、それぞれ同じ値を利用したりする組み合わせを網羅的に検証しており、どちらも独立してランダムに (shake) する形が良いと結論付けています。
BackwardでのShakeは、residual unit毎に、learning rateをランダムにスケーリングしているような効果があり、SGDにおいて最適解に辿り着く確率を上げているのではないでしょうか(※個人の感想です)。

αlβlは、バッチ単位で同一にするか、画像単位で独立に決定するかの2通りが考えられますが、こちらは画像単位で独立に決定するほうが良いと実験的に示されています。
これらの外乱効果は、ニューラルネットからすると迷惑限りないことですが、結果として強い正則化の効果をもたらし、既存手法に対しかなりの高精度化を実現できています。

なお、Shake-Shakeの学習で特徴的な点として、学習率の減衰をcosine関数で制御6し、通常300エポックかけて学習を行うところを、1800エポックかけてじっくりと学習することが挙げられます。これはShake-Shakeの効果により、擬似的に学習データが非常に大量にあるような状態となっているため、長時間の学習が有効であるためと考えられます。

python opencv による2値化

#!/usr/bin/python
#-*- coding:utf-8 -*-

import numpy as np
import cv2

# original image (gray scale image)
org_img = cv2.imread('image_example.jpg', 0)

# preference
THRESHOLD = 127
MAXVALUE  = 255

# binarization using opencv
_, bin_cv2 = cv2.threshold(org_img, THRESHOLD, MAXVALUE, cv2.THRESH_BINARY)

# binarization not using opencv
bin_npy = np.zeros(org_img.shape, org_img.dtype)
bin_npy[np.where(org_img > THRESHOLD)] = MAXVALUE

# check
cv2.imwrite('original.png',   org_img)
cv2.imwrite('binary_cv2.png', bin_cv2)
cv2.imwrite('binary_npy.png', bin_npy)

 

ytbilly3636.hateblo.jp

ssh通信 ev3-devの初期設定

ev3にpip3の入れ方

sudo apt-get install curl

curl -kL https://bootstrap.pypa.io/get-pip.py | sudo python

エラーの場合

apt get update

してみるといいかも

 

ssh接続エラーの場合

SSHで接続した際に「Host key verification failed」

Debian wheezyからFreeBSDSSHで接続した際に「Host key verification failed」のエラーになりました。サーバー側がメンテナンスで再インストールされたような記憶がありましたので、古いホストキーを削除すればよいはずです。

直接"/home/ユーザ名/.ssh/known_hosts"を編集してもよいのですが、今回コマンドでやってみましたのでメモしておきます。
$ ssh-keygen -F ホスト名
$ ssh-keygen -R ホスト名

-Fオプションは確認、-Rオプションで削除できました。

参考
PRiMENON:DiARY「[Ubuntu]ssh 接続しようとすると「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!」が表示されるときは

 

python環境の構築方法

python等でプロジェクトごとに環境構築する

 

prenvを用いた環境構築

 

prenv install

sudo git clone git://github.com/yyuu/pyenv.git ./pyenv


pathの設定
export PYENV_ROOT=$HOME/.pyenv
export PATH=$PYENV_ROOT/bin:$PATH
eval "$(pyenv init -)"


pythonバージョン指定したインストール
pyenv install 3.6.1


pyenv versions

で現在使っているバージョンとインストールされているバージョンを確認できる。

あとは、ローカルだったり、グローバルだったり、お好みにpythonのバージョンの設定を行うだけ。

今回は全てのディレクトリにおいて、2.7.9を使うようにします。

$pyenv global 2.7.9

でOK。

 

 

pip install インストール先指定 方法

 

pip install --install-option="--install-scripts=/home/kobayashi/.prenv/versions/3.6.1/lib/python3.6/site-packages" keras

 

 

 

# pyenv-virtualenvのインストール。
    $ git clone https://github.com/yyuu/pyenv-virtualenv.git ~/.pyenv/plugins/pyenv-virtualenv

    # .xxxrcに初期設定を追記する
    # 何故evalを使っているのか、オプションの`-`ってなんだ、と疑問に思ったのでスタックオーバーフローで質問してみました。
    #  http://ja.stackoverflow.com/questions/32043/xxxenv-の初期化時のeval-xxxenv-init-の意味
    vi ~/.bashrc
        eval "$(pyenv virtualenv-init -)"

    # pyenv virtualenv にPythonバージョンと仮想化環境を識別する任意の名称(tag)を指定します。
    $ pyenv virtualenv <pyversion> <tag>

    # するとそれに対応するsite-packagesディレクトリが生成されます
    Requirement already satisfied: setuptools in /home/vagrant/.pyenv/versions/<pyversion>/envs/<tag>/lib/python<X.Y>/site-packages
    Requirement already satisfied: pip in /home/vagrant/.pyenv/versions/<pyversion>/envs/<tag>/lib/python<X.Y>/site-packages

    # 作成した仮想環境はversionsから確認できます。
    $ pyenv versions
      system
      3.5.3/envs/virtual-3.5.3 # << この二つは多分同じ
      virtual-3.5.3            # << 

    # 作成したタグ名をactivateサブコマンドに指定すると、仮想環境が有効になります。
    $ pyenv activate <tag>

    # こんな感じでシェルのプロンプトの左にタグ名が表示されるはず
    (<tag>)$

    # 仮想環境を終了するにはdiactivateを実行します。
    $ pyenv diactivate

    # 通常のpyenvと同様にディレクトリローカルのvirtualenvも作成できます。
    # アプリケーション開発プロジェクトのルートディレクトリに対して、pyenv localを
    # 指定しておくとよいでしょう。
    $ pyenv local <tag>

 

 

仮想環境有効

$ pyenv activate <tag>