Edited at

GAN と親しもう!(機械学習名古屋第17回勉強会)

More than 1 year has passed since last update.


GANとは



GAN

GANは「generative adversarial networks」の略

日本語だと敵対的生成ネットワークという意味(adversarial=敵対的)

その一種のDCGANでブレーク(以下DCGANベースで説明)



生成モデル

出力が画像等になるモデル

DCGANでは、乱数を入力すると画像が生成される

generative_model.png



敵対的とは

生成するネットワークと品評するネットワークを切磋琢磨させながら訓練


  • 生成するネットワーク・・・Generator

  • 品評するネットワーク・・・Discriminator

と呼ばれる(モデルによっては別の名も)

Discriminatorは、画像がデータセットに含まれる画像なのか生成した画像かを分類



DCGANの訓練の登場人物


  • 訓練データセット・・・画像データセット


  • 生成される画像・・・訓練データセットにありそうな画像

  • Generatorの入力・・・ランダムなベクトル

  • Generator・・・ランダムなベクトルを入力して画像と同じ形のテンソルを出力するネットワーク

  • Discriminator・・・画像を入力して0から1の値を出力するネットワーク

    (例えば、1に近いと本物、0に近いと生成したものの意味)



DCGANの訓練の雰囲気

GeneratorとDiscriminatorを交互に訓練


  • Discriminatorは、生成された画像かデータセットの画像かを識別するように訓練

  • Generatorは、Discriminatorがデータセットの画像と誤認するように訓練



DCAGNの概要図

DCGAN_abstract.png



具体的な実装方法

$x$: データセットの画像

$z$: ランダムなベクトル

\begin{align}

L_G(z) &= -\log D(G(z)) \\
L_D(x,z) &= -\log D(x)-\log(1-D(G(x)))
\end{align}

$L_G$はGeneratorの損失、$L_D$はDiscriminatorの損失

ごちゃごちゃしているけど、通常の分類問題であるようなcross entropyを使った損失関数

$L_G$はGenenratorが生成した画像を、Dが本物と分類するための損失関数

$L_D$はGenenratorが生成した画像を、Dが偽物と分類し、データセットの画像を本物と分類するための損失関数



実例



生成例

result_gan.png

入力の値を少しずつかえると連続的に顔が変わったり



デモ

tensorflow-hubに訓練済みのモデルがあるのでそれを試しましょう

https://www.tensorflow.org/hub/modules/google/progan-128/1


  • モデル・・・progressiveGANというタイプのモデル

  • データ・・・人の顔のデータセットCelebA

  • 入力・・・512次元のベクトル

  • 生成・・・128x128の画像(0〜1の値に正規化されている)



必要なもののインストール

pip install tensorflow tensorflow-hub pillow

(pillowは生成した画像を保存する用)

今回の環境は、

Python 3.6.6

tensorflow 1.10.1

tensorflow-hub 0.1.1

pillow 5.2.0



サンプルコード

import tensorflow as tf

import tensorflow_hub as hub
from PIL import Image
import numpy as np

# モデルのダウンロード(時間がかかる)
gan = hub.Module("https://tfhub.dev/google/progan-128/1")

# 入力の乱数(placeholderなどを使ってカスタマイズも可)
z_values = tf.random_normal(shape=[10, 512])
images = gan(z_values)

with tf.Session() as sess:
sess.run(tf.global_variables_initializer())

# 画像生成
out = sess.run(images)

# 保存
for i, image in enumerate(out):
Image.fromarray(np.uint8(image * 255)).save(f"result_{i}.png") # 値を0〜255にして保存



GANの訓練の例

訓練には例えば



GANの発展



GANの訓練は難しい

理屈は、ゆっくり考えると難しくない

けど、実際に訓練させると簡単じゃない


  • Discriminatorが厳しくなりすぎて、Generatorがどんな画像を生成したらいいかわからなくなって、ノイズのような画像を生成

  • 同じような関数を片方では増やそうとして、もう一方では減らそうとして、これが0に近づけばいいって指標がない

  • いつ訓練を終わらせたらいいか分からない

  • 分類問題みたいに正解がきっちりしているわけではない

2017年を中心に色んなGANの亜種が盛んに研究された



とりあえずGANすることになったら

とりあえずGANするならこれにしとけってものが


  • WGAN

  • WGAN-gp(WGANを少し変更したもの)



WGAN


  • データセットは画像の確率と解釈できる

  • 乱数から生成される画像の確率分布も考えている対象

この2つの確率が近いようにするのが生成モデルのテーマ

近いかどうかを表現するためにWasserstein距離というものを使う



WGANのありがたみ


  • Wasserstein距離が近似的に計算可能

  • 訓練の進捗をWasserstein距離(の近似値)だけで判断可能

    これが小さくなっていくとOK



応用



応用パターン

単純に画像などを生成するだけではない


  • cycleGAN

    画像の傾向を交換するようなことを行う


  • Everybody Dance Now

    姿勢(関節などの位置)から、その姿勢をした姿をGANで生成。

  • 異常検知

  • 超解像

どんな入力でどんな意味合いのものを生成するかがポイント



他にも

画像以外にも


  • 文書

    SeqGAN

  • 音楽

    WaveGAN

など

機械学習名古屋研究会でもGANを扱った論文を紹介する人が結構いたり



以上、ご静聴ありがとうございました