20
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

CycleGANをpytorchで実装してみた

Last updated at Posted at 2020-08-03

TL;DL

CycleGANとして有名な,"Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks"をpytorchで実装してみました.
実装については下記Gitを確認してください.
https://github.com/DH-rgb/cycle-gan

論文タイトルにある"Unpaired Image-to-Image Translation"が示す通り,画像変換をペアデータの無いデータセットでも実現したという研究ですね.ドメイン間の1対1変換という制約があるとはいえ,ペアデータを作ることはかなり困難な分野であり,この論文がどれほど衝撃的かつ重要なモノかは想像に難くないですね(5295cites...ばけもの...)

有名な例は馬⇔シマウマの変換.これ,コンピュータビジョンに関わっている人で知らない人いないんじゃないですかね?

今回の記事ではCycleGANの凄いところを簡単にまとめながら,GANの実装方法を同時に勉強しました.所謂"The Devils in the Details"が多くて大変だった...

概要

GANの詳細についてはこの記事には書いていません.気になる方はQiitaで探すなり,原論文読むなりして調べてみてください.
ここでは,個人的に「CylceGAN凄いなぁ」と思った点とCycleGANの構造について書いていきます.

凄いところその1:Unparedデータで画像変換

この研究の目的は,二つの画像ドメインX,Yに対して,画像変換G:X->Yを行うモデルGを実現することです.
CycleGANの出現前にも同様に画像変換を行うネットワーク(pix2pix等)はありましたが,その多くがペアデータ,つまり画像変換前後のペア,が必要なモノでした.

CycleGANは画像変換タスクをペアデータなしで,つまり2ドメインの画像だったらなんでも良いという条件で実現しました.ここがこの論文の第一の貢献!paired & unpaired

凄いところその2:Cycle Consistentという新しいロス概念

CycleGANの貢献としてUnparedな画像変換の実現ばかりが注目されがちですが,個人的にはこのCycle Consistentという考え方がこの論文の重要なところだと思っています.

まずは背景から...

GANの出現は教師なし学習の敷居を下げることになりましたが,画像変換にGANをそのまま使うにはいくつかの問題点がありました.
一つ目が,ドメイン間の対応が正しく行われないこと.別のドメインに変換できたとしても,画像内容が全く変わってしまったら意味がありません.
二つ目が,複数画像が同じ画像に変換されてしまうこと.別のドメインに変換できたとしても,すべての画像が同じ画像に変換されては意味がありません.
これらの問題を解決するためには,GANのAdversarial Lossのほかに何か別の概念をロスとして表現する必要がありました.CycleGANではこの課題に対し,一度変換した画像を再度変換元のドメインに変換すること,つまりX→Y→Xというサイクルで画像を変換することを行い,サイクル後の画像が正確にもと画像を再現しているかを損失として考慮しています.
ここに込められたお気持ちとしては,「しっかりドメイン変換できるのなら,元に戻すこともできるでしょ??」というあたりでしょうか.

これがCycle Consistency Loss,2ドメインを移動するサイクルにおいての一貫性を評価したロスの考え方です.(別解釈もあるかもしれません)

CycleGAN

それではCycleGANの具体的な構造について見ていきます.

論文中から抜粋した構造図は以下のよう.「え,これだけ?」と思ってしまいそうですが,モデル自体とてもシンプルなのでこれだけでも十分.重要なのは,先にも述べたように,ドメイン間で行って帰ってくるサイクルがあることです(a,b,cすべてでそれが強調されていますね)image of cycle gan

損失関数には,通常のAdversarial LossにCycle Consistency Lossを加えたものとなります.式に書くと以下のよう.

$L(G,F,D_x, D_y)=L_{GAN}(G,D_{Y},X,Y) + L_{GAN}(G,D_{X},Y,X) + λL_{cyc}(G,F)$

Cycle Consistency Lossの式は以下のようです.単純に,元画像とサイクル後の復元画像のL1ノルムを取っている形ですね.λはAdversarial Lossに対する相対的な重みのようです.これが強いとより形状を保持しようとするようです.

$L_{cyc}(G,F) = E_{y∼pdata(y)}[||G(F(y))-y||]+E_{x∼pdata(x)}[||F(G(x))-x||]$

実装

これだけ強力なモデルであるのに関わらず,提案手法とインプリ記述部分がたった1.5ページしかないことにまず驚き.CycleGANがどれだけシンプルなモデルであるかをまざまざ見せつけられ感じがします(自分もシンプル&つよつよネットワーク作りたい...)

Appendixにインプリの詳しいことが書かれているのも親切すぎる(こういう実装を細かく書くのは意外とめんどくさい).
いろいろな面で神論文.

各種パラメータ

まずは細かいパラメータだけ列挙します.
(これを間違えると,再現実装が不可能.CNNのストライドとかは後述)

  • λ=10 : cycle consistency lossの係数
  • learning rate = 0.0002 (all model) : 200epochの学習の内,初め100epochは固定,その後100epochで0まで下げる(線形に)
  • 重みはガウス分布に基づいて正規化(0,0.02)

Generatorの構造

