2018年6月22日金曜日

論文読み2018, ADVERSARIAL DROPOUT REGULARIZATION

元ネタ: Saito et al, Adversarial Dropout Rgeularization, 2018
図表は特に断りがない限りこの論文から引用

Adversarial Dropout Regularization(ADR)はDomain Adaptationの手法で,dropoutの場所だけが異なるネットワークの出力の差異が大きくなるデータ点がdecision boundaryに近いと考えて,ネットワークの出力がそのdecision boundaryから遠ざかるように最適化する.

  • 従来手法(Tzeng et al. 2014, Ganin and Lempitsky, 2014)
    ネットワークをエンコーダー(generator)G, クラス分類器C, ドメイン分類器(Discriminator)Dに分けG->D->CかC<-G->Dの順に並べる.Eによって元の画像から生成された表現を,Dがsource domainに属するか,target domainに属するかを推測し,Gはその推測を間違わせるように最適化される.これによってGによる表現はsource, target domainにおいて共通となる.またsource domainのデータ点についてDが正しく分類できるようにDを最適化する.

従来手法ではDはドメインの違いしか考えていなかったので,Gがクラス分類に役に立たない表現にされてしまう(fig1, 左).

本手法ではDを廃する.source domainではGとCは一連のclassification networkとして学習を行い,target domainではCはdecision boundaryに近いデータ点の検出器となって,GとCは敵対的に学習を行う.というのもCがクラス間のdecision boundaryに近い点に敏感なら,GはCを騙すためクラス間のdecision boundaryの近くにデータ点を写像するのをやめるはずで,したがってGはよりtarget domainでのクラス分類に役立つ表現を学習するようになる.(fig.1, 右)


figure 1. 従来手法と本手法の概念図

クラス間のdecision boundaryを決めているのはクラス分類器Cであって,Cのdropoutの場所を変えることで,Cが僅かに変化し,したがってdecision boundaryも僅かに変化する.decision bondaryの近くの点ほどこのdecision boundaryの変化によって大きくCの出力が変化する. この変化によってCはdecision boundaryに近いデータ点を検出する.
Cのdropoutの位置の異なった2つの現れをC1, C2として,データ点xtx_tに対するそれぞれの出力をp1,p2p_1, p_2とする.その距離を
d(p1,p2)=12(DKL(p1p2)+DKL(p2p1))d(p_1, p_2) = \frac{1}{2} (D_{KL}(p_1||p_2) + D_{KL} (p_2||p_1))
と定める.

学習のプロセス

  1. GとCは一連の分類器として学習する.最適化する対象は
    minimizeG,CL(Xs,Ys)\text{minimize}_{G, C} L(X_s, Y_s)
    L(Xs,Ys)=Exs,ysk1k=yslogp(yxs)L(X_s, Y_s) = -E_{\mathbf{x}_s, y_s} \sum_k 1_{k=y_s} \log p(y|\mathbf{x}_s)
  2. Cはdecision boundaryに近いtarget domainの点を検出するように学習する.また,1.ですでに行ったことだが,source domainでの分類器としても学習を行うと性能が向上した. 最適化する対象は
    minimizeC{L(Xs,Ys)ExtXt[d(p1,p2)]}\text{minimize}_C\{ L(X_s, Y_s) - E_{\mathbf{x}_t \in X_t} [d(p_1, p_2)]\}
  3. Gがtarget domainでのCを騙すように最適化する.最適化する対象は
    minimizeG{Ladv(Xt)+ExtXtkp(y=kxt)logp(yxt)}\text{minimize}_G\{ L_{adv}(X_t) + E_{\mathbf{x}_t \sim X_t} \sum_k p(y=k|\mathbf{x}_t) \log p (y|\mathbf{x}_t)\}
    Ladv(Xt)=ExtXt[d(p1,p2)]L_{adv}(X_t)=E_{\mathbf{x}_t \sim X_t} [d(p_1, p_2)]
    このステップは複数回行うと性能が向上する.

