transfer learning, fine tunning, distillationについて調べてみました

Transfer learning

ある領域で学習したモデルを別の領域の学習に利用する手法のことだそうです。
というとわかりにくいですが、例えばimage netのような膨大な量の学習データを使用して1000カテゴリ分類の学習を行ったとして、その結果を用いて学習データの少ない10カテゴリ分類の問題を解くという手法です。
具体的には、1000カテゴリ問題を解くネットワークと解きたい問題のネットワークを途中までは同じにして、重みに転移元(ここでは1000カテゴリ分類問題)の学習結果を使用します。
そして、少ないデータを使用して出力層近くの重みのみを学習することで、非常に精度よく10カテゴリ問題のモデルを構築できるという手法。
仕組みからわかりますが、転移元と転移先の問題が似ていることが転移がうまくいく条件になります。
画像の分類なら、共通する特徴や、それを使用してクラス分類するという問題設定が共通しているので、転移学習が有効に働いています。

Fine tunning

fine tunningとはすでにあるのモデルの一部を再利用して、新しいモデルを構築する手法のことだそうです。 素粒子理論で出てくる超対称性の話とは違います。
転移学習と同じ?手法に見えますが、以下のような違いがあります。
転移学習は上の例で書いたように、既存の学習済モデル(出力層以外の部分)を、重みデータは変更せずに特徴量抽出機として利用して、出力層部分のみ学習することで、新しいモデルを構築する手法です。
これに対して、ファインチューニングは既存の学習済モデル(出力層以外の部分)の重みデータを一部再学習して特徴量抽出機として利用するという手法です。
つまり転移学習では転移済み学習モデルは固定しているが、ファインチューニングでは元の学習済み重みをさらに書き換えて、新しいモデルに"詳細にtunningする"手法だといえます。
fine tunningを使用する目的はtransfer learningと同じで、少ない学習データで高い正解率を得るためですが、fine tunningの方がtransfer learningよりも柔軟性があるといえます。

Transfer learningは特徴量抽出機の部分を固定したfine tunningといえるかもしれません。

Distillation

Distillation(蒸留)というのは、上の二つと違いネットワークの構造にかかわる技術です。
Distillationは学習済みの複雑なネットワークと"ほぼ"同等なシンプルなネットワークを新たに学習する手法です。
なぜそんなことが必要かというと、ディープラーニングの実用上より少ないメモリでより高速に動作する必要があり、そのためには出力は同等のよりシンプルなネットワークを作ることに意味があるからです。
元のネットワークが非常に大規模なアンサンブルモデルの場合、それをシンプルなたった一つのネットワークで表現できるということには実用上大きな意味があります。
具体的には、例えば1000カテゴリ分類する複雑なネットワークの出力に対して、その出力の確率分布をソフトターゲットと呼び、そのソフトターゲットを出力するようなシンプルなネットワークを構築することでdistillationができます。
蒸留について非常にわかりやすく解説してあるサイトです。
Deep Learningにおける知識の蒸留
たとえて言うなら、教師が正解だけでなく問題の解き方までかみ砕いて教えることで、生徒は少ない学習量で効率よく問題に正解できるようになるということですね。

Anaconda でよく使うコマンド

Windows10でのpython環境の管理にAnacondaを利用していますが、Anaconda Navigatorが重いので大抵はコマンドラインで操作しています。
以下のサイトでよく使うコマンドがまとめられていましたのでご紹介します。
qiita.com

仮想環境のrenameをするときには

conda create -n [new name] --clone [old name]
conda remove -n [old name] --all

とすればいいんですね。

tensorboardではまった話

最近久しぶりにtensorboarを使ったらはまったので顛末をメモ 動作環境はWindows10 + Anacondaでtensorflow1.9です。

現象

tensorboard --logdir LOG_FILE_PATH

(LOG_FILE_PATHは絶対パス)
でtensorboadは以下のメッセージが表示され問題なく動いているように見えます。

TensorBoard 1.10.0 at http://MachineName:6006 (Press CTRL+C to quit)

(MachineNameは動作させているPCの名前)   chromehttp://MachineName:6006 に接続するとなぜか接続できないです。
http://MachineName:6006の代わりにhttp://localhost:6006でもつながらないです。

解決策

起動する際に明示的にホストアドレスを以下のように指定しました。

tensorboard --logdir LOG_FILE_PATH --host=127.0.0.1

これで、http://127.0.0.1:6006 に接続すると以下のように動作しました。

f:id:wshinya:20181004112633p:plain
動作結果

