こんにちは
今回は「Cassava Leaf Disease Classification」というコンペに挑戦しました。
Cassava Leaf Disease Classification
結果はpublic891位からshake downしてprivate1303位という大惨敗です。
まず、どんな目標を立てて取り組んでどうなっかに軽く触れて、コンペへの取組内容と敗北者ソリューションを載せます。それではよろしくおねがいします。
このコンペでの目標
本コンペは運要素が強いと言われていましたが、やることはシンプルな画像分類で評価値も正解率だったためとっつきやすいです。なので、画像タスクの基本的な部分を学ぶということで下記目標を設定して挑戦しました。
- MLOpsを小さく始める
- Hydra
- MLflow Tracking
- (Optuna)
- (Kedro)
- 参考リンク
- Data Augmentationについて理解を深める
- Psuedo-labelingの実装
- TTAの実装
- 銀メダル以上
- ViTを使ってみる
ここでは達成度を完結に書いて、後日余裕があったらそれぞれアウトプットします。
- Hydra
- 導入した
- MLflow Tracking
- 導入した。保存先がD直下からうまくいじれずにもうここで良いやってなった
- Data Augmentation
- 自分で試行錯誤するところまで行かなかったが雰囲気をつかめた
- Psuedo-labeling
- 余裕がなく使いませんでした。
- TTAの実装
- TTachを使った
- 銀メダル以上
- ?
- ViT
- VitではないがDeitを使った学習はした。
コンペの概要
コンペのタイトルを読んで字の如くキャッサバの病気を分類する画像タスクです。
背景
- キャッサバはアフリカ第2の炭水化物供給源
- 過酷な条件でも育てることが可能なため零細農家の収入源
- サハラ以南のアフリカでは少なくとも8割の家庭よう農場で作られている
- ウイルス性の病気が収穫不良の主な原因となる
- 現在は政府が出資する専門家の協力のもと目視でどんな病気にかかっているかを調べている
- コストがかかる
キャッサバの病気を安価に特定し、適切な対処をすることで収穫不良を防ぐことは重要なことのようです。
データについて
- 21367枚のラベル付き画像データ
- 病気は4種類と健康な状態を加えた5カテゴリ
- アノテーションミスが多いらしい1
- image size H:600,W:800
- 事前に揃えてくれていたみたいですがたまにアスペクト比のおかしいものも混ざってました。
- label
- trainとtestの比率はだいたい一緒
label | 数 | 割合 | public |
---|---|---|---|
0 | 1087 | 5% | 4.8% |
1 | 2189 | 10% | 10.6% |
2 | 2386 | 11% | 10.3% |
3 | 13158 | 61% | 60.2% |
4 | 2577 | 12% | 14.1% |
計 | 21397 | - | - |
評価値
評価値はAccuracyなので何枚正解したかで決まります。内訳は下記のようになっています。
- テストデータ 約15000枚
- public約4650枚
- private約10350枚
Leaderbordを見るとかなり団子になっていて、publicは5枚多く正解すると0.001上がってかなり順位が動きます。
取組内容
それでは取組内容に入ります。これまでに述べたように、本コンペはtrainもtestもノイジーなコンペと言われていました。
芋の画像がたくさん有る件
まず実際に画像を見てみると芋の画像がたくさんありました。う○こ画像と自分は呼んでたのですが、まずはこのう○こ画像を学習データから取り除いてみました。
結果、スコアは悪化しました。う○こ画像達のラベルを見てみるとほとんどが1にラベリングされているので、う○こは1であると学習することができ、テストデータにも同様なデータが含まれているのではないかと推測しました。
アノテーションミスデータへの対応
lossfunction
ラベルノイズにうまく対応するための Loss function の候補がいくつか議論されていたのがこのコンペの特徴ではないかと思います。実装については公開ノートとして公開2されていました。私は実際に全部試してみてTaylor Cross Entropy Loss with LabelSmoothing
を採用しました。
trainデータの加工
アノテーションミスが多いことに対して私の方針は、正しくアノテーションされているデータをできるだけ高い精度で予測することでした。
(ミスってるものの正確な推測はあきらめる)
下記2つのソリューションを参考にしました。参考にしておいて散々たる結果になって申し訳ございません。
1.間違っていそうなデータは学習に使わない
全テストデータを複数のモデルで学習したあと、その全モデルからの予測値が著しく悪いものをnoiseデータ、それ以外をcleanデータと分割しました。実際に848枚をnoiseデータにしました。
※誤って正しいアノテーションをされているデータを間引いても大きな問題はないと判断しました
単体の結果では目立った精度向上は見られなかったのですが、最終的にCVの高いアンサンブルには使用されました。
noiseデータを加えてfinetuningしてみた
cleanなデータで学習してからnoisyなデータを含めてfine tuningしてみましたが、最初から全データで学習するよりも悪い結果になりました。
2.明らかに間違っているものはラベルを付け替える
1のアプローチに似ていますが、全モデルが同じ間違いをしているデータにはアノテーションし直しなおしたalangelabelを作成しました。上より慎重に、条件厳しめなので400データほどアレンジしました。
少しだけ精度の向上が見られましたがLBが良くなることもなく、有効なアプローチとは言えませんでした。
※1ではノイズデータの予測も行ってCV計算。2ではoriginal labelを使ってCVを計算しました。
以上2つのアプローチに加えて、画像サイズ、scheduler、epoch数等のハイパーパラメータを調節、複数のmodelアーキテクチャで学習をすることで精一杯でした。あとはoofを使ってアンサンブルしてCVが良いものをsubして、新しいアーキテクチャを試す流れを繰り返しました。
その他
- image size
- 512だと学習時間が長さにみあった精度向上がなかったことから、基本的に384を使いました。
- scheduler
- CosineAnnealingLR
- GradualWarmupSchedulerV2
- epoch数
- 時間の関係で10にしたり、20にしたり、何が最適かはわかりませんでした。
- optimizer
- Adam
- finetuningでSGDを試しましたが冴えない結果でした。
- Adam
- Augmentation
- RandomResizedCrop
- Transpose
- HorizontalFlip
- VerticalFlip
- ShiftScaleRotate
- TTA
- HorizontalFlip
- VerticalFlip
Solution
CVが一番高く、LBもそれなりに良いスコアが出ていたものを提出しました。蓋を開けてみると自分のサブの中でprivateは高い方とは言えないものでした・・・。
続いて、privateが手持ちで唯一銅圏に行っていたものも貼っておきます。これはCVがそこまで良くなく、LBもあえて選ぶほどいいスコアではなかったため提出しませんでした。
最後に自分のCV,LBのスコアを時系列で並べたものも置いておきます。
これを見るとガッツリアンサンブルをし始めた頃からCVだけ上がっていますね・・・。
反省
実験の手数が少なかったことに力不足を感じました。毎回resnext,effnetの2つで試すというのも非効率的だった気がします。実験して、結果を見て、何かを決定して次の実験を決める。ような進め方をすべきなんでしょうか?
実装面では、終盤にArcFaceを導入してみようと思って取り掛かりましたが、「最終そうに差し込むだけ」とあちこちに書いてあるにも関わらずうまく導入できませんでした・・・反省というよりはまだまだだなぁと悔しい思いをしました。 また、discussionでcutmix系が効かないとあったため使わなかったのですが、画像タスクに取り組むには知ってなきゃいけないものなので実装してみるべきでした。
また次がんばります。