10
16

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を実装してみた(1)

Last updated at Posted at 2020-05-23

Linux上でCycleGANの実装をしてみた

今回は、CycleGANの実装をしてみました。
基本的に、githubで公開されているコードをもとに実装を行っていきます。
本ページでは、軽い論文の説明と実装をしていきます。
自分のデータセットを用いて適用する回は、次回やっていきたいと思います。

  • CycleGANについて
  • Linux上での実装

簡単ではありますが、上の2項目に従って説明します。

CycleGANについて

論文:https://arxiv.org/pdf/1703.10593.pdf
こちらの論文に沿って説明をしていきます。

導入

CycleGANは、画風変換を可能とするGenerative Adversarial Network (GAN)です。
コメント 2020-05-23 144015.png
上の図は、論文内記載のものですが、左のような画風変換(色塗り)をしたい場合は、pix2pixに代表されるような、入力と出力の画像のペアで用いる学習方法が採用されていました。
つまり、図のPairedに示されるような1対1の対応が必要となります。
一方で、右に表されるような、Unpairedの画風変換を可能とする手法も提案されています。
Unpairedの手法では、画風変換のタスクごとに、クラスラベル空間、画像特徴空間、ピクセル空間など、様々な距離空間を定義し、それらを用いて入力と出力の距離を近づける必要がありました。

そこで、CycleGANは、1対1のペア画像を必要とせず、さらにタスクに合わせて学習方法を変える必要がない、そんな手法として提案されました。
コメント 2020-05-23 145111.png
これが、CycleGANによって変換された画像たちです。
風景などの写真が、世界的画家であるMonetやGoghの画風へと変換されています。
これは、pix2pixのようなペアを必要とする学習ではなし得ません。
なぜなら、Goghらが描いた風景の写真を撮るためには、タイムスリップしなければいけないからです。
そして、ZebraとHorseの変換、SummerとWinterの変換も可能としています。
タスクに沿って学習方法を変えることなく、CycleGANでは画風変換を学習可能となります。


目的関数

それを可能とするのが、Cycle-consustency lossの導入です。
これが本手法の肝となりますので、後ほどこちらについて説明します。
コメント 2020-05-23 152841.png
上の画像は、Cycle-GANで用いられるlossを表したものになります。
まず、(a)は、GANの一般的なlossである、Adversarial lossになります。
コメント 2020-05-23 153449.png
上式で定式化されますが、第1項では、Discriminatorは、本物のデータyを本物と識別することを意味します。
第2項では、Generatorによって生成されたデータを偽物と識別することを意味します。
このAdversarial loss
をDiscriminatorに対して最大化(正しく識別する)かつGeneratorに対して最小化(誤識別させる)ように学習を行います。
Discriminatorに関して、第1項の最大化の意味は、本物のデータyの確率値が1(本物)と識別されることです。
また、第2項の最大化の意味は、zに対して*G( )を用いて生成した偽物G(z)の確率値を0(偽物)と識別することです。
Generatorに関しては、その逆、ということになります。
Discriminatorが識別できないような
G()*を作ることを目的としています。
これらの最大化・最小化を行う際は、片方は固定します。
この最大化・最小化を交互に行うことで、学習を進めていきます。
これを、両方のドメインに対して、行います。
つまり、コメント 2020-05-23 160615.pngコメント 2020-05-23 160533.pngに対して、最適化を行っていくということです。


続いて、**(b)(c)**についてです。
こちらが、Cycle-consustency lossと呼ばれ、下式で表されます。
コメント 2020-05-23 160243.png
こちらの第1項では、xG( )を用いて生成したデータG(x)F( )を用いて元のドメインに戻したデータF(G(x))が、ちゃんとxになっているか、というものをL1ノルムを使って表しています。
第2項では、その逆をやっていますね。
考え方としては簡単です。


最終的に、**(a)~(c)**を合わせて、
コメント 2020-05-23 161325.png
こちらのように目的関数を設定します。
コメント 2020-05-23 161539.png
この最適化問題を解くことで、目的のGFが学習できます。


実験結果