ちなみに、LOG_FILE_PATHは ./hoge のように相対パスでも動きました。
ブラウザーChrome以外にもFirefoxでも問題なく動作しました。

tensorboardの詳しい解説は以下にあります
https://github.com/tensorflow/tensorboard

論文: "CNN-PS: CNN-based Photometric Stereo for General Non-Convex Surfaces"

"CNN-PS: CNN-based Photometric Stereo for General Non-Convex Surfaces"
https://arxiv.org/abs/1808.10093
ECCV2018 Accept論文
実装コード:
github.com
Photometric stereoで法線を取得する話。
複雑な光源環境でオブジェクトのphotometric stereo 画像からsurface normalをCNNを使って予想する方法の研究.
学習データはsyntheticに作成。

GitHubやBitBucketを使った一人プロジェクトの作業方法

一人でコードの開発をするときにも、バージョン管理とバックアップも兼ねてのリモートリポジトリの利用は便利だなと思います。
そのために必要なコマンドのメモ集です。

作成したリポートリポジトリをローカルにリポジトリに複製する方法

> git clone https://someuser@bitbucket.org/someuser/test.git

そして作成されたディレクトリにファイルを置きます。

ステータスの確認には以下のコマンドを使用

> git status
すると追加したファイルの状態が表示されます。

追加したファイルのリポジトリに登録するには

> git add -A

  • A オプションはすべてのファイルをステージにセットすることを意味します。

まだステージにセットされただけでコミットはされていません。
git status で状態を確認できます。

実際にコミットを行うには

git commit -m"this is a message for this commit"
と -m の後にコミットのメッセージを入れておきます。

以上でコミットは終わり、ローカルで作業します。

作業後の差分を確認するには、

>git diff
で最後にコミットされているファイルと現在のファイルの比較がされ、差分が表示されます。

何度もコミットした後はコミットの履歴が見たくなります。

そんな時は、
> git log --stat
で履歴を確認できます。

ここまでの作業はあくまでもローカルでのファイルの操作でリモートリポジトリに変更は反映されていません。

バックアップも兼ねて、リモートリポジトリにコミット履歴を送信するには、

>git push origin master
originはgit clone した元のリモートリポジトリのデフォルトのニックネームです。
master はブランチ名です。
これでローカルリポジトリのmasterがリモートのmasterに同期されます。

(ここまでをまとめると)

Gitサーバー上でプロジェクトを作成.すると,内容が空のリポジトリができる(GUI 操作)
Gitサーバーからリポジトリを複製して,手元に作業ツリーを作成 (git clone).空の作業ツリーができる.
作業ツリーにソースコードを追加し, フォルダをGitに追加 (git add)
変更をコミットする (git commit)
コミットした変更をGitサーバに送り込む (git push)
他のメンバーもGit上のリポジトリを複製 (git clone) すると, ソースコード一式が既に入った作業ツリーが取得できる

ブランチの切り方

> git branch devbranch
devbranchという名前でブランチを切ります。
> git branch
とやると
devbranch
master
の両方が表示され、*がついているほうが現在の作業対象です。
作業対象を切り替えるには
> git checkout devbranch
とやります。
ブランチの状況の確認には、
>git log --all --graph --pretty=oneline
です。
分岐したブランチの作業が終了して二つのブランチを統合するときには、
> git merge devbranch
とやれば、masterにマージされます。
同じファイルをmasterブランチで書き換えていればconflictが起きますので気を付けましょう。

過去の状態に戻す方法:

>git branch devbranch2
>comitID

ブランチの強制削除は:

> git branch -D devbranch2

最新のマスターブランチをとってきて自分のローカルブランチに上書きする

>git checkout master
>git pull

論文: "UNet++: A Nested U-Net Architecture for Medical Image Segmentation"

"UNet++: A Nested U-Net Architecture for Medical Image Segmentation"
https://arxiv.org/abs/1807.10165
医療画像のセグメンテーションや領域切り出しでよく使われているU-Netを変形してUNet++という新しいネットワークを
提案した論文。

Unetはencoder-decoderタイプの深層学習アーキテクチャだが、Unet++も同様の構造をしている。
ただし、encoderの出力がskip connectionにより同じサイズのdecoderにマージされるところが、異なり、Unetの場合には単純にdecode側にくっつけるだけだったが、
Unet++ではskip connectionのところをCNN(nested dense skip pathways.)にしてencoderとdecoderの持っているセマンティックに対する非対称性を緩和できるようにする。
目的は領域のセグメンテーションの精度を上げるため。