生成モデルGANとVAEについて

Python, ML03 February 2021

What's 生成モデル?

ニューラルネットワークのモデルを非常に大きなジャンルで分けると以下の2つになる。

  • 分類モデル
  • 生成モデル

このうち分類モデルは、一般的な問題を解く。例えば以下のような感じ。

  • 画像が猫である確率は?
  • タイタニックで生き残れる?
  • 英語を日本語に翻訳

などなど、いわゆる学習におけるほとんどの問題がこれにあたる。(画像認識や自然言語処理なども)
これに対して生成モデルは分類モデルとは逆の問題を解くことにあたる。

画像生成の例

例えば、ある画像Aを与えた時にそれが猫であると言う問題の逆を考えると、
猫と判断される入力(画像A)を求めることにあたる。

上記はベイズの定理で考えることができる。

あるデータXがクラスYに属する確率 $$ P(Y|X) = \frac{P(X|Y) P(Y)}{P(X)} $$

ちなみに、$P(X|Y)$は尤度

VAE(Variational Autoencoder)

比較的学習しやすい。しかし、画像が多少ぼやけると言う欠点がある。

そもそもAE(Autoencoder)とは?

  • 入力と同じものを出力させるNN
    • 入力層と出力層の次元数(ニューロンの数)は等しい
  • 隠れ層は入出力層よりも次元数(ニューロンの数)を減らす
    • Undercomplete
    • ちなみに隠れ層の方がニューロンの数が多いのはOvercomplete
  • 再構成ロス(Reconstruction Loss)を使用
    • 入力と出力が一致しているかを判定
    • 判定はなんでもいい、例えばMSEなど

次元を減らしても復元できると言うことは、次元削減をしているとみなせる

AEの問題点

  • 隠れ層の内容(分布)がランダムすぎる
  • 連続的な確率分布になって欲しい
    • 入力と出力が等しいと言う条件だけでは、未学習のデータに弱すぎる
    • だから連続的であって欲しい

VAEの特徴

  • AEの問題点を隠れ層の分布にガウス分布(正規分布)を用いることで解決した
  • 平均と分散を出力する部分と、サンプリングする部分にわかれている
  • ガウス分布の中からランダムな値を使用する
  • 隠れ層への入力をEncoder, 隠れ層からの出力をDecoderと言う

Reparametrization Trick

VAEではガウス分布の中からランダム値を使用するため、その部分がバックプロパゲーションできない

なので、逆伝搬の時だけは以下の式で近似して勾配を求める。

$$ z = \mu (X) + \epsilon \sigma^2 (X) $$

これにより、バックプロパゲーションが可能になる。

損失関数

VAEでは損失関数にKLダイバージェンスを用いる。
変形後の具体的な式は以下の通り。

$$ L = D_{KL} [N(\mu (X), \Sigma (X)) || N(0, 1)] + \beta || Y - X ||^2 $$

  • 第1項では、平均0, 分散1の分布にどれだけ近いかを求める
  • 第2項では、入力と出力が似ているかを求める

VAEのデメリット

  • 出力画像がぼやける
    • ピクセルごとに元画像との一致度を見たりするので、全体的にぼやけてる方が損失が少なくなる

GAN(Generative Adversarial Networks)

VAEよりも綺麗で精度の高い画像を生成できる。
しかし、学習は難しい。

GeneratorとDiscriminator

GANでは、画像を生成するGeneratorとその画像が生成画像なのかを判別するDiscriminatorの2つのNNが存在する。

名前 役割
Generator 本物みたいな画像を生成する
Discriminator Generatorが生成しか画像なのか見抜く

敵対的生成ネットワークと呼ばれ、GeneratorとDiscriminatorが敵対して競い合うことで精度がどんどん上がっていく。

Generator

  • Generatorは入力にノイズを受け取る。本物の画像データは受け取らないことに注意!!
  • 学習が進むにつれどんどん精度の高い画像を生成できるようになる。
  • 最終的に学習が十分に完了すると、Generatorのみで画像を生成できる。

Discriminator

  • Discriminatorは入力に本物の画像データかGeneratorの生成した画像データを受け取る。
  • 入力が本物の画像データである確率を出力する
  • 学習が終わると不要になる

損失関数

GANの損失関数は、値を最大化したいDiscriminatorと値を最小化したいGeneratorの相反する需要がある。
これをミニマックス問題と言う。

$$ V(D, G) = E_x∼pdata(x)[ \log D(x)] + E_z∼pz(z)[ \log(1 − D(G(z)))] $$

  • $\log D(x)$はDiscriminatorが本物の画像を見抜けていると大きくなる。
  • $\log(1 − D(G(z)))$はDiscriminatorがGeneratorの生成した画像を見抜けていると大きくなる。

学習

  • 普通に考えてDiscriminatorが有利すぎる
  • Discriminatorが圧勝すると、0, 1しか出力されず勾配が消えてしまう
  • ハンデとして、DiscriminatorがK回学習した勾配でGeneratorを学習する
    • GeneratorがK倍学習を先取りする

モード崩壊(Mode Collapse)

  • Generatorが同じような画像しか出力しなくなる
    • Discriminatorを騙せばいいだけなので、同じ画像で精度を上げようとする
  • Wasserstein GAN(WGAN)
    • 分布の重なりをみる(重なりが全くないとアウト)
    • EMD(Earth Mover’s Distance)と言う分布の片方を砂山にみたて、それをもう一方の山に移すには?と考える
    • 完全には防げない
  • Minibatch Discrimination
    • 生成されたミニバッチ内のデータがどの程度似ているかの情報をDiscriminatorに渡す。
    • 似ている度合いが高い場合は偽物と判断する。

評価

GANはリアルな画像を生成するので、それをどうリアルと判断するのかの指標が難しい。

  • Frechet Inception Distance(FID)
    • InceptionV3に画像を入力し本物の画像を入れたときとGANで生成した時の画像の出力の差を見る

DCGAN

  • Batch Normalizationを世の中に浸透させた
  • stride2の畳み込みを行う
Generator Discriminator
Deconvolutionを使用 Global Average Pooling を使う
活性化関数はReLU、出力層はtanh Leaky ReLU (α=0.2) を使う

Conditional GAN

条件付きのGAN。そのまんまで条件ラベルを設定できる。 - 20代男性の画像とか - MNISTなら1の画像とか

Generatorは条件のラベルも一緒に学習する。

Pix2Pix

  • GANの中では比較的安定して精度が出せる
  • 画像のペアから変換方法を学習し生成する
    • 衛星写真にする
    • モノクロにする
    • などなど
  • Generatorの出力にはUNETが使用されている

PGGAN(Progressive GAN)

  • 画像の解像度に限界があったがそれを解決した。
  • 徐々に画像を大きくしていく

StyleGAN

  • 綺麗すぎてヤバイ
  • 普通の環境ではできないくらいメモリ食う
  • 独自の手法と今までのGANの手法をふんだんに入れてる
  • 現在StyleGAN2が出てる
    • あまりに世の中に影響を与えすぎるので段階的にリリースされる

tags: Python, ML