はじめに
「GridMix?聞いたことないな」とお思いでしょう。
そりゃそうです。GridMaskとCutMixに感化されて勝手に作った下図のようなAugmentationです。
効果があるかどうかちょっと試してみたので、メモ程度に残しておきます。
概要
目的:なにをしたか
- 上述したGridMixの効果をcifer10で確認した。
- 同系列のAugmentationであるCutMixと比較した。
結論:どうだったか
精度:提案手法(GridMix)の方が微妙に優れる
収束:既存手法(CutMix)が優れる
チューニング:提案手法(GridMix)の方が手間かも
お遊び程度なので半信半疑ですが、最低限のポテンシャルを確認できました。
背景
GridMaskの紹介
最近発表されたData AugmentationにGridMaskというものがあります。下図のように格子状に画像をマスクするような手法で、従来手法であるCutout等よりも優れているとのことです。
※本記事の主題はこの手法の紹介ではなく、これをMixに展開したものの提案となります
引用元論文:https://arxiv.org/abs/2001.04086
CutMixの紹介
これについてはQiita等でも既に様々な方が紹介していますので詳細は割愛しますが、ランダムに画像の一部を切り取り、それを他の画像に張り付けて、面積比率でラベルを与える手法になります。
引用元論文:https://arxiv.org/abs/1905.04899
CutMix ⇒ GridMix へのモチベーション
前からCutMixに少し疑問がありました。
中央近辺の方が情報量が多そうなのに、単純に面積比でラベルを決めて良いものかと。
たとえば、下図は面積比で半分が猫、半分が犬になっているが、これに対してラベルを半々にするのは中々に酷だと思う。私にはワンワンにしか見えない。
⇒よし、じゃあメッシュ状にミックスしてみよう。
と思ったわけです。
アプローチ
共通のモデルで、cifer10のデータセットに対して以下の3ケースで学習をおこなって精度を比較する。
- Augmentation無し
- CutMix Augmentation (既存手法)
- GridMix (提案手法)
###使用するモデル
Conv8層の浅いCNN(not pretrained)
input shape: 32x32x3
###GridMix Augmentation
提案手法は、適当なサイズのグリッドで画像をミックスするという、CutMixとGridMaskの合いの子のようなもの。マスクは基本的には市松模様とするが、確率的に網目模様やMix無しが生じるようにした。
市松模様のみにしてしまうと、ミックス比率がほぼ0.5で一定となり収束が悪かったのでたまにイージーなケースがはいるようにした。網目模様も入れることで、既存手法であるCutMixに近いものも再現できる。
def grid_mixer(img_1, img_2, interval_h, interval_w, thresh=0.3):
#make checkerboad
h, w, _ = img_1.shape
h_start = np.random.randint(0,2*interval_h)
w_start = np.random.randint(0,2*interval_w)
h_grid = ((np.arange(h_start, h_start+h)//interval_h)%2).reshape(-1,1)
w_grid = ((np.arange(w_start, w_start+w)//interval_w)%2).reshape(1,-1)
checkerboard = np.abs(h_grid-w_grid)
#reverse vertical and/or horizontal
if np.random.rand()<thresh:
checkerboard += h_grid*w_grid
if np.random.rand()<thresh:
checkerboard += (1-h_grid)*(1-w_grid)
#mix images
mixed_img = img_1*checkerboard[:, :, np.newaxis]+img_2*(1-checkerboard[:, :, np.newaxis])
mix_rate = np.sum(checkerboard)/(h*w)
return mixed_img, mix_rate
h,w,_=img_1.shape
interval_h = h//np.random.uniform(2, 4)
interval_w = w//np.random.uniform(2, 4)
img, mix_rate = grid_mixer(img_1, img_m_2, interval_h, interval_w, 0.3)
以下のように、少しパラメータが多いのがネック。
グリッドの間隔幅:
グリッド幅が細かすぎると、浅い層でしか拾えなくなりそうなので(cifer-10のデフォルトサイズは32x32なので)、画像が縦横それぞれ2~4分割になるようにセットした。この辺りはモデルにも依存しそうに感じる。
グリッドのアスペクト比も一応ランダムになるようにしているが、効果は未確認。
市松模様~網目模様の切り替え閾値:
30%確率で横方向マスクを除外、30%確率で縦方向マスクを除外するようにしている。
これによって、49%が市松模様、42%が網目模様、残り9%がミックス無しとなる。
結局のところはCutMixなどで使用されるβ分布などの調整と同じようなことをしている。
###学習条件
- Initial Learning Rate: 0.005
- Epochs(lr Schedule): 調整パラメータ
- Optimizer: Adam (beta_1=0.9, beta_2=0.999, decay=0.)
- Batch Size: 128
###結果評価
学習率やスケジュールのパラメータチューニング後、3回実行した平均値を下表に示す。
Case | Epochs | Val_Accuracy | Val_Loss |
---|---|---|---|
No Augmentation | 25 | 0.805 | 0.710 |
CutMix (beta=alpha=0.7) | 32 | 0.841 | 0.505 |
GridMix | 45 | 0.852 | 0.463 |
※epoch数はベストパフォーマンスが出るところで調整している |
GridMixは収束が遅い…。最初の数エポックは切っておいた方がいいかもしれない。
でも精度はちょっと良くなっている。たかだか1ケースではあるが、僅かな可能性を感じる。
#まとめ
結論として、Grid状にCutMixすることで、通常のCutMixよりもよくなる可能性はあります。検証不足ですので、あくまで可能性程度です。
もうすこし色々試さないとなんともいえないところです。もしどなたか気分の乗った人は試してみていただけると泣いて喜びます。もし全然効かなかったら泣いて謝ります。