u++の備忘録

【特徴量の追加編】機械学習を用いた大相撲千秋楽の勝敗予想

はじめに

前回は、「Sports Analyst Meetup #4」でのLTに向けて、ベンチマークとなる機械学習モデルを構築しました。新しい特徴量を追加することで、予測モデルの性能が向上することも確認しました。

upura.hatenablog.com

本記事では、新しい特徴量を加えて、ベンチマークのLightGBMモデルの改善に挑戦します。

「連勝・連敗」特徴量の追加

千秋楽を迎えるに当たって、力士が何連勝・何連敗しているかを示す特徴量です。例えば9日に勝利した後で10〜14日に5連敗している場合は 'wins_till_final_day' が 0 で 'loses_till_final_day' が5になります。直感的には、千秋楽の勝敗に影響を与えそうな特徴量です。

def calc_wins_till_final_day(row):
    cnt = 0
    for i in range(14):
        if row.iloc[14 - i] == 1:
            cnt += 1
        else:
            return cnt
    return cnt


def calc_loses_till_final_day(row):
    cnt = 0
    for i in range(14):
        if row.iloc[14 - i] == 0:
            cnt += 1
        else:
            return cnt
    return cnt


df['wins_till_final_day'] = df.apply(calc_wins_till_final_day, axis=1)
df['loses_till_final_day'] = df.apply(calc_loses_till_final_day, axis=1)

この2つの特徴量を前回の機械学習モデル(CVスコアはAUC: 0.554915)に加えたところ、CVスコアはAUC: 0.561075に向上しました。feature importanceで見ると上から3, 4番目に登場してきています。

f:id:upura:20190808171307p:plain

testデータセットでの性能を見たところ、0.5を閾値にした場合の正答率と混同行列は次の通りに変化しました。

0.5476190476190477
→ 0.5561904761904762
array([[302, 218],
       [257, 273]])

→

array([[299, 221],
       [245, 285]])

tsfresh特徴量の追加

次いで、tsfreshという時系列特徴量を作成してくれるライブラリを利用します。勝敗の0, 1を時系列情報と見なし、特徴量を抽出する狙いがあります。

tsfresh.readthedocs.io

tsfreshの利用に当たって、dataframeを加工します。現在は1行ごとに列方向に勝敗を保持していますが、tsfreshでは縦方向にデータを保持する必要があります。

f:id:upura:20190803220932p:plain

df_list = []
for index, row in df.iterrows():
    _df = pd.DataFrame(row.iloc[1:15].T)
    _df.columns = ['results']
    _df['id'] = index
    df_list.append(_df)

df_tsf = pd.concat(df_list).reset_index(drop=True)
df_tsf['results'] = df_tsf['results'].astype(float)
df_tsf.head()

f:id:upura:20190810164537p:plain

あとは extract_features 関数を利用するだけで、800近くの特徴量を生成できます。今回は select_features 関数を利用し選定した9個の特徴量を利用しました。

from tsfresh import extract_features
extracted_features = extract_features(df_tsf, column_id='id')

f:id:upura:20190810164738p:plain

これらの特徴量を機械学習モデルに加えたところ、CVスコアはAUC: 0.5699616に向上しました。feature importanceで見ると、追加した特徴量が予測に寄与していると確認できます。しかし残念ながら、testデータセットでの性能は「連勝・連敗」特徴量を追加した時点を上回ることはありませんでした。

f:id:upura:20190810165506p:plain

おわりに

本記事では、ベンチマークとなる機械学習モデルに新しい特徴量を加えて、ベンチマークのLightGBMモデルの改善に挑戦しました。特徴量の追加を試した所感から言うと、LightGBMベースで特徴量を増やしていく方法には限界がありそうです。次回以降は、勝ち負けの「01111...」の流れをRNNに入れるなど、時系列的な特徴を加味した機械学習モデルを試してみたいと思います。

【書籍メモ】『データマイニングエンジニアの教科書』

データマイニングエンジニアの教科書』を読んだので、雑感を書きます。

www.c-r.com


書籍の概要

  • データマイニングエンジニアの教科書』
  • 著者:森下壮一郎・編著、水上ひろき/高野雅典/數見拓朗/和田計也・著
  • 出版社:シーアンドアール研究所 (2019/6/27)

以下は書籍紹介ページから引用。

本書は、プロとしてデータマイニングを行うための教養を身に付けるための1冊です。
データを分析するための知識を技術について、統計・エンジニアリング・ビジネス・倫理の基礎知識を解説しています。 データマイニングを始めようとしている人にオススメの1冊です。

目次は次の通りで、特にCHAPTER 11, 13など普通の技術書ではあまり扱わない話題を広範に掲載しています。

