TensorFlowで絵を描いてみた(機械学習名古屋第9回勉強会)

  • 8
    いいね
  • 1
    コメント

目次

  • 経緯
  • 画風を変えるアルゴリズム
  • はまりどころ

(TensorFlow成分はほとんど無し)


自己紹介・近況

  • 名前: 中西克典
  • 所属: 有限会社 来栖川電算(バイト)
  • twitter: @n_kats_
  • 発表は今回で2回目。(前回はfastTextの話)
  • 昔は数学をしていた

経緯・目的

  • AIっぽいことをしたい
  • 何ができるとAIっぽいか。創造的なことができるとそれっぽい
  • 絵を描かせてみよう

技術

関連する技術が活発に研究されている。
有名なもので、

  • DCGAN
  • pix2pix

など(ただし、細かい工夫があって難しそう)


したこと

画風を変換するアルゴリズムをTensorFlowで書いた。

日本だと、mattyaさんのchainer-goghが有名だと思う。
これを参考にTensorFlowで書いてみた。https://github.com/n-kats/tf-gogh

参考リンク


画風を変換するとは

元画像と画風画像を用意し、元画像の色合いなどを画風画像の色合いにする。


out_720x480.png


使い方

git clone https://github.com/n-kats/tf-gogh.git
cd tf-gogh
pyenv install 3.6.0
pyenv virtualenv 3.6.0 benkyoukai
pyenv local benkyoukai
pip install -U -r requirements.txt
wget https://www.dropbox.com/s/0cidxafrb2wuwxw/nin_imagenet.caffemodel
python main.py \
  -m nin \
  -i 元画像パス \
  -s 画風画像パス

仕組み(一部単純化しています)

CNNを用いた、画像のある特徴量$F(X)$を用意する。($X$は画像)

画像$X$が元画像$X_\text{orig}$からどれだけ異なるかを特徴量の差のユークリッド距離で表す。(【追記】コンテンツ誤差)


L_\text{orig}(X)  = \left|\left| F(X) - F(X_\text{orig})\right|\right| ^2.

画風の方は・・・


そもそも画風って何よ?


画風をどう扱うか

CNNの特徴量は、TensorFlowの言葉で大雑把に言えば、shapeが[高さ, 横幅, チャンネル数]のテンソルで表される値。
これを次元がチャンネル数と等しいベクトルが高さ×横幅だけあると考える。
これらのベクトルの分布を画風だと考える。

実際には、平均や共分散行列のようなもので数値化し、画風がどれだけ画風画像から異なるかを表す関数$L_\text{style}(X)$を作る。


学習

何を学習するのか

機械学習がすることは、アルゴリズムで良いパラメータを見つけること。
絵を描くということは、各ピクセルの色の値を決めること。

絵を表すshapeが[高さ, 横幅, 3]の変数を学習で良いものにしていく。
(特徴量などは学習しない)


損失関数

作成する画像が元画像に似ていながら、画風画像と近い画風であってほしい。


L(X) = \alpha L_\text{orig}(X) + \beta L_\text{style}(X).

というように単純に係数をつけて足す。

学習法

tf.train.AdamOptimizerというものを使う。


その他

画像の特徴量

特徴量は画像識別のCNNで現れる途中の層を使う。
有名なモデルは学習済みのパラメータが公開されているので、それを使う。

  • NIN
  • VGG (CNNならどうにかなるはず)

NINを用いると速いが、出来上がる画像は微妙。
VGGを用いると遅いが、繊細な画像ができる。
(実は、パラメータの読み込みにchainerを使った)


はまりどころ

  • 学習レートなどのパラメータを自分で適当につけても簡単には行かない。(先人のパラメータをそのまま使いましょう)
  • 学習済みモデルを正しく使えていなかった。(opencvはBGR、pillowはRGB。魔法の数値を引く)
  • VGGで動作確認すると時間を取られる。(速いNINからすべきだった)

覚えて帰ってほしいアイデア

  • 画像の各ピクセルの値を学習する
  • 学習済みモデル(特徴量)から新しい損失関数を作る
  • 画風を特徴量の分布で解釈する