【DCGAN-Keras入門】令和ちゃん完成させるためにDCGANで遊んでみた♪

いきなりですが、DCGANを利用して、今年の目標である令和ちゃんのシンボル画像を作成しようと思います。
別に声も作成中ですが、そちらはまだまだな感があるので画像を先に作ってしまおうと思います。
で、目標のものができたかなの画像は以下のとおり。。。勝手に宣言します。
。。。
たくさんいろいろ出力しすぎたので...みつからないので学習の様子のGif貼ります。
![128x128_32x32_final.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233744/cceb567f-200c-3159-71bf-2c446d9ca66a.gif)


ということで、遊んだことを記そうと思います。今回の記事は前例記事があるのでそれらを試した記録です。
参考①がKeras-dcganのベースで、参考②でカラー画像というかアニメ画像に応用されています。そして、参考④のような違いはあるが綺麗に出力してくれます。
参考③は論文との違いを埋める意味でも参考にさせていただきました。
【参考】
①[jacobgil/keras-dcgan](https://github.com/jacobgil/keras-dcgan)
②[DCGANで画像の自動生成](https://qiita.com/elm200/items/def0880b9afc1d60a707)
③[Chainerを使ってコンピュータにイラストを描かせる](https://qiita.com/rezoolab/items/5cc96b6d31153e0c86bc)
④[Disrepancy in architecture in paper vs implemented version #5](https://github.com/jacobgil/keras-dcgan/issues/5)
###やったこと
・参考①をexampleを動かす（省略）
・参考②を動かす
・参考②のアプリの構造を参考①に合わせる
・参考④の課題を見つつ、参考③のコード参考に遊んでみる
###・参考②を動かす
特別なのは、
①学習データを[animeface-character-datasetからダウンロード](http://www.nurs.or.jp/~nagadomi/animeface-character-dataset/)して所定のディレクトリin_images に学習したい任意の画像（のフォルダ）を格納する
**ダウンロードしたファイルにReadmeがあるので、研究等利用に限定して利用しよう**
画像読み込みは以下のコードで実施している
このコードはin_images配下に置かれたディレクトリ配下からpngファイルを読み込み、そしてbatch_size分だけランダムに抽出して、一つずつ読み込みres配列で返しています。

```py
def image_batch(batch_size):
    files = glob.glob("./in_images/**/*.png", recursive=True)
    files = random.sample(files, batch_size)
    # print(files)
    res = []
    for path in files:
        img = Image.open(path)
        img = img.resize((64, 64))
        arr = np.array(img)
        arr = (arr - 127.5) / 127.5
        arr.resize((64, 64, n_colors))
        res.append(arr)
    return np.array(res)
```
学習は参考①と同様ですが、genrator()関数とdiscriminator関数が２Dに拡張されています。
ということで、動かしてみようと思うと、main()がぽつんとありますが、これで実行できました。結果は、参考②を参照してください。とてもキレイにアニメ画像が出力するので驚きました。
###・参考②のアプリの構造を参考①に合わせる
しかし、参考①と比較すると少し機能が不足していたので、まずは参考①の機能を追加します。 
ということで以下の三つのものを追加します。
コード全体は以下におきました。
[DCGAN-Keras/keras-dcgan_original.py](https://github.com/MuAuan/DCGAN-Keras/blob/master/keras-dcgan_original.py)
１．TrainモードとGenerateモードを追加

```py
if __name__ == "__main__":
    args = get_args()
    if args.mode == "train":
        main(BATCH_SIZE=args.batch_size,ite=args.iteration)
    elif args.mode == "generate":
        generate(BATCH_SIZE=args.batch_size,ite=args.iteration, nice=args.nice)
```
これを実現するために、

```py
def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--mode", type=str)
    parser.add_argument("--batch_size", type=int, default=55)
    parser.add_argument("--iteration", type=int, default=10000)
    parser.add_argument("--nice", dest="nice", action="store_true")
    parser.set_defaults(nice=False)
    args = parser.parse_args()
    return args
```
とし、`def generate(BATCH_SIZE=55, ite=10000, nice=False):`を追加しました。
２．学習再開のためにWeightsの保存と読み込みを追加しました
３．改変しやすいので、関数を`Conv2DTranspose(64, (5, 5), activation='tanh', strides=2, padding='same'))`で書き換えました
ちなみに、このコード入力を（１２８，１２８）として、必要な部分（主に乱数発生しているところ）を変更するとこの流れで学習できました。
・また、os.makedirs(os.path.join(".", "gen_images"), exist_ok=True)に訂正しています。
###・参考④の課題を見つつ、参考③のコード参考に遊んでみる
しかし、参考④の記載の論文との以下三点の違い

```
・the use of relu and leakyrely activations.
・batchnormalisation between the layers
・striding instead of pooling
（The paper also uses Adam instead of SGD）→ここはAdam使われています
```
そして、参考③のパラメータ調整についての感想に書かれていることがちょうど符号しているように思えました。ちなみにGANで出来る多様なお遊びはあとでやるとして、以下のように[元論文もこのあたりが一つの売り（pdf）](https://arxiv.org/pdf/1511.06434.pdf)なように読めます。

```
Architecture guidelines for stable Deep Convolutional GANs
• Replace any pooling layers with strided convolutions (discriminator) and fractional-strided
convolutions (generator).
• Use batchnorm in both the generator and the discriminator.
• Remove fully connected hidden layers for deeper architectures.
• Use ReLU activation in generator for all layers except for the output, which uses Tanh.
• Use LeakyReLU activation in the discriminator for all layers.
```
ということで、以下のコードで上記の論文の指示のとおり、変更して実施しましたが、結局収束したのは以下のコードでした。
・[DCGAN-Keras/keras-dcgan_trial_paper.py](https://github.com/MuAuan/DCGAN-Keras/blob/master/keras-dcgan_trial_paper.py)
つまり、

```
• Use batchnorm in both the generator and the discriminator.⇒use only in the generator
• Remove fully connected hidden layers for deeper architectures.⇒OK
• Use ReLU activation in generator for all layers except for the output, which uses Tanh.⇒use Tanh for every layers in generator
• Use LeakyReLU activation in the discriminator for all layers.⇒Use Tanh in the discriminator fo all layers
```
実は以下の回答がちょっと微妙です。上記は以下が前提ですが、実際は以下の条件でなかなか安定的に収束に向かいませんというか偏りな分布になってしまいます。
ということで、前提的ですが、一応、

```
• Replace any pooling layers with strided convolutions (discriminator) and fractional-strided
convolutions (generator).⇒OK for generator but not for discriminator
```
コード以下で実現しています。

```py
def discriminator_model():
    model = Sequential()
    model.add(Conv2D(16, (5, 5), input_shape=(128, 128, n_colors), padding='same'))
    model.add(LeakyReLU(alpha=0.01))
    model.add(BatchNormalization())
    #model.add(Activation('tanh'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    
    model.add(Conv2D(32, (5, 5),  strides=2, padding='same'))
    model.add(LeakyReLU(alpha=0.01))
    model.add(BatchNormalization())
    #model.add(Activation('tanh'))
    #model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Conv2D(64, (5, 5),  strides=2, padding='same'))
    model.add(LeakyReLU(alpha=0.01))
    model.add(BatchNormalization())
    #model.add(Activation('tanh'))
    #model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Conv2D(128, (5, 5),  strides=2, padding='same'))
    model.add(LeakyReLU(alpha=0.01))
    model.add(BatchNormalization())
    #model.add(Activation('tanh'))
    #model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Conv2D(256, (5, 5), strides=2, padding='same'))
    model.add(LeakyReLU(alpha=0.01))
    model.add(BatchNormalization())
    #model.add(Activation('tanh'))
    #model.add(MaxPooling2D(pool_size=(2, 2)))
       
    model.add(Flatten())
    #model.add(Dense(128))
    #model.add(Activation('tanh'))
    #model.add(LeakyReLU(alpha=0.01))
    model.add(Dense(1))
    model.add(Activation('sigmoid'))
    return model
```
###まとめ
・DCGAN-Kerasで遊んでみた
・いくつか気になることを変化させて再現性を見た
・参考②のコードが比較的安定して収束する
・入力サイズを大きくして学習できた

・学習教材集めて、いよいよ令和ちゃんを作ろ
###おまけ
```
generator.summary()---
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
dense_3 (Dense)              (None, 8192)              8396800
_________________________________________________________________
batch_normalization_1 (Batch (None, 8192)              32768
_________________________________________________________________
activation_8 (Activation)    (None, 8192)              0
_________________________________________________________________
reshape_1 (Reshape)          (None, 8, 8, 128)         0
_________________________________________________________________
conv2d_transpose_1 (Conv2DTr (None, 16, 16, 128)       409728
_________________________________________________________________
batch_normalization_2 (Batch (None, 16, 16, 128)       512
_________________________________________________________________
conv2d_transpose_2 (Conv2DTr (None, 32, 32, 64)        204864
_________________________________________________________________
batch_normalization_3 (Batch (None, 32, 32, 64)        256
_________________________________________________________________
conv2d_transpose_3 (Conv2DTr (None, 64, 64, 32)        51232
_________________________________________________________________
batch_normalization_4 (Batch (None, 64, 64, 32)        128
_________________________________________________________________
conv2d_transpose_4 (Conv2DTr (None, 128, 128, 3)       2403
=================================================================
Total params: 9,098,691
Trainable params: 9,081,859
Non-trainable params: 16,832
_________________________________________________________________
discriminator_on_generator.summary()---
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
sequential_2 (Sequential)    (None, 128, 128, 3)       9098691
_________________________________________________________________
sequential_1 (Sequential)    (None, 1)                 1614241
=================================================================
Total params: 10,712,932
Trainable params: 9,081,859
Non-trainable params: 1,631,073
_________________________________________________________________
discriminator.summary()---
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
conv2d_1 (Conv2D)            (None, 128, 128, 16)      1216
_________________________________________________________________
activation_1 (Activation)    (None, 128, 128, 16)      0
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 64, 64, 16)        0
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 64, 64, 32)        12832
_________________________________________________________________
activation_2 (Activation)    (None, 64, 64, 32)        0
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 32, 32, 32)        0
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 32, 32, 64)        51264
_________________________________________________________________
activation_3 (Activation)    (None, 32, 32, 64)        0
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 16, 16, 64)        0
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 16, 16, 128)       204928
_________________________________________________________________
activation_4 (Activation)    (None, 16, 16, 128)       0
_________________________________________________________________
max_pooling2d_4 (MaxPooling2 (None, 8, 8, 128)         0
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 8, 8, 256)         819456
_________________________________________________________________
activation_5 (Activation)    (None, 8, 8, 256)         0
_________________________________________________________________
max_pooling2d_5 (MaxPooling2 (None, 4, 4, 256)         0
_________________________________________________________________
flatten_1 (Flatten)          (None, 4096)              0
_________________________________________________________________
dense_1 (Dense)              (None, 128)               524416
_________________________________________________________________
activation_6 (Activation)    (None, 128)               0
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 129
_________________________________________________________________
activation_7 (Activation)    (None, 1)                 0
=================================================================
Total params: 1,614,241
Trainable params: 1,614,241
Non-trainable params: 0
_________________________________________________________________
C:\Users\MuAuan\Anaconda3\envs\keras-gpu\lib\site-packages\keras\engine\training.py:490: UserWarning: Discrepancy between trainable weights and collected trainable weights, did you set `model.trainable` without calling `model.compile` after ?
  'Discrepancy between trainable weights and collected trainable'
step 0 d_loss, g_loss : 0.661299 0.202175
C:\Users\MuAuan\Anaconda3\envs\keras-gpu\lib\site-packages\keras\engine\training.py:490: UserWarning: Discrepancy between trainable weights and collected trainable weights, did you set `model.trainable` without calling `model.compile` after ?
  'Discrepancy between trainable weights and collected trainable'
step 100 d_loss, g_loss : 0.0992669 2.52034
step 200 d_loss, g_loss : 0.111913 3.94367
step 300 d_loss, g_loss : 0.258464 2.59087
step 400 d_loss, g_loss : 0.279365 1.27632
step 500 d_loss, g_loss : 0.460313 2.9765
step 600 d_loss, g_loss : 0.238148 2.01341
step 700 d_loss, g_loss : 0.338979 2.62911
step 800 d_loss, g_loss : 0.452544 0.720869
step 900 d_loss, g_loss : 0.273319 2.7806
step 1000 d_loss, g_loss : 0.24975 2.87003
step 1100 d_loss, g_loss : 0.278847 3.31953
step 1200 d_loss, g_loss : 0.188068 2.30928
step 1300 d_loss, g_loss : 0.180659 2.14206
step 1400 d_loss, g_loss : 0.269469 3.89713
step 1500 d_loss, g_loss : 0.146608 3.29651
step 1600 d_loss, g_loss : 0.179147 3.31555
step 1700 d_loss, g_loss : 0.122445 3.0854
step 1800 d_loss, g_loss : 0.0856069 3.68894
step 1900 d_loss, g_loss : 0.193407 3.93947
step 2000 d_loss, g_loss : 0.0925356 2.88718
step 2100 d_loss, g_loss : 0.104538 3.95823
step 2200 d_loss, g_loss : 0.0568399 4.23423
step 2300 d_loss, g_loss : 0.0714832 4.66563
step 2400 d_loss, g_loss : 0.516044 2.81248
step 2500 d_loss, g_loss : 0.118183 5.07315
step 2600 d_loss, g_loss : 0.0842467 3.63953
step 2700 d_loss, g_loss : 0.0799995 4.50931
step 2800 d_loss, g_loss : 0.0854145 5.33003
step 2900 d_loss, g_loss : 0.113456 4.1126
step 3000 d_loss, g_loss : 0.102548 4.76754
step 3100 d_loss, g_loss : 0.133966 3.61077
step 3200 d_loss, g_loss : 0.0848466 3.04316
step 3300 d_loss, g_loss : 0.0462944 4.61841
step 3400 d_loss, g_loss : 0.073567 5.63333
step 3500 d_loss, g_loss : 0.0567865 5.41634
step 3600 d_loss, g_loss : 0.0469644 4.85979
step 3700 d_loss, g_loss : 0.11105 4.2469
step 3800 d_loss, g_loss : 0.145755 6.52955
step 3900 d_loss, g_loss : 0.0742965 4.0609
step 4000 d_loss, g_loss : 0.0781675 3.91089
step 4100 d_loss, g_loss : 0.0912378 6.35192
step 4200 d_loss, g_loss : 0.0884004 5.30037
step 4300 d_loss, g_loss : 0.154173 4.83642
step 4400 d_loss, g_loss : 0.0422458 4.26942
step 4500 d_loss, g_loss : 0.0497214 4.24877
step 4600 d_loss, g_loss : 0.0699701 6.11376
step 4700 d_loss, g_loss : 0.0227912 5.81378
step 4800 d_loss, g_loss : 0.0475269 4.95001
step 4900 d_loss, g_loss : 0.0253329 4.76479
step 5000 d_loss, g_loss : 0.100017 4.95773
step 5100 d_loss, g_loss : 0.0624697 5.47602
step 5200 d_loss, g_loss : 0.0510602 7.3932
step 5300 d_loss, g_loss : 0.0443467 4.86556
step 5400 d_loss, g_loss : 0.0266479 7.32272
step 5500 d_loss, g_loss : 0.125236 5.65234
step 5600 d_loss, g_loss : 0.0130315 4.99994
step 5700 d_loss, g_loss : 0.0312069 6.51652
step 5800 d_loss, g_loss : 0.00162216 5.88866
step 5900 d_loss, g_loss : 0.000379454 7.692
step 6000 d_loss, g_loss : 0.019156 5.14982
step 6100 d_loss, g_loss : 0.00956071 5.58252
step 6200 d_loss, g_loss : 0.0392237 6.56101
step 6300 d_loss, g_loss : 0.108367 4.77981
step 6400 d_loss, g_loss : 0.048856 5.38055
step 6500 d_loss, g_loss : 0.0164732 6.31698
step 6600 d_loss, g_loss : 0.048983 6.07043
step 6700 d_loss, g_loss : 0.0348159 6.18282
step 6800 d_loss, g_loss : 0.0275375 6.84896
step 6900 d_loss, g_loss : 0.55915 2.74205
step 7000 d_loss, g_loss : 0.0232004 5.40238
step 7100 d_loss, g_loss : 0.00442515 5.71259
step 7200 d_loss, g_loss : 0.0226002 5.88016
step 7300 d_loss, g_loss : 0.0599934 6.73299
step 7400 d_loss, g_loss : 0.0305902 6.52438
step 7500 d_loss, g_loss : 0.0292496 5.84567
step 7600 d_loss, g_loss : 0.026301 6.48846
step 7700 d_loss, g_loss : 0.0085861 7.18842
step 7800 d_loss, g_loss : 0.0445716 6.9633
step 7900 d_loss, g_loss : 0.000403208 7.94849
step 8000 d_loss, g_loss : 0.0276422 6.89717
step 8100 d_loss, g_loss : 0.397753 1.48598
step 8200 d_loss, g_loss : 0.0334777 7.81227
step 8300 d_loss, g_loss : 0.0614538 6.99127
step 8400 d_loss, g_loss : 0.0915911 2.6487
step 8500 d_loss, g_loss : 0.0215191 6.65791
step 8600 d_loss, g_loss : 0.012072 6.68557
step 8700 d_loss, g_loss : 0.0168208 7.07054
step 8800 d_loss, g_loss : 0.0141823 6.18281
step 8900 d_loss, g_loss : 0.0258561 6.86101
step 9000 d_loss, g_loss : 0.0316221 6.52956
step 9100 d_loss, g_loss : 0.00847772 6.85588
step 9200 d_loss, g_loss : 0.0166051 6.41966
step 9300 d_loss, g_loss : 0.0657021 6.88139
step 9400 d_loss, g_loss : 0.0190996 7.99712
step 9500 d_loss, g_loss : 0.0012951 8.4474
step 9600 d_loss, g_loss : 0.0155907 7.72163
step 9700 d_loss, g_loss : 0.0362807 7.98473
step 9800 d_loss, g_loss : 0.0216097 8.21648
step 9900 d_loss, g_loss : 0.00143361 6.95926
step 10000 d_loss, g_loss : 0.00543872 7.24704
step 10100 d_loss, g_loss : 0.0158229 6.75718
step 10200 d_loss, g_loss : 0.00777546 6.7276
```