Instance-aware Image-to-Image Translation — About InstaGAN

Introduction

この記事は「ICLR2019を読むアドベントカレンダー」の15日目の投稿記事です

ノンパラレルなデータに対してのスタイル変換はCycleGAN登場以降様々な分野に適用されてました。しかし、変換させたいインスタンスの形がまるっきり変化していたり、一枚の画像にインスタンスが多く存在すると下画像のOriginal→CycleGANのように対象が変換されなかったり意図しない変換になってしまうことがありました。今回紹介する論文では、このような問題に対してインスタンス毎のスタイル変換を行うInstaGANを提案しています。このInstaGANを用いることによって下画像のOriginal→InstaGANのように狙った対象の変換や、インスタンス毎の変換を行うことが可能になります。

この論文の貢献は以下のように三つあります。

  • An instance-augmented neural architecture
  • A context preserving loss
  • A sequential mini-batch inference/training technique

それぞれについて説明していきます。

Instance-augumented Neural Architecture

あるドメインXYがあってその二つのドメインを行き来するような変換を考えます。CycleGANではこのドメインに属する画像のみを用いて変換を行っていました。今回紹介するInstGANではCycleGANをベースにしてはいますが、そのドメインの各画像にあるインスタンス情報ABも用います。ABにはインスタンスの情報となっていれば何でもよく、論文中ではインスタンス毎のSegmentation Maskを用いています。ドメインに属する画像と各インスタンス毎のSegmentation Maskを用いて変換を行う様子を以下画像に示します。

まず画像とマスクそれぞれの特徴抽出を行います(上画像のfに相当)。そしてマスクからの特徴量はSumを取り、下式のようなEncodingを行います。

  • 画像に対しては「画像からの特徴量」と「各マスクからの特徴量のSum」をConcat
  • 各マスクに対しては「画像からの特徴量」と「各マスクからの特徴量のSum」と「各マスクからの特徴量」をConcat

以上によってEncodeされたものを、画像とマスク別々のDecode(上画像のgに相当)を行い変換後の画像とマスクが出力されます。ここまでがGeneratorの挙動です。
次にDiscriminatorの挙動について説明します。Generatorのようにまず、画像と各マスクから特徴抽出を行います。次に、以下の式のように「画像からの特徴量」と「各マスクからの特徴量のSum」をConcatしDiscriminatorに通して、属しているドメインからきているかどうかの判別を行います。論文中でも述べられていますが、画像からの特徴量と各マスクからの特徴量を分離してそれぞれDiscriminatorに通さず、Concatして通す必要があります。これは画像とマスクの関係も学習させるためです。

Context Preserving Loss

次に損失関数を説明していきます。と言ってもCycleGANをベースにしているのでAdversarial LossとCycle-consistency LossとIdentity-mapping Lossに関しては同じです。Adversarial LossにはLSGANを用いています。InstaGAN特有の損失関数項としてはContext Preserving Lossを提案しています。
Context Preserving Lossとは、インスタンスだけの変換を他の部分(例えば背景など)は変化させずに行わせる項です。一般的には、変換前と変換後の画像の要素毎のL1 Lossに対して背景だったら重み1、インスタンスだったら重み0の重み付けをします。しかし、インスタンスの形が劇的に変わってしまうような場合では、変換前では背景だった部分が変換後では背景でない可能性も多々あります。そこで、変換前と変換後の両方において背景である場合のみ重み1をつけるような操作をします。したがって、Context Preserving Lossの式は以下のようになります。

Sequential Mini-batch Inference/training Technique

InstaGANでは任意の数のインスタンスを変換できますが、インスタンスの数が多くなればなるほどGPUのメモリを要します。使うGPUの種類によってはインスタンスの数に制限がかかってしまうので、なるべく一回のIterationに使うGPUメモリを減らす学習法を提案しました。その学習法の概要を以下の画像に示します。

一回に全てのインスタンスを学習に用いるからGPUメモリを要するのであってインスタンスを分けて学習していけばいい、というのが主です。学習させるマスクをいくつかのミニバッチに分けて以下を繰り返していきます。

  • ミニバッチに含まれるインスタンスのみを変換させて、残りのインスタンスは変換させずに変換前画像のままにしておく。
  • Discriminatorの入力には画像の特徴量と、変換させたインスタンスのマスクから抽出した特徴量のConcatを用いる
  • 次のミニバッチの変換前画像として、今回のミニバッチで変換させた画像を用いる

以上を繰り返して、全てのミニバッチを終えると最終的には全てのインスタンスを変換させた画像が生成されます。
損失関数の計算時には、Adversarial Loss以外の項(Content Loss)に関しては各ミニバッチにおいて逆伝搬します。全てのミニバッチを終えるとContent Lossだけでなく今までに計算したAdversarial LossのSumを取って逆伝搬します。
この学習法によってGPUメモリが決まっていても、任意の数のインスタンスの変換が可能なります。

Experiment

以上でInstaGANの概要について説明をしたので、実験結果について述べていきます。定量的な指標というよりも、CycleGANとの比較を行っています。以下三つのデータセットから二つのドメインを取ってきてそのドメイン間での変換を行っています。

ただし、InstaGANでは画像とマスクそれぞれに別々のネットワークを用いているので、パラメータの数を等しくするためにCycleGANのネットワーク構造におけるパラメータ数は2倍にしています。