CHAPTER 01 データマイニングを始める前に
CHAPTER 02 統計学の基礎
CHAPTER 03 計算機上のデータ
CHAPTER 04 構造を持つデータ
CHAPTER 05 テーブル
CHAPTER 06 可視化
CHAPTER 07 パターンと距離
CHAPTER 08 多変量解析
CHAPTER 09 時系列解析
CHAPTER 10 計算量の見積もり
CHAPTER 11 エンジニア的財務会計
CHAPTER 12 指標を考える
CHAPTER 13 技術者倫理

所感

どの章も、端的に要点がまとまっています。全般に基礎的な内容を扱っている書籍なので、ある程度知っているトピックの場合は物足りない感は残ると思います。自分の場合は、サクサク読み流しながら、自分の知識の抜け漏れを確認するような使い方をしました。

精読したのは、CHAPTER 11「エンジニア的財務会計」から。昔に簿記3級を学んだ経験があるので、思い出しながらエンジニア向け書籍に会計の話題がある理由を噛み締めていました。

CHAPTER 12「指標を考える」は、個人的に一番好きな内容でした。「会社のビジネスを紐解いて指標に落とし込む」という自分が業務において常々意識している話が明文化されていて、統計や分析の手法だけでなく視野の広い話が掲載されている点で、本書への好感度が更に高まりました。

CHAPTER 13「技術者倫理」は、期せずしてタイムリーな話題でした。当たり前の内容が多かったですが、データを扱う人間として一読して改めて思いを馳せる良い機会となりました。

おわりに

本記事では、『データマイニングエンジニアの教科書』を紹介しました。単なる統計や分析の手法だけでなく、会計・指標・倫理などの話題も広範に扱っています。各トピックは基礎的な内容が掲載されている印象なので、前から目を通して気になった部分を重点的に学ぶような使い方もできそうです。網羅的に知識の確認ができる、良い本でした。

【ベンチマーク編】機械学習を用いた大相撲千秋楽の勝敗予想

はじめに

前回は、「Sports Analyst Meetup #4」でのLTに向けて、「Sumo Reference」から収集したデータを用いて特徴量作成のための簡単な可視化を実施しました。

upura.hatenablog.com

本記事では、ベンチマークとなる機械学習モデルを構築します。ベンチマークに新しい特徴量を加えることで、性能の変化も確認します。

github.com

ベンチマークの構築

特徴量

特徴量としては、前回の記事で取得した「1〜14日目の勝敗」と、可視化を通じて予測に寄与しそうだと確認した「14日目終了時点での勝数」を用います。

  • day_1, day_2, ... , day_14: N日目の勝敗(1 or 0)
  • wins_at_day_14: 14日目終了時点での勝数

目的変数

  • final_day: 15日目の勝敗(1 or 0)

機械学習モデル

Kaggleでテーブル形式データを扱う上での定番になっている「LightGBM」を用います。

Validation の構築

今回2000〜2019年のデータを取得していますが、test検証用に2015年以降のデータは学習に用いないことにします。

split_datetime = 201501
train = df[df['datetime']<split_datetime]
test = df[~(df['datetime']<split_datetime)]

その上で、Validationは下図のように時系列で切りました。具体的には、validationに用いる28場所分のデータを、1場所ずつズラしていくことで複数の {train, valid} のペアを作成しています。それぞれでvalidationのデータセットに対する性能を今回はAUCで測り、それらの平均をCVスコアとして採用しています。ペアの数をいくつにするかは計算量との兼ね合いですが、現時点ではさほど計算量が多くないので30組を作成しました。

f:id:upura:20190804130114p:plain

評価性能

CVスコアはAUC: 0.52895で、二値分類なのでランダムよりは僅かに良い程度の性能になりました。 "gain" で測定した feature importanceは次の通りです。「wins_at_day_14」が圧倒的に高い値で、その他は相対的に0に近いです。(強いて挙げれば「day_1」が高く、定性的には「初日の結果が場所全体の調子に影響を与え得る」くらいの解釈ができるかもしれません)

f:id:upura:20190804170551p:plain

testデータセットでの性能を見たところ、AUCはCVとほぼ同様の0.54になりました。(こんなにcurve感のないAUCも珍しいですね)

f:id:upura:20190804171048p:plain

0.5を閾値にした場合、正答率と混同行列は次の通りでした。

from sklearn.metrics import accuracy_score
accuracy_score(y_test, y_sub)
0.5304761904761904
from sklearn.metrics import confusion_matrix
confusion_matrix(y_test, y_sub)
array([[333, 187],
       [306, 224]])

新しい特徴量の追加

追加する特徴量

追加する特徴量は「千秋楽の対戦相手の14日終了時点での勝数」です。理由は単純で、本人の「14日終了時点での勝数」が効くなら、同様に対戦相手のものも効くだろうという発想です。