2018年6月20日水曜日

論文読み 2017, Temporal Ensembling for Semi-Supervised Learning manifold

元ネタ: Samuli Laine and Timo Aila, Temporal Ensembling for Semi-Supervised Learning, 2017, ICLR 2017
図表は特に断りがない限りこの論文から引用

複数のモデルのensembleは教師の有無にかかわらずよく使われる手法で,dropoutによる性能向上も内部で複数のモデルのensembleが起きているためだという人もいる.この論文ではdropout(とdata augmentation)によるensembleによって高精度な教師モデルを構成し,生徒モデルが教師モデルの出力を真似ることで半教師あり学習を行う.
Data Distillatinを思い出すが,Data Distillationは教師モデルがハードなラベル(すなわちクラスラベルそのもの)を推測してNLLやCrossEntropyをLossとして生徒モデルを最適化したのに対し,こちらでは同じ入力からの教師モデルと生徒モデルの出力の差異をLossとする. またラベル付きのデータ点に対してのみ,CrossEntropyをLossに足して最適化する.

dropoutの場所を変えてensembleを行うΠ\Pi-modelと,過去のepochにおける出力とensembleを行うTemporal ensemblingが提案されている.

Π\Pi-model

同じexample xxについて,確率的なaugmentationやdropoutによってニューラルネットワークfθf_\thetaは非決定的な関数だから,z=fθ(x),z~=fθ(x)z=f_\theta(x), \tilde{z} = f_\theta(x)は異なっているはずで,その差異zz~\|z - \tilde{z}\|を小さくする.さらにxxがラベル付きであるとき,z,z~z, \tilde{z}とそのラベルの乖離を小さくする.この場合,教師モデルと生徒モデルは同じものである.


fig.1 Π\Pi-modelのダイアグラム

fig.2 Π\Pi-modelのアルゴリズム

Temporal ensembling

Π\Pi-modelではネットワークのパラメータθ\thetaを変えずにz,z~z, \tilde{z}を計算したが,Temporal ensemblingでは過去のepochで計算した値のexponential moving averageを教師モデルの出力z~\tilde{z}とする.


fig.3 Temporal Ensemblingのダイアグラム


fig.4 Temporal Ensemblingのアルゴリズム

論文読み 2018, Self-ensembling for visual domain adaptation

元ネタ: French and Mackewicz, Self-ensembling for visual domain adaptation, 2018
図表は特に断りがない限りこの論文から引用

Mean Teacherモデルをdomain adaptationに転用. VisDA-17 Classification 優勝

Domain adaptationとは

“新規タスクの効果的な仮説を効率的に見つけ出すために,一つ以上の別のタスクで学習された知識を得て,それを適用する問題”(朱鷺の杜)

例えば人・自動車・犬・猫といった物体ののデータセットから分類モデルを学習し,それらの写真を分類するような問題のことである.学習を行うドメインをsource domain,モデルを適用したいドメインをtarget domainという.この例では絵がsource domainで,写真がtarget domainとなる.
VISDA-2017では3次元モデルから生成した画像をsource domainに,写真をtarget domainとして,domain adaptationモデルを競った.なお,source domainではすべてのデータ点にラベルが与えられ,target domainではunsupervisedな学習が許された.

Self-ensembling for visual domain adaptation


fig.1 (a) mean-teacher (b) self-ensembling for visual domain adaptation
(a)における破線はラベルが与えられた場合にのみ実行されることを示している.

source domainとtarget domainをそれぞれXS,XTX_{S}, X_{T}とする.XSX_{S}には対応するラベルが与えられており,それをYSY_Sとする. Mean-teacherでは,CrossEntropyによるLossはラベルが与えられた場合にのみ最適化していたが,self-ensembling for visual domain adaptationでは教師モデルがtarget domainのデータ点のクラスを推測し,それがconfidence threshold以上であれば,そのラベルを教師データとして生徒モデルの出力とCrossEntropyをlossとして最適化する.

