金融と工学のあいだ

興味関心に関するメモ(機械学習、検索エンジン、プログラミングなど)

ChainerでGANのチュートリアルを書いてみた

Intoroduction

このチュートリアルではgenerarive adversarial network(GAN)を使って画像を生成します。ご存じの方も多いと思いますが、GANはdeep learningを用いた生成モデル(generative model)の一種で、よくある応用例に画像生成があります。昨今有名な線画自動着色サービスPaintsChainerもGANの技術が応用されています。

このチュートリアルでわかることは以下の通りです。

  1. 生成モデル(generative model)とは
  2. GANと他の生成モデルとの違い
  3. GANの仕組み
  4. Chainerを使ったDCGANの実装

生成モデル (generative model)とは

数理モデルといった場合、対象のふるまいを数式で記述することである。 特に、機械学習の文脈の場合、対象のふるまいを xから yの変換  fで表現し、モデルとする。

\begin{eqnarray*} \mathrm{model} \ \ \ f : x \mapsto y \end{eqnarray*}

したがって、モデルの学習とは、与えられた訓練データを元に変換 fを得ることである。教師なし学習の場合、訓練データは入力データ  dのセット \left\{s^{(n)} \right\} = \left\{ d_1, d_2, \cdots, d_N \right\}を元に変換 fを得る。教師あり学習の場合、訓練データは入力データ  dと出力データ  cのペアのセット \left\{s^{(n)}  \right\} = \left\{ (d_1, c_1), (d_2, c_2), \cdots, (d_N, c_N) \right\}を元に変換 fを得る。例えば、画像を犬か猫かに分類するといった分類問題の教師あり学習考えてみよう。訓練データは入力画像  d_1, d_2, \cdots, d_nとそれに対応する出力ラベル c_1='cat', c_2='dog', \cdots, c_n='cat'となる。

生成モデルと言った時、モデル化の対象は訓練データ sを生成する確率分布   p : s \mapsto p(s) である。最も単純な生成モデルは、訓練データ sを生成する確率分布   p : s \mapsto p(s) を変換 fでモデル化することである。その場合、 f : x \mapsto y x yにそれぞれ以下を割り当てる。

  •  x:訓練データ s
  •  y:訓練データ sを生成する尤度  p(s)

上記設定では、確率分布  p(s) 自体を陽にモデル化しているので、尤度 p(s)を計算することができる。尤度を計算できればその最大化もできるので、モデルの学習工程が単純という利点がある。しかし、尤度を計算できるだけではサンプリングを行うことはできないため、別途サンプリングをするための工程が必要であるという欠点がある。

そもそも、尤度 p(s)は単にモデルの学習に必要なだけで、実用では s \sim p(s)に従うサンプリングをしたいだけの場合も多い。その場合、確率分布 p(s)を直接モデル化せず、サンプリングしやすいように他の対象をモデル化する場合がある。1つ目は、潜在変数 zを導入して確率分布 p(z) p(s|z)をモデル化する場合である。後述するVAEはこれに属する。2つ目は、潜在変数 zを導入して s \sim p(s)に従うサンプル生成器 s = G(z)をモデル化する。GANはこれに属する。 これらのモデルは、分布潜在変数 zを乱数に基いて生成することで、確率分布  p(s)を満たす訓練データ sをサンプリングできる。例えば、画像生成の場合、潜在変数 zから画像を生成する確率分布  p(s)を計算し、尤もらしい画像 sを生成結果として出力する。

このように定義された生成モデルをどのように使うかというと、以下の用途を挙げることができる。

  • 創作活動の補助(線画着色など)
  • 人に対するインターフェイスの提供(自然文生成など)
  • データ作成コストの削減(シミュレータとしての利用など)

注意

生成モデルといったとき、分類問題において判別モデルと対比して説明する場合がある[1]。しかし、GANにおいて生成モデルといったとき、単に訓練データを生成する確率分布のモデルと定義したほうが自然である。

