はじめに
前回は、顔キーポイント座標回帰モデルに対して、
- prediction可視化
- worst sample分析
- 部位別誤差分析
- 左右反転augmentation
を行い、モデルがどのような画像・部位で失敗しやすいのかを確認しました。
その結果、
- 口周り
- 眉外側
- 鼻先
などで誤差が大きいことがわかりました。
また、左右反転augmentationは今回の単純CNNでは改善が見られなかったため、不採用としました。
今回はその続きとして、
- Brightness Augmentation(明るさ調整)
- Contrast Augmentation(コントラスト調整)
を追加し、
- 薄い眉毛
- 暗い顔
- 低コントラスト画像
への耐性向上を試してみました。
この記事でやること
この記事では、以下の内容を扱います。
- Brightness Augmentationを追加する
- Contrast Augmentationを追加する
- validation lossの変化を見る
- 部位別誤差の変化を見る
- Kaggle提出スコアを比較する
- augmentationを採用するか判断する
前回までの状態
前回までに作成したベースラインCNNでは、以下の結果でした。
| 指標 | 値 |
|---|---|
| Public Score | 3.59348 |
| Private Score | 3.56800 |
| Best Validation Loss | 0.00046 |
今回のKaggleコンペでは、スコアは小さいほど良い評価になります。
なぜBrightness / Contrastを試したのか
前回の誤差分析では、特に以下の部位で誤差が大きくなっていました。
誤差が大きかった部位
mouth_left_cornermouth_right_cornermouth_center_bottom_lipeyebrow_outer_endnose_tip
また、失敗例を確認すると、
- 眉毛が薄い
- 顔全体が暗い
- コントラストが低い
といった画像が比較的苦手そうでした。
顔キーポイント検出では、
- 輪郭
- エッジ
- 明暗差
が重要になります。
そのため、照明条件や画像の濃淡を変化させるaugmentationを入れることで、モデルの汎化性能を改善できる可能性があると考えました。
Brightness Augmentationとは
Brightness Augmentationは、画像全体を明るくしたり暗くしたりすることで、学習データの見た目のバリエーションを増やす方法です。
顔画像であれば、たとえば以下のような状況にモデルを慣れさせる目的で使えます。
- 照明が強く、顔が明るい画像
- 部屋が暗く、顔が見えにくい画像
- 逆光気味の画像
目的
モデルが画像全体の明るさに引っ張られすぎず、顔の形や目・眉・鼻・口などの構造を安定して見るようにすることが目的です。
今回の顔キーポイント検出では、
- 暗い顔
- 薄い眉
- 光の当たり方が違う画像
への対策として有効そうだと考えました。
Contrast Augmentationとは
Contrast Augmentationは、画像の明暗差を強くしたり弱くしたりするデータ拡張です。
コントラストを上げると、
- 黒い部分はより黒く
- 白い部分はより白く
- 輪郭や影はよりはっきり
見えるようになります。
逆にコントラストを下げると、全体的にぼんやりとした画像になります。
目的
モデルが画像のくっきり具合に依存しすぎず、多少ぼやけた画像や薄い顔画像でも特徴点を推定できるようにすることが目的です。
顔キーポイント検出では、特に以下のようなケースへの対策として有効そうだと考えました。
- 眉が薄い
- 目元の影が弱い
- 顔全体がのっぺりしている
- 撮影条件によって濃淡が変わる
一言で整理すると、
- Brightnessは「画像の明るさ」を揺らす処理
- Contrastは「画像の濃淡の強さ」を揺らす処理
です。
どちらも、撮影条件に振り回されにくいモデルにするための前処理として使います。
実装
今回は、学習時のみBrightness / Contrast Augmentationを適用しました。
validationデータにはaugmentationを適用せず、元画像に近い条件で評価しています。
これにより、学習時のデータ拡張が評価条件を変えてしまわないようにしています。
import torchvision.transforms as T
train_transform = T.Compose([
T.ToPILImage(),
T.ColorJitter(
brightness=0.2,
contrast=0.2
),
T.ToTensor()
])
val_transform = T.Compose([
T.ToPILImage(),
T.ToTensor()
])
Dataset側では、transform を受け取れるように修正しました。
class FacialKeypointDataset(Dataset):
def __init__(self, df, transform=None):
self.df = df.dropna().reset_index(drop=True)
self.transform = transform
def __getitem__(self, idx):
...
if self.transform is not None:
image = self.transform(image)
return image, keypoints
学習データのみaugmentationを適用します。
train_dataset = FacialKeypointDataset(
train_part,
transform=train_transform
)
val_dataset = FacialKeypointDataset(
val_part,
transform=val_transform
)
Validation Loss比較
Before
Epoch 30/30
train_loss: 0.00123
val_loss: 0.00046
best_val_loss: 0.00046
After
Epoch 30/30
train_loss: 0.00112
val_loss: 0.00041
best_val_loss: 0.00041
Validation Lossは以下のように改善しました。
0.00046 → 0.00041
改善率としては、約10.9%です。
(0.00046 - 0.00041) / 0.00046 ≒ 10.9%
部位別誤差比較
改善した部位
nose_tip
left_eyebrow_outer_end
right_eyebrow_outer_end
mouth_left_corner
mouth_right_corner
特に、前回課題だった
- 眉外側
- 口角
- 鼻先
で改善が見られました。
悪化した部位
一方で、
mouth_center_bottom_lip
left_eye_inner_corner
など、元々誤差が小さかった部位では若干の悪化も見られました。
つまり、全ての部位が改善したわけではありません。
今回の結果は、
苦手だった部位の改善量が大きかった
と見るのがよさそうです。
Kaggle提出結果
このコンペでは、スコアは小さいほど良い評価になります。
Before
| Score | 値 |
|---|---|
| Public | 3.59348 |
| Private | 3.56800 |
After
| Score | 値 |
|---|---|
| Public | 3.36349 |
| Private | 3.28890 |
Public / Private の両方で改善しました。
考察
Brightness / Contrast Augmentationは、
- 薄い眉
- 暗い顔
- コントラストの低い顔
への耐性向上に寄与した可能性があります。
特に、前回の誤差分析で弱点だった
- 眉外側
- 口角
- 鼻先
が改善していることから、照明変化に対する汎化性能が向上した可能性があります。
また、PublicだけではなくPrivateも改善しているため、少なくとも今回の提出結果では、Public側だけに偏った改善ではありませんでした。
そのため、Leaderboard上の偶然だけではなく、汎化性能の改善につながった可能性があると考えています。
今回の結論
今回の結果から、Brightness / Contrast Augmentationは採用することにしました。
| 手法 | 結果 |
|---|---|
| 左右反転augmentation | 不採用 |
| Brightness / Contrast Augmentation | 採用 |
左右反転augmentationでは改善が見られませんでしたが、Brightness / ContrastはValidation LossとKaggle Scoreの両方で改善が確認できました。
次にやる予定
Brightness / Contrastによって、照明変化への耐性はある程度改善しました。
次は、ピンぼけや軽微な解像度低下への耐性を追加するために、Blur Augmentationを検証する予定です。
その後、augmentationの結果を踏まえて、CNN本体の強化も進める予定です。
今回の学び
今回の実験から、以下のことがわかりました。
- augmentationは、誤差分析から仮説を立てて選ぶと効果を確認しやすい
- 顔キーポイント検出では、明るさやコントラストの違いが予測精度に影響する
- 全ての部位が改善しなくても、苦手部位の改善が大きければ全体スコアが改善することがある
- validation lossだけでなく、Public / Private Scoreも合わせて見ると判断しやすい
まとめ
今回は、
- Brightness Augmentation
- Contrast Augmentation
を追加して検証しました。
結果として、
- Validation Loss改善
- Public Score改善
- Private Score改善
が確認できました。
前回試した左右反転augmentationでは改善が見られませんでしたが、Brightness / Contrastは今回のモデル・データセットでは有効なaugmentationとなりました。
次は、ぼやけた顔画像への耐性向上を目的として、Blur Augmentationを試していきます。