今回提案されたInstaGANを用いる事で、CycleGANだけでは出来なかった変換が可能になっていることが分かります。また、Context Preserving Lossの効果も現れています。例えばFigure6 (b)Giraffe→Sheepの上図においては、CycleGANにおいては羊が生成されているものの背景がまるっきり異なるものになっています。しかしInstaGANでは背景がきちんと変換前画像の通りであり、Context Preserving Lossがあるためだと考えられます。

Ablation Study

最後に今回提案した三つの貢献が、それぞれどのように効いているのかを見てみます。また、今までは単なるCycleGANと比較していましたが、CycleGANにSegmentation Mask(CycleGAN+Seg)を適用したものとも比較しています。この場合のSegmentaion maskは、各インスタンスではなく全てのインスタンスを統合したマスクを用いています。比較画像を以下に示します。

上画像より以下のことが分かります。

  • CycleGAN + Segだけでは、変換前画像の全てのインスタンスに対して変換できていない。インスタンスの数が減っている。
  • InstaGANだけでは、特に一番上の列において背景が異なったものになっている
  • InstaGAN+Content Preserving Loss+Sequentialという全部乗せで全てのインスタンスに対して背景もある程度維持したまま変換が可能となっている。

Hair Style Transfer

上記までは、単なる論文紹介でしたが実装難易度的にもそこまで高くなさそうなので、実装してみることにしました。タスクとしては髪型変換です。実はCycleGANやCycleGAN+Segmentation maskでこのタスクを行おうとしたことがあるのですが、CycleGANでは大局的な特徴しか掴めないためか、髪の色だけ変化して髪型は変化しない変換結果となっていました。これに対処するために、InstaGANを用いて髪型を一つのインスタンスとして扱い、髪型変換を行おうとしました。

① Dataset

今回はミディアム・ショートヘアからツインテールへの変換を試みました。Getchuのサイトから各髪型の美少女画像を集め、髪型が収まるように顔画像を作りました。ミディアム・ショートヘアが1694枚、ツインテールが1158枚でした。また、それらに対して髪型だけのsegmentation maskを以下画像のように作りました(雑ですが….)。マスクを作る際には、こちらのツールを使わせていただきました。慣れれば10~30秒で一枚出来るため非常に助かりました。

② Experiment

実験の詳細は以下に示します。

  • バッチサイズは3
  • NormalizationにはInstance Normalizationを用いた
  • 最適化手法はAdam(α=0.0002,β1=0.5)
  • Adversarial loss、Cycle-consistency loss、Identity-mapping loss、Context preserving lossの重みはそれぞれ1.0、10.0、10.0、10.0とした
  • Data augmentationとしてはhorizontal flipを行った

③ Results

まず、この実験は学習が安定しなかったです。ある程度までロスは落ち込みますが、後は振動するばかりで収束はしなかったですね….Style-Transferのタスクなので1000枚ほどでも足りるかなと思っていましたがどうやら足りなかったみたいです。それを踏まえて結果を見ていきます。まずはミディアム・ショートからツインテールへの変換です。

微妙というか全然ですね。一応マスク上ではちゃんとツインテールになっていることが分かりますが、じゃあイラストはというとまだまだ課題が残る結果になります。残課題については、後で述べるとして次にツインテールからミディアム・ショートへの変換を見てみます。

こちらもマスク上ではちゃんと変換出来ているのが確認できますが、イラストのクオリティが….

④ Future Works

結果を受けて以下の2点についての対策を練ります。

  • 単純に変換結果としてのクオリティが低い
    特にミディアム・ショートからツインテールが顕著ですね。月次な考察になって申し訳ないですが、これはデータ量の少なさだと思います。ツインテールは髪が横に伸びるだけでなく、リボンがつく場合もあります。このリボンの生成に1000枚ちょっとで可能になるとは考えにくいです。そういう意味では、ショートヘアからロングヘアの方がやりやすいのですかね….
  • 髪色まで変換されてしまう
    今回は髪型変換であり、髪色変換ではありません。沢山の髪色を混ぜて学習データとしている以上そうなってしまうのかもしれませんが、何とかしたいところです。マスク情報を用いて変換前と変換後の、髪の領域におけるチャンネル毎にGlobal Average Poolingした値の平均絶対値誤差を損失関数に加えてみましたが効果なしでした。髪色に注意を向けさせず、髪の形だけに注意を向けさせたいですが現状特に思いつかないですね….

Summary

今回はノンパラレルデータに対するスタイル変換ということで、インスタンス毎の変換を可能とするInstaGANを紹介しました、またInstaGANを用いて髪型変換を行った結果についても述べました。
髪型変換の結果は散々でしたが、従来のCycleGANだけでは不十分だったので、道筋が見えただけでも個人的には大きな進歩です。今回の結果を受けて更に変換のクオリティを上げたいですね。将来的にはStarGANAugmented CycleGANとも組み合わせれば、あるキャラクターの髪型を様々な髪型へと変化させられるので夢が広がりますね。また、今回は髪型のみに着目しましたが、segmentation maskさえ用意できればキャラクターの任意の部分を変換させられるはずです。個人的には服飾系はやってみたいところです。