Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AkarengaLT#11 python

AkarengaLT#11 python

python predictions keiba

KHTTakuya

March 05, 2022
Tweet

Other Decks in Technology

Transcript

  1. 主成分分析 21 df = df[df['days'] < datetime(2021, 1, 1)] df.loc[df['result']

    >= 4, 'result'] = 0 df.loc[(df['result'] <= 3) & (df['result'] >= 1), 'result'] = 1 # 各ジョッキーコース別の複勝率(2021年1月1日まで集計対象) table_jockey = pd.pivot_table(df, index='jocky', columns='place', values='result', aggfunc='mean', dropna=False) table_jockey = table_jockey.fillna(0) table_jockey = pd.DataFrame(table_jockey) table_jockey = table_jockey.round(4) table_jockey = table_jockey.add_prefix('jockey_') # 主成分分析:次元削除 pca = PCA() pca.fit(table_jockey) df_score = pd.DataFrame(pca.transform(table_jockey), index=table_jockey.index) df_score = df_score.loc[:, :5] df_score = pd.DataFrame(data=df_score) df_score = df_score.rename(columns={0: 'jockey_pca1', 1: 'jockey_pca2', 2: 'jockey_pca3', 3: 'jockey_pca4', 4: 'jockey_pca5', 5: 'jockey_pca6'})
  2. Target Encoding • Target Encodingとは一般的に説明 変数に含まれるカテゴリ変数と目的 変数を元にして特徴量を作り出す。 • 今回は騎手名をカテゴリ変数とし て特徴量を作成している。

    22 jocky flag holdout_ts 津村明秀 0 0.137001 井上敏樹 0 0.050512 吉田隼人 0 0.173719 秋山真一 0 0.1422 藤岡康太 1 0.160703 ... ... ... 小崎綾也 1 0.104527 富田暁 0 0.082949 川又賢治 0 0.103596 浜中俊 0 0.228835 国分恭介 0 0.074155
  3. 前走成績 24 Name_days_df = df[[“horsename”, “place”, “turf”, “distance”, “days”, “pop”,

    “odds”, “rank3”, “rank4”, “3ftime”, “result”, ‘speedindex’, ‘last_race_index’, ‘count’, ‘rentai’]].sort_values([‘horsename’, ‘days’]) name_list = name_days_df[‘horsename’].unique() df_shift_list = [] df_rolling_list = [] For name in name_list: name_df = name_days_df[name_days_df[‘horsename'] == name] shift_name_df = name_df[["place", "turf", "distance", "pop", "odds", "rank3", "rank4", "3ftime", "result", 'speedindex', 'last_race_index']].shift(1) rolling_name_df = name_df[["pop", "odds", "3ftime", 'speedindex', "result", 'count', 'rentai']].rolling(5, min_periods=1)¥ .agg(agg_list).shift(1) shift_name_df['horsename'] = name rolling_name_df['horsename'] = name df_shift_list.append(shift_name_df) df_rolling_list.append(rolling_name_df)
  4. 特徴量の生成 25 # 特徴量生成 df['flag_konkan'] = (df['distance'] % 400 ==

    0).astype(int) df['flag_pre_konkan'] = (df['pre_distance'] % 400 == 0).astype(int) df['odds_hi'] = (df['odds'] / df['pop']) df['re_odds_hi'] = (df['pre_odds'] / df['pre_pop']) df['odds_hi*2'] = df['odds_hi'] ** 2 df['re_odds_hi*2'] = df['re_odds_hi'] ** 2 df['re_3_to_4time'] = (df['pre_rank4'] - df['pre_rank3']) df['re_3_to_4time_hi*2'] = (df['pre_rank4'] / df['pre_rank3']) ** 2 df['re_pop_now_pop'] = (df['pre_pop'] - df['pop']) df['re_odds_now_odds'] = (df['pre_odds'] - df['odds']) df['re_result_to_pop'] = (df['pre_result'] - df['pre_pop']) df['popmax_popmin'] = df['popmax'] - df['popmin'] df['oddsmax_oddsmin'] = df['oddsmax'] - df['oddsmin'] df['rentai_ritu'] = (df["rentai5sum"] / df["count5sum"]).round(3)
  5. カテゴリ変数化 df = df.astype({'distance': 'string', 'pre_distance': 'string'}) cat_cols = ['place',

    'turf', 'distance', 'weather', 'condition', 'sex', 'horsename', 'trainer', 'pre_place', 'pre_turf', 'pre_distance'] for c in cat_cols: le = LabelEncoder() le.fit(df[c]) df[c] = le.transform(df[c]) df['days'] = pd.to_datetime(df['days']) df = df.dropna(how='any') drop_list = ['days', 'raceid', 'result', 'racenum', 'class', 'jocky', 'horsecount', 'weight', 'father', 'mother', 'fathertype', 'legtype', 'fathermon’] LightGBMはカテゴリ変数を読み込める ので使用する。 しかしTensorflowを使う場合は(調べた 限り)カテゴリ変数を使うことができな い感じでしたのでダミー変数化や targetencodingで直していきます。 28
  6. (補足)ダミー変数化 df = df.replace({'distance': [1000, 1200, 1400, 1500]}, 'sprint') df

    = df.replace({'distance': [1600, 1700, 1800]}, 'mile') df = df.replace({'distance': [2000, 2200, 2300, 2400]}, 'middle') df = df.replace({'distance': [2500, 2600, 3000, 3200, 3400, 3600]}, 'stayer') df = df.replace({'pre_distance': [1000, 1200, 1400, 1500]}, 'sprint') df = df.replace({'pre_distance': [1600, 1700, 1800]}, 'mile') df = df.replace({'pre_distance': [2000, 2200, 2300, 2400]}, 'middle') df = df.replace({'pre_distance': [2500, 2600, 3000, 3200, 3400, 3600]}, 'stayer') columns_list = ['place', 'class', 'turf', 'weather', 'distance', 'condition', 'sex', 'pre_place', 'pre_turf', 'pre_distance'] df = pd.get_dummies(df, columns=columns_list) df = df.drop(['father', 'mother', 'fathermon', 'fathertype', 'legtype', 'jocky', 'trainer'], axis=1) このようにダミー変数化をした際 に特徴量の数を増やし過ぎないよ うにグループを作って変数化する。 29
  7. params = { 'task': 'predict', 'objective': 'binary', 'verbosity': -1, }

    model = lgb.train( params, lgb_train, categorical_feature=cat_cols, valid_sets=lgb_eval, num_boost_round=100, early_stopping_rounds=10, ) best_params = model.params model = lgb.train( best_params, lgb_train, categorical_feature=cat_cols, valid_sets=lgb_eval, num_boost_round=100, # 100 early_stopping_rounds=10, # 20 ) lightGBMのハイパーパラメータの作成は自動 最適化フレームワークoptunaを利用して作成 モデル(LightGBM) 30
  8. model = keras.Sequential([ keras.layers.Dense( 256, activation='relu', input_shape=(train_features.shape[-1],)), keras.layers.Dense( 128, activation='relu',

    input_shape=(train_features.shape[-1],)), keras.layers.Dense( 128, activation='relu', input_shape=(train_features.shape[-1],)), keras.layers.Dropout(0.1), keras.layers.Dense( 256, activation='relu', input_shape=(train_features.shape[-1],)), keras.layers.Dense( 128, activation='relu', input_shape=(train_features.shape[-1],)), keras.layers.Dense( 128, activation='relu', input_shape=(train_features.shape[-1],)), keras.layers.Dropout(0.1), keras.layers.Dense( 256, activation='relu', input_shape=(train_features.shape[-1],)), keras.layers.Dense( 128, activation='relu', input_shape=(train_features.shape[-1],)), keras.layers.Dense( 128, activation='relu', input_shape=(train_features.shape[-1],)), keras.layers.Dropout(0.1), keras.layers.Dense( 256, activation='relu', input_shape=(train_features.shape[-1],)), keras.layers.Dense(1, activation='sigmoid', bias_initializer=output_bias), ]) Tensorflowのドキュメントを利用して作成しています。 右のコードのように層を作成していく。 http://marupeke296.com/IKDADV_DL_No2_Keras.html モデル(Tensorflow) 31
  9. モデルの評価 • TensorFlow binary_logloss: 0.5291 accuracy: 0.7176 • LightGBM binary_logloss:

    0.4118 accuracy: 0.80951 正確度(Accuracy)が割といい感じにできているが Loglossが高くなっている。 →競馬予想であるため高くなるのは必然的な気がする。 33
  10. 結果 • 合計は8,300円で回収率は119%と 目標である回収率100%を達成するこ とができた。 • 場所別でみると • 中山競馬場:回収率136% •

    阪神競馬場:回収率110% • 小倉競馬場:回収率95% 35 単勝 複勝 合計 ¥3,960 ¥4,340 回収率 113% 124% 的中数 12 27 的中率 34% 77%
  11. さいごに <使用可能言語/ツール> 得意言語:Python Django (Django-Rest-Framework) /Ruby on Rails / Pandas

    / TensorFlow / React.js / AWS / GCP / Docker データ分析やWebアプリケーションの開発やりたいです。もし気になりま したらFaceBookなどメッセージをいただけると幸いです! 39