評価性能(新しい特徴量の追加)

CVスコアは0.554915で、特徴量追加前よりも微量ですが向上しました。feature importanceを確認すると、追加した特徴量が上位に来ていると分かります。

f:id:upura:20190804173559p:plain

testデータセットでのAUCも0.57に上昇しました。

f:id:upura:20190804172605p:plain

0.5を閾値にした場合の正答率と混同行列は次の通りです。

0.5476190476190477
array([[302, 218],
       [257, 273]])

おわりに

本記事では、「Sports Analyst Meetup #4」でのLTに向けてベンチマークとなる機械学習モデルを構築しました。新しい特徴量を追加することで、予測モデルの性能が向上することも確認しました。

次回以降、次の2つの方向性で取り組んでいく予定です。

  1. 新しい特徴量を加えて、ベンチマークのLightGBMモデルを改善する
  2. 時系列性を扱える機械学習モデルを利用する別のアプローチを試す

【可視化編】機械学習を用いた大相撲千秋楽の勝敗予想

はじめに

前回は、「Sports Analyst Meetup #4」でのLTに向けて、大相撲のデータを収録している「Sumo Reference」を紹介しました。

upura.hatenablog.com

本記事では、「Sumo Reference」から収集したデータを用いて、特徴量の作成に向けた簡単な可視化を実施します。

データの収集

データは「Sumo Reference」から取得し、次の形式に加工しました。

df.head(3)

f:id:upura:20190803220932p:plain

各行に、特定の場所の特定の力士の情報を格納しています。

「day_1」〜「day15」は、1〜15日目の勝敗です。NaNは、欠場を意味します。千秋楽の勝敗予想に当たって必要になる情報として「千秋楽の対戦相手」を「final_opponent」として取得しました。「datetime」は「yyyymm」形式で開催場所を示しています。

データは2000年1月場所から、最新の2019年7月場所までを取得しました。

len(df)
4340

仮説

いきなり思考停止で特徴量を作って機械学習モデルにデータを突っ込んでも良いですが、まずはこの分析を始めるに当たっての仮説に立ち戻ります。

千秋楽の勝敗は、その場所の調子(14日目までの結果)までに左右される部分があるのでは?

具体例を考えると、次の通りです。

  1. 7勝7敗で千秋楽を迎えた力士は、何としてでも勝ち越しをしたい(「ここ一番」の本気を出す)
  2. 13勝1敗のように大勝している場合は、勝率が高くなりそう
  3. 千秋楽を前にN連勝している場合は、その流れで千秋楽も勝利しそう

今回の分析ではこのような仮説に基づき、1〜14日目の勝敗データから、千秋楽(15日目)の勝敗を予測するモデルの構築を目指します。

可視化

ここでは、上述した仮説1, 2に対応する特徴量「14日目までの勝数」を考えます。勝数が決まれば敗数は14からの差分として自明に定まるので、カテゴリとしては「勝数」と「勝敗」に違いはありません。

まずは「14日目までの勝数」の分布を見てみます。

ここでの可視化に当たって、1日でも欠場のある力士は削除しているので、0勝はかなり少なくなっています。

f:id:upura:20190729121703p:plain

次いで「14日目までの勝数」別の「千秋楽の勝率」です。

f:id:upura:20190729121736p:plain

個人的に着目したのは次の2点です。それぞれ、先に述べた仮説の1, 2に対応します。

  • 7勝7敗の場合の勝率が(6勝8敗や8勝6敗の場合に比べて)高い
  • 14日目までに12〜14勝している場合は勝率が0.5よりも高い

※ 前者について、こういう数字が出ると「八百長」のような話が出がちですが、今回は話題として取り上げません。ここに因果があるかを議論するには扱っている情報量が少なすぎるためです。

可視化を通じて、事前に持っていた仮説がある程度正しそうだと分かりました。つまり、今回作成した「14日目の勝数」という特徴量は、千秋楽の勝敗を予想するモデルに寄与する可能性がありそうです。

おわりに

本記事では「Sports Analyst Meetup #4」でのLTに向けて、「Sumo Reference」から収集したデータを用いて特徴量作成のための簡単な可視化を実施しました。次回は、ベンチマークとなる機械学習モデルを構築する予定です。

Djangoで「名古屋/東京」の画像分類アプリを作った


はじめに

Djangoを使って「名古屋/東京」を判定する画像分類アプリを作ってみました。下記の記事で学んだことを活かして、自分で手を動かしてみたという経緯です。

upura.hatenablog.com

インターフェイス

index.html

この画面で、画像を選択します。「推定する」ボタンを押すと、result.htmlに推移します。