GANと他の生成モデルとの違い

NIPS2016でのGANのチュートリアル[2]に説明があるように、以下の図のように主な生成モデルを分類することができる。f:id:kumechann:20180103225446p:plain

GANの他にも有名な生成モデルとして、Fully visible belief networks (FVBNs)、Variational autoencoder (VAE)などがある。

Fully Visible Belief Networks (FVBNs)

FVBNsは以下の式のように、訓練データを生成する確率分布  p(s)ベイズの定理を使って1次元の確率分布に分解する。

\begin{eqnarray*} p_{\mathrm{model}}({\bf s}) = \prod^{n}_{i=1}p_{\mathrm{model}} (s_i | s_1, \cdots, s_{i-1}) \end{eqnarray*}

最初の1次元  s_1を除く他の次元 s_2, \cdots, s_nは、それ以前に生成された自身のデータを条件に生成しているので、自己回帰モデルと言うこともできる。 FVBNsの一種であるPixcelRNN、PixcelCNNは1次元の分布関数をそれぞれRecurrent Neural Networks(RNN)、Convolutional Neural Networks(CNN)でモデル化している。FVBNsの長所は、陽に計算可能な尤度を用いて学習できることだ。短所は、各次元をシーケンシャルにしか生成できないのでサンプリングが高コストなことだ。

Variational Auto-Encoder (VAE)

VAEは以下の式のように、訓練データを生成する確率分布  p(s)をモデル化する。この時、 p(s)は潜在変数 zを使って2つの確率分布 p(z) p(s|z)をモデル化している。

\begin{eqnarray*} p_{\mathrm{model}}(s) = \int p_{\mathrm{model}} (s|z) p_{\mathrm{model}} (z) dz \end{eqnarray*}

 \left\{s^{(n)}  \right\}だけを用いてモデルを学習する場合、

 p_{\mathrm{model}}(z|s)を計算できる必要があるが、 上記式に積分が含まれるため計算困難である。そのため、

 p_{\mathrm{model}}(z|s)

 q_{\mathrm{model}}(z|s)で近似する。

その結果、尤度の下限を計算が可能になり、尤度の下限を最大化することで学習を行う。VAEの長所は、サンプリングが低コストなこと、 q_{\mathrm{model}}(z|s)を使用して潜在変数の推定ができることだ。短所は、確率分布  p(s)の計算が困難なこと、学習に近似値を用いていることだ。

Generarive Adversarial Networks (GAN)

GANは、FVBNsやVAEと異なり、訓練データを生成する確率分布  p(s)を陽にモデル化しない。その代わりに、潜在変数 zを使って  s \sim p(s)に従う生成器 s = G(z)をモデル化する。それとは別に、生成器によるサンプル s = G(z)と真のデータ s \sim p(s)の識別器 D(x)を作る。識別器 Dを学習しつつ、識別できないように生成器 Gも学習する。 GANの長所は、サンプリングが低コストなこと、画像生成で state-of-the-artであること。短所は、そもそも確率分布を一切モデル化していないので確率分布  p(s)の計算ができないこと、潜在変数の推論ができないことだ。

GANについて詳しく

GANの仕組み

上記で説明したように、GANは潜在変数 zを使って s \sim p(s)に従う生成器 s = G(z)自体をモデル化する。そして、生成器によるサンプル s = G(z)と真のデータ s \sim p(s)の識別器 D(x)を作る。つまり、生成器と判別器という2つのネットワークが登場する。

学習時にすべきことは、真の分布から生成されたサンプル s \sim p(s)と生成器から生成されたサンプル s = G(z), s \sim p(z)の分布をマッチングすることである。

画像

GANでは、ゲーム理論ナッシュ均衡のアイデア元に、分布がマッチするような生成器 Gを学習する。具体的には、識別器 Dを学習しつつ、識別できないように生成器 Gも学習していく。

