Kaggle Bengali Classificationコンペに参加した記録
KaggleのBengali.AI Handwritten Grapheme Classificationコンペに参加して24位(2059チーム中)でソロ銀メダルを取れました。ついでにkaggle expertになりました。
以下ではその記録についてまとめます。
本記事の概要
- コンペ概要
- 私の取り組み
- 興味深かった上位ソリューション
- 感想
コンペ概要
Bengali.AI Handwritten Grapheme Classification | Kaggle
タスク概要
データ
- 入力データ:手書きのベンガル語1文字の画像データ。
- 予測対象データ:書式素、母音、子音のラベル。
- 学習データ数200840。 Bengali - Quick EDA | Kaggle
- 入力データ:手書きのベンガル語1文字の画像データ。
予測性能の評価方法
- 書式素、母音、子音それぞれのマクロリコールを0.5、0.25、0.25で重みづけ平均したものが評価値。
- 書式素、母音、子音それぞれのマクロリコールを0.5、0.25、0.25で重みづけ平均したものが評価値。
スタンダードな解法
- 解法(1):CNN系統の画像分類器で画像から書式素(169クラス)、母音(11クラス)、子音(7クラス)それぞれのラベルを予測する。
- 解法(2):CNN系統の画像分類器で画像から文字のラベル(1295クラス)を予測する。学習データ中には書式素、母音、子音の組合せが1295パターンあったため1295クラス。ただし、実際のベンガル語では当然他の組合せも存在する(169×11×7パターン?)。
- 解法(1):CNN系統の画像分類器で画像から書式素(169クラス)、母音(11クラス)、子音(7クラス)それぞれのラベルを予測する。
大規模なshake
- このコンペでは大規模なshakeが発生し、一部のトップ層を除いて、Public LBとPrivate LBの順位が激しく入れ替わった。原因は、学習データに含まれていない書式素、母音、子音の組合せがテストデータに多く含まれていたことである。上記の解法(2)のような学習データ中に存在している組合せに適合する方法を採用していた人は、Public LBではいいスコアであったが、Private LBでは大幅に下落した。トップ層は学習データに含まれている組合せに適合させつつ、見えていない組合せもケアする工夫をしていたので、Public LBでもPrivate LBでもいいスコアであった。ほんますごい。
- 僕はこの恩恵にあずかってshakeupし、銀メダルになった。Public LBではメダル圏外で完全にあきらめていたので心底びっくりした。
https://www.kaggle.com/c/bengaliai-cv19/leaderboard
- このコンペでは大規模なshakeが発生し、一部のトップ層を除いて、Public LBとPrivate LBの順位が激しく入れ替わった。原因は、学習データに含まれていない書式素、母音、子音の組合せがテストデータに多く含まれていたことである。上記の解法(2)のような学習データ中に存在している組合せに適合する方法を採用していた人は、Public LBではいいスコアであったが、Private LBでは大幅に下落した。トップ層は学習データに含まれている組合せに適合させつつ、見えていない組合せもケアする工夫をしていたので、Public LBでもPrivate LBでもいいスコアであった。ほんますごい。
私の解法
私の解法は以下のとおりです。基本は上記の解法(1)で、工夫した点は評価値であるマクロリコールに最適化するために実数値遺伝的アルゴリズムを使ったところです。
コード
概要
Discussionにもsolutionをあげましたが、ここでは日本語をのせておきます。(下手な英語だから理解してもらえているのかかなり不安。。笑)
https://www.kaggle.com/c/bengaliai-cv19/discussion/136064
私のソリューションでは、単純なアンサンブルモデルと、マクロリコールを最大化するための後処理を使いました。後処理では、モデルが出力したlogitにバイアスを足します。後処理が私のスコアの多くを占めており、後処理なしではメダル圏外でした。
Inference Label
まず、DL modelでlogitを出力します。後処理として、logitにバイアスを加えます。それをargmaxしたものを推定ラベルとします。
Model
モデルは5つのモデルをアンサンブルしたものです。学習にはトレーニングデータをすべて使いました。私の時間と計算資源が限られていたので、クロスバリデーションをほとんどできていません。
model 1, 2, 3, 4
- Seresnext50_32x4d (pretrained model using imagenet)
- image size 128x128
- Three linear head (output is grapheme root logit(168), Vowel diacritic logit(168), Consonant diacritic logit(168))
- Mish activation, Drop block
- Cross Entropy Loss
- AdaBound
- 以下のパラメータをモデル毎に変える
- Manifold mixup (alpha, layer), ShiftScaleRotate, Cutout
- Manifold mixup (alpha, layer), ShiftScaleRotate, Cutout
- Seresnext50_32x4d (pretrained model using imagenet)
model 5
- Seresnext50_32x4d (pretrained model using imagenet)
- image size 137x236
- Three linear head (output is grapheme root logit(168), Vowel diacritic logit(168), Consonant diacritic logit(168))
- Mish activation, Drop block
- Cross Entropy Loss
- AdaBound
- Manifold mixup (alpha, layer), ShiftScaleRotate, Cutout
- Seresnext50_32x4d (pretrained model using imagenet)
後処理のバイアスの計算
モデルはCross Entropy Lossで学習されているので、一般的にマクロリコールを最大化しません。そこで、私はlogitに加えることでマクロリコールを最適化するようなバイアスを使うことを考えました。最適なバイアスを以下の手順で計算しました。
- 学習データ全てに対してlogitを計算する。
- 実数値遺伝的アルゴリズムでマクロリコールを最大化するバイアスを計算する。
- データ拡張した学習データ全てに対してlogitを計算する。
- 実数値遺伝的アルゴリズムでマクロリコールを最大化するバイアスを計算する。
- 上記のバイアスを平均し、最終的なバイアスとする。
テストデータの推定では、学習データで算出したバイアスを使います。
実数値遺伝的アルゴリズムについてはこちらのページを参考にしてください。
st1990.hatenablog.com
Score (Public LB / Private LB)
- model1(wo bias) : 0.9689 / 0.9285
- model2(wo bias) : 0.9680 / 0.9270
- model3(wo bias) : 0.9691 / 0.9317
- model4(wo bias) : 0.9681 / 0.9243
- model5(wo bias) : 0.9705 / 0.9290
- ensemble1~5(wo bias) : 0.9712 / 0.9309
- ensemble1~5(with bias) : 0.9744 / 0.9435
興味深かった上位のソリューション
- 学習データに存在しない書式素・母音・子音の組み合わせに対応するための工夫。
- Arcfaceを使って学習データに存在しない組み合わせを検知し、存在するしないで別のモデルを使っていた。https://www.kaggle.com/c/bengaliai-cv19/discussion/135982
- 存在しない組み合わせの場合はCycle GANで既存のベンガル語フォントに変換。変換したものをベンガル語フォントの分類モデルにいれてクラス分類していた。既存のベンガル語フォントは外部データを使用。https://www.kaggle.com/c/bengaliai-cv19/discussion/135984
- マクロリコールのハック。https://www.kaggle.com/c/bengaliai-cv19/discussion/136021
- Arcfaceを使って学習データに存在しない組み合わせを検知し、存在するしないで別のモデルを使っていた。https://www.kaggle.com/c/bengaliai-cv19/discussion/135982
上位はかなり工夫しててソリューションみるのも楽しかった。
まとめ
https://www.kaggle.com/c/bengaliai-cv19/discussion/136030
感想
- パラメータチューニングやモデルの構造など細かいところに時間をとってしまい、問題の特性を踏まえた大局的な取り組みができなかったのが反省。評価値について考察し、それに最適化させる方法を考えられたのは良かった。
- 今回のコンペの上位ソリューションは発想が素晴らしかった。問題についてよく考えて人と違う発想をしないと勝てないってことがよくわかった。