コメント 2020-05-23 161951.png 実験結果の一例です。 「うま」と「しまうま」の変換、風景写真における「夏」と「冬」の変換、「りんご」と「みかん」の変換など、様々なタスクにおいて、高精度な画風変換が実現していることが分かります。 コメント 2020-05-23 162151.png これは、失敗例です。 プーチン大統領がしまうまになっちゃっていますね。 この様に、テクスチャの変換はうまくいくものの、形状を捉えた変換は難しい場合もあるようです。 物体検出手法の導入なんかで解決されていくのではと思います。

もっと結果を見たいという方は、論文をのぞいてみてください。


Linux上での実装

公開コード
https://github.com/xhujoy/CycleGAN-tensorflow

実装環境

  • Ubuntu 18.04 LTS
  • Python 3.6
  • PyTorch 0.4.0
  • Tensorflow 1.4.0
  • numpy 1.11.0
  • scipy 0.17.0
  • pillow 3.3.0

公開データセットで実装

まずは、任意のディレクトリにgitをクローンします。
続いて、CycleGAN-tensorflow/のディレクトリに移動します。
今回は、論文でも使用されていたhorse2zebraのデータセットをダウンロードしていきます。

$ git clone https://github.com/xhujoy/CycleGAN-tensorflow
$ cd CycleGAN-tensorflow/
$ bash ./download_dataset.sh horse2zebra

学習

続いて、ダウンロードしたhorse2zebraのデータセットで学習を行っていきます。

$ CUDA_VISIBLE_DEVICES=0 python main.py --dataset_dir=horse2zebra

GPU指定の場合は、CUDA_VISIBLE_DEVICES=で指定してください。
学習が始まります。

Epoch: [ 0] [   0/1067] time: 14.2652
Epoch: [ 0] [   1/1067] time: 16.9671
Epoch: [ 0] [   2/1067] time: 17.6442
Epoch: [ 0] [   3/1067] time: 18.3194
Epoch: [ 0] [   4/1067] time: 19.0001
Epoch: [ 0] [   5/1067] time: 19.6724
Epoch: [ 0] [   6/1067] time: 20.3511
Epoch: [ 0] [   7/1067] time: 21.0326
Epoch: [ 0] [   8/1067] time: 21.7106
Epoch: [ 0] [   9/1067] time: 22.3866
Epoch: [ 0] [  10/1067] time: 23.0501
Epoch: [ 0] [  11/1067] time: 23.7298
.
.
.

初期設定では、Epochは200回になっています。
こちらは自身が適用するデータセットに合わせて、変更しても良いと思います。
そこまで大きな差異を含む変換の学習ではないのならば、Epochを減らしてみてもいいかもしれません。
ここで注意なのですが、ダウンロードしたdatasets/horse2zebra/ディレクトリの中にtestA/testB/trainA/trainB/が存在し、それぞれのディレクトリ内には画像が入っています。
学習時であっても、testA/またはtestB/のいずれにもデータが入っていないと、以下のエラーを吐かれてしまいます。

ValueError: Cannot feed value of shape (1, 256, 256, 6) for Tensor 'real_A_and_B_images:0', which has shape '(?, 512, 512, 6)'

自分自身でデータセットを構築し、実装する際は注意が必要です。

テスト

テストは以下のコマンドで行います。

$ CUDA_VISIBLE_DEVICES=0 python main.py --dataset_dir=horse2zebra --phase=test --which_direction=AtoB

--which_direction=のオプションで、AtoBかBtoAを指定します。
datasets/horse2zebra/testAもしくはdatasets/horse2zebra/testB内の画像が変換され、test/に保存されていきます。
それぞれの画像にはわかりやすく、AtoB_もしくはBtoA_が記されます。

以下はテスト結果の一例です。

  • horse2zebra (AtoB)
コメント 2020-05-23 164534.png
  • zebra2horse (BtoA)
コメント 2020-05-23 164735.png しっかりと変換ができています。すごいです。 以上がLinux上での実装となります。 次回は、自身のデータセットに適用してみたいと思います。

参考資料

論文:https://arxiv.org/pdf/1703.10593.pdf
Github:https://github.com/xhujoy/CycleGAN-tensorflow

10
16
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
10
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?