Kaggle:Linking Writing Processes to Writing Quality 振り返り

# 1. はじめに
2024年1月に終了したKaggleのコンペティション、Linking Writing Processes to Writing Qualityに参加して銀メダルを獲得したので振り返りをしていきます。

# 2. コンペ概要
**[Linking Writing Processes to Writing Quality](https://www.kaggle.com/competitions/linking-writing-processes-to-writing-quality)**
![タイピングコンペ1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683909/d37f60bd-fb6e-2dd1-3150-656a1c6e74b3.png)


キーストロークログからエッセイの質(0.5~6の12段階)を予測するテーブルデータコンペです。
タイピングの動作がエッセイの質に影響するかを検証することが趣旨のコンペとなっていて、入力された文字はすべて'q'に置換されてエッセイの内容は隠蔽されています。日本だとタイピングコンペと呼ばれることが多かったです。

- データセット
trainとtestでそれぞれ1ファイルずつ与えられて、1イベント1レコードで格納されています。中身は以下のようになっています。

    <table>
    <tr>
      <th>カラム</th>
      <th>概要</th>
    </tr>
    <tr>
      <td>id</td>
      <td>エッセイID</td>
    </tr>
     <tr>
      <td>event_id</td>
      <td>イベントID</td>
     </tr>
     <tr>
      <td>doen_time</td>
      <td>ダウンイベントの発生時刻(ミリ秒)</td>
     </tr>
     <tr>
      <td>up_time</td>
      <td>アップイベントの発生時刻(ミリ秒)</td>
     </tr>
     <tr>
      <td>action_time</td>
      <td>ダウンイベントとアップイベントの差</td>
     </tr>
     <tr>
      <td>activity</td>
      <td>アクティビティのカテゴリ(Nonproduction, Input, Remove/Cut, Paste, Replace, Move From [x1, y1] To [x2, y2])</td>
     </tr>
     <tr>
      <td>down_event</td>
      <td>キーorマウスを押したときのイベント名</td>
     </tr>
     <tr>
      <td>up_event</td>
      <td>キーorマウスを離したときのイベント名</td>
     </tr>
     <tr>
      <td>text_change</td>
      <td>イベントの結果、変更されたテキスト</td>
     </tr>
     <tr>
      <td>cursor_position</td>
      <td>イベント後のカーソル位置</td>
     </tr>
     <tr>
      <td>word_count</td>
      <td>イベント後のエッセイの文字数</td>
     </tr>
     <tr>
      <td>score</td>
      <td>0.5~6のエッセイの質を表すスコア。<a href="https://www.kaggle.com/competitions/linking-writing-processes-to-writing-quality/discussion/447933">このディスカッション</a>に記載されている基準でスコアリングされたとのこと。</td>
     </tr>
    </table>
    
    データセットのイメージ
![タイピングコンペ4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683909/290460f4-4be7-89c1-2692-62daa1414ecd.png)  
<br/>

- データセット数(≒エッセイ数)
train: 2142
test: 2500(Public LBはその内50%で評価)
- 評価指標
RMSE
- コンペ結果
ソロで参加し、25位/1876チームで銀メダル獲得！
![タイピングコンペ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683909/94818079-639c-cc3c-d5cc-147278a285a7.png)


# 3. 基本解法
予測する値が12値のみなので分類問題で解くことも可能でしたが、どのチームも回帰問題で解いた方が精度が出ていました。

特徴量作成としては大きく分けて3つのアプローチがありました。
1つ目はキーストロークの挙動を特徴量化
2つ目はキーストロークログからエッセイを再構成し、エッセイの構造(段落数、文章数など)を特徴量化
3つ目は同様にエッセイを再構成し、自然言語処理にて特徴量化
上位解法では3つ目の自然言語処理にてDeBERTaがよく使用されていました。

モデルはLightGBMを始めとしたGBDTが中心で、アンサンブル要員としてLightAutoMLを使用したNNが良く使用されていました。
また、提供されたデータセット数が少ないことを補うために過去コンペのデータを外部データとして使用している上位チームもいました。

Public LBとCVに相関がなく大幅なShake Up/Downが生じましたが、結果的にはCVがよいモデルを選べばよかったようです。

# 4. 個人解法
[公開ノートブック](https://www.kaggle.com/code/suryanshsharma1/lgbm-nn-fusion-xgb-ensemble)と個人解法の予測値をアンサンブルしたものを最終提出としました。
個人解法部分を紹介していきます。

- 特徴量作成
特徴量作成は上記基本解法に記載した1つ目と2つ目に注力しました。その中でもスコア向上に効いたものをピックアップして紹介します。
  - 同じアクティビティが何回/何秒続いたか
  - 5/10文字以上の単語の出現回数
  - word size in sentences
  - ncharacters / nwords in paragraphs
  - nsentences in paragraph
  - イベント遷移のパターンをクラスタリング
  - イベント遷移からState Machineを作成し、特徴量に使用([参考論文](https://files.eric.ed.gov/fulltext/EJ1109988.pdf))

- 特徴量採用/選択
新たな特徴量を追加した際、CVとLBの両方が改善したときの特徴量のみを採用しました。
また、特徴量が多くなりすぎたのでfoldごとにLightGBMの特徴量重要度上位200個を選択し、再度各モデルで学習しました。

- バリデーション
n=5のStratified KFold

- モデル
自分のモデル(LightGBM(extra trees) + CatBoost)と公開ノートブックをアンサンブル/スタッキングしものを最後に更にアンサンブルしました。また、seedによってスコアがぶれるため、自分のモデルはn=10のseed averagingを行いました。

  ちなみに、LightGBMの"extra trees":Trueにするだけでかなりスコアが良くなりました。過去コンペでも"extra trees":Trueにするだけでスコアが良くなることが多かったのでおすすめです。

![タイピングコンペ3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683909/5cab0b4a-7dc5-086a-68c8-4a906f0b7eb3.png)


- その他テクニック
このコンペの特徴として、新たに特徴量を追加した際にCVは向上するがLBが悪化することが多かったです。この原因の仮説としてエッセイのスコアは人間がつけているので±0.5程度の誤差は生じてしまうのではないかと考えました。つまり、誤差が乗っているtrainデータのスコアに過学習することでtestデータを予測する際に悪さしているのではないかということです。
そこで、train時のターゲットにあえてノイズを加えることでtrainデータに過学習することを避けられるのではないかと考え実行した結果、ある程度は改善されました。

  ただ、コンペ期間の中盤から終盤にかけてはこの対処に時間を使いすぎてしまったように思います。結果としてはCVをひたすら向上させることだけに注力すれば良かったです。

- 試したが上手くいかなかったこと
  - PCAを使用したデータ拡張
  - Pseudo Labeling
  - Meta Featuresの追加
  - イベント遷移をグラフネットワーク化した際の特徴量
  - PCAで次元圧縮した特徴量

# 5. さいごに
LightGBMのシングルモデルでも銀メダル圏のスコアだったので良いモデルが作れたと思っています。
一方で、自然言語に特化した特徴量作成やモデリングには時間を割けなかったのでそこが金メダルチームとの差かなと感じました。