collect, analyze, and visualize data
/ produced by Hiroyuki Shinoda
collect, analyze, and visualize data
Article
2024.8.3
Kaggle LEAPコンペ振り返り(Silver / 28th)


・Kaggleやデータ分析初学者向けのチュートリアル解説本を執筆しました。本記事とあわせてご参照くださいませ。

『Pythonで動かして学ぶ!Kaggleデータ分析入門』


・その他のKaggle参戦記事一覧はメニューのKaggle挑戦記事からご参照くださいませ。


はじめに
今回はKaggleLEAPコンペこと、「LEAP – Atmospheric Physics using AI (ClimSim)」の参戦振り返り記事となります。テーブルデータからの気候予測というお題で、データ量が多く非常にCV/LBが安定していることやNNの細かなチューニングの工夫の試し甲斐があるコンペでした。結果はteamでの参加でprivate LB28位でsilverとなりました。本記事では本コンペの取り組みやscore推移、上位ソリューションを振り返っていきます。




| (1) LEAPコンペの概要

本コンペは、緯度経度・時点ごと(緯度経度・時点は伏せられている※詳細補足後述)の気温・比湿度・放射量など556の説明変数が与えられ、その点における風速などの時間変化や降雨量・積雪量など368の目的変数を予測するものとなります。556/368の値は独立ではなく、各点では説明変数・目的変数ともに垂直方向の60次元の値があるものが含まれていました。たとえば気温は垂直方向の60次元の値が与えられており、温度変化は60次元ごとに予測する必要がありました。(説明変数は9個の60次元の値と16個のスカラー値、すなわち9*60+16=556。目的変数は6個の60次元の値と8個のスカラー値、すなわち6*60+8=368)評価指標はr2metricでした。


※図はKaggleコンペページより引用

本コンペのデータは7年分のデータから1/7にサンプリングされたデータが提供されていましたが、そのサンプリングされたデータですら370GBを超える容量のデータとなっており、この点が本コンペの参加ハードルをそれなりに上げていたと思われます。実際にテーブルコンペではあるものの最終的な参加者数は877人と他のテーブルコンペよりも少ない参加者となっていました。さらにサンプリングしていない元のデータも公式のhugging faceページ上にアップされていました(このデータをどのように利用するかは工夫が必要※詳細後述)。ただ環境を整備できたら、本コンペのデータ量はCV/LBの安定をもたらしたためむしろ良い点かと思います。なお本コンペはいわゆる推論時間や推論環境がkaggle上で制限されているコードコンペではなく、予測結果ファイルを提出するコンペでした。


| (2) 本コンペの取り組み

本コンペに取り組むに当たり最初に考えたことは以下のことでした。
・ドメイン知識がどの程度役に立つか
毎コンペごとのことではありますが、ドメイン知識不足で各特徴量の意味が正確にはわかりませんでした。
しかしホスト論文も公開されていましたし、大気シミュレーションに関する様々な公開情報もあり、調べながら特徴量追加を検討することにしました。

・大規模データをどのように効率的に処理するか
kaggle上のtrainデータだけで370GB、さらにhugging face上でその7倍以上のデータが公開されており、
submitファイルすらそれなりの容量になる中でどのようにデータを処理し、学習を効率的に行うか考える必要がありました。
parquet、tfrecordファイルやpolarsの活用、さらに実験管理の工夫についてコンペ中に学んでいきました。

下記が主な取り組みの推移です。(※testデータがコンペ途中に変更されています)
・ホスト論文をもとにまずはベースラインを作成し、1D-CNNレイヤーなどを追加 (public:0.47561 / private:0.47334)
・レイヤー追加、テストデータのweightを学習時に事前にかけ、weight0やppで処理するものは予測対象(loss計算)から除外 (public:0.63315 / private:0.63007)
・残差ブロック、dropout、lstmレイヤーを追加 (public:0.67701 / private:0.67957)
・transformerレイヤーを追加、lstmをbidirectionalに、loss計算のr2scoreのバグ修正 (public:0.71791 / private:0.71627)
・epochを15から70に増加 (public:0.73092 / private:0.72734)
・lossをhuber lossに変更、metricのr2score計算を修正 (public:0.74508 / private:0.74019)

ここでleaderboardで順位の近かった、nikitaさん、tatsuyaさんにお声がけしてチームマージしていただきました。
squeezeformerの利用やdiff特徴量など素晴らしいアプローチであり非常に感銘を受けました。
基本的にはアイデアは共有しつつそれぞれ別のアプローチで取り組み、アンサンブルして提出するということをしていました。
最終的には個人では[public:0.76786 / private:0.76623]、
チームで[public:0.77828 / private:0.77456]となりました。

個人的に最後までうまくいかなかった/活用できなかったのは以下です。
・hugging faceの追加データの活用(オーバーフィット)
・ドメイン知識からの特徴量追加(改善せず)
・特に60次元の目的変数に関する後処理(スムージングなど、改善せず)
後述するとおり、上記の一部は上位解法ではうまく工夫することで改善につなげいるようでした。



| (3) 余談:リーク・コンペの展開

本コンペは気候モデル(E3SM-MMF)による合成データを用いたものでした。
与えられたデータは緯度経度・時間情報はブラインドされており、これらに依存しないモデルを構築することがコンペホストの狙いでした。
※ただし、公式hugging face上の非サンプリングデータでは時間・位置情報を紐づけ可能。テストデータは公式には不可。
しかしテストデータは384個の場所と時間ステップごとに順序付けられていることがわかりました。
さらに今回の気候モデルの合成データでは年に関係なく、時間・位置情報で固定の値が含まれていました。(pbuf_ozone:オゾン量混合比)
よってこの値を用いて時間・位置情報をテストデータに対してもマッピングできるということがわかりました。

