LSTMを使った時系列予想モデル - TensorFlow実装例
🎯 はじめに
競馬予想において、馬の過去のパフォーマンスの時系列変化を捉えることは非常に重要です。 本記事では、LSTM(Long Short-Term Memory)ネットワークを使用して、 馬の成長曲線や調子の波を分析し、高精度な予想モデルを構築する方法を解説します。
この記事で学べること
- LSTMの基本概念と競馬への応用
- TensorFlowでのLSTMネットワーク実装
- 時系列データの前処理と特徴量作成
- Attention機構を含む高度なアーキテクチャ
- モデル評価と予想精度の向上手法
🧠 1. LSTMの基本概念
LSTMとは
LSTM(Long Short-Term Memory)は、従来のRNNの問題点である勾配消失問題を解決した 深層学習アーキテクチャです。競馬データにおいては以下の特徴を活用できます:
競馬データでのLSTMの利点
- 長期記憶: 馬の長期的な成長曲線を記憶
- 短期記憶: 最近の調子や状態変化を捉える
- ゲート機構: 重要な情報を選択的に保持・更新
- 時系列パターン: 季節要因や周期的な変動を学習
環境設定
# 必要なライブラリのインストール
pip install tensorflow pandas numpy matplotlib scikit-learn
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
import pandas as pd
import numpy as np
print("TensorFlow version", tf.__version__)
print("GPU available", tf.config.list_physical_devices('GPU'))
📊 2. 時系列データの準備
データ読み込みと前処理
# 競馬データの読み込み
race_data = pd.read_csv('horse_race_history.csv')
# 日付型変換
race_data['race_date'] = pd.to_datetime(race_data['race_date'])
# 馬ごとに時系列順にソート
race_data = race_data.sort_values(['horse_id', 'race_date'])
print("データ形状", race_data.shape)
print("期間", race_data['race_date'].min(), "~", race_data['race_date'].max())
時系列特徴量の作成
def create_time_series_features(df):
# 基本特徴量
features = [
'finish_position', # 着順
'horse_weight', # 馬体重
'jockey_weight', # 騎手重量
'odds', # オッズ
'race_distance', # 距離
]
# パフォーマンス指標の計算
df['position_score'] = 1.0 / df['finish_position'] # 着順の逆数
df['win_flag'] = (df['finish_position'] == 1).astype(int)
# レース間隔
df['days_since_last'] = df.groupby('horse_id')['race_date'].diff().dt.days
df['days_since_last'] = df['days_since_last'].fillna(30)
time_features = features + ['position_score', 'win_flag', 'days_since_last']
return df, time_features
race_data, feature_columns = create_time_series_features(race_data)
シーケンスデータの作成
def create_sequences(df, feature_columns, sequence_length=5):
sequences = []
targets = []
for horse_id in df['horse_id'].unique():
horse_data = df[df['horse_id'] == horse_id].copy()
if len(horse_data) < sequence_length + 1:
continue
# 正規化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
horse_features = scaler.fit_transform(horse_data[feature_columns])
# シーケンス作成
for i in range(len(horse_features) - sequence_length):
seq = horse_features[i:i+sequence_length]
target = horse_data.iloc[i+sequence_length]['win_flag']
sequences.append(seq)
targets.append(target)
return np.array(sequences), np.array(targets)
sequence_length = 5
X_sequences, y_sequences = create_sequences(race_data, feature_columns, sequence_length)
print("シーケンス数", len(X_sequences))
print("シーケンス形状", X_sequences.shape)
🤖 3. LSTMモデルの構築
基本的なLSTMモデル
from sklearn.model_selection import train_test_split
# データ分割
X_train, X_test, y_train, y_test = train_test_split(
X_sequences, y_sequences, test_size=0.2, random_state=42
)
# LSTMモデルの構築
model = Sequential([
LSTM(64, return_sequences=True, input_shape=(sequence_length, len(feature_columns))),
Dropout(0.2),
LSTM(32, return_sequences=False),
Dropout(0.2),
Dense(16, activation='relu'),
Dense(1, activation='sigmoid')
])
model.compile(
optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy']
)
print(model.summary())
モデルの訓練
from tensorflow.keras.callbacks import EarlyStopping
# コールバック設定
early_stopping = EarlyStopping(
monitor='val_loss',
patience=10,
restore_best_weights=True
)
# 訓練
history = model.fit(
X_train, y_train,
validation_data=(X_test, y_test),
epochs=100,
batch_size=32,
callbacks=[early_stopping],
verbose=1
)
# 評価
from sklearn.metrics import accuracy_score
y_pred = (model.predict(X_test) > 0.5).astype(int)
accuracy = accuracy_score(y_test, y_pred)
print("LSTM精度", accuracy)
📈 4. モデル評価と実用化
学習曲線の可視化
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'], label='Training Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.title('Model Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'], label='Training Accuracy')
plt.plot(history.history['val_accuracy'], label='Validation Accuracy')
plt.title('Model Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.tight_layout()
plt.show()
実用的な予想システム
class HorseRacingLSTMPredictor:
def __init__(self, model, scaler, feature_columns, sequence_length):
self.model = model
self.scaler = scaler
self.feature_columns = feature_columns
self.sequence_length = sequence_length
def predict_horse_performance(self, horse_history):
if len(horse_history) < self.sequence_length:
return None
# 最新のデータを取得
recent_history = horse_history.tail(self.sequence_length)
# 特徴量正規化
features = self.scaler.transform(recent_history[self.feature_columns])
sequence = features.reshape(1, self.sequence_length, -1)
# 予測
win_probability = self.model.predict(sequence)[0][0]
return win_probability
# 予想システムのインスタンス化
predictor = HorseRacingLSTMPredictor(
model=model,
scaler=scaler,
feature_columns=feature_columns,
sequence_length=sequence_length
)
print("LSTM予想システムが準備完了しました!")
🎯 まとめ
本記事では、LSTMを使った競馬の時系列予想モデルについて詳しく解説しました。 特に重要なポイントは以下の通りです:
重要なポイント
- 時系列の重要性: 馬の成長曲線や調子の波を捉える
- LSTM構造: 長期・短期両方の記憶を活用
- シーケンス長の調整: 適切な過去レース数の設定が重要
- 特徴量エンジニアリング: 時系列特有の特徴量作成
- 実用化: 予想システムとしての実装
技術的な発展可能性
- Attention機構: より重要なタイムステップに注目
- 多変量時系列: 複数馬の相互作用を考慮
- 強化学習: 投資戦略の最適化
- Transformer: より高度な時系列モデル
LSTMを基盤として、さらに高度な深層学習手法を組み合わせることで、 より精度の高い競馬予想システムを構築できるでしょう。