はじめに
こんにちは! 株式会社インダストリー・ワンのエンジニア、角田です。
昨年末、弊社と同じ三菱商事グループのMC Digital様 主催のMCD Data Science Competition 2023(以降Kaggleコンペ)に、弊社から数名参加してきました。
今回はコンペの内容や、コンペを通じて得られた知見を共有したいと思います!
背景・目的
MC Digital様が主催のKaggleコンペの内容や、コンペを通じて得られた知見共有。
コンペについて
概要
Kaggleのプラットフォームを用いた、三菱商事関連会社のみ参加可能なプライベートコンペです。
- 日時:2023/12/18(月)
- 9:30-10:00: 開会式&準備
- 10:00-16:45: Kaggleコンペ
- 17:00-19:00: 閉会式&懇親会
- 場所:日比谷ミッドタウン 11F MC Digital様オフィス
- チーム:12チーム
コンペ時の風景
コンペ内容
比較的シンプルな、テーブルコンペでした。
以下、具体的なコンペの内容です。
データ分析の背景
現代の教育環境では学生の学習パターンと成績の関係を理解することが重要です。教育機関、教育者、学生にとって、早期に学習の課題を特定し適切なサポートを提供することで学生の成功に貢献できます。
データ分析の目的
このコンペティションの目的は学生の学習行動、評価特性、および他の関連情報をもとに未来のテストの点数を予測するモデルを構築することです。このような予測モデルは、学生の学習サポートやカリキュラムの最適化に役立てることができます。
Evaluation
提出はRMSE(root-mean-square error)で評価されます。小さい方が良いです。
※RMSEとはRoot Mean Squared Error”の略です。以下の式で表されるように、予測値が実際の値に近いほど小さくなります。
出典 : 【評価指標】二乗平均平方根誤差(RMSE)とは - AI Academy Media
Submission File
sample_submission.csvに含まれる全てのidに対して予測値を出力してください。 ファイルはヘッダ(id, score)を含むcsvである必要があります。
データ概要
- 匿名化された大学の講義とその成績に関するデータです。
- 講義、生徒、Virtual Learning Environment (VLE)などの情報が与えられます。
- test.csv の各行について、その生徒がその講義の最終試験で何点を取れたかを予測してください。
- test.csv および train.csv は "exam" と呼ばれるその講義の最終試験の点数(score)が入っています。
- "exam" ではない、その講義の小テストの結果などは non_exam.csv に入っています。
- 外部データは使用禁止です、本コンペで提供されているデータのみ使って下さい。
- 今回のオープンデータセットを利用しており簡単に答えがわかる状況になっています。コンペの競技性、公平性を保つためにルールを遵守してください。
データ一覧
データ | 内容 |
---|---|
train.csv | その講義の最終試験のscoreが入っています |
test.csv | こちらのscoreを予測するのが目的です |
courses.csv | 利用可能なすべてのモジュールとそのプレゼンテーションのリスト、モジュール発表の日数が含まれています |
vle.csv | VLE(仮想学習環境)で利用可能な教材に関する情報が含まれています。通常、これらはhtmlページ、pdfファイルなどです。学生はオンラインでこれらの教材にアクセスでき、教材とのやり取りが記録されます |
studentInfo.csv | 成績とともに生徒の人口統計学的情報(性別、年齢、モジュール受験回数など)が含まれています |
studentRegistration.csv | 学生がモジュール発表に登録した時間に関する情報が含まれています。登録解除した学生については、登録解除日も記録されます |
studentVle.csv | 各受講生とVLEの教材とのやり取りに関する情報が含まれます |
non_exam.csv | その講義の小テストの結果が含まれます |
参加活動記録
メンバー
- エンジニアメンバー2名で参加
- 2名とも、普段の業務ではデータサイエンスとは関わりないが、Kaggleの経験は少しあり
チーム方針
コンペで勝ちにいくのではなく、知見を得ることがメインの目的だったので、個人で分析を行い、各々のベストを目指すという方針で進めました。
サンプルNotebook
運営側からすでにサンプルのNotebookが教示されていたため、まずはそれをsubmitしました。サンプルNotebookは以下のようなモデルです。
- LightGBMによる学習、予測(LightGBMについてはこちらを参照)
- データは以下を使用(最低限)
- 学習データをホールドアウト
- 訓練データ:75%
- 評価データ:25%
publicスコアは'20.397'になりました。これをベースラインとして改善していきます。
EDA
私は、全体的にデータを見ていったところ、試行錯誤はあったものの、
サンプルで使われていなかったデータのうち、最終的に以下に着目しました。
- non_exam
- その講義の小テストの結果のスコアが入っている
- weightという特徴量があり、各小テストの成績に対する「重みづけ」であると予想
- studentVle
- 各受講生とVLEの教材とのやり取り
- 教材のクリック数が多いと、しっかりと学習している場合が多いと予想
- studentRegistration
- 学生がモジュール発表に登録した時間に関する情報
- 登録が早ければ、意欲が高いためスコアに影響するのでは、と予想
- 登録解除があった場合も、スコアに影響するはず
特徴量の追加
上記のEDAより、以下の特徴量を追加しました。
小テスト点数* 重みの平均(non_examから計算)
- code_module, code_presentation, id_studentごとに、「score * weight」の合計値を求め、weightの合計値での除算値
- weightの合計値で除算したのは、平均を求めるのに「件数」で割ってしまうと、重みが少ない小テストの数が多いと特徴量が不利な減り方をしてしまうため
- 以下のように、スコアとの相関関係が見られました
教材のクリック数の合計(studentVleから計算)
- code_module, code_presentation, id_studentごとに、sum_clickの合計値を算出
- 相関関係はそこまで見られない
登録日と解除日
- date_registration, date_unregistrationをstudentRegistrationからマージ
学習モデル
サンプルNotebookで使われていたLightGBMをそのまま使用
ハイパーパラメータチューニング
以下の範囲でランダムサーチ
- boosting_type : ['gbdt', 'dart', 'goss']
- num_leaves : 20〜300
- min_data : 10〜100
- max_depth : 5〜200
- iterations : 10〜1000
結果
最終的に、以下のようになりました!
- publicスコア:15.162 (1位:14.321、2位:14.537)
- privateスコア:14.562 (1位:13.677、2位:14.239)
- ※2位との差はそこまでなく、スコアとして悪くはなかったと思います。
主催者側の想定解
最後に主催者側から、想定解についての解説がありました。
重要なテーブルは主に以下の二つ
non_exam
- その講義の小テストの結果のスコアが入っている
- 小テストの得点と最終テストの得点には強い相関がある
- EDAすると明らか+直感的にも明らか
studentVle
- その生徒の仮想環境での挙動
- たくさんクリックしている生徒ほど熱心に勉強していそう
主催者が作った特徴量
- non_exam
- 小テストは何度もあるため、統計的に処理する
- non_exam_scoreの'mean', 'median', 'count', 'max', 'min',"std","var","sum"を生徒ごとに作る
- studentVle
- ログインは何度もしているため、こちらも統計的に処理
- 合計クリック数、平均クリック数などを生徒ごとに作る
※筆者の方針は大きく間違っていませんでしたが、「平均クリック数」など検討不足の特徴量もありました。また不要な特徴量も増やしてしまっていたかもしれません。
アンサンブル
- 提供したNotebookでは、全体の25%をvalid, 残りをtrainにしていた
- このvalid/train splitを変えることで、多様性のあるモデルが作れる
- 複数モデルを作ってtestデータを独立に予測させるその後、それぞれの出力を単純に平均する
- 良い特徴量を追加することに比べると効果は小さいが、ほぼ確実にスコアが伸びる手法
出典 : MC Digital様 解説資料
上位チームのNotebook共有
主催者に加え、上位2チームのNotebookも共有していただきました。
後で復習に使えるので、こういった配慮は大変ありがたいですね。
ふりかえり
参加メンバーの意見をまとめました。
- 課題としてはシンプルなテーブルコンペで取り組みやすかった
- 特徴量作成が命で、モデルはGBDT系を使えば良いと考えていたので、模範解答のアンサンブルがほぼ確実に効くというのは勉強になった
- ベースのLightGBMをどう改善していくかや、学習データの用意の仕方でチーム毎に個性がでるような仕組みだったのが良かった
- イベント終了後、他の人のコードを見て、LightGBMのCVのやり方や何を学習データ(特徴量)とすると良いのかを学べた
まとめ
今回はMC Digital様 主催のKaggleコンペの参加記録と、得られた知見を共有させていただきました。
現在弊社では、データサイエンス関連の業務は多くはないのですが、今回のような機会をきっかけに、データサイエンス関連業務にも携われればと思います。
個人的には参加者と懇親を深められて情報共有もでき、有意義でした。
以上、最後まで読んでくださり、ありがとうございました。
LightGBMの補足
LightGBMは、Boostingアルゴリズムの1つです。他のBoostingアルゴリズムと異なる特徴がいくつかあります。代表的な特徴を以下に挙げます。
スピードとメモリ使用量を最適化
多くのブースティングツールは、決定木の学習に事前ソートベースのアルゴリズムを使用していますが、その最適化は容易ではありません(決定木についてはこちらの記事などを参照)。
出典 : LightGBMを超わかりやすく解説(理論+実装)【機械学習入門33】
LightGBMはヒストグラムベースのアルゴリズムを使用し、連続的な特徴値を離散的なbinにまとめます。これにより、学習が高速化され、メモリ使用量が削減されます。
出典 : LightGBMを超わかりやすく解説(理論+実装)【機械学習入門33】
Leaf-wise (Best-first) Tree Growth
前提としてBoostingアルゴリズムは以下のように、決定木を作る→予測する→実際の値との誤差を小さくするような新たな決定木を作る→既存の決定木と新たな決定木を足し合わせた値との誤差を小さくするような新たな決定木を作る→... と繰り返し、木を成長させていきます。
出典 : Understanding Gradient Boosting. This is part three of the following… | by Hemashreekilari | Medium
多くの決定木によるアルゴリズムは、木全体の深さが深くなっていくように木を成長させます(Level-wise)。 つまり、優先度を決めずに深くなるように成長させていきます。
出典 : Features — LightGBM 4.0.0 documentation
LightGBMは、最も損失が小さくなるようなノードから分割していきます(Leaf-wise)。
出典 : Features — LightGBM 4.0.0 documentation
これにより、ある程度精度が出る決定木をLevel-wiseよりも早く構築することができます。
カテゴリ特徴量の最適分割
カテゴリ特徴量はワンホットエンコーディングするのが一般的ですが、カーディナリティ(選択肢)の大きい特徴量では、ワンホットエンコーディングで作られた木はバランスが悪くなりがちで、精度を上げるためには非常に深く成長させる必要があります。 そのため、カテゴリ特徴量のヒストグラムをその累積値に従ってソートし、ソートされたヒストグラム上で最適な分割を見つけます。
さらに詳しく知りたい方は、参考URLの記事を見ていただければと思います。
おわりに
インダストリー・ワンでは一緒に働く仲間を募集しています。
少しでも興味を持っていただいた方は、是非以下から応募していただければと思います。もちろんカジュアル面談からでも OK!
どうぞ宜しくお願いいたします。