今回は、Conditional GAN を使って、生成される顔画像の向きをコントロールしてみます。
こんにちは cedro です。
Neural Network Console には、0~9の画像を生成するいわゆる DCGAN のサンプルプロジェクトがあります。この DCGAN とはどういう働きをしているのでしょうか。
DCGANとは?
これは DCGAN の模式図です。Generator は Noise を入力として、Discriminator に本物と間違わせるような偽物を作成することを学習します。
一方、Discriminator は本物と偽物を間違えないように学習します。この2つのネットワークが切磋琢磨することで高度な画像生成ができる様になります
Generator はノイズから画像を作るという難しい作業をしているので、最初の頃は砂嵐の様な画像ばかりしか作れなくて、Discriminator はすぐ偽物だと分かっちゃう様な気もしますよね。
でも、最初は Discriminator も何も学習してませんから、砂嵐が来ようが、本物が来ようが分かりゃしません。そのうち、両者の切磋琢磨が始まる、というわけです。
学習完了後は、ノイズをGeneratorに入力するとFake Imageが自動生成されるモデルが完成します。
サンプルプロジェクトの Gnerator 側の基本構造がこれです(実際には、これにラベル付与機能が追加されます)。
100次元ベクトルのノイズを入力とし、全結合層を通じて逆畳み込みで、64枚の7×7画像 → 32枚の14×14画像 → モノクロ28×28画像のFake Image を作成します。そして、畳み込みで、モノクロ28×28画像 → 32枚の14×14画像 → 64枚の7×7画像 として全結合層につなげています。
生成画像のカテゴリーをコントロールする
Neural Network Console の DCGAN は、どのカテゴリーの画像を生成するか、コントロールするための工夫が加えられたモデルです。
これはConditional GANと呼ばれるモデルで、通常のGANはランダムノイズから画像を生成するため生成画像のカテゴリーを制御することはできないのですが、ラベルを付与して条件付きモデルとすることでこれを可能にしています。
具体的に、DCGAN のサンプルプロジェクト( mnist_dcgan_with_label.sdcproj ) のラベル付与機能を見てみましょう。
generator の画面です。赤で囲んだ部分が、ラベルを生成する部分です。
Inputでyラベル(0~9)を読み取り 、OneHot でそれに対応して特定の要素だけを1にし、残りは全部0にした10次元ベクトルを作成します。
これを Reshpe で1×1サイズの10枚の画像にしてから、 Unpooling を順次掛けて行くと、7×7、14×14、28×28のサイズの画像が10枚づつ作成されます。各10枚の画像は、いずれも10枚の内1枚だけが1で埋め尽くされ(真っ黒)、残り9枚は0で埋め尽くされています(真っ白)。
これらの画像を、Concatenate(青枠で囲んだレイヤー)で入力画像にプラスすると、重みを学習する Affine、Deconvolution、Convolutionでラベルとして機能します。
例えば、Deconvolution には、7×7サイズの画像64枚と7×7サイズのラベル10枚が入力されます。もし、ラベルの5枚目が1で埋め尽くされている(真っ黒)ならば、yラベル=4という条件で、7×7サイズの画像64枚を学習することになります。
顔画像の向きをコントロールする
この画像生成のカテゴリーをコントロールする機能というのは、良く考えるとかなりのポテンシャルを持っていて、色々な応用が考えられると思います。
今回は、顔画像を生成する時に、右向きか、左向きか、正面か、をコントロールすることをやってみます。
例によって、ImageSpaider で画像収集してOpenCVで顔画像を切り取り(詳細はこのブログ参照)、その後顔の向きによって3種類に分類しました。
やってみると、この顔の向きによって分類するというのは結構手間で、3種類ともほぼ同数にしたいという事情もある中、結果的にはかなりアバウトなものとなりました。
右向き2,400枚です。ラベル0とします。正面ぽいのも交じってしまいました ^^;
左向き2,400枚です。ラベル1とします。左向きと言っても左斜め下とか、左斜め下もあったり ^^ ;
正面2,400枚です。ラベル2とします。どこまでを正面とするかは、悩みます。 ^^;
これらのデータをXnConvert でカラー28×28にリサイズして、Neural Network Console の + Create Dataset 機能で、データセットを作成します。2,400枚×3方向=7,200枚を 学習用:評価用=8:2に振り分けました。
EDIT画面は、入出力データをモノクロ28×28からカラー28×28に変更するだけです。
Generator(1枚目)、DiscriminatorFake(2枚目),RuntimeGenerator(4枚目)の Deconvolution_2 を 1,28,28 → 3,28,28 に変更し、DiscriminatorReal(3枚目)の Input を 1,28,28 → 3,28,28 に変更します。
バッチ64、エポック100で学習をスタートします。2時間51分で学習完了です。Validation error が上昇の一途を辿ったので、少し心配でしたが、この後評価したら顔画像はちゃっと生成されました。
評価結果です。全体的に見るとまだ不十分な部分もありますが、概ねこんな形でラベルの指示に沿った顔の向きで画像が生成されました。
今回は、カテゴリーとして顔の向きを選びましたが、顔だけで言っても、「表情」でカテゴリーに分けするとか、「アクセサリー(メガネ、サングラス、帽子など)」でカテゴリー分けするとか、色々考えられます。
Neural Network Console の Conditional GAN カテゴリーの選び方によっては結構面白い使い方ができそうです。
では、また。