YOLOv5　データ拡張(Data Augmentation)を徹底解説

# 1. はじめに

YOLOv5のデータ拡張(水増し、Data Augmentation、データオーギュメンテーション)について、調べたことをまとめます。
何か間違っていること等あればご指摘いただき、内容を充実させていければと思います。 

YOLOv5のデータ拡張ですが、Hyperparametersで指定をしている部分と、Albumentationsを使用している部分があるそうです。
それぞれについて解説をしていきたいと思います。

参考サイト

https://docs.ultralytics.com/FAQ/augmentation/


# 2. Hyperparametersでの指定

Hyperparametersはデフォルトでは.\data\hyps\hyp.scratch-low.yamlが呼び出されるので、その内容から確認します。

```yaml:hyp.scratch-low.yaml
# YOLOv5 🚀 by Ultralytics, GPL-3.0 license
# Hyperparameters for low-augmentation COCO training from scratch
# python train.py --batch 64 --cfg yolov5n6.yaml --weights '' --data coco.yaml --img 640 --epochs 300 --linear
# See tutorials for hyperparameter evolution https://github.com/ultralytics/yolov5#tutorials

lr0: 0.01  # initial learning rate (SGD=1E-2, Adam=1E-3)
lrf: 0.01  # final OneCycleLR learning rate (lr0 * lrf)
momentum: 0.937  # SGD momentum/Adam beta1
weight_decay: 0.0005  # optimizer weight decay 5e-4
warmup_epochs: 3.0  # warmup epochs (fractions ok)
warmup_momentum: 0.8  # warmup initial momentum
warmup_bias_lr: 0.1  # warmup initial bias lr
box: 0.05  # box loss gain
cls: 0.5  # cls loss gain
cls_pw: 1.0  # cls BCELoss positive_weight
obj: 1.0  # obj loss gain (scale with pixels)
obj_pw: 1.0  # obj BCELoss positive_weight
iou_t: 0.20  # IoU training threshold
anchor_t: 4.0  # anchor-multiple threshold
# anchors: 3  # anchors per output layer (0 to ignore)
fl_gamma: 0.0  # focal loss gamma (efficientDet default gamma=1.5)
hsv_h: 0.015  # image HSV-Hue augmentation (fraction)
hsv_s: 0.7  # image HSV-Saturation augmentation (fraction)
hsv_v: 0.4  # image HSV-Value augmentation (fraction)
degrees: 0.0  # image rotation (+/- deg)
translate: 0.1  # image translation (+/- fraction)
scale: 0.5  # image scale (+/- gain)
shear: 0.0  # image shear (+/- deg)
perspective: 0.0  # image perspective (+/- fraction), range 0-0.001
flipud: 0.0  # image flip up-down (probability)
fliplr: 0.5  # image flip left-right (probability)
mosaic: 1.0  # image mosaic (probability)
mixup: 0.0  # image mixup (probability)
copy_paste: 0.0  # segment copy-paste (probability)
```

データ拡張に関わるのは、hsv_hから下の部分となります。
一般的なものがほとんどですが、mosaicより下の部分についてはどのようになるのか気になったので、実際に動作を確認してみました。

**mosaic** : 4枚の画像をつなぎ合わせて1枚の画像を生成しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2048607/afef5a83-d1df-1335-2a17-d1c8ed56d356.png)

**mixup** : 複数の画像を透過させ重ね合わせています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2048607/a0de89ed-92b5-9c53-b16e-0e7c28c88c51.png)

**copy_paste** : 対象物体を切り貼りしています。
(物体のBBoxラベルでなく、セグメンテーションラベルがないと使用できないそうです)

https://github.com/ultralytics/yolov5/pull/3845

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2048607/7a72094c-e183-3804-8c1d-7b7775a7f6cc.png)


# 3. Albumentationsの使用

Albumentationsがインストールされていると、.\utils\augumentations.pyの画像変換部が自動で実行されるようです。下記ファイルの T = [ ------ ]の部分が該当部分になるので、その中身を変更することで自由に関数を設定することができます。


```python:augmentations.py
class Albumentations:
    # YOLOv5 Albumentations class (optional, only used if package is installed)
    def __init__(self):
        self.transform = None
        try:
            import albumentations as A
            check_version(A.__version__, '1.0.3', hard=True)  # version requirement

            T = [
                A.Blur(p=0.01),
                A.MedianBlur(p=0.01),
                A.ToGray(p=0.01),
                A.CLAHE(p=0.01),
                A.RandomBrightnessContrast(p=0.0),
                A.RandomGamma(p=0.0),
                A.ImageCompression(quality_lower=75, p=0.0)]  # transforms
            self.transform = A.Compose(T, bbox_params=A.BboxParams(format='yolo', label_fields=['class_labels']))

            LOGGER.info(colorstr('albumentations: ') + ', '.join(f'{x}' for x in self.transform.transforms if x.p))
        except ImportError:  # package not installed, skip
            pass
        except Exception as e:
            LOGGER.info(colorstr('albumentations: ') + f'{e}')
```

Albumentationsのインストールは下記コマンドで可能です。

```
pip install -U albumentations
```

https://qiita.com/ToppaD/items/7cc8c54538c8dd5f6af2

例えば雪を降らしたような画像にするRandomSnowを適用するとこのようになります。

```python
T = [A.RandomSnow(p=1.0)]  # transforms
self.transform = A.Compose(T, bbox_params=A.BboxParams(format='yolo', label_fields=['class_labels']))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2048607/798bb3bb-82c5-7392-ffde-79a92aded9e7.png)

適用できる関数についてはこちらをご参照ください。

https://qiita.com/kurilab/items/b69e1be8d0224ae139ad

https://albumentations.ai/docs/api_reference/augmentations/

# 4.まとめ

今回はYOLOv5に組み込まれているデータ拡張を解説しました。
より効率よく学習するためにはここらへんの理解を深めていくことが必要かと思います。