Arc's blog

競プロなど

割と真面目にKaggleをやってみた話

しばらくの間,割と真面目にKaggleをやっていたので記録(とポエム)を残します.

Kaggleに挑戦するまで

どうしてKaggleを始めたか

大学に入学してから機械学習つよつよな人々に会って刺激を受け,機械学習に興味を持ちました. また,競プロ純粋培養ではスキルセット的に不安を感じたこともあり,機械学習をやってみようと考えました.

競技プログラミングの人間が機械学習に手を出そうとすると,当然(?)始めるにあたっての初手は競技機械学習になります.競技機械学習プラットフォームで有名なKaggleに登録しました. 私のアカウントはこれです.

自分のスキル

  • Python3の基本構文はなんとなく書ける
  • 実はTitanicコンペ(Kaggleのチュートリアル的なコンペ)をちょっとだけやったことがある
    • scoreは0.77511がベストでした.ロジスティック回帰で分類したりしていました.
    • 当時はKaggle版蟻本として自分の中で名高いKaggleで勝つデータ分析の技術(長いので以下「Kaggle本」とします)の存在を知らなかったため,よく分からないまま止めてしまいました.今回はその本を入手できたため,これを参考にしながら進めました.

コンペ概要

参加したのはReal or Not? NLP with Disaster Tweetsです. Twitterの英語ツイート本文(以下"Text"),キーワード1 (以下"Keyword"),送信された場所の地名(以下"Location")が与えられ,それらの情報を元に「そのツイートが災害に関連するものか否か?」を予測するものです. 正確に予測できるほど高いスコアが得られます2

やったこと

特徴量の作成

入力データを機械学習ライブラリが処理しやすいように変換します. 具体的には,文字列をベクトルとして表現したりします.

次の処理を行いました.

Textのクリーニング,ベクトル化

文を処理しやすいような形に変換した後,何らかの手法でベクトル情報に変換します. Kaggleで公開されているGetting started with Natural Language Processing A general IntroductionというNotebookを参考にしながら,以下の処理をしました.

  1. "Word"と"word"が別の単語として認識されたりすると嬉しくないので,Textを全て小文字化.
  2. 句読点やURLなどを除去.
  3. "a"や"the"などの,ごく一般的で解析上深い意味を持たない単語(Stopwords)を除去.
  4. ここまでの処理で綺麗になったTextをベクトル化.

ベクトル化には様々な手法があるようですが,今回は最終的にSWEM-maxという物を利用しました. SWEM: 単語埋め込みのみを使うシンプルな文章埋め込みに詳しい説明があります. NotebookやKaggle本にあったTf-Idfという物も試しましたが,あまりスコアが伸びませんでした.

Keywordの変換

Keywordもベクトルに変換します.今回はOne-hot encodingという手法を用いました. KaggleのNotebookだとusing-categorical-data-with-one-hot-encodingが参考になります.

Locationの削除

NLP with Disaster Tweets - EDA, Cleaning and BERTを読むと,データの33%が欠損していることがわかります. 欠損値の適当な埋め方も分からないので削除しました.

モデルの作成

特徴量を入力して予測結果を出力する「モデル」を作成しました. Kaggle本が勾配ブースティング木(GBDT)というアルゴリズムを推していたのでそれに倣いました. ライブラリはXGBoostを使いました.このライブラリもKaggle本で詳しく紹介されています.

使い方がPython: XGBoost を使ってみるにまとめられていたので参考にしました.

訓練データ(そのツイートが災害に関連するかどうか事前に分かっているデータ)でモデルを作成し,できたモデルでテストデータ(災害に関連するかどうかわからないデータ)の予測結果を出力します.

パラメータチューニング

XGBoostの挙動を決めるハイパーパラメータを調整しました. 手動でやると辛いので,チューニングを自動化するフレームワークを用いました.今回はOptunaを使いました. パラメータの調整範囲などはKaggle本を参考にしました.

チューニングによってPublic Leaderboardのスコアが0.78220から0.79652に伸びました.その後チューニング過程を可視化し,パラメータの調整範囲を変更するなどしてさらなるチューニングを試みましたが,これ以上伸びませんでした.

結果

一般的なKaggleのコンペでは,Public LeaderboardとPrivate Leaderboardという2つの順位表が存在します. コンペ期間中は予測結果の何割か3で算出したスコアに基づくPublic Leaderboardが更新され,コンペ終了後に残りの予測結果で算出したスコアに基づくPrivate Leaderboardが公開される,というシステムになっています. 最終結果として用いられるのはPrivate Leaderboardの方です.

Public Leaderboardのために過学習したモデルを用いて上位になっていても,Private Leaderboardでは順位がとんでもなく落ちている...ということになりかねないワクワク要素です(当然,逆にPrivate Leaderboardで順位が上がることもあります).

このコンペはPrivate Leaderboardが公開されませんでした. ちょっとよく分かってないのですが,ランキング計算外のコンペ(チュートリアルのTitanicなど)ではPrivate Leaderboardが公開されないのかもしれません......

ということで最終結果は一応0.79652ということになります. 3/26現在3403人中1718位で,上から数えて51%の位置でした4. 予測結果の提出は今もできるようです.

f:id:arcslab:20200326224614p:plain

ちなみにGoogle Cloud AutoMLを用いたモデルで上位入賞すると賞金がもらえたそうですが,少し調べた所AutoMLがブラックボックス過ぎた(個人の感想)ので止めました.勉強にならないので......

感想

スコアを0.8に乗せたかったので残念でしたが,Titanicコンペよりはそれっぽいことをできたのかなと思います. 自然言語処理の基本的な手法を知ることができました. Kaggleで勝つデータ分析の技術機械学習コンペを体系的に学ぶ上で非常に良いと思うので,これから始める人は買いましょう(ダイマ).

コンペ終了後に気づいたんですが,どうやらこのコンペもチュートリアルの一種だったようです5. 次回は公式コンペに参加しようと思います.

今後の課題

  • アルゴリズムの中身を理解する
    • 今回はAPIを叩くだけの人になってしまったので.
  • Notebookについて
    • Notebookに全てのコードと考察を書くのは無理があると分かったので,運用を改める.
    • "Notebook JSON is invalid"と言われ,KaggleにNotebookをアップロードできなくなってしまったので解決する(ググっても情報が出てこない......).
  • アンサンブルなど
    • 複数のモデルを組み合わせて性能を上げる手法.これには手を付けられなかったのでやってみる.
  • 実行環境について
    • RAM16GBで足りなくなってしまったのでビビった(Jupyter Notebookの使い方に問題があるような気もするが).また,一般的な4Core CPUだとパラメータチューニングにはどうしても時間がかかる.GCPを使えるようにならないといけないかもしれない.

  1. ツイートに「キーワード」なんて情報は含まれてないような気がします… 「キーワード」はどこから入手した情報なのか結局わかりませんでした.

  2. 正確に言うとF1 scoreという指標です.単純な正答率ではありません.

  3. どのデータがPublic Leaderboardのために用いられているかを参加者が知ることはできません.

  4. 実は「コンペの入出力データのソースを入手して比較する」というチート手法を用いて満点を取っている人がいるようです(ソース).そのため本来の自分の順位はもうちょっと上です(は???)(チュートリアル扱いのコンペらしいので仕方ないね)

  5. “Getting Started"にカテゴライズされているコンペはチュートリアル扱いらしい(ソース).Titanicコンペ以外にチュートリアルがあるとは思ってなかった……