読者です 読者をやめる 読者になる 読者になる

Stimulator

機械学習とか好きな技術話とかエンジニア的な話とかを書く

DCGANで名刺のデザインを試みた

- はじめに -

社内ハッカソンと社内勉強会のネタとして、今更ながらGenerative Adversarial Networks*1 (GAN)とその応用とも言えるモデルであるDeep Convolutional Generative Adversarial Networks*2 (DCGAN)について調査し、実際に検証を行った。

この記事は、DCGANについていくらか調査、検証した部分について記述しておくものである。
なお、画像生成系のモデルは以前より話題になっていたため論文には目を通していたが、実際に触ったのは初めてである。

題材として「名刺」の画像をDCGANで生成する事を試みた。
その過程と結果を示す。


- GANとDCGAN -

DCGANはGANに対してConvolutional Neural Networks(CNN)を適応する構成手法のようなものである。

生成モデルにおけるGAN

GANは、2つの生成モデルを相互に学習させることで学習データが形成する分布をより汎化な状態として保持できるというもので、PRML的に言うと伝承サンプリング(ancestral sampling)を使う生成モデルの一種である。
伝承サンプリングはMCMCのようなサンプリングを使うモデルに対して、計算量が少なく済む事がメリット。中でもHelmholtz Machineや変分AutoEncoderに代表される生成モデルと推論モデルを同時に学習させる手法に比べ、よりシャープな自然画像を生成できるのがGANである。

GAN自体は利用する生成モデルについては限定していないが、2つのモデル間のJSダイバージェンスに対してmin-max最適化を行うように捉える事で、2つのモデルは相互に更新しあいながら学習させられ、またBackpropagationが適応できるので勾配の近似と計算量削減ができて良いよねという旨である。

GANの2つのモデルはDiscriminatorとGeneratorに分かれる。
学習におけるGeneratorの目的は、ランダムノイズからDiscriminatorが誤認識するようなGenerator用の入力を作れるようになること。
学習におけるDiscriminatorの目的は、学習データとGeneratorが作る入力を正しく判定できること。
この2つが相互に上手く学習できれば、Generatorはより学習データに近いものが生成できるはずという旨である。

後述するが実際には、この学習は難しく、大きなネットワークモデル等を利用する場合にはパラメータ設定ゲーとなる。

DCGAN

本題のDCGANは、GANにCNNを上手く適応させるため以下のような事を行っている。

  • Pooling layerを以下に置き換えてアップサンプリング
    • D : Strided convolution
    • G : fractional-strided convolution
  • Batch Normalizationを使う
    • 学習を早くできるし過学習をそれなりに防げる
  • 全結合の隠れレイヤーは取り除く
    • 全結合層を全部除くとの文献を見かけるが正確にはglobal average poolingに置き換える(?)である。「出力層手前では、全結合するのではなくて一つの特徴マップに一つのクラスが対応するように設計する」というのが正しそう。
  • Leaky ReLU関数を使う
    • D : 全てLeaky ReLU
    • G : 基本はReLUで出力層はtanh
    • x<=0でも学習が進み、かつ過学習しないように

こういう感じでGANにCNNを適応していくと、CNN使っても安定して上手いこと画像データの生成ができるよ!というのがDCGANの立ち位置だと思われる(?)。
今回後述の実験では利用してないが、他にも「DCGAN(もしくはGAN)で上手いこと画像を生成する方法」は多く論文としてまとめられていて、社内勉強会で上記内容を発表した際にいくつか教えて頂いたので記述しておく。

[1606.03498] Improved Techniques for Training GANs
Feature matching含むいくつかの最適化手法と半教師あり学習によって、画像の生成の成功確率が上がる。

[1606.00709] f-GAN: Training Generative Neural Samplers using Variational Divergence Minimization
GANで使うJSダイバージェンスをfダイバージェンスというものに置き換えましょうという論文。
KLダイバージェンス等とも比較している。

他にも、GeneratorがDiscriminatorを確実に騙せるような画像を学習によって得てしまい、出力画像が特定の画風に固定化してしまう問題に対して「バッチ重みを上手く全体に適応すると良いよ」等の指摘を頂いた。今後時間があれば試してみたい。


- DCGAN関連のプロダクト -

社内勉強会なので、プロダクトと一緒に紹介した。
若干雑だがせっかくなのでそのままコピペで以下にまとめておく。

その他

- DCGAN参考文献 (Web) -

Web上で学ぶ時に有益だと感じた文献。

関連研究を知る

周辺のモデルの流れを掴むには@beam2d氏が公開する以下の資料が分かりやすい。
https://www.slideshare.net/beam2d/learning-generator

生成モデルに関する論文をまとめた以下のような記事もあり、RBMやVAE関連で調べる際は参考になる。
(こちらは随時更新されているようだが誰が書いているか知らない)
memonone: 生成モデル(Generative Model)関連の論文まとめ

GAN系の最適化とか応用研究についてのスライド
[DL輪読会] GAN系の研究まとめ (NIPS2016とICLR2016が中心)

概要を掴む

@miztiさんのブログ。DCGANの概要がつかめる。
できるだけ丁寧にGANとDCGANを理解する - 午睡二時四十分

わかりやすくDCGANについて書いている。概要がつかめる
なんちゃって!DCGANでコンピュータがリアルな絵を描く - PlayGround

スライド。概要がつかめる。画が多い。
Deep Convolutional Generative Adversarial Networks - Nextremer勉強会資料

GANの更新規則についての記事。GIFが分かりやすい。
An Alternative Update Rule for Generative Adversarial Networks