2018年5月24日木曜日

glibcのインストールをしくじったがどうにか復旧した話

問題

CentOS 6.7にPyTorchをインストールしてインポートしようとしたところ,glibc 2.14以上が必要だと怒られた。そこでUnitasBrooks氏の助言に従ってglibcをアップグレードしたつもりが、
export LD_LIBRARY_PATH=/opt/glibc-2.14/lib
を見逃していたため、またPyTorchに怒られてしまった。
私は/opt/glibc-2.14/lib/libc.so.6を直接/lib64にコピーしたのだが、このlibc.so.6というのはシンボリックリンクであって、このような直接的なコピーはシステムを破綻させるものだった。
sudoやlsのような基本的なコマンドを呼ぼうとしてもerror while loading shared libraries: /lib64/libc.so.6: file too short というエラーが出て、ほとんど手も足も出ない状態になった。

解決

Linuxやってみる!, (6) ldconfigでライブラリパスを更新によると、linuxは
(1) 環境変数で指定されたパス
(2) /etc/ld.so.conf に記述されたパス
(3) 通常ライブラリが置かれるパス
の優先順位でライブラリを読み込んでいく。今回は(3)を壊してしまったので、(1)か(2)でうまく正しいglibcライブラリを読み込むようにさせる。それに使えるコマンドにexport (環境変数にパスを追加する) とldconfig (共有ライブラリの依存関係を更新する=(1)~(3)の順でライブラリを読み込み直す?) があり、

$export LD_LIBRARY_PATH=/opt/glibc-2.14/lib
$ldconfig

を実行することでとりあえず復旧できた。
上の操作をする前にはsucpを実行しようとすると

su: error while loading shared libraries: /lib64/libc.so.6: file too short
cp: error while loading shared libraries: /lib64/libc.so.6: file too short

と同じエラーを返していたが、上の操作の後、lscpは動くようになったが、susudoは同じエラーを返してくる。これらはスーパーユーザー権限を得るコマンドなので、ldconfigという、通常のユーザーが実行できるコマンドで何か悪さができないよう、何か特別な仕組みがあるというのは想像できることだが、sudoできないと困る。

Eliah Kagan氏のコメントが力になる気がする・・・

2018年5月8日火曜日

論文読み 2018, 1cycle policy

The 1 cycle policy

ネタ元: A DISCIPLINED APPROACH TO NEURAL NETWORK HYPER-PARAMETERS: PART 1 - LEARNING RATE, BATCH SIZE, MOMENTUM, AND WEIGHT DECAY, Leslie N. Smith, 2018

著者の過去の論文では,learning rateを図1のように,イテレーションの間で何度も大きくしたり小さくしたり変化させる(boundaryの決め方は後で).この,小さなlearning rateがmax_lrに至り,またもう一度base_lrになるまでを著者はcycleと呼んでいる.
図1図1

一方,この論文では図2のように,最初は小さいlearning rateから初めて,全学習過程においてただ1度だけcycleを回し,最後にbase_lrよりも小さいlearning rateに線形に変化させている.
図2

また,learning rateとmomentumがともに大きいと学習が不安定になるので,momentumは図3のようにlearning rateとは反対の方向に減らしたり増やしたりすることを提案している.
図3

これによって高速かつ高性能なモデルが学習できるという.
また著者は大きなlearning rateはregularizationに有益と主張していて,そのため他のregularizationの手法の力を弱めるべきだと主張している.例えばweight decayやdropoutの係数を小さくするなどである.

max_lr, base_lrの決め方
学習を小さなlearning rateから初めて徐々に大きくしていく.最初はvalidation errorは小さくなっていくが,ある値からはvalidation errorが発散を始める.このときの値をmax_lrとし,base_lrはmax_lrの0.1~0.05倍とする.

(イテレーション回数は試行錯誤して決めるしかないようだ)

