SIGNATE 超解像度コンペ 6位解法【Axell AI Contest 2024】

株式会社アクセルが主催する超解像度化コンペに参加し、最終6位(金メダル)を獲得しました。コンペの参加者は266人でした。

![GWbnRgBXEAAk7gH.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557909/ae49211b-4d5c-c937-8cf9-93ab8ec17d31.jpeg)


## コンペ概要
今回参加したのはSIGNATEにて行われた「[Axell AI Contest 2024](https://signate.jp/competitions/1374)」というコンペです。
特設サイト：

https://ailia.ai/contest/

本コンペは、配布された自然画像データセット(851枚のトレーニングデータ + 100枚のテストデータ)に対して、4倍超解像モデルの精度を競うものでした。開発したモデルは、ONNX形式に変換して提出する必要があります。加えて、リアルタイムでの実用化を目指す背景から、推論時間に以下の制限がありました。
> SIGNATEのプラットフォーム上で0.035sec以内に超解像処理を完了させるモデルを必須条件としています。

そのため、Swin2SRといった巨大なモデルは使えません。この制限が非常に面白く、工夫のしがいがありました。

また、評価指標は[PSNR](https://qiita.com/toshi_machine/items/3ff0a09279a8e71c4e82)が採用されました。

## 参加のきっかけ
大学院にて画像認識(セマンティックセグメンテーション)を用いた研究をしており、知見をもとに何かのコンペに出たいと思っていたところ、本コンペを見つけました。

## 解法概要
- モデル：EDSR
- 外部データ：
    - DIV2KとFlickr2Kを追加
    - 人が主要な被写体の画像を除外
- データ拡張：
    - 1-400epoch：水平反転 + 外部データ
    - 401-500epoch：水平反転 (外部データなし)

具体的なコードは以下にて公開しています

https://github.com/Koichi73/Axell-AI-Contest

## 解法詳細
### モデル
[EDSR](https://arxiv.org/abs/1707.02921)を採用しました。シンプルで拡張性が高く、パラメータ数を調整しやすいためです。最終的な構成は以下のようになりました。

![edsr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557909/a2a423ce-4990-a696-376b-cd69c0be0eb0.png)

運営提供のサンプルコードではESCPNを使っていましたが、EDSRを使うことで精度を大幅に向上させることができました。

### 外部データの使用
本コンペは外部データの使用が認められていたので、[DIV2K](https://data.vision.ee.ethz.ch/cvl/DIV2K/)と[Flickr2K](https://www.kaggle.com/datasets/daehoyang/flickr2k)を追加しました。
その際、運営より配布されたデータには人が主要な被写体として含まれていなかったため、追加した外部データの調整を行いました。

![external-data.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557909/44dab0d7-cde2-13e4-20e7-9352d6d3b038.jpeg)

具体的には、YOLOv5を用いて人物検出を行い、画像内における人の占める割合が閾値(今回は0.1)を超える画像を除外しました。これにより、精度向上に繋がりました。

### データ拡張
基本的に、水平反転のみ行いました。配布データが標準的な向きの画像だったため、垂直反転は不要と判断しました。
しかし、反省点として、回転は加えた方が良かったと思います。理由は以下の2つです。
- 検証データ内に90度傾いた画像が2,3枚含まれていた(コンペ中は少量と見なして無視してしまった)
- DIV2Kなどをのデータセットでも、回転を加えたデータ拡張が一般的である([参考](https://engineering.dena.com/blog/2019/09/cv-papers-19-single-image-super-resolution-1/#Augmentation))

また、学習の途中からは外部データを使用せず、配布データのみで行いました。これにより、最後まで外部データを使用した場合よりも精度を上げることができました。

### その他
- 学習率はWarmup付きCosine Annealingでスケジュールしました
- ONNX形式に変換する際、FP16で保存することで、推論速度をあげました
- 損失関数はMSELoss(L2誤差)を使いました。L1誤差よりもうまくいきました

## うまくいかなかったこと
### Wavelet変換
最も期待した改善策でしたが、時間切れもあり、精度向上には至りませんでした。

アイデアの元となった論文↓
[ニューラルネットワークを用いた単一画像超解像のウェーブレット変換による高速化](https://ipsj.ixsq.nii.ac.jp/ej/?action=pages_view_main&active_action=repository_view_main_item_detail&item_id=212269&item_no=1&page_id=13&block_id=8)

ざっくりまとめると
- Wavelet変換を用いた画像処理によって、画像は1つの低周波成分と3つの高周波成分に分解される。この時、各成分のサイズは元画像の縦横1/2になる
![Wavelet変換.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3557909/640b21c3-3b92-c7dc-b23f-86fbcb0b8505.jpeg)

- これをSRCNNモデルに導入すると、高精度化と高速化に繋がったことが報告されている
- そこでSRCNNより高性能なEDSRで試したところ、Wavelet変換を行う前と同程度の精度を保ちながら、大幅な高速化に成功した

Wavelet変換は[Pytorch Wavelets](https://pytorch-wavelets.readthedocs.io/en/latest/index.html)というライブラリを使って実装し、先ほどのEDSRに組み込みました。すると、推論時間は短くなったものの、精度は低下してしまいました。また、短縮した推論時間分EDSRのパラメータを増やしても、Wavelet変換なしの精度を越すことはできませんでした。

(モデルのコードを供養しておきます)
https://github.com/Koichi73/Axell-AI-Contest/blob/main/src/models/edwsr.py

### CutMix
データ拡張として試したのですが、精度向上に繋がりませんでした。[参考にした記事](https://hack.nikkei.com/blog/solafune202304)のように衛星画像では有効ですが、今回のデータには異なるエリアが混ざるようなものがなかったため、うまくいかなかったと考えています。

### 知識蒸留
事前学習済みの[Swin2SR](https://huggingface.co/caidas/swin2SR-classical-sr-x4-64)を教師モデル、自作のEDSRを生徒モデルとして行いましたが、精度は改善せず、学習が遅くなったので不採用としました。

## その他
3位解法

https://github.com/HKodai/Axell2024

## 参考にしたサイト(一部掲載)
衛星画像の超解像コンペで1位

https://hack.nikkei.com/blog/solafune202304

精度向上の方法まとめ

https://qiita.com/okateru/items/7e537a3e10cc3f107291

論文まとめ

https://qiita.com/jiny2001/items/e2175b52013bf655d617

https://engineering.dena.com/blog/2019/09/cv-papers-19-single-image-super-resolution-1/

## 最後に
初めてのコンペで金メダルを獲得でき、とても嬉しいです。コンペ開始まで超解像度については何も知らなかったので、新しいことを学びつつ、楽しく挑戦できました。
これからもkaggleを含めた様々なコンペに参加していきます。