数式に対する解釈が分かりやすいと思う。
[Survey]Generative Image Modeling using Style and Structure Adversarial Networks - Qiita

めちゃくちゃ丁寧にGANについて書かれている。多分Webだと一番丁寧。
はじめてのGAN


- DCGANで名刺画像生成に挑戦した -

事前準備

今回は社内ハッカソンと社内勉強会のための時間を使って、DCGANを試した。
主には以下の@mattya氏がchainerで書いたDCGANをcloneし、モデルとパラメータを調整した。

GitHub - mattya/chainer-DCGAN: Chainer implementation of Deep Convolutional Generative Adversarial Network

課題として、「DCGANは文字や文字構成を学習できるか」という事を見ておきたく、画像サイズが小さく定形な物があるという事で「名刺」を選択した。

学習データに利用した名刺画像はStanfordのデータセットや「名刺 サンプル」「Business Card」で検索してスクレイピングし、2万枚程集めた。
たまに「企業名 名刺」で検索すると山のように名刺を出してる所があって、日本語の企業一覧使って検索してみて包含したので、データセットとしては若干偏っているかもしれない。

名刺のサンプル画像には1枚の画像に数枚入っていたり、お洒落を意識した傾きがあったりするので、ラプラシアンフィルタを使ってエッジを取って、四角があったら名刺だろうといったコードを書いた。
以下を参考に(というかほぼコピペ)したが、2値化するよりHough変換した方が良かった気がする。
ホワイトボードの画像からポストイットを検出する - Qiita

増量して大体5万枚くらいになって、1週間程仕事終わりに目視で「あ~まあこれならええやろ」くらいの絞り込みを行った。
学習データとしては画像集めるだけだったので、まだマシだった。

元々、これをやろうと思い立ったきっかけは画像認識系のコンテストで、そちらのデータセットには名刺の画像と各情報の矩形位置まであったのを見て「これ使ってアップサンプリングすれば行けそうだな」と思っていて使いたかったんだけど、コンテストページ行ったらもうダウンロードできなかった…

名刺管理系のサービスは大体スクレイピング禁止なる項目が書かれてあるので、大丈夫そうなデータしか集められなかったのは事実。

また、名刺は縦横があるんだけど、全部横向きの物を目で選んだ。
理由は同時に学習できるか分からないのと、widthとheightが違うので合わせるのが大変そうなのと、サンプル名刺では等に横向きの物が大半だったから。
縦向きの名刺ダサいし仕方ないね。

名刺は日本語や英語だけでなく、色々な言語の名刺を入れた。
(じゃないと学習データが確保できなかった)
一応アラビア文字とかは目視で見つけた場合のみ外したはず。
あと画像サイズを縮小して、名刺の縦横比率の2倍の110*182にした。

学習とその結果

学習には絶対最強のp2.16xlargeを利用した。申請して2日くらいかかって使えるようになったと思う。構成はChainer周りのDockerでドッカーン。

会社からAWSサービスを使う時に補助が出たりするけど、4~5日程p2インスタンスを利用したら、会社補助上限を突き抜けて+3万円くらいが消えた。
事前準備とサーバへの画像アップロードも時間がかかったが、大体学習の時間。
方法としてはモデルをまず考えて、数時間回してみて期待できそうなら~という感じ。アナログ。
最初の画像が見れるまでの速度的にp2.16xlargみたいな高火力なやつ使った方が、実験はできると思う。
これから見せる画像は、インターネットにある名刺画像と俺の財布が作り出した結果だと思って見ていって欲しい。

学習初期

> い つ も の <
f:id:vaaaaaanquish:20170319191349p:plain:w200:h200

f:id:vaaaaaanquish:20170319191754p:plain:w200:h200

それっぽさがあるがこの辺りはまだ不安。

画像が生成されはじめる

50万回程が学習を回した段階
f:id:vaaaaaanquish:20170319191920p:plain:w200:h200

100万
f:id:vaaaaaanquish:20170319192040p:plain:w200:h200

この辺で少し安心できる

かなり名刺

330万程学習を回した時

f:id:vaaaaaanquish:20170319193627p:plain:w550:h400

いやこれ名刺っぽいなと思った。
こういうデザインの名刺見たことある。
企業アイコンがあって、よくわからん線が入ってて名前の横に役職とかがあって~というやつ。
ちょっと感動した。

学習過程をGIFにしてみた。

f:id:vaaaaaanquish:20170319215634g:plain

学習終盤では一度生成画像がリセットされ固定化されてしまっている。
これは、GeneratorがDiscriminatorを確実に騙せるような画像を学習によって得てしまった故の結果であり、先述したようにバッチ重みを上手く全体に適応する等の対策があるらしい。一応途中途中でモデルと出力は保存しておくのが良い。


- おわりに -

GANとDCGANについて調べ、ソースを見てモデル調整を行った。
また、そのモデルを用いて名刺画像の生成を試みた。

文字を上手く出して欲しかったが、あまり文字として読めるものにはならなかった。
後で学習データを眺めると画像によっては文字が潰れていたので、学習結果で思ったより文字が上手く出てなかった原因はここにもあるかもしれない。

また、学習データが少なかった事と背景が真っ赤だったりする名刺が混ざっていたために、一部名刺とは言えない画像が生成されるのがネックという感じだった。学習データは大事。

ただ、名刺で見たことあるような全体のデザインや、有り得そうなロゴマーク、背景等が生成できた。
DCGANは、画像内に描かれているものが文字であってもそれらの配置を学習し、生成する事ができるという事が分かった。


ちなみに明日は僕の誕生日です。やったね。