ディープラーニング　脱超初心者向け基礎知識

#まずはじめに
初めての投稿なので、拙い部分は多々あると思いますが、頑張って書きます。笑
この記事は僕が画像処理のディープラーニングの勉強をしていく上ではまったなーってところを初心者の方に向けて書こうと思います。なので、できる人からしたら、なんてことはない記事だと思います汗
この記事は、kerasを使い始めたけど、まだあまりよくわからない！って人向けです

#環境
- python 3.6.6
- tensor-flow 1.12.0
- Keras 2.2.4

#どんなところでハマったのか
まあ、どんなところも何も新しく何かをやろう思うと毎度ハマるわけですが、、笑
中でも個人的にかなりハマってしまったところが、学習データが多すぎてメモリに全ては展開できねえ！って時です。
そんな時はImageDataGeneratorという便利なモジュールがkerasには用意されてます

##ImageDataGeneratorとは
まず、kerasのドキュメントのURLを載せておきます。
[keras-imagedatagenerator](https://keras.io/ja/preprocessing/image/)

つまり、簡単に言うと、データの前処理（せん断や回転など）を行うのに便利なモジュールになります。それに加えて、学習データなどをジェネレータとして生成できるので、メモリに一度で乗り切らないような巨大なデータでも扱えるようにしてくるものです。
ジェネレータってなんぞやって方は以下の記事がわかりやすいと思います。
[pythonのイテレータとジェネレータ](https://qiita.com/tomotaka_ito/items/35f3eb108f587022fa09)

データをバッチごとに読み込むから、バッチサイズの画像がメモリにさえ乗ればデータが莫大でも学習できるよって感じですね。

##基本的な使い方
まずデータを読み込むのに、準備としてImageDataGeneratorクラスのインスタンスを作ります。

 ```python:imagedatagenerator_example.py
import keras.preprocessing.image as Image
datagen = Image.ImageDataGenerator(
            featurewise_center = False,
            samplewise_center = False,
            featurewise_std_normalization = False,
            samplewise_std_normalization = False,
            zca_whitening = False,
            rotation_range = 30,
            width_shift_range = 0.3,
            height_shift_range = 0.3,
            horizontal_flip = True,
            vertical_flip = False,
            validation_split = 0.1
        )
```
引数に関してはドキュメント見るのが早いと思うので、そちらを参照してください。標準化の有無などを決められます。ここで、ポイントなのはvalidation_splitです。この値を決めておくと、読み込んだデータを自動でvalidationデータとtrainデータに分けてくれます。この場合は１割がvalidationデータとなります。
これで下準備は完了です。
注：標準化などの基本統計量が必要になる前処理をしたい場合はfitする必要があります詳しくは調べてみてください

##データを読み込む
では、実際にデータを読み込んでみましょう。

```python:imagedatagenerator_example.py
train_generator = datagen.flow_from_directory(
            train_dir,
            target_size=(224,224),
            batch_size=batch_size,
            class_mode='categorical',
            shuffle=True,
            subset = "training" 
        )

val_generator = datagen.flow_from_directory(
            train_dir,
            target_size=(224,224),
            batch_size=batch_size,
            class_mode='categorical',
            shuffle=True,
            subset = "validation"
        )
```
ここで出てきた'flow_from_directory'がデータのあるディレクトリからデータを自動で読み取ってジェネレータを作ってくれます。
引数は

- train_dir:データのあるディレクトリのpath
- target-size:画像データのサイズ
- batch-size:一度に読み込むデータの数
- class_mode:正解ラベルの形（複数のクラスであれば'categorical'、2クラスであれば'binary'など
- suffle:データをシャッフルするかどうか（真偽値）
- subset:はじめに書いたvalidationかtrainのデータかを指定する。

ここで意地悪なのが、kerasの日本語公式ドキュメントにはsubsetの説明が無い、、（英語の方には確かあったけど）
train_dirの中をラベルごとに分けてフォルダを作っておけば、自動でデータにlabelづけしてくれます。便利ですね。

##ジェネレータを使った学習
では、ジェネレータを使った学習をしましょう。

```python:imagedatagenerator_example.py
self._target.fit_generator(
            train_generator,
            steps_per_epoch=5,
            epochs=epochs,
            validation_data=val_generator,
            validation_steps=1,
            callbacks=[
                TensorBoard(log_dir=self.log_dir),
                ModelCheckpoint(os.path.join(self.log_dir, self.model_file_name), save_best_only=True)
            ],
            verbose=2,
            workers=1
        )
```
ここは、主な引数の説明をします。

- train_generator:先ほどの学習データのジェネレータ
- steps_per_epoch,epochs:steps_per_epoch * epochs=全データ数となるようにします。
- validation_data:先ほどのバリデーションデータのジェネレータ
- validation_steps:ジェレータから使用するサンプルのバッチ数

こんな感じになります

ちょっと注意なのが、普通のfitだと、ここでvalidationデータに分けられるのですが、fit_generatorはここでvalidationデータに分けることはできないので、あらかじめ二つのジェネレータを用意する必要あります。

これで一通りメモリに乗り切らないようなデータの学習もできるようになったのでは無いかと思います

##余分な話
これで、メモリに乗らないデータを扱えるようになったと思います。
ちょっと余分な知識を書いていこうと思います。
#####正解ラベルが欲しい
学習データのフォルダ名にラベルをつけたのはいいが、ラベルが多くて取り出すのが大変な時とかに使えるかな、と

```python:imagedatagenerator_example.py
_label = train_generator.class_indices
#{'label1':0, 'label2':1, 'label3':2,....}

```

#####テストデータでもジェネレータを使いたい
もちろんテストデータにもジェネレータは使えます

- predict_generator
- evaluate_generator

あたりが使えるともいます。基本的な機能はジェネレータを使わないものと同じになると思います。


#最後に
ここまで読んでいただいてありがとうござました。
個人的には、keras日本語ドキュメントあるけど、英語の方がいいかなって思います。笑