上記を直感的に説明する時の例として、紙幣の偽造者と警察の関係が頻繁に使用される。偽造者は本物の紙幣とできるだけ似ている偽造紙幣を造る。警察は本物の紙幣と偽造紙幣を見分けようとする。次第に警察の能力が上がり、本物の紙幣と偽造紙幣をうまく見分けられるようになったとする。その時、偽造者は偽造紙幣を使えなくなってしまうため、更に本物に近い偽造紙幣を造るようになる。警察は本物と偽造紙幣を見分けられるようにさらに改善し…という風に繰り返していくと、最終的には偽造者は本物と区別が付かない偽造紙幣を製造できるようになる。

数式を用いて学習工程を説明すると以下のとおりである。 まず、識別器 D(x)は、真のモデルか識別する確率であるので以下のように表記できる。

\begin{eqnarray*} D(x) = \frac{p(x)}{p(x) + p_{\mathrm{model}}(x)} \end{eqnarray*}

この時、真の分布から生成されたサンプル s \sim p(s)

生成器から生成されたサンプル s \sim p_{\mathrm model}(s)

( s = G(z), s \sim p(z)のこと)の分布をマッチングするということは、2つの分布の相違度を最小化するということである。 よく使用される分布間の相違度の定義として、Jensen-Shannon Divergence

 D_{\mathrm{JS}}が存在する。

 s \sim p_{\mathrm{model}}(s)

 s \sim p(s)

 D_{\mathrm{JS}}は識別器 D(x)を使って以下のように書ける。

\begin{eqnarray*} 2 D_{\mathrm{JS}} &=& D_{\mathrm{KL}}(p(x)||\bar{p}(x)) + D_{\mathrm{KL}}(p_{\mathrm{model}}(x)||\bar{p}(x)) \\ &=& \mathbb{E}_{p(x)} \frac{2p(x)}{p(x) + p_{\mathrm{model}}(x)} + \mathbb{E}_{p_{\mathrm{model}}} \frac{2p_{\mathrm{model}}(x)}{p(x) + p_{\mathrm{model}}(x)} \\ &=& \mathbb{E}_{p(x)} \log D(x) + \mathbb{E}_{p_{\mathrm{model}}} \log (1-D(x)) + \log 4 \end{eqnarray*}

上記  D_{\mathrm{JS}}を識別器 D(x)に対しては最大化し、生成器 G(x)に対しては最小化すれば、

真の分布から生成されたサンプル s \sim p(s)

生成器から生成されたサンプル s \sim p_{\mathrm model}(s)

のマッチングができる。

\begin{eqnarray*} \min_{G} \max_{D} \mathbb{E}_{p(x)} \log D(x) + \mathbb{E}_{p_{\mathrm{model}}} \log (1-D(x)) \end{eqnarray*}

実際に学習を行うときは、識別器 D(x)と生成器 G(x)を交互に更新することで上記min-max問題をときます。

f:id:kumechann:20180108184120p:plain

DCGANとは

このあたりがわかりやすい 。 はじめてのGAN

Chainerを使ったDCGANの実装

- chainer/examples/dcgan at master · chainer/chainer · GitHub

参考文献

作業ログ

作業用参考文献

ひとまずchainer-gan-libを動かしてみよう

  • これ pfnet-research/chainer-gan-lib
  • なんか久しぶりにcupy, chainerをupdateしてみたら動かなかったので再install。pip install -e . --no-cache-dirとかやったらうまくいった。今まで使っていたpython setup.py developではうまくinstallできなかった。
  • あとちゃんとpyenv virtualenvをつかってみた 参考
  • 動かした結果

    • 1000 epoch

    f:id:kumechann:20171231131008p:plain

    • 10000 epoch

    f:id:kumechann:20171231131014p:plain

  • 1000epochから10000epochで生成される画像に変化があるので学習はしてそう。夢に出てきそうな謎画像が生成された。

関連論文を読んで見る

ブログを読む