ヌルヌルコンピューター

機械学習、ニューラルネットワーク、その他色々と書くつもりですが三日坊主なので続かないかもしれません。あとまだ学士も取ってないへなちょこなので書いてある情報は正確性に欠いているかもしれません。てか多分間違いがいっぱいあります。何かありましたらご指摘お願いいたします。https://github.com/hirokik0811

Deep Gradient Compression (2)

前回の続き。

 

さて、Deep Gradient Compression を用いたDistributed Trainingの正確性を上げるために、論文中ではmomentum correction, local gradient clipping, momentum factor masking, そしてwarmup training という四つのテクニックを用いている。

 

まずmomentum correctionは、

http://ufldl.stanford.edu/tutorial/supervised/OptimizationStochasticGradientDescent/

によると、SGDによって最適化する関数(つまりloss function) が狭い谷のような形状をしているとき、通常のSGDだとgradientが最小値ではなく谷の傾斜の最も大きい点を向いてしまい、収束が極めて遅くなってしまう。

f:id:May-kwi:20171124152351p:plain

from http://www.stokastik.in/optimization-methods-for-deep-learning/

そこでweightの更新を、momentum  u_{t+1} = mu_t+\nabla_tを用いて、

 

 w_{t+1} = w_t-\eta u_{t+1}

 

とするのがmomentum SGDだ。

