なんちゃって!DCGANでコンピュータがリアルな絵を描く
最近、Deepな生成モデルが熱いです。
中でもDeep Convolutional Generative Adversarial Networks (DCGAN) は、写真並みの画像を生成できるということで、非常に有名になりました。以前書いた記事でも少し触れましたが、計算の果てに画像を生成できるってところになんか惹かれますね。
Deepな生成モデルの歴史的な流れについては以下のPFNの動画が参考になります。
ということで、DCGANの元となるGANについて説明しつつ実装し、そのあとDCGANもどきを実装し、画像生成を行おうと思います。
Generative Adversarial Nets (GAN)
GANでは、2つのNNを学習させることによって、生成モデルを構築します。2つのNNは、それぞれDiscriminatorとGeneratorと呼ばれていて、これは競合関係にあります。
どういうことかというと、まず、Generatorが一様乱数zからデータxを生成します。DiscriminatorはGeneratorから生成されたデータと元のデータを識別するように学習します。それに対して、Generatorは、Discriminatorが元のデータと区別できないようなデータを生成するよう学習します。このように、お互いに切磋琢磨して学習していくことで、Generatorを真の確率分布に近づけることができます。元の論文では、Generatorは偽札職人で、Discriminatorはそれを見破るものだ、という概念的な説明がなされていました。
厳密には、まずとの2つのネットワークを用意します。ここで、とはそれぞれの学習すべきパラメータを示します。このとき、は、xが真の確率分布とGeneratorの確率分布のどちらから生成されたのかを識別するような出力を得たいのでデータxを入力とした時のの最適な値は次式のようになります。
このとき、はxがから生成される確率を表し、はから生成された確率を表すことになります。ここで、とのダイバージェンスを考えます。
これを先に定義したを用いて表すと以下のようになります。
Discriminatorとしては、これを最大化するように、また、Generatorとしては、これを最小化するようにとをそれぞれ学習したいです。よって、パラメータの更新はそれぞれ以下のようになります。
ここで、は学習率です。ただ、実際にはこの更新ではうまく学習ができないらしく、その原因としては、データを生成するタスクよりも分類するタスクが容易であることが元の論文で指摘されています。つまり、の学習が早く進むため、がすごく小さな値になり、の勾配も小さくなって良い結果がでないらしいです。そのため、論文ではの更新を少しいじって学習させています。具体的には次式の通りで、を最小化する代わりにを最大化するよう学習しています。
しかし、この式は論理的に説明できないということがこちらの記事で指摘されていて、もう少しこの式をいじることでダイバージェンスの最小化として解釈できると説明されています。具体的には次式のように変形します。
ここで、の理想的な値の定義を思い出してみると、次式のように変形でき、これはと間のダイバージェンスを最小化していると説明することができます。
となります。こっちのほうがなんかすっきりしますね。まあ、今回は元の論文で示されている手法で実装を行っていますが...。
実践
それでは、GANを利用してデータ生成を行ってみます。利用するネットワークは3層の多層パーセプトロンです。
Deep Convolutional Generative Adversarial Network (DCGAN)
DCGANは、その名の通り、GANのそれぞれのネットワークをdeepにしたものです。これによってほとんど写真と見分けがつかないほどの精度の画像を生成することが可能となりました。
DCGANのネットワーク構造(論文より引用)
この論文の成果としては、ネットワークをdeepにしてもそこそこ安定して学習を進めることができるような条件を示したとろこにあります。また、学習したDiscriminatorで生成した特徴量を利用した画像認識問題も良い精度を示しているようです。その安定して学習できるような条件は以下のようになっています。
実践
私が実装したDCGANは、厳密には上記の論文で示されているネットワークの構造とは少し違っていて、論文のものと比べてパラメータの数が結構少なくなっています。というか層は3つしかないので、そもそもdeepかどうか怪しいです。ということで「なんちゃってDCGAN」と呼んでいます。まあ、これはCPUで早く学習して欲しいということで、そういう構造にしました。
それでは、「なんちゃってDCGAN」でリアルな絵を描かせてみましょう。学習した結果がこちらです。
おお...!そこそこいいんじゃないでしょうか!ところどころグロテスクなものもありますが、とりあえず顔っぽいものが生成されているのがわかります。しかも割とくっきりしていて、ぼやけたりはしてません。というところで、DCGANの威力が垣間見れたかなと思います。学習にはskit-learnで用意されているこちらのデータセットのメソッドを利用しました。やっぱり、計算することでこういったことができるのはすごいですね!
GitHubに今回実装したDCGANのソースコードをアップしています。よかったらどうぞ。
GitHub - YasukeXXX/DCGAN
最後に
これまで見てきたように、GANは非常に素晴らしい成果を上げています。しかし、問題もかなりあって、それについてはPFNの岡野原さんのスライドが参考になります。
また、Adversarial AutoencodersとかAdversarial Learned Inferenceとかいろいろ出てきてたりしてこの辺の研究が盛り上がっていきそうです。まあ、Deepにするだけでなんでも性能上がっちゃって怖いですが、この流れは止まらないどころか加速していくでしょうね。