本コンペはこれらがコンペ期間中に随時判明していき混乱をもたらしました。おおよそ下記のような展開がありました。
・当初2024/4/19開始、2024/7/2終了のコンペとしてスタート。
 コンペ開始当初から時間・位置情報に依存しないモデルを構築することが主題であることをコンペホストが示唆(ただしルール上で明確に縛ってはいなかった)
・特定の期間(4-9月)の特定位置での予測が困難であることを共有するディスカッションがポスト。

 ※図は上記ディスカッションより引用
・上記のポストに関連して、テストデータにおける時間/位置情報をリバース・エンジニアリングできることを指摘。
 ※384個の場所と時間ステップごとに順序付けされている。
 これらの値を使用することの可否をホストに確認
・ホストがテストデータを再作成したうえでシャッフルして再度公開、モデルの作り直しやsubファイルの作成のために2週間コンペの延長が決定
・延長後のコンペ終了6日前に固定の値を用いて時間・位置情報をテストデータに対してもマッピングできるということが判明
・あらためてコンペホストから、時間・位置情報の使用を禁じることが明示される。
 さらにチーム名で[no leak]を明言したうえで、コンペ終了後、学習/推論コードの提出が求められることに。
・コード提出は最終的に賞金圏内のみに求められた。暫くの間コンペ終了後も解法紹介は不可とされた。
 ※コンペ終了後に、上位解法を参考に学習/推論コードの改善を防ぐため。

あらためて合成データはリバースエンジニアリングできる危うさがあるということ、
コードコンペでないとテストデータに対して様々なハックができるということ、を痛感した次第です。
そして何よりコンペ延長はなかなかに辛いものがありました…。(コンペ6日前の発覚はさらなる延長がくるかとヒヤヒヤしました)



| (4) 上位ソリューション

1位ソリューションは下記のとおりでした。
 
・モデルアーキテクチャ: Squeezeformerブロックを使用。最初の1DconvブロックでLayerNormを削除し、ECA層を追加。TensorFlowで実装。
・モデル構成: 12ブロックモデル(256/384/512次元)。入力データをモデル次元にエンコードするためのdenseとLayerNorm、その後swish denseとGLUMlp(1024/2048次元)。
・ドロップアウト: 初期に使用したが、サンプル数が増えると不要に。削除することでトレーニングが速くなるため削除。
・最適化: AdamW optimizerとcosine reduce scheduler。最大学習率1e-3、重み減衰 = 4*LR。
・損失関数: MAEを使用。収束が速く、安定している。補助損失として、正規化された緯度/経度と日/年のサイクルに対するMAEを使用。
・コンフィデンスヘッド: 各ターゲットの損失を予測。MAEを使用。スコア向上に効果的。
・特徴量のソフトクリッピング: 正規化後の極端な値に対して2段階のソフトクリッピングを適用。

squeezeformerは過去コンペのASLFRやRibonanzaで有効、confidence headはRibonanzaで有効だったようです。

squeezeformerはCNNとTransformerの利点を組み合わせたアーキテクチャであり、
効率的なパラメータ数で優れた性能を発揮することが知られています。
まず入力データに対して畳み込み層とSqueeze-and-Excitation(SE)ブロックを通過させ、重要な特徴を抽出し重要でない特徴を抑制します。
その後、transformerベースのアテンションメカニズムを用いて、時系列や文脈情報を考慮した特徴抽出を行います。

confidence headはモデルが各ターゲットの予測に対してその自信度(confidence)を予測するための追加のヘッド(層)です。
各ターゲットの予測に対する誤差(損失)を予測するように設計されており、この損失を予測するためにMAE(平均絶対誤差)が使用されているようです。

その他、hugging face上の高解像度データを使用したようですが、その際には、低解像度のデータと高解像度のデータを2:1でブレンドするとともに
ソフトクリップングの処理が必要で、そうでないと安定せず悪化するとのことでした。



| (5) おわりに

本コンペを3つの観点から振り返りたいと思います。

・チームマージの重要性
これまで私は特にこだわりがあるわけではないもののソロ参加が多かったのですが(2人チームはしばしば)今回初めて3人チームで参加しました。
言うまでもないですがチームで参加することには様々なメリットがあります。
まずは同じ問題に対して他の人のアプローチをコンペ中に知ることができるのは大きなアドバンテージとなるだけではなく学習という意味でも大変有用です。
また、私の場合はチームへの共有や彼らのアイデアを取り入れるために自分のコード/パイプラインを見直すきっかけになりました。
何より今回たまたまNikitaさん、Tatsuyaさんと参加しましたが彼らの素晴らしいコードとリザルト、そして彼らのハートフルなコミュニケーションは
今回のカオスな展開のコンペの中で自分が最後までスコアを上げることにチャレンジし続ける大きなモチベーションになりました。

・継続的にKaggle参加する重要性
本コンペは直接的に過去のコンペが関係はしていないものの、過去コンペの上位ソリューションで使われていたいくつかのテクニックやアーキテクチャが有効でした。
継続的にKaggleコンペに参加することはもちろん、上位ソリューションをもとに自分の環境にコードを整理して、
いつでも使えるようにしておく、手数を増やしておくことは非常に重要だと思いました。
※この点からも自分のパイプラインを整理し直そうと思った次第です。

・アイデア/コーディングのLLM活用
今回、これまでで一番アイデア出しやアーキテクチャの変更の際のコーディングにGPTやgeminiなどのLLMを活用しました。
これらは万能ではないものの様々な点でコーディングの効率化に役立ちました。
今後ディスカッションや関連論文の要約など別の観点からでも広く活用方法を模索していきたいところです。

以上、LEAPコンペの振り返りとなります。
Thank you so much for teaming up with me, Nikita-san and Tatsuya-san !!


人気記事: