search
LoginSignup
10

More than 1 year has passed since last update.

posted at

updated at

Kaggle振り返り PetFinder.my - Pawpularity Contest

初めに

 この記事は2021年から2022年にかけて開催された「PetFinder.my - Pawpularity Contest」の内容を振り返るために書いています。開始1か月後から参加し、私の結果は、114 / 3537 (Solo silver medal, Leaderboard) でした。

Kaggle に コード を公開していますので、ご興味のある方は是非。

top.png

PetFinderコンペについて

概要

 2020年にも開催されたPetFinderコンペです。今年のお題は PetFinder.my にて掲載されている犬 or 猫の写真のページビュー(統計処理あり)を当てることでした。コンペではページビューのことを「Pawpularity」と呼んでいました。
 Petfiner.my には捨てられた犬や猫の写真が掲載されています。Pawpularity を正確に予測するモデルを構築することによって、どのような写真を撮影すればクリック数が多くなるのか/少なくなるのかが分かるようになります。これにより、犬や猫の里親が早く見つかることに貢献できます。ちなみに、前回コンペは、里親が見つかるまでの早さを直接的に予測するコンペでした。

データと評価方法

 与えられたデータは、画像データ(9,912枚)と、CSVデータです。今回も Code competition であり、テストデータは数枚だけ提供されている状況でした。しかし、今回のテストデータは完全なノイズ画像/ランダムな数値の CSV となっていたため、テストデータに関する情報は一切与えられていませんでした。Metrics は RMSE でした。

以下にデータの詳細を記載します。

  • 画像データ
    犬と猫の画像データです。1枚の画像の中に複数の犬/猫が写っているケースや、文字情報(性別、年齢等)が記載されているケース等がありました。全てのデータを見たわけではないですが、犬か猫のどちらかが写っていると思われます。
  • CSVデータ
    各画像データに対するメタデータです。メタデータは12列あり、目が写っているか、写真がぼやけているか等の項目に対して 0 or 1 の値が入力されていました。1 が該当を意味します。最後の13列目が Pawpularity です。これは、0~100 の値を取ります。

提出したアプローチ

 最終的には、Pseudo Label による Semi-Supervised Learning を実施したモデル + 通常の手法で学習を実施したモデル、計7モデルのアンサンブルを提出しました。Pipeline は以下の通りです。

pipeline.png

 図中に出てくるモデルの正式名称及び timm での設定名称(利用したPre-trained model)は以下の通りです。上図の中央上に出てくる「Pre-trained weight」を入力している3モデル以外は、timm の Pre-trained weight を利用しています。これらのモデルは timm のサイトに掲載されている 精度表 を基に、Kaggle の GPU 環境に乗るアルゴリズムを選定しました。アルゴリズムの詳細は今回の記事では割愛します。

  • Swin: Swin Transformer, swin_large_patch4_window7_224_in22k / swin_large_patch4_window7_224 , paper
  • EffNet: EfficientNet, tf_efficientnet_b5_ns, paper
  • ViT: Vision Transformer, vit_large_patch16_224, paper
  • BEiT: BERT Pre-Training of Image Transformers, beit_base_patch16_384 , paper
  • CaiT: Class-Attention in Image Transformers, cait_s24_384, paper

 以下で詳細を説明する Semi-Supervised Learning 以外の学習は、KFold = 4 で実施しています。また、全ての推論は TTA1 = 2 で実施しています。そのため、実際の推論は各モデル 4 * 2 = 8 推論している計算です。
 Transformer 系のアルゴリズムは、画像の入力サイズが固定されているため、timm の Weight の名称に付いている画像サイズを利用しています(例:swin_large_patch4_window7_224 は、画像サイズ 224)。EfficientNet は画像サイズ 512 で学習しています。
 次の章からパイプラインの詳細及び Tips を書いていきます。

詳細

Semi-Supervised Learning

 2020年に開催された PetFinder コンペがあったため、過去データを使って Pseudo Label を作成しました。作成手順は色々あるようですが、基本的には、まずは現コンペのデータで1つ以上のモデルを学習させることから始めます。次に、正解ラベルを保有していない別データに対して推論を行い、疑似ラベル(Pseudo Label)を取得します。
 クラス分類系のタスクであれば、出力が確率になっているため、例えば、別データに対して推論した結果、確率 0.9 以上のデータを採用する、といったように、比較的推論結果が合っていると思われるデータを利用することが出来ます。しかし、今回の出力は、0~100 の値をとる連続値データであったため、この方法が使えません2。そのため、こちら の TensorFlow Speech Recognition Challenge 3rd place solution を参考に、Semi-Supervised Learning を実施しました。Discussion の中で2つの方法が紹介されています。1つ目は、学習データとして「100% of training data + 20%-35% of test data selected per epoch」を利用する方法、2つ目は「100% of test data」を利用する方法です。どちらも試した結果、精度向上が出来た2つ目の方法を採用しました。
 Pipeline の図を見てわかるよう、Semi-Supervised Learning を実施したのは、Swin と EffNet だけです。この2つのモデルは精度向上が出来たのですが、例えば、BEiT を同じ手順で学習させると、通常の学習手法(現コンペのデータで普通に学習)より、精度が悪化しました。ViT、CaiT で試す時間はなかったのですが、こちらも同じ傾向になる可能性があったため、最終的には Swin と EffNet でのみ Semi-Supervised Learning を実施しました。

