YOLOX理解④：Augmentationを理解する（Mosaic, MixUp, etc）

## YOLOXとは

:::note info
YOLOX2021年に発表されたリアルタイムの物体検知でベンチマークとなるモデルです。リアルタイムの物体検知モデルはいくつもありますが、YOLOXは商用利用が可能な`Apache License 2.0`であることから、各社で開発が盛んに進んでいると思われます。YOLOXを各方面から理解を深めるために、実装を中心に深掘りしていきます。
:::

https://arxiv.org/abs/2107.08430

### YOLOX理解の道のり

1. YOLOXのBackbone理解（CSPDarknet）
2. YOLOXのNeck/Head理解 （YOLOXPPFPN, YOLOXHead）
3. YOLOXのLoss理解（4種類のLossと重み付け）
4. ⭐️（今回はこれ）YOLOXのAugmentation（Mosaic, Mixup, etc）
5. YOLOXのSim OTAの理論と実装
6. YOLOXのモデル毎の性能差（Tiny, S, M, L, X）
7. YOLOXの実用例（社会実装された例など）

今回は、4番のAugmentationについて取り上げます。可視化にあたってはmmdetectionを用います。

## YOLOXのAugmentation

今回、YOLOXのTransformを一つひとつ可視化するにあたって、[mmdetectionのbrowse_dataset.py](https://github.com/open-mmlab/mmdetection/blob/main/tools/analysis_tools/browse_dataset.py)を使用します。

### 1. YOLOXの前処理工程

mmdetectionの実装を見ると、Mosaic → RandomAffine → MixUp → YOLOXHSVRandomAug → RandomFlip (→ Resize → Pad)の順番でtrainの際のパイプラインが設計されています。一つ一つどんな前処理なのか画像を可視化しながら調査していきましょう。

```python
train_pipeline = [
    dict(type='Mosaic', img_scale=img_scale, pad_val=114.0),
    dict(
        type='RandomAffine',
        scaling_ratio_range=(0.1, 2),
        # img_scale is (width, height)
        border=(-img_scale[0] // 2, -img_scale[1] // 2)),
    dict(
        type='MixUp',
        img_scale=img_scale,
        ratio_range=(0.8, 1.6),
        pad_val=114.0),
    dict(type='YOLOXHSVRandomAug'),
    dict(type='RandomFlip', prob=0.5),
    # According to the official implementation, multi-scale
    # training is not considered here but in the
    # 'mmdet/models/detectors/yolox.py'.
    # Resize and Pad are for the last 15 epochs when Mosaic,
    # RandomAffine, and MixUp are closed by YOLOXModeSwitchHook.
    dict(type='Resize', scale=img_scale, keep_ratio=True),
    dict(
        type='Pad',
        pad_to_square=True,
        # If the image is three-channel, the pad value needs
        # to be set separately for each channel.
        pad_val=dict(img=(114.0, 114.0, 114.0))),
    dict(type='FilterAnnotations', min_gt_bbox_wh=(1, 1), keep_empty=False),
    dict(type='PackDetInputs')
]

```

### 2. transformない場合

COCO2017は元々の画像の解像度が統一されておらず、縦長や横長の画像があるため、学習用画像にする際にresizeをしてからpaddingをして指定の解像度（640, 640）に調整しています。余白部分はグレーですが、これはpad_valが(114.0, 114.0, 114.0)に設定されているからです。この数字はハイパラ調整された結果なのか慣習なのかはよくわからずでした。

![000000574769.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/6f66726f-892b-a384-9093-e09a3f984a72.jpeg)


|![000000554625.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/3a097852-5448-0eff-9f0f-2f2440ca9d7c.jpeg)|![000000522418.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/0c31d008-f97f-2101-f69d-40b8eea6441b.jpeg)|![000000391895.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/b8898f5f-f0fb-0f61-1b31-711e8216b562.jpeg)|
|-|-|-|
|![000000318219.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/58ce2d52-8376-238f-0c2e-7b776da9830f.jpeg)|![000000309022.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/0c6d1c75-03a6-122f-cc4f-312ba3304da2.jpeg)|![000000224736.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/3ef20c3b-86aa-4146-7572-feb0fb1c92db.jpeg)|
|![000000222564.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/2e90bc3c-73b4-115c-e3cf-9a4c56ae7b12.jpeg)|![000000193271.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/7a4b5177-7205-7b1f-b1ee-0d2e39248907.jpeg)|![000000184613.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/8b0959ac-0bd3-25ed-b18f-6e5f05ab9697.jpeg)|
|![000000118113.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/7bc781eb-1073-1b91-c3c2-bc838d87e961.jpeg)|![000000060623.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/f767b6f1-9271-78a0-6230-d15b1a008b82.jpeg)|![000000005802.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/e3363b3f-bf74-f637-ca54-3142921386aa.jpeg)|

### 3. YOLOXのtransform全部載せ

YOLOXのAugmentationを直感的に理解するのは難しいです。例えば以下のような画像が学習データとして使われています。

ピザを食べているおじさんの下に、うっすらおじさんが写っていて、しかも遠近法がおかしいキッチンにコップやナイフが多数写っています。下手な合成写真（心霊写真？）にも見えます。

このわかりづらさは、mosaicとmixupが併用されていることが原因で、人には理解しづらいです。学習効率が良いので採用されているようです。

![000000005802.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/dbca10e4-728c-3859-636f-a4bb1335dc0f.jpeg)

以下は、同じくYOLOXの学習時にモデルに入力されている画像のサンプル。RandomAffineなども機能しているせいか、こんなに混雑した画像で学習させているのか、と驚きます。

|![000000574769.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/cb58af6d-9f12-1abb-0477-cdefca3f1919.jpeg)|![000000554625.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/117f7ccb-00a9-4aae-83ba-213d32c092ed.jpeg)|![000000522418.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/c779212a-d8e3-5678-73f0-ca51e140a943.jpeg)|
|-|-|-|
|![000000391895.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/af29e054-4af5-353e-06fd-8ebbe9721af7.jpeg)|![000000318219.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/57acb37b-4236-340b-75dc-91192f5c5065.jpeg)|![000000309022.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/52c23eef-a24b-bf23-0ce0-579e9d114451.jpeg)|
|![000000222564.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/d189e4cd-2a89-e2c1-bd0d-83c5f2fa9471.jpeg)|![000000184613.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/042ef000-9770-6246-0bbf-f5b7d275704f.jpeg)|![000000060623.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/05724ebd-a290-ecba-1ced-e30af802da3f.jpeg)|



### 4. Mosaicだけ入れた場合

:::note info
mosaic transformはyolov4で初登場した前処理手法。1枚の画像で複数のコンテクストを学習することができるので、スケールやアスペクト比に対するロバスト性が向上するというメリットがあります。一方で、データセットが小さすぎる場合に過学習してしまったり、現実世界では存在し得ないスケール比での画像を生成してしまうリスクもあります。
:::

![mosaic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/f04085c5-4160-2d32-689a-b146300d3601.png)
[mmdetectionのMosaic実装箇所](https://github.com/akiralab/mmdetection/blob/ecac3a77becc63f23d9f6980b2a36f86acd00a8a/mmdet/datasets/transforms/transforms.py#L2061-L2318)

1. mosaicの中心座標を決める
2. 左上の画像をまず配置して、残りの3枚の画像をランダムでデータセットから選択して配置する
3. 選択された3枚の画像のうち、mosaicエリアよりも大きい場合は取り除く

<details><summary>mosaic transform</summary>
    ```python
    @TRANSFORMS.register_module()
    class Mosaic(BaseTransform):
        """Mosaic augmentation.
    
        Given 4 images, mosaic transform combines them into
        one output image. The output image is composed of the parts from each sub-
        image.
    
        .. code:: text
    
                            mosaic transform
                               center_x
                    +------------------------------+
                    |       pad        |  pad      |
                    |      +-----------+           |
                    |      |           |           |
                    |      |  image1   |--------+  |
                    |      |           |        |  |
                    |      |           | image2 |  |
         center_y   |----+-------------+-----------|
                    |    |   cropped   |           |
                    |pad |   image3    |  image4   |
                    |    |             |           |
                    +----|-------------+-----------+
                         |             |
                         +-------------+
    
         The mosaic transform steps are as follows:
    
             1. Choose the mosaic center as the intersections of 4 images
             2. Get the left top image according to the index, and randomly
                sample another 3 images from the custom dataset.
             3. Sub image will be cropped if image is larger than mosaic patch
    
        Required Keys:
    
        - img
        - gt_bboxes (BaseBoxes[torch.float32]) (optional)
        - gt_bboxes_labels (np.int64) (optional)
        - gt_ignore_flags (bool) (optional)
        - mix_results (List[dict])
    
        Modified Keys:
    
        - img
        - img_shape
        - gt_bboxes (optional)
        - gt_bboxes_labels (optional)
        - gt_ignore_flags (optional)
    
        Args:
            img_scale (Sequence[int]): Image size after mosaic pipeline of single
                image. The shape order should be (width, height).
                Defaults to (640, 640).
            center_ratio_range (Sequence[float]): Center ratio range of mosaic
                output. Defaults to (0.5, 1.5).
            bbox_clip_border (bool, optional): Whether to clip the objects outside
                the border of the image. In some dataset like MOT17, the gt bboxes
                are allowed to cross the border of images. Therefore, we don't
                need to clip the gt bboxes in these cases. Defaults to True.
            pad_val (int): Pad value. Defaults to 114.
            prob (float): Probability of applying this transformation.
                Defaults to 1.0.
        """
    
        def __init__(self,
                     img_scale: Tuple[int, int] = (640, 640),
                     center_ratio_range: Tuple[float, float] = (0.5, 1.5),
                     bbox_clip_border: bool = True,
                     pad_val: float = 114.0,
                     prob: float = 1.0) -> None:
            assert isinstance(img_scale, tuple)
            assert 0 <= prob <= 1.0, 'The probability should be in range [0,1]. ' \
                                     f'got {prob}.'
    
            log_img_scale(img_scale, skip_square=True, shape_order='wh')
            self.img_scale = img_scale
            self.center_ratio_range = center_ratio_range
            self.bbox_clip_border = bbox_clip_border
            self.pad_val = pad_val
            self.prob = prob
    
        @cache_randomness
        def get_indexes(self, dataset: BaseDataset) -> int:
            """Call function to collect indexes.
    
            Args:
                dataset (:obj:`MultiImageMixDataset`): The dataset.
    
            Returns:
                list: indexes.
            """
    
            indexes = [random.randint(0, len(dataset)) for _ in range(3)]
            return indexes
    
        @autocast_box_type()
        def transform(self, results: dict) -> dict:
            """Mosaic transform function.
    
            Args:
                results (dict): Result dict.
    
            Returns:
                dict: Updated result dict.
            """
            if random.uniform(0, 1) > self.prob:
                return results
    
            assert 'mix_results' in results
            mosaic_bboxes = []
            mosaic_bboxes_labels = []
            mosaic_ignore_flags = []
            if len(results['img'].shape) == 3:
                mosaic_img = np.full(
                    (int(self.img_scale[1] * 2), int(self.img_scale[0] * 2), 3),
                    self.pad_val,
                    dtype=results['img'].dtype)
            else:
                mosaic_img = np.full(
                    (int(self.img_scale[1] * 2), int(self.img_scale[0] * 2)),
                    self.pad_val,
                    dtype=results['img'].dtype)
    
            # mosaic center x, y
            center_x = int(
                random.uniform(*self.center_ratio_range) * self.img_scale[0])
            center_y = int(
                random.uniform(*self.center_ratio_range) * self.img_scale[1])
            center_position = (center_x, center_y)
    
            loc_strs = ('top_left', 'top_right', 'bottom_left', 'bottom_right')
            for i, loc in enumerate(loc_strs):
                if loc == 'top_left':
                    results_patch = copy.deepcopy(results)
    ```
</details>

mosaicだけtransformさせた場合はこのようになります。mosaicの中心座標はまちまちですが、必ず4枚画像が並んでいることがわかります。mosaicは大変シンプルで直感的にも理解しやすいtransformであることがわかります。

![000000060623.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/c051eeff-de8b-614e-a42e-5887212100ea.jpeg)

|![000000574769.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/92b53d22-8526-4703-3d4b-44cfcc60d2d9.jpeg)|![000000554625.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/6d3eabff-88cc-a46f-c23e-c380265b38c3.jpeg)|![000000522418.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/a67da0b7-501e-7298-7498-b1a10738c53f.jpeg)|
|-|-|-|
|![000000391895.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/2201386e-d230-eb2e-6c15-29f7d94c5bd7.jpeg)|![000000318219.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/fa42dee7-8f1a-1f20-f4e6-35390ed9b065.jpeg)|![000000309022.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/cb42eee8-d275-46b3-8d9d-d110bb8c1de3.jpeg)|
|![000000222564.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/1cb6fb6a-f99b-4af6-e897-e01616291459.jpeg)|![000000184613.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/eddfbe58-b62f-f006-1bf0-25dfe8791a24.jpeg)|![000000118113.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/f9194ac2-f843-3be4-4430-d3693a54a179.jpeg)|



### 5. Mixupだけ入れた場合

:::note info
2017年に提案された前処理手法。学習データセットからランダムに選択された2枚の線形的に混合し、かつラベルも同様に混合することでモデルがより一般化することを狙った前処理手法。元々は画像分類タスクむけに開発された手法ですが、物体検知やセグメンテーションにも活用されています。異なるクラス間の遷移を識別しやすくするメリットがある一方、学習過程の解釈性が低下するデメリットやデータセットによっては非現実的な画像が生成されるためモデルを混乱させるリスクもあります。
:::

https://arxiv.org/abs/1710.09412

![mixup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/41e35c65-d007-79db-901b-6cf441463148.png)

1. 1枚の画像を中央に配置し、ランダムにピックアップした2枚目の画像を左上に配置
2. 混合割合（λ）から正解ラベルの数値を決める
    1. 犬猫データセット（犬のラベル[1, 0]と猫のラベル[0, 1]）においてλが0.6の場合、混合された画像のラベルは[0.6, 0.4]となる。画像は60%犬に似ていて40%猫に似ているように生成する

実際の画像を見てみると、わかりづらいですが正面のおばさんは猫を抱えています。加えて、箱に入った猫もうっすら見えます。ある意味奇跡的な画像ですね。猫被りしている・・・。二つのcatを認識する必要があるのですが、これは難しそう。さらに画像中央左側には果物やボウルが散乱しています。
![000000574769.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/50b007d6-859e-fb52-f533-4d6bf35f5410.jpeg)

MixUpは2枚の画像がベースになっているので、その前提でそれぞれの画像を確認する必要があります。他の画像も注意深くみると2枚の画像が重なっていることがわかります。MixUpだけでも直感的に認識しづらい画像となることがわかります。valの結果が良ければ文句は言わないことにしましょう。

|![000000554625.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/504da429-6b57-7594-ed2e-14cdd7d276ff.jpeg)|![000000522418.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/8938f0e1-ffbf-070f-de17-706506a3c809.jpeg)|![000000391895.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/ced8c828-9048-69a3-def5-68147c112879.jpeg)|
|-|-|-|
|![000000318219.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/2f805ce8-fc62-62a5-ae98-d8972b1d17fe.jpeg)|![000000309022.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/772927b7-1a27-dc9f-2412-0be1d651e375.jpeg)|![000000222564.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/81eeb19c-d573-d1c7-4fd6-0da6d7087bfa.jpeg)|![000000184613.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/bc3f00ce-fba5-bd65-eea4-addabf754a2e.jpeg)|
|![000000118113.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/3aa248c5-8501-aad2-1a12-d7ea867b15f1.jpeg)|![000000060623.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/afbe49ee-3682-9486-c52c-b4dcac132b8d.jpeg)|![000000005802.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/ee2cd175-7fd3-a73b-59f2-b3bdb858fa37.jpeg)|


### 6. RandomAffineだけ入れた場合

RandomAffineについては、回転させているだけなので珍しい手法ではないですが、YOLOXでは`scaling_ratio_range=(0.1, 2)`となっており、最小で10%に縮小/最大で2倍に拡大している。transformの出現確率が100%であることも特徴です。

![000000005802.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/28261955-74e3-808a-105d-5d89086826af.jpeg)

COCO2017の矩形はかなり小さいものもあるので、10%まで小さくしてしまうと数pxくらいしか残らないラベルも中にはある可能性があり、それらはほぼ認識無理なものとなっていることは予想がつきます。このscaling_ratio_rangeのハイパラ調整時に精度1番良かったのが今の(0.1, 2)に落ち着いたということなのでしょうか。

|![000000574769.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/eb33b1e2-8d24-a90d-3286-c91df8f529c9.jpeg)|![000000554625.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/ecf7d4ed-e92e-9024-4d05-b5eb437390be.jpeg)|![000000522418.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/c59dd16d-420d-e556-ee39-0211ad7d00d1.jpeg)|
|-|-|-|
|![000000391895.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/9b2ead3d-acb9-fa8f-5385-d175bd68935b.jpeg)|![000000318219.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/9133b0d7-7ea1-568b-eb80-1c1c3c4faf12.jpeg)|![000000309022.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/bfe4aee8-7d3b-03eb-ae49-0197e4de1edb.jpeg)|
|![000000222564.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/0ac7ffdf-6811-337a-03e2-b77fe30bcd50.jpeg)|![000000184613.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/b65d2e25-c2c0-2b78-7be1-325974b62231.jpeg)|![000000118113.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/9e4479ab-06f4-5dba-bf19-73bbc55ce5ef.jpeg)|![000000060623.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/f26dfa22-8467-8f65-4a97-0df4f5dbbac6.jpeg)|


### 8. YOLOXHSVだけ入れた場合

:::note info
Hue（色相）, Saturation（彩度）, Value（明度）を調整するための前処理。モデルが異なる照明条件や色のバリエーションに対してロバスト性を上げるための調整。
:::


|オリジナル|HSVtransform後|
|-|-|
|![000000574769.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/4c65ab89-b51f-197e-8054-a12df8dfccee.jpeg)|![000000574769.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/12c71d98-f51a-5ab3-bb97-7aa776213d7e.jpeg)|
|![000000554625.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/22c9e329-c02b-af5f-222a-e46489f20316.jpeg)|![000000554625.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/b149c5e8-379b-0335-346d-7741c13111bf.jpeg)|
|![000000522418.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/b1d1b7ec-3444-14fd-1a29-b7455008f285.jpeg)|![000000522418.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/1f743ec9-0406-3049-4ae2-7e41ffed3b25.jpeg)|
|![000000391895.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/e7fd7e24-9e3c-10d5-964d-ae4cdaacdbac.jpeg)|![000000391895.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/c0606958-c01f-a96d-6280-1f1b45da7a7a.jpeg)|
|![000000318219.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/efe7397e-3fcf-4acf-d880-dc2a44670c81.jpeg)|![000000318219.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/19c6aee0-22c8-be9c-66ab-6cf664f3163c.jpeg)|
|![000000309022.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/2a7db378-f092-4520-db5a-acbf409ef313.jpeg)|![000000309022.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253735/9a6bf48a-217b-d9c2-7743-5fd8ce5d7270.jpeg)|

本当はHueを弱〜強と変化させた場合の画像の変化をグラデーションのようにして並べた方がわかりやすいような気もしますが、HueやSaturation, Valueを少し変えるTransformがYOLOXには入っていることがわかれば十分のような気がするので割愛します。


## まとめ

YOLOXで用いられているTransformを理解することは、チューニングする上でとても重要。COCO2017データセットではこれらの前処理が全体の精度を上げることに貢献しています。とはいえ、別のデータセットを用いて転移学習させた場合でもうまくいくかどうかはわかりません。個人的にはMixUpが難解でこれを思い切って外してみても良いような気もしています。