f:id:upura:20190728064910p:plain

result.html

推論結果の画面です。前画面で選択したファイル名・画像ファイル・推論結果・推論確率を表示しています。

f:id:upura:20190728064915p:plain

分類器

画像の収集

画像は、flickr API を用いて収集しました。「名古屋」「東京」の関連度順の検索結果を400枚ずつ収集しています。

機械学習モデル

KerasのVGG16使って転移学習させています。AUCは.65程度でお世辞にも良い精度とは言えませんが、今回はWebアプリ化が目的だったのでハイパーパラメータなどを少しだけチューニングして終わりました。

おわりに

本記事では、Djangoを使って自作した「名古屋/東京」を判定する画像分類アプリを紹介しました。やはり自分で手を動かすと、特に慣れてないDjango部分は詰まりどころが少なからずあって勉強になるなるなと感じました。

実装はGitHub上で管理していますが、講座で提供されたコードを流用している部分が大半なので、private設定にしています。

f:id:upura:20190728082935p:plain

大相撲のデータ収集は「Sumo Reference」が便利

8月24日(土)に開催予定の「Sports Analyst Meetup #4」で大相撲関連の分析をするに当たって、まずはデータ収集に取り組んでいます。

spoana.connpass.com

Sumo Reference

筆者は「Sports Analyst Meetup #2」のtomi_ さんのLTで知ったのですが、大相撲のデータ収集は「Sumo Reference」が便利です。

sumodb.sumogames.de

f:id:upura:20190726205258p:plain

収録されている項目

デフォルトは英語のサイトですが、日本語版も公式でサポートしています。

歴代力士

例:横綱一覧表

力士の出世記録検索

例:大関取り

取組検索

例:対戦相手

おわりに

本記事では「Sports Analyst Meetup #4」でのLTに向けて、大相撲のデータを収録している「Sumo Reference」を紹介しました。次回は、収集したデータの簡単な探索的分析・可視化をしていく予定です。

Udemy講座「【Python・Django・TensorFlow + 転移学習】画像分類AIアプリ自作入門」をやった

Udemy講座「【PythonDjango・TensorFlow + 転移学習】画像分類AIアプリ自作入門」をやりました。タイトル通り、PythonのTensorFlowで作成した機械学習モデルをDjangoを用いてWebアプリ化する講座です。全3.5時間を一晩で流し見しながら追体験しましたが、個人的に求めていた内容にピンポイントで合致して満足しています。

f:id:upura:20190723072704p:plain

https://www.udemy.com/django-ai-app/

受講の動機

受講した理由は、機械学習モデルをWebアプリに組み込む方法をザックリと知りたかったためです。最近、Kaggleなどで機械学習モデルの構築に取り組んでいる中で、Webアプリなど自分・他人が扱いやすい形で表現する必要性を感じていました。普段からPythonを使っているので、Djangoが選択肢となりました。

下記の講座の受講を経て、Udemy講座には好印象を持っていたのも大きかったです。

upura.hatenablog.com

受講前の知識

  • 教師あり機械学習はKaggleなどで経験あり
  • DjangoもTo doアプリなど簡単なチュートリアル経験あり
  • 保存した機械学習モデルをどう組み込んでいくか、ある程度の当たりは付いていたが、手っ取り早く動画で一連の流れを勉強したかった

各セクションの雑感

基本的に、全部1.5〜2倍速で観ていました。聞き逃した際には15秒戻る機能があるので、ある程度自信がある内容なら講師の話し方に合わせた早回しで受講して問題ないと考えています。

イントロ

概要です。一応聞いておいた方が良いと思いますが、事前の講座説明に書いてある通りです。

環境構築(既修者はスキップOK)

セクション名にある通り、飛ばしました。

データの収集・クレンジング

Flickr APIでのデータ収集の流れが説明されているので、自分で独自データを集める際に参考になりそうです。

CNNによるトレーニン

機械学習の学習・推論の流れはある程度事前に知っていたので、2倍速で流し見しました。

転移学習でスコアアップを図ろう!

同上。

コマンドラインアプリ化しよう!

Djangoでのアプリ化に向けて、一段階置いた橋渡しになっている構成は分かりやすいなと思いました。

Djangoでウェブアプリ化しよう

本講座の本丸です。「Djangoのインストールと動作確認」から始め、機械学習モデルを用いたWebアプリを段階的に作成していく構成になっています。自分でWebアプリを作っていく上でも模倣しやすい形式で、自分の受講理由に合致していると感じました。

おわりに

Udemy講座を通じて、機械学習モデルをDjangoを用いてWebアプリに組み込む方法を学びました。次は今回学んだ内容を用いて、自分なりの簡易的なWebアプリを作っていこうと思います。