Synthesisを試してみたのでまとめてみます。tensorflowで実装してみたのでその際に詰まった点なども書いておこうと思います。名前についてですが、このGANは「LightweightGAN」と呼ばれることが多いと思います。公式実装よりも早く公開されたhttps://github.com/lucidrains/lightweight-ganからそう呼ばれているのでしょう。GAN」」のように紹介されています。後に著者による実装(FastGAN-pytorch)が公開されたのでここでは「FastGAN」と呼ぶことにします。FastGANについてモデルの構造について簡単に説明します。ポイントは以下の2つ。内容はほとんど論文の要約+自分の解釈なので、間違っていることがあればご指摘頂きたいと思います。DISCRIMINATORtf.keras.utils.plot_modelで出力した図です。サイズが大きいので折りたたんであります。block(SEblock)と似ています。NetworksよりSEblockではチャンネルごとに重みづけを行います。これによってAttentionのような効果が期待できるようです。mapからweightを求めます。connectionによって勾配の伝播が効率的に行えるようになることが期待されます。mixingのような画像生成も可能です。styleGANについては詳しくは書きませんが、解像度ごとにstyleベクトルを作用させて画像生成を行います。その際ある解像度から別のstyleベクトルを使うことで複数の特徴を持った画像を出力させることができるというものです。EXCITATIONにおいて、別の潜在変数から生成したweightを掛け合わせることで同様の画像生成を行えます。これについては後述します。DISCRIMINATORこちらはDiscriminator側の工夫で、やっていることはかなりシンプルです。DiscriminatorをAutoEncoderのような構造にし、Discriminatorの中間層の出力から元の画像を復元するDecoderを追加しその復元誤差をDのロスに加えて学習させます。Decoderの構造は以下のようにシンプルなネットワークになっています。Decoderの出力は128x128で、同じサイズにリサイズした画像と誤差を取ります。mapを8x8にクロップして復元します。クロップはランダムに行いますが、完全にランダムクロップするのではなくHW方向にそれぞれ2分割した4つの中からランダムにピックアップしてDecoderに通します。それを同じ部分を切り取り・128x128にリサイズした画像と誤差を取ります。AutoEncoder構造によってDiscriminatorがより包括的(comprehensive)な特徴を抽出するようになります。8x8から画像全体を復元することで全体的な特徴を、クロップして部分的に復元することで局所的な特徴を学習することが期待されます。実装時にハマった点や、著者実装と論文との差異・(私が読んだ限り)論文に明記されていない点などを書いていきます。Normalizationを用いています。NormalizationはGANの正規化の手法でGANの安定化にかなり有効だと言われています。私は数学的な理論や背景を詳しく理解しているわけではないので解説はできませんが、解説記事などもあるので詳しく知りたい方はそちらや元論文を参照してください。Tensorflow+kerasで実装する際に一番苦労した点です。Normalizationを用いていましたが、学習が全く進まずこの調査にかなりの時間を要しました。0.13.0-dev時点での内容なのでご注意下さい(開発中のバージョンですが、ソースコードを読む限り2021/4/15時点では修正されていないようです)githubのissuesで指摘されているので近いうちに修正されるかもしれません。問題点は以下の2つです。iterationの実装wのassign以下はtensorflow_addonsの実装の一部です。wは正規化の対象となる畳み込み層や全結合層のweightです。iterationを通して伝播してしまいます。Normを求める(近似する)ためのものでこれを通してbackpropagationされてしまうと学習がおかしくなります。tf.stop_gradientを使って勾配の逆伝播を止める必要があります。2つ目の問題として、正規化したwを直接assignしている点です。Normalizationを用いて学習させる際は順伝播には正規化されたweightを使います。Norm)を求めて定数倍することです。backpropagationの際は、順伝播時に用いた正規化されたweightを通して正規化前の元々のweightに対して勾配を求めてweightの更新を行うものと理解しています。正規化されたweightを直接assignしてしまうと学習に問題が起こると思われます。これらを踏まえて修正したコードが以下になります。計算上の問題はクリアされていると思いますが、かなり使い勝手が悪いので要改善です。EXCITATIONが用いられていました。DiscriminatorGeneratorのモデル図の中に128x128x3の出力があります。lossを取り学習させています。これも論文中で特に言及されていなかったと思いますが、これはかなり効果的だと思います。一度しか試していませんが、この構造を除いた際に学習がほぼ進みませんでした。中間層から低解像の出力をしてそちらも使って学習させることで安定化につながるor学習スピードが上がる効果があると考えられます。lossDiscriminatorのロスとして再構成誤差を使うことは上述しましたが、その誤差を取る際にMAEやMSEではなく、LPIPSを使用しています。LPIPSは2つの画像間の差異を測る指標でalexnetやVGGなどの学習済みモデルの中間層の出力を全結合層に入力して画像間の差のスコアを出力します。pageに詳しく書かれています。今回はhttps://github.com/richzhang/PerceptualSimilarityで公開されている学習済みモデルを利用しました。+αここからは自分が試すときに追加で試してみた手法についてです。Discriminator低解像のDiscriminatorを学習させる際にGeneratorの出力を1チャンネルにしてグレースケール画像を出力させるようにしました。この目的としては低解像部分ではテクスチャを、高解像部分では色についての特徴を学習するように役割分担させるためです。以下はanimefaceで学習させた10,000step時点での出力の比較です。normalizationの扱いについてです。この問題点についてbigGANの論文中で次のように指摘されています。(以下は私の要約です。詳細はbigGANの論文を参照してください。normalizationは通常、推論時には学習時に保存していた平均・分散の移動平均を用いて正規化を行います。GANにおいては推論時にもbatch内の平均・分散を用いたほうがよいといわれています。推論時にbatch内の統計量を用いることは生成画像がbatchsizeの影響を受けてしまうことや、生成画像の再現性が失われてしまうという問題があります。これについてbigGANでは学習後のモデルでbatch内の平均・分散を保存しておき、推論時はその平均を用いて正規化を行っています。約5000枚で学習させました。それぞれ約50000step学習させました。normalizationでかなり苦労しました。最初は何も考えずにライブラリを使っていましたが、それがどういった実装になっているかまで見ていくことは必要だと思いました。