Deep Learningのためのデータ拡張処理について

#はじめに
　今回は、pythonを用いた画像のデータ拡張処理を一括で行うプログラムを作成しました（kerasのImageDataGeneratorで取り扱っているものを参考にしています）。また、データ拡張処理の簡単な説明と注意点にも触れていきます。
ソースコードは、[こちら](https://github.com/oHjm/Data_Augmentation)です。

#データ拡張処理とは
　Deep Learning（深層学習）による画像認識・分類モデルを構築するためには、大量の高品質な学習データが必要となります。しかしながら、ほとんどの場合において、学習データ数が少ないという状況に直面すると思います。学習データが少ない場合は、力技（学習の対象物を撮影するなど）で増やすことも可能ですが、多くの時間と労力がかかります。
　データ拡張処理は、「学習データが少ない」という際に、活躍するテクニックです。具体的には、元の学習データに対して、左右に反転、拡大・縮小処理などを適用することによって、データ数を拡張させていきます。


# 今回扱うデータ拡張処理
 現時点で様々な種類のデータ拡張処理がありますが、今回は以下の処理を扱います。拡張処理を適用した結果を表示するために、[「商用無料の写真検索さん」](https://www.nairegift.com/freephoto/)より、猫の画像（[ある日のよもぎ by sabamiso](http://www.igosso.net/se.cgi?q=%E3%81%82%E3%82%8B%E6%97%A5%E3%81%AE%E3%82%88%E3%82%82%E3%81%8E&sa=%E6%A4%9C%E7%B4%A2&lid=1&lia=1&lib=1&lic=1)）を用いました。

- 回転
　任意の角度に回転させる処理です。この処理は、撮影される猫の角度が異なる場合を想定していると思います。
![cat.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/c656baaf-050a-58e5-1668-55dd17290b55.jpeg) ![rot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/38b2444f-ed6c-e7e1-6fa9-db37a1595ead.jpeg)


- 水平・垂直方向に平行移動
　画像の被写体を水平・垂直方向に平行移動させる処理です。この処理は、撮影される猫が左にいたり上にいたりする場合を想定していると思います。
![cat.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/c656baaf-050a-58e5-1668-55dd17290b55.jpeg) ![shift.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/4fa5107b-478c-4dd1-9a7b-5423343e2254.jpeg) ![height.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/643d83c8-739f-99f0-7606-b2fe937a569a.jpeg)


- 拡大・縮小
　画像の被写体を拡大したり縮小したりする処理です。この処理は、近くにいる、もしくは、遠くにいる猫を撮影する場合を想定していると思います。
![cat.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/c656baaf-050a-58e5-1668-55dd17290b55.jpeg) ![scale.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/3b2df576-17ce-04ea-7de1-e339ae2e9cf0.jpeg)


- 色調変更
　全体的に明るくする、もしくは、暗くする処理です。この処理は、撮影環境が明るい、もしくは、暗いことを想定していると思います。
![cat.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/c656baaf-050a-58e5-1668-55dd17290b55.jpeg) ![test.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/2804514e-48dc-3c3e-48cf-8ed08d995c2e.jpeg)


- 左右反転
　画像の左右を逆にする処理です。この処理は、左向きや右向きの猫を撮影する場合を想定していると思います。
![cat1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/f991e339-ffc5-a2fa-8948-0bfa95add760.jpeg) ![res_flr.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/78da9a8a-2f80-57a7-8e96-e74b2c8d6d0b.jpeg)


- Random Erasing
　画像の一部を矩形でマスク（覆う）する処理です。このとき、1. マスクするかしないか、2. 矩形の大きさ、3. 矩形の縦横比がランダムに決定されます。
![cat1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/f991e339-ffc5-a2fa-8948-0bfa95add760.jpeg) ![res_re.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/d6da1584-ff09-ce73-afb9-854a7de46176.jpeg)

# データ拡張処理プログラムの操作方法
　「main.py」を実行することによって、「今回扱うデータ拡張処理」で挙げた処理を組み合わせて適用し、学習画像を作成します。以下のソースコードにおける変数を設定することによって、好きなようにお使いいただけます。

```python:main.pyの一部
# ------------------- 以下，個別で指定する各変数 -------------------

input_dir = 'trainImg' # 学習の原画像が入っているフォルダ名
output_dir = "output" # 拡張処理後の出力フォルダ名
num = 10 # 拡張する画像枚数

generator = ImageDataGenerator(
                rotation_range=90, # 回転する角度を90°までに設定
                width_shift_range=0.1, # 水平方向にランダムでシフト
                height_shift_range=0.1, # 垂直方向にランダムでシフト
                zoom_range=0.3, # 拡大・縮小する範囲
                channel_shift_range=50.0, # ランダム値を画素値に加える
                horizontal_flip=False, # 垂直方向にランダムで反転
                vertical_flip=True # 水平方向にランダムで反転
                )
# ------------------- 以上，個別で指定する各変数 -------------------
```
「input_dir」に5枚の学習原画像が入っており、上記のような変数で「main.py」を実行した場合、「output_dir」に5×10枚の画像が生成されます。

# データ拡張処理の注意点
　データ拡張処理は、適用すれば良いというわけではありません。例えば、平仮名の文字認識モデルを作成することを考えた際に、文字画像（参照：[https://lab.ndl.go.jp/cms/hiragana73](https://lab.ndl.go.jp/cms/hiragana73)）に対してデータ拡張処理を適用した場合に、以下のような問題点が生じます。


- 平仮名の「い」に対して、回転処理を適用した場合（左：原画像、右：処理後の画像）
　　　　![1930_1175565_0024.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/584f1bd3-64fd-57e2-86d2-9c19260d7244.png)　　　　　　![test1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/d2760379-62a8-2af8-a0a6-7609acd16257.png)
上の結果のように、処理後の画像は「こ」に似ている文字となるため、誤認識される可能性があります。


- 平仮名の「う」に対して、左右反転処理を適用した場合（左：原画像、右：処理後の画像）
　　　　![1930_1176246_0041.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/876535c7-a527-d40a-bd61-749ab861a29d.png) 　　　　　　![test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499475/79d894da-eadf-dacf-5c4f-d743c19c5dd6.png)
上の結果のように、処理後の画像は、存在していない文字であり、文字認識モデルの精度を低下させる原因（無意味な学習）になります。

# まとめ
　今回の内容では、pythonを用いたデータ拡張処理プログラムの作成とデータ拡張処理の簡単な説明をさせていただきました。データ拡張処理は手軽に行える上、上手くいけば精度向上につながります。しかしながら、学習画像の対象によっては、データ拡張処理を適用することによって、無意味な学習画像を作成してしまいます。したがって、学習画像の対象に応じて、どの変換（回転など）を用いて、どのくらい変換（回転であればどのくらいの角度）させるのかを検討する必要があると思います。