Swin Transformer + Image + Meta data

 Semi-Supervised Learning で学習した Pre-Trained weight をベースに、Meta data を加えて Fine-tuning を実施しました。アーキテクチャは下図の通り大きく2パターンを考えました。ただ、パターン1だと画像自体に改良を行うため、学習した表現が壊れてしまう恐れがありました。そのため、パターン2を採用し、低めの学習率で数エポックだけ学習を実施しました。Meta data との結合部分は、結合だけでなく足し算や掛け算等でもOKです。色々試した結果、精度が良かった足し算を採用しました。

archtecture.png

 ちなみに、パターン1と2の両方実施するのもありです。Semi-Supervised Learning ではなく、通常の Pre-trained weight を使って学習する場合は、両方実施したケースが一番精度が高かったです。

アンサンブル

 今回のコンペで精度向上に繋がった一番の要素は、色々な種類のモデルをアンサンブルすることだったと思います。多くの人が、多種多様なモデルをアンサンブルしていました。私もコンペ序盤にアンサンブルで精度が上がることに気付き、Semi-Supervised Learning の実装を一通り終えた後は、アンサンブル用のモデルを作成していました。
 今回のコンペでは、アンサンブル手法に単純な平均を利用しました。他には 重み付き平均、Stacking 等、アンサンブル手法にも色々種類があります。私も Stacking は実装して、最終提出の2枠に入れた(CV Best)のですが、過学習していたようでスコアが非常に低かったです。銀メダルが取れたのは、もう一つの Public Leaderboard Best でした。

Tips

Pytorch vs FastAI

 今回のコンペでは、FastAI を利用している人が多数いました。私は、コンペ序盤は Pytorch で実装した学習スクリプトを利用して、実験を繰り返していました。その後(約1カ月後)、Public Notebook/Discussion を一通り確認したところ、FastAI の部分以外は同じような実装をしているにも関わらず、精度が高い、という Notebook が散見されました。そこで、Pytorch の実装を全て FastAI に変えて学習したところ、精度改善に繋がりました。
 FastAI には「lr_find」「fit_one_cycle」という強力な手法が提供されています。ir_find は、学習率と Loss の関係性を Plot してくれるため、良い精度に到達する学習率の目星をつけることが出来ます。また、fit_one_cycle は、学習時に学習率を上下させることによって、鞍点(Saddle point)に落ちにくくすることが可能な手法です。今回のデータでは、これらの手法が効いたのだと思います。実装も簡単なので、是非試してみてください。

BCE Loss

 今回のコンペの目的変数は 0~100 の値を取る変数でした。通常ですと、Loss を RMSE 等の連続値を扱うものにすると思います。しかし、今回は 0~100 の値を 100 で割り、0~1 に変換し、BCE Loss(Binary Cross Entropy Loss)を計算するという手法が主流になっていました。Loss を変更しただけで精度向上が確認できたので、これは応用範囲の広い手法だと思いました。

Cross Validation (bin)

 KFold の手法として、今回は Stratified KFold を利用しました。これは、設定した列の値の分布を維持するようにデータを分割してくれる手法です。最初は、Pawpularity を設定し、これの分布を維持するように4つのデータセットに分割をしていました。コンペ終盤、改めて Public Notebook/Discussion を読んでいたところ Pawpularity を Rice Rule で分割した bin で、Stratified KFold しているものがありました。またしても、コードの内容はほぼ同じで、 bin のところだけが異なり精度が高いという現象が起きていたため、私も bin に変更しました。
 Rice Rule は、正規分布のデータに対して bin 数を算出する式であり、他にも Sturges’ Rule や、Square-root Rule 等があります。どれを選ぶかは分布の形と、試行錯誤というところでしょうか。

重複データの削除

 今回のコンペには全く同じ、または、ほぼ同じ画像が数十枚含まれていました。これも Public Notebook/Discussion を見ていて気付いたものです。除外の方法 が公開されており、手法としては、画像の Hash 値を計算して、画像の類似度を計算するものでした。今回私が利用したデータは全て、この処理を実施した後のデータです。

終わりに

 前回参加したNFLコンペ(記事はこちら)から連続しての Kaggle 参加で、銀メダルを獲得することが出来ました。いつも Kaggle の環境しか使わないのですが、銀圏はいけたものの金圏はまだまだ遠い印象です。画像・言語系コンペの上位入賞者の多くは、Cloud 契約して GPU 使ってたりする印象なので、勉強も兼ねて Cloud 使ってみるのもありかなと思い始めています。今年1回ぐらいはやってみようかな。もちろんもっと独自の手法を考えるのも非常に重要ですが。今回も学びの多いコンペでした。参加された皆様、お疲れさまでした。


  1. TTAは、Test Time Augmentation の略です。参考 cifar10 で Test Time Augmentation (TTA) の実験 

  2. 連続値を 10 刻みでクラス化し、分類問題として解くことを試しましたが、精度が非常に低く、向上できる気がしなかったので諦めました。 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
10