2018年4月24日火曜日

RefineDet メモ 2

PytorchSSD の実装で,loss functionは,ARM, ODMの出力に対してそれぞれarm_criterion , odm_criterion で、ともにPytorchSSD/layers/modules/refine_multibox_loss.py にあるRefineMultiboxLoss のインスタンスである.

arm_criterion は,PytorchSSD/utils/box_utils.py/match によって,ground truthと最も一致する(Jaccard Indexの大きい) prior boxを計算し,そのprior boxに対応する arm_locarm_conf の組に対してconfidence lossとlocalization loss を計算する.さらに,ground truthに対応していないがarm_conf が高いものたちを選んでconfidence loss を計算し,足す(Hard negative mining).
([Learning Note] Single Shot MultiBox Detector with Pytorch が参考になる)

arm_criterion ではPytorchSSD/utils/box_utils.py/match を,ground truthとprior boxの対応づけにつかうのだが, loc_criterionでは PytorchSSD/utils/box_utils.py/refine_matchによって,ground truthとarm_loc を対応づけて,そのarm_loc に対応したodm_locodm_conf の組に対してarm_criterion と同じ操作を行う(confidence loss はクラスごと).

もとの論文では,ARMはbounding boxの粗いlocalizationを行う ((2) coarsely adjust the locations and sizes of anchors) としていたが,この実装では特別ARMでのbounding box regressionを粗くする工夫は見当たらなかった(オリジナルの実装にはあるのかも).

2018年4月23日月曜日

RefineDet メモ1

RefineDetSSDの進化系.CNNは後ろの方のレイヤーほど(poolingによって)空間的な情報を失い,抽象的な情報を持つようになってくるので,SSDの検出器は前の方にある検出器の性能が低く,したがって小さい物体の検出が苦手だった.(参考:リアルタイム物体検出向けニューラルネット、SSD(Single Shot Multi Detector)及びその派生モデルの解説)
そこで,後ろの方のレイヤーの情報をTransposed Convolutionによって大きくして前のほうのレイヤーと足し合わせ(Elementwise sum)(fig.1),前の方のレイヤーがより多くの抽象的な情報を利用できるようにした.さらにAnchor Refinement Module(ARM)という,bounding boxのあらいrefinementと,objectである/ない の2値のクラス分類を行うモジュールと,Object Detection Module(ODM)という,bounding boxの精密なrefinementとobjectのクラス分類をおこなうモジュールを併用している(fig.2).

figure 1
(figure 1)

(figure 2)

PyTorch実装の一つであるPytorchSSDのコードを読んで混乱したところがあったのでいくつかメモする.

PytorchSSD/models/RefineSSD_vgg.py

ARM部分(fig.3). VGGと追加のレイヤーからの出力(feature map)のうち,いくつかは arm_sources というリストに入れられる.self.arm_loc というレイヤーがバウンディングボックスの座標(x, y, width, height)をself.arm_conf というレイヤーがobjectであるか否かという二値の推定を行い,その値は arm_loc, arm_conf というリストに格納される. arm_sources はARMでは変更されず,そのままTCBに渡される.

(figure 3)

TCB部分(fig.4). TCBというブロックをまとめて実装しているのではなく,ARMからの情報 arm_sourcesをconvolutionするself.trans_layers ,Transposed Convolutionによって小さなfeature mapを引き伸ばすself.up_layers , それらの結果の和をODMに引き渡す前にconvolutionを行うself.latent_layers というレイヤー群をそれぞれ実装していて,最終的にODMに渡す値は obm_sources である.
(この実装ではobmというワードが散見されるが,おそらくODMのタイポである. 混在しててこわい.)

(figure 4)

ODM部分(fig.5).
obm_sourcesself.obm_loc, self.obm_conf に渡され,それぞれbounding boxの精密な座標と,objectのクラス分類を行い,結果はobm_loc, obm_conf に格納される.

(figure 5)