時系列データ予測は、販売数やアクセス数など、時間の経過とともに変化するデータを扱う際に欠かせない手法です。たとえば、観光客が多く訪れる京都では、季節やイベントに応じて需要が大きく変動します。そうした変動を正確に把握し、ビジネスや運営に活かすためには、時系列データの予測スキルが非常に重要になります。本記事では、時系列データを予測するうえで押さえておきたい基本的な流れや手法を、コード例とあわせてわかりやすく解説します。
1. データの前処理
時系列データを扱う上で、最初に行うべき作業がデータの前処理です。正確な予測モデルを構築するためにも、欠損値や異常値の処理、変換手法などを適切に実施する必要があります。
1-1. 欠損値処理
- 補間 (Interpolation): 線形補間 (linear)、スプライン (spline)、多項式 (polynomial) など
- 前後の値で補完:
ffill() / bfill()
- 中央値・平均値で補完:
fillna(df.mean())
- 時系列のトレンドを考慮した補間:
interpolate(method="time")
1-2. 異常値処理
- IQR (四分位範囲) 法: Q1 – 1.5×IQR, Q3 + 1.5×IQR
- 標準偏差法: ±3σ
- LOF (局所外れ値因子)
- Isolation Forest
1-3. データの変換
- 対数変換 (Log Transform): トレンドを抑え、分布を正規化
- Box-Cox変換 / Yeo-Johnson変換: 非負データの正規化
- Differencing (階差変換): 一階差分や二階差分を取ることでトレンドを除去
df["diff"] = df["target"].diff().dropna()
2. データの探索的分析 (EDA)
データの特徴を理解するためにトレンドや季節性、外れ値をチェックします。こうした分析結果を踏まえてモデルを選定することで、より適切な予測が可能になります。
2-1. トレンドの可視化
- 移動平均 (Moving Average): ローカルなトレンドの把握
- LOESS や HPフィルタ: 長期的なトレンドの抽出
import matplotlib.pyplot as plt
df["target"].plot(figsize=(12, 6), title="時系列データ")
df["target"].rolling(window=30).mean().plot(label="30日移動平均", linestyle="dashed")
plt.legend()
plt.show()
2-2. 季節性の分析
- STL 分解 (Seasonal-Trend decomposition using Loess)
- ACF (自己相関関数) / PACF (偏自己相関関数)
from statsmodels.tsa.seasonal import seasonal_decompose
result = seasonal_decompose(df["target"], model="additive", period=7)
result.plot()
plt.show()
3. モデル選定
データの特性と分析の目的に応じて、適切なモデルを選択します。
3-1. 古典的な時系列モデル
モデル | 適用する場合 |
---|---|
ARIMA | トレンドがあるが明確な季節性がない |
SARIMA | 季節性があるデータ |
Prophet | 欠損値があるデータや休日効果を考慮したい場合 |
3-2. 機械学習モデル
モデル | 適用する場合 |
---|---|
XGBoost / LightGBM | 外れ値に強く、特徴量エンジニアリングを活かしたい場合 |
Random Forest | 非線形なパターンを学習できる |
3-3. ディープラーニング
モデル | 適用する場合 |
---|---|
LSTM / GRU | 長期間の依存関係を学習 |
Temporal Fusion Transformer (TFT) | 時系列の依存関係を学習しながら解釈性も確保 |
4. 特徴量エンジニアリング
予測精度を引き上げるうえで重要なのが特徴量エンジニアリングです。時系列特有の特徴量を設計し、より多角的な情報をモデルに与えます。
4-1. 時間関連の特徴量
- 曜日 (day_of_week), 月 (month), 季節 (season), 祝日フラグ (is_holiday)
df["day_of_week"] = df["date"].dt.dayofweek
df["is_weekend"] = (df["day_of_week"] >= 5).astype(int)
4-2. 過去の統計量
• 移動平均 (Rolling Mean)
• 過去の同じ曜日の平均
• 指数移動平均 (EMA)
df["7day_avg"] = df["target"].rolling(7).mean()
df["14day_avg"] = df["target"].rolling(14).mean()
df["21day_avg"] = df["target"].rolling(21).mean()
4-3. ラグ特徴量
• 1日前、7日前、30日前の値など
df["lag_1"] = df["target"].shift(1)
df["lag_7"] = df["target"].shift(7)
4-4. 天気データ
• 気温 (temperature)
• 降水量 (precipitation)
df = df.merge(weather_data, on="date", how="left")
5. モデルの学習と評価
モデルを学習して予測を行い、RMSEなどの指標を用いて精度を評価します。
5-1. モデルの学習
import lightgbm as lgb
train_data = lgb.Dataset(X_train, label=y_train)
model = lgb.train({"objective": "regression", "metric": "rmse"}, train_data)
5-2. 評価指標
指標 | 説明 |
---|---|
RMSE | 大きな誤差を強調 |
MAE | 平均的な誤差の大きさ |
SMAPE | 0-100%で直感的に評価可能 |
from sklearn.metrics import mean_absolute_error, mean_squared_error
rmse = mean_squared_error(y_test, y_pred, squared=False)
mae = mean_absolute_error(y_test, y_pred)
6. 精度向上のための手法
最終的に精度をさらに上げるためのアプローチです。ハイパーパラメータ調整や新しい特徴量の追加、アンサンブル学習などを検討することで、より良い予測を実現します。
6-1. ハイパーパラメータの調整
- LightGBM:
num_leaves
,learning_rate
,min_child_samples
- LSTM:
batch_size
,hidden_size
,dropout
from optuna import create_study
study = create_study(direction="minimize")
6-2. 特徴量エンジニアリングの改善
- 新しいラグ特徴量
- 曜日ごとの平均
- 時系列クラスタリングによる分類
6-3. アンサンブル学習
- LightGBM + ARIMA のハイブリッド
- XGBoost + LSTM など
final_pred = 0.5 * lightgbm_pred + 0.5 * lstm_pred
6-4. 外れ値の処理
- Isolation Forest で除外
- Winsorization(外れ値を補正)
まとめ
- データの前処理: 欠損値補間や異常値処理、対数変換などの手法を活用
- EDA: トレンド・季節性・外れ値を把握して、データの特性を理解
- モデル選定: ARIMA・LightGBM・LSTM などデータ特性に応じたモデルを使い分け
- 特徴量エンジニアリング: ラグ特徴量やカレンダー情報、天候情報などを追加
- 学習と評価: RMSE、MAE、SMAPE などの指標でモデルを比較
- 精度向上: ハイパーパラメータ調整、アンサンブル、外れ値処理などを検討
時系列データは京都の観光需要予測や店舗売上予測など、幅広い分野で活用が期待されています。適切な手順とモデル選定、さらに的確な特徴量エンジニアリングを行うことで、正確な予測と実務的なインサイトを得ることができます。ぜひ本記事を参考に、時系列データ予測のプロセスを実践してみてください。