Reflection Paddingの位置に注意.備忘録参照.(論文中だとさも全てのpaddingがReflection Paddingのように書いている).
generatorの最初と最終層だけpaddingサイズは3,他は1(discriminatorも)
太字は実装からしか分からない情報.

  1. Reflection Padding size 3
  2. CNN: 64 channel, 7x7 kernel, 1 stride
  3. InstanceNorm
  4. ReLU
  5. CNN: 128 ch, 3x3 kernel, 2 stride, 1 padding, bias
  6. InstanceNorm
  7. ReLU
  8. CNN: 256 ch, 3x3 kernel, 2 stride, 1 padding, bias
  9. InstanceNorm
  10. ReLU
  11. Resnet Block x Block num(6 or 9)
    1. Reflection Padding size 1
    2. 256 ch, 3x3 kernel, 1 stride(論文中に言及無し,変えてよいかも)
    3. InstanceNorm
    4. ReLU(https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix/blob/5fd11c27a1b9a5d79ef4ab879146c6b065f6e2a8/models/networks.py#L365 から読み取った)
    5. Reflection Padding size 1
    6. 256 ch, 3x3 kernel, 1 stride(論文中に言及無し,変えてよいかも)
    7. InstanceNorm
  12. CNN: 128 ch, 3x3 kernel, 1/2 stride, 1 padding, bias
  13. InstanceNorm
  14. ReLU
  15. CNN: 64 ch, 3x3 kernel, 1/2 stride, 1 padding, bias
  16. InstanceNorm
  17. ReLU
  18. Reflection Padding size 3
  19. CNN: 3 channel, 7x7 kernel, 1 stride
  20. Tanh

Discriminatorの構造

Leaky ReLUの負の部分の傾きは0.2

  1. CNN: 64 channel, 4x4 kernel, 2 stride, 1 padding
  2. leaky_ReLU
  3. CNN: 128 channel, 4x4 kernel, 2 stride, 1 padding, bias
  4. InstanceNorm
  5. leaky_ReLU
  6. CNN: 256 channel, 4x4 kernel, 2 stride, 1 padding, bias
  7. InstanceNorm
  8. leaky_ReLU
  9. CNN: 512 channel, 4x4 kernel, 2 stride 1 stride(になっている), 1 padding, bias
  10. InstanceNorm
  11. leaky_ReLU
  12. CNN: 1 channel, 4x4 kernel, stride 1, 1 padding

さて疑問が一つだけ.PatchGANを用いると言っているのですが,いまいちどこで使っているのかが分からない.最終出力が一次元な辺りからしてこれは,標準的なAdversarial Lossなのでは?と思ったけど,どうやらこれでいいらしいようです(Githubのissueより).256x256の画像入力の場合,最終的に30x30のマップが出力されました.
それと,Appendixだと全てのストライドが2となっていますが,実は最終層とその前だけは1だったりします(devils in details)

Discriminator Loss

本来はDiscriminatorLossを最大化,つまり以下の式を最大化することが目的ですが,

$L_{GAN}(G,D_{Y},X,Y)=E_{y∼pdata(y)}[logD_Y(y)]+E_{x∼pdata(x)}[log(1−D_Y(G(x)))]$

実装上は基本的にロスを下げる方向に学習する必要があるため,上式を以下のように変えます.

$L_{GAN}(G,D_{Y},X,Y)=E_{y∼pdata(y)}[log(1-D_Y(y))]+E_{x∼pdata(x)}[logD_Y(G(x))]$

注意したいのは,実装上の式の場合Generatorはロスを最大化する方向に動くということ.
(この式を使ってminGを考えると,generatorはdiscriminatorが判別しやすいように嘘っぽい画像を生成するようになってしまう)

Discriminatorの更新

論文では過去50の画像を利用してDiscriminatorを更新していると書いてありますが,具体的な実装については何一つ書かれていなかったので,コードを確認.

以下のようなものを発見.
https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix/blob/f5834b3ed339ec268f40cf56928234eed8dfeb92/util/image_pool.py#L5
とりあえずGeneratorで生成したものについてはランダムにバッファに格納していき,最大50の画像をfakeとしてDiscriminatorを学習するっぽい.バッファに格納する画像についてもランダムに選択している点に要注意.

##備忘録&The Devils in the Details
実装時に困ったところを羅列していく(誰かの参考のために).

結果

画像はoriginal -> fake -> after cycleの順番.
A_7.png
A_9.png
B_13.png
B_16.png

Additional

趣味で集めているマイクラの建築物画像と,それと似ている(かなぁと勝手に思っている)画像をFlickrなどで集めて,マイクラ⇔実写変換できるか試してみました.
結果はこんな感じ.
実写画像変換
実写
マイクラ画像変換
マイクラ

...微妙....
なんかいい感じにブロック感でたり,ブロック感なくなったりするかなぁと夢見てたけど実際は難しそう.CycleGANではConsistency Lossによって形状変化に対応できずテクスチャ変換のみになってしまう問題点が指摘されていて,ブロック感出すための形状変化はやっぱりできないみたいです(猫犬変換が上手くできないのはこの理由).ただ,マイクラ画像を実写風に変換したときに,色合いや影はいい感じに実写感出ていると個人的には感じました.

係数の調整とかでもう少しましになるかもだけど,そもそもデータセットのクリーニングも済んでないのでそこからか...(いつかまでの宿題)

Todo

就活で時間がとられてしまった...
今年のCVPRを見ていたら,3次元オブジェクトを微分レンダラー等で2次元に落とし込んで学習させているものが多くみられるので,
CycleGANに組み合わせてオブジェクトのテクスチャ変換ができないか試してみたいです.

20
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?