(ここで

 w_{t+1} = w_t-\eta (u_{t+1}

とするとNestrov SGDとなる。)

 

論文中ではvにさらにmomentumを加算していき、

 u_{t+1}^k = mu_t^k + \nabla_t^k

 v_{t+1}^k = v_t^k+u_{t+1}^k

 w_{t+1} = w_t - \eta \sum_{k=1}^N sparse(v_{t+1}^k)

 としている。

 

次にLocal Gradient Clippingを用いてGradient explosion を防いでいる。これはGradient のL2ノルムが閾値を超えた際にリスケールというものだ。通常LGCはepochごとに各ノードのgradientを全て加算してから適用されるが、DGCでは各ノードに局所的にgradientが蓄積されていくため、加算はせず個々にLGCを適用する。

 

さてあと二つのMomentum Factor Masking と Warm-up Trainingだが、これはどちらも錆び付いたgradientを排除するという目的で用いられている。DGCではgradientを一定期間Tの間ローカル側で加算し、まとめてサーバー側に送ってそれに基づいてweightを更新するため、古いgradientが学習に悪影響を及ぼす可能性がある。

そこでまずMFM

 U_t \leftarrow U_t \odot \neg Mask

 によって値の大きいgradientに対応するmomentumを排除して、学習に大きな影響を及ぼさないようにする。

さらに、Warm-up Training によって、学習初期に発生するトンデモgradient(すいません語彙力不足でなんて訳せばいいかわかりません。。。原文ではaggressive gradients と言ってます) の影響を抑える。これはただ単にlearning rateを動的にするというだけで、論文中では線形的にではなく指数関数的に増加させることで、より疎なgradients に対応できるとしている。

 

さて、論文中ではこの四つのテクニックを用いて、正確性において通常の学習を上回っており、さらに最大1/600にまで、伝達されるgradientの容量を減らすことができたとしている。

f:id:May-kwi:20171201142354p:plain

論文より

どうやってこれらの手法を思いついたのか論文中に全く書かれていないため、なかなかに魔法のような論文だ。しかも匿名というのがまたカッコいいよなあ。

 

複数マシンでの学習をコンパクトにするDeep Gradient Compression

今日大学で議論した論文について忘れないうちにまとめておこうと思う。

Deep Gradient Compression: Reducing the Communication Bandwidth for Distributed Training
https://openreview.net/pdf?id=SkhQHMW0W

11月の初めに匿名で発表されたものだ。現在double blind で審査されている。正直言って発表されてすぐであるからリバイズされておらず、ところどころに説明不足感が否めないというのが議論に参加した全員の感想だったが、しかしほとんど既存のテクニックの組み合わせだけでdistributed trainingにおいてボトルネックとなるgradientの伝達量が大幅に圧縮されるのは面白い。

複数マシンに学習タスクを並列処理させて学習スピードを上げようというのがdistributed Trainingで、これが最初に提唱されたのがGoogleによる2012年の
http://www.cs.toronto.edu/~ranzato/publications/DistBeliefNIPS2012_withAppendix.pdf
の論文(この研究中で開発されたDistBeliefがtensorflowの前身となっている)。

f:id:May-kwi:20171124150044p:plain
from http://www.andrewng.org/portfolio/large-scale-distributed-deep-networks/

まずweightなどの学習対象のパラメータを保存するサーバー1つを、個々にNNのレプリカを持った複数の子マシンに接続する。これら複数の子マシンそれぞれに学習データを分割して入力し、それぞれ学習結果のgradientをサーバーに送信することでサーバーがパラメータを更新、その新しいパラメータを送り返して子マシンのパラメータを更新する。これが論文内で提示された並列処理の方法だ。論文中では子マシンの持つネットワークをさらに小さな部品に分割して並列化している(この論文の詳しい要約もそのうち書きます)。

しかしながら、マシン同士の送受信というのは、データ量が多いとかえって学習を遅くしてしまう原因になる。実際に大きなサイズのデータを入力とし、レイヤー数が数十、百以上に上るようなNNを学習する場合、送信されるgradient の容量は軽く数百MBになってしまう。

そこでgradientの容量を減らす工夫をしなくてはならない。DGCの論文中で、これまで提唱されてきた方法として、
Gradient Quantization
元論文https://arxiv.org/pdf/1610.02132.pdf
(まだちゃんと読んでないですけど面白い技術なんで読んだらそのうち記事書きます)
Gradient Sparsification
元論文https://arxiv.org/pdf/1704.05021.pdf
の二つをあげている。

DGCは、Gradient Sparsificationに改良を加え、gradient matrixを要素選択によって疎にするだけでなく、元のgradientも子マシン側に蓄積し加算したうえで一定の間隔ごとにサーバーに送信することで、過度な情報の消失を防ぎ正確性を高めている。

さて、まずgradient matrixを疎にするわけだが、これは非常に簡単で、matrix のノルム(論文中ではl1-normを使ってるっぽい)のs%を閾値として、これより大きいgradientのみをmatrixに残す。

数式でいうと、

 G_{t+1} = G_t + {1 \over Nb} \sum_{k=0}^N \sum_{x \in X_{minibatch}} \nabla f(x, w_t)

でgradientを取得し、

 sparse G = G \odot Mask

(Mask は閾値以上のgradientの位置を1とするbinary matrix)
によって得られた疎なgradient matrixをサーバーに毎epoch送信する。
そして、

 w_{t+1} = w_t - \eta * sparse G

によってサーバーに格納されているweightを更新する。

さらに与えられた一定期間T中、元のgradientを加算しておき、
(数式でいうと

 sum G = {1 \over NbT}  \sum^N_{k=0} \sum_{\tau=0}^{T-1} \sum_{x \in X_{minibatch}} \nabla f(x, w_{t+\tau})

)
Tごとにこれをサーバー側に送信、

 w_{t+T} = w_t - \eta T sum G

によりweight を更新する。

しかし、論文によるとsparsityを99.9%近くするとこれだけではロスが1%以上になってしまうという。
そこで正確性を高めるためさらにmomentum correction, local gradient clipping, momentum factor masking, そしてwarmup training という四つのテクニックが用いている。これらについては次回の記事で話そうと思います。


つづく

じゃあDCGANって?

前の記事で書いたGANの発展がDCGANであるわけだが、より高精度な画像生成をするために、名前の通り複数の2D Convolutional Layers を持っている。

f:id:May-kwi:20171121183832p:plain

from http://gluon.mxnet.io/chapter14_generative-adversarial-networks/dcgan.html



https://arxiv.org/pdf/1511.06434.pdf

では、まずgenerator においては入力をGANの論文のようにrandomではなくuniformで平均が0、標準偏差0.02、100次元の分布としており、それを4*4*1024に変形、それを4つのtranspose of convolutional layers に通すことで最終的に64*64*3の出力を得ている。出力層以外のすべての層においてReluを活性化関数として使い、出力層においてはtanhを用いる(そもそもどんなニューラルネットワークモデルであってもReluは出力層には使えない)。

 

discriminatorはgeneratorとほぼ全く同じ構造をしており、alpha値0.2のleakyReluを活性化関数として用い、最終的には global average pooling layer を通して出力を得るという形になる。

全体的な特徴として、各層にbatch normalization を用い、多くのconvolutional NNにおいて用いられる pooling layers を用いない、fully connected layerは用いないという点を著者は上げている。

 

ニューラルネットワークを用いた画像生成について

前の記事でDCGANといったが、これはDeep Convolutional Generative Adversarial Network の略である。その大本であるGenerative Adversarial Network、GANというのが
https://arxiv.org/pdf/1406.2661.pdf
で2014年にGoodfellow et al.によって提唱され、これが現在ニューラルネットワークを用いた画像生成における一つのスタンダードになっている。
理論としては
$$
G(z): \mathbb R^n \rightarrow \mathbb R^m \\
D(x): \mathbb R^m \rightarrow \mathbb R
$$
 の二つのニューラルネットワークモデルを用いる。
ここでG(z) はgenerator, D(x)はdiscriminatorである。
zというのはn次元のrandom noise vectorであり、そのノイズを入力としてGはm次元のvectorを出力する。このvectorが生成された出力データにあたる。
ここでDの役割はこの出力データ、あるいは学習用データを入力とし、これらを識別することである。つまり与えられたデータが生成されたものであると判断した場合0、学習データであると判断した場合1を出力する。

さて、ではこの二つのモデルをどう学習させるかということであるが、GはD(G(z))=1となるように、対してDはD(G(z))=0となるように学習する。要はGの出力データを学習データに十分似せることが目的なので、Gはその出力データをDに学習データと勘違いさせるまでに学習する。対してDは生成されたデータと学習データを正確に識別できるように学習する。

たとえて言うなら、絵画の贋作を作る職人は、贋作をアホな客に売りつけるための技術を持ち、鑑定家は騙されぬように高い審美眼を持っている。すると職人はその鑑定家を騙そうとさらに腕を磨いてゆき、鑑定家はさらにその眼を極める。そのイタチごっこを繰り返せば、最終的には職人の作る贋作は本物と見分けがつかなくなるだろうという話だ。

数式で表現すると
$$
\min_G \max_D V(G, D) = \mathbb E(log D(x)) + \mathbb E(log(1-D(G(z)))
$$
となる。
二つのloss functions
$$
\mathbb E(log D(x))
$$
および
$$
\mathbb E(log(1-D(G(z)))
$$
は通常のニューラルネットワーク同様 back propagation によってGおよびDのweightを最適化することで最小化する。

こうして得られたGが、与えた学習データと似た画像を生成してくれる画像生成機となるわけだ。

初投稿です。

当面の目標はDCGANモデルの性能向上。

 

https://arxiv.org/pdf/1511.06434.pdf で提示されたVanilla のDCGANだと、例えば

http://web.mit.edu/emeyers/www/face_databases.htmlの一覧にあるデータセット
画像のように、ほぼ同じ特徴を持った物体が同じアングルで写っているような画像のみを含んだデータセットを用いてtrainingすれば、かなり綺麗な画像が生成される(Overfitting していると言えなくもないが)。

f:id:May-kwi:20171121162753j:plain

Aberdeen face dataset で5000 epochs学習後の生成画像

しかし、色形のさまざまな物体(例えば車)を被写体とした画像を含んだデータセットでは、生成された画像からその物体を識別するのは非常に困難となってしまう(頑張ってもなんか遠目に見てわからんでもないなーくらい)。

f:id:May-kwi:20171121163239j:plain

ポケットモンスターエメラルドポケモンのスプライト画像をもとに9900 epochs学習したDCGANの生成した画像。遠目に見れば鳥ポケモンに見えなくもない。

 

人間であれば、車を描けと言われれば大抵の人間が(一部の並外れた「画伯」は別として)車の特徴をとらえた絵を描ける。

こうしたニューラルネットワークを用いた画像生成技術の一つの目標が人間を完全に模倣し、凌駕することにある以上、与えられたデータセットがどのような形式であろうが、それに共通する特徴を正確に認識し、その特徴を生成画像に反映するモデルを構築する必要がある。

DCGANの改良に関する研究はいくつかあるが、取り敢えずは

https://arxiv.org/pdf/1606.03498.pdf を実装してみようと思う(すでに論文著者がgithubで実装公開してるけど)。論文の要約は次回の記事で。