Regonn&Curry.fm Episode 125収録後記 KaggleのSimulationコンペでscoreの変動を通知する仕組みを作る

このnoteは、Regonn&Curry.fm というポッドキャストの第125回の収録後記です。

第125回では、Papers with Datasets、不動産テックDiscord、CoeFont Studio、アップル春の新製品、4月目標結果、今週のKaggleについて話しました。

このnoteではSimulationコンペでscoreの変動をlineで通知する仕組みについて書きます。

何故作ったか、通知の例

KaggleのSimulationコンペでは、1日に数回の対戦が行われ、対戦の勝敗によりscoreが変動します。

この対戦は、いつ行われるかわからないため、scoreの変動が気になってしまい、My Submissiosのページを見に行く回数が増えてしまいました。

そこで、スコアの変動があると、Lineに通知するようにしました。

次のように通知がされます。

画像3

この画像の通知だと、対戦の結果、スコアが1166.4から1171.1に変動したことがわかります。またurlはリプレイのURLにしており、クリックするとどのような試合だったかがわかるリプレイのページに飛ぶことができます。

方法

Kaggle apiを使うと自分のサブミット一覧を取得することができます。

これを利用し、Kaggle apiを定期的に実行し、前回とscoreが変わっていればLineに通知します。

手順1:LineとKaggle apiの設定

次のブログを参考に、Lineのパーソナルアクセストークンを取得します。

また、次のブログを参考に、Kaggle apiの設定をしましょう。


手順2:My submissionsからrefとコンペ名の取得

KaggleのMy submissionsから、通知したいサブのref番号を取得します。

スクリーンショット 2021-05-03 4.40.13

ref番号は、このPublic Scoreの隣にあるEpisodesのViewのリンク先のURLから取得することができます。
Hungry Geezeであれば、次のようなリンクになっているので、このxxxxxxの部分です。


https://www.kaggle.com/c/hungry-geese/submissions?dialog=episodes-submission-xxxxxx

これを通知したいサブの分だけ取得します。例えば10000と10001の2つのサブを通知したい場合は、後のコードのCHECK_SUB_REF_LISTは 次のようにします。

CHECK_SUB_REF_LIST = ['10000', '10001']

また、kaggleのコンペ名も後のコードのCOMPETEにします。
先程のurlの真ん中にあるもので、今回の場合は'hungry-geese'です。

COMPETE = 'hungry-geese'

手順3:コードを書く

from pathlib import Pathimport requests
from kaggle.api.kaggle_api_extended import KaggleApi


SAVE_TXT_DIR = Path('hungry-geese-txt')  # スコアの一時保存フォルダ
if not SAVE_TXT_DIR.is_dir():
    SAVE_TXT_DIR.mkdir()
LINE_TOKEN = <lineのtokenを入れる>
COMPETE = 'hungry-geese'  # コンペにより変更する


def send_line_notification(message):
   line_token = LINE_TOKEN
   endpoint = 'https://notify-api.line.me/api/notify'
   message = "\n{}".format(message)
   payload = {'message': message}
   headers = {'Authorization': 'Bearer {}'.format(line_token)}
   requests.post(endpoint, data=payload, headers=headers)


def get_before_score_from_file(ref):
   file_path = Path(SAVE_TXT_DIR / f'{ref}.txt')
   if file_path.is_file():
       with open(file_path, 'r') as f:
           before_score = f.readline()
   else:
       before_score = '0'
   return before_score


def write_score_to_file(ref, public_score):
   """次に前回のスコアとして読み込むため、txtファイルにscoreを保存しておく"""
   with open(SAVE_TXT_DIR / f'{ref}.txt', 'w') as f:
       f.write(str(public_score))


def get_sub_info(submission):
   public_score = submission['publicScore']
   file_name = submission['fileName']
   return public_score, file_name


def main():
   api = KaggleApi()
   api.authenticate()
   submissions_list = api.competitions_submissions_list(COMPETE)

   for ref in CHECK_SUB_REF_LIST:
       for submission in submissions_list:
           if str(submission['ref']) != ref:
               continue
           public_score, file_name = get_sub_info(submission)

           message = f'score: {public_score + ",":<7} {file_name + ",":<40} url: https://www.kaggle.com/c/hungry-geese/submissions?dialog=episodes-submission-{ref}'
           print(message)

           before_score = get_before_score_from_file(ref)
           write_score_to_file(ref, public_score)
           
           if before_score != public_score:
               message = f'score: {before_score} -> {message}'
               send_line_notification(message)
           break


if __name__ == "__main__":
   CHECK_SUB_REF_LIST = ['10000', '10001']  # 通知したいサブに変更する   
   main()

上のコードで、前回と異なる場合に次のような通知がLineにされます。

画像2

手順4:定期的に実行する

MacやLinuxであれば、watchで定期に実行できます。10分ごとに実行する場合は、次のコマンドとなります。

watch -n 600 python main.py

終わりに

時間を節約できる仕組みの作成良いです。

これから次のページにSimulationコンペで使えるコードをまとめていきたいと思います。是非参照いただき、また書いてもらえれば。


コメントお待ちしています。匿名の質問はマシュマロから→https://marshmallow-qa.com/currypurin