13日目:時系列データの扱い方!特徴量作成とモデルへの適用
皆さん、こんにちは!AI学習ロードマップ13日目を迎えました。これまでの学習で、構造化データ、画像データ、テキストデータといった様々なデータ型について、その前処理やモデルへの適用方法を学んできました。今日は、もう一つの非常に重要なデータ型である「時系列データ(Time Series Data)」に焦点を当てていきます。
時系列データは、時間の経過とともに記録されたデータであり、株価、気温、センサーデータ、電力消費量など、私たちの身の回りに溢れています。これらのデータは、過去のパターンから未来を予測する「時系列予測」や、異常を検知する「異常検知」といった、独自の分析課題を伴います。
本日は、時系列データが持つ特有の性質、そのための特徴量作成テクニック、そして時系列予測に適したモデルの考え方について、Pythonでの実装例とともに詳しく解説していきます。
1. 時系列データとは?その特有の性質
時系列データは、時間順に並べられた一連の観測値です。一般的な表形式データと異なり、以下の特有の性質を持ちます。
- トレンド (Trend): 時間とともにデータが上昇または下降する傾向。
- 季節性 (Seasonality): 特定の期間(日、週、月、年など)で繰り返されるパターン。
- 周期性 (Cyclicity): 季節性よりも長い期間で繰り返されるパターン。周期は固定ではないことが多い。
- 自己相関 (Autocorrelation): 過去のデータが未来のデータと相関を持つ性質。
- 定常性 (Stationarity): 時系列の統計的性質(平均、分散、自己相関など)が時間によって変化しない性質。多くの時系列モデルは定常性を仮定します。
これらの性質を考慮せずに一般的な機械学習モデルを適用すると、予測性能が著しく低下する可能性があります。
2. 時系列データのための特徴量作成(Feature Engineering for Time Series)
時系列データから特徴量を作成する(過去の情報を使って未来を予測できる形にする)ことは、時系列予測モデルの性能を大きく左右します。
2.1. タイムスタンプからの特徴量生成
日付や時刻情報から、周期性や季節性を捉える特徴量を作成します。
-
年 (Year)
、月 (Month)
、日 (Day)
-
曜日 (Day of Week)
、週番号 (Week of Year)
-
時間 (Hour)
、分 (Minute)
-
週末かどうか (Is Weekend)
、祝日かどうか (Is Holiday)
四半期 (Quarter)
import pandas as pd
import numpy as np
# サンプル時系列データの生成 (日次データ)
date_range = pd.date_range(start='2024-01-01', periods=365, freq='D')
np.random.seed(42)
data = np.random.rand(365) * 100 + np.sin(np.linspace(0, 30, 365)) * 20 + np.arange(365) * 0.1
df_ts = pd.DataFrame({'Value': data}, index=date_range)
print("--- 元の時系列データ (一部) ---")
print(df_ts.head())
# タイムスタンプからの特徴量生成
df_ts['Year'] = df_ts.index.year
df_ts['Month'] = df_ts.index.month
df_ts['Day'] = df_ts.index.day
df_ts['DayOfWeek'] = df_ts.index.dayofweek # 月曜=0, 日曜=6
df_ts['WeekOfYear'] = df_ts.index.isocalendar().week.astype(int) # 週番号
df_ts['Quarter'] = df_ts.index.quarter
df_ts['IsWeekend'] = (df_ts.index.dayofweek >= 5).astype(int) # 週末なら1, そうでなければ0
print("\n--- タイムスタンプからの特徴量 ---")
print(df_ts.head())
2.2. ラグ特徴量 (Lag Features)
過去の時点における目的変数や特徴量の値です。時系列データにおける自己相関を捉える最も基本的な方法です。
-
例:
前日の株価
、3時間前の気温
# ラグ特徴量の作成 (例: 1日前、2日前のValue)
df_ts['Value_Lag1'] = df_ts['Value'].shift(1)
df_ts['Value_Lag2'] = df_ts['Value'].shift(2)
print("\n--- ラグ特徴量 ---")
print(df_ts[['Value', 'Value_Lag1', 'Value_Lag2']].head())
2.3. 移動平均 (Moving Averages)
過去一定期間の平均値です。トレンドや季節性を平滑化し、ノイズの影響を軽減するのに役立ちます。
-
例:
過去7日間の平均株価
# 移動平均特徴量の作成 (例: 7日間の移動平均)
df_ts['Value_MA7'] = df_ts['Value'].rolling(window=7).mean()
print("\n--- 移動平均特徴量 ---")
print(df_ts[['Value', 'Value_MA7']].head(10)) # 最初の6行はNaN
2.4. 移動標準偏差 (Moving Standard Deviation) / 指数移動平均 (Exponential Moving Averages) など
- 移動標準偏差: ボラティリティ(変動の激しさ)を捉えます。
- 指数移動平均 (EMA): 最近のデータにより重みを与える移動平均です。
- 差分 (Differencing): 時系列データを定常にするために、現在の値と過去の値の差を取ります。トレンドや季節性を除去するのに使われます。
# 移動標準偏差 (例: 7日間の移動標準偏差)
df_ts['Value_Std7'] = df_ts['Value'].rolling(window=7).std()
# 差分 (例: 1次差分)
df_ts['Value_Diff1'] = df_ts['Value'].diff(1)
print("\n--- 移動標準偏差と差分 ---")
print(df_ts[['Value', 'Value_Std7', 'Value_Diff1']].head())
3. 時系列データのためのデータ分割
6日目で学んだデータ分割の原則は時系列データでも重要ですが、ランダムに分割してはいけません。
-
時間順分割 (Temporal Split): 過去のデータで学習し、未来のデータで評価するという原則を守るため、常に時系列順にデータを分割します。
- 訓練データ:最も古い期間のデータ
- 検証データ:訓練データより新しい期間のデータ
- テストデータ:最も新しい期間のデータ
# 時系列データは欠損値(NaN)を含む特徴量が存在しうるため、適宜処理
df_ts_clean = df_ts.dropna()
# データの分割 (80% 訓練, 20% テスト)
train_size = int(len(df_ts_clean) * 0.8)
train_df = df_ts_clean.iloc[:train_size]
test_df = df_ts_clean.iloc[train_size:]
print(f"\n--- 時系列データ分割 ---")
print(f"訓練データ開始: {train_df.index.min()}, 終了: {train_df.index.max()}, サイズ: {len(train_df)}")
print(f"テストデータ開始: {test_df.index.min()}, 終了: {test_df.index.max()}, サイズ: {len(test_df)}")
# 特徴量と目的変数の準備
# ここではラグ特徴量と移動平均を使って、翌日のValueを予測するタスクを想定
features = ['Value_Lag1', 'Value_Lag2', 'Value_MA7', 'Value_Std7', 'Value_Diff1', 'Year', 'Month', 'DayOfWeek', 'IsWeekend']
target = 'Value'
X_train = train_df[features]
y_train = train_df[target]
X_test = test_df[features]
y_test = test_df[target]
print(f"\n訓練特徴量 (X_train) サイズ: {X_train.shape}")
print(f"テスト特徴量 (X_test) サイズ: {X_test.shape}")
4. 時系列予測に適したモデルの考え方と例
一般的な機械学習モデル(線形回帰、決定木など)も時系列特徴量を作成すれば利用できますが、時系列データ特有の性質を考慮したモデルも存在します。
4.1. 統計的時系列モデル
-
ARIMA (AutoRegressive Integrated Moving Average):
- 自己回帰 (AR)、差分 (I)、移動平均 (MA) の3つの要素を組み合わせた古典的なモデルです。
- 定常時系列に適用されます。非定常な場合は差分をとって定常化します。
- 季節性を持つデータにはSARIMAが使われます。
-
Prophet (Facebook開発):
- トレンド、季節性、祝日などを加法モデルで分解し、直感的に予測を行います。
- 欠損値や外れ値に強く、非専門家でも扱いやすいのが特徴です。
4.2. 機械学習モデルの活用
前述の特徴量(ラグ特徴量、移動平均、時間情報など)を作成することで、ランダムフォレスト、勾配ブースティング(LightGBM, XGBoost)、サポートベクターマシンなどの一般的な機械学習モデルも時系列予測に利用できます。
- メリット: 複雑な非線形関係を学習できる。
- デメリット: 時系列特有の依存性(自己相関など)を直接モデルに組み込むわけではないため、特徴量エンジニアリングが重要。
4.3. ディープラーニングモデル
-
RNN (Recurrent Neural Network) / LSTM (Long Short-Term Memory) / GRU (Gated Recurrent Unit):
- 時系列データやシーケンスデータを扱うために設計されたニューラルネットワークです。
- 過去の情報を記憶し、それを現在の予測に利用する能力があります。
- LSTMやGRUは、RNNが抱える長期依存性学習の課題を克服した改良版です。
- Transformer: 自然言語処理でブレイクスルーを起こしたTransformerモデルも、時系列予測に応用されています。
4.4. Pythonでの線形回帰による時系列予測例
ここでは、前処理した時系列データに、8日目で学んだ線形回帰モデルを適用する例を示します。
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, mean_squared_error
import matplotlib.pyplot as plt
# LinearRegressionモデルの初期化と学習
ts_model = LinearRegression()
ts_model.fit(X_train, y_train)
# テストデータで予測
y_pred_ts = ts_model.predict(X_test)
# モデルの評価
mae = mean_absolute_error(y_test, y_pred_ts)
rmse = np.sqrt(mean_squared_error(y_test, y_pred_ts))
print(f"\n--- 線形回帰による時系列予測の評価 ---")
print(f"平均絶対誤差 (MAE): {mae:.2f}")
print(f"二乗平均平方根誤差 (RMSE): {rmse:.2f}")
# 予測結果の可視化
plt.figure(figsize=(12, 6))
plt.plot(train_df.index, train_df['Value'], label='Train Actual')
plt.plot(test_df.index, y_test, label='Test Actual', color='orange')
plt.plot(test_df.index, y_pred_ts, label='Predicted', color='green', linestyle='--')
plt.title('Time Series Prediction with Linear Regression')
plt.xlabel('Date')
plt.ylabel('Value')
plt.legend()
plt.grid(True)
plt.show()
この例では、基本的な線形回帰モデルでも時系列特徴量を適切に作成すれば、ある程度の予測が可能であることを示しています。しかし、より複雑な時系列パターン(非線形性、長期依存性など)を捉えるには、ARIMAやLSTMなどの専門的なモデルがより適しています。
5. まとめと次へのステップ
本日は、AI学習ロードマップの13日目として、時系列データの特性と、そのための効果的な特徴量作成、そしてモデルへの適用について学びました。
- 時系列データは、トレンド、季節性、自己相関といった特有の性質を持つことを理解しました。
- タイムスタンプからの特徴量抽出、ラグ特徴量、移動平均などが、時系列データから有用な情報を引き出すための重要なテクニックであることを学びました。
- 時系列データの分割は、時間順に行う必要があることを確認しました。
- 時系列予測には、統計的モデル(ARIMA, Prophet)、一般的な機械学習モデル(特徴量エンジニアリングを介して)、そして ディープラーニングモデル(RNN, LSTM, Transformer) が利用できることを知りました。
時系列分析は、ビジネスの意思決定、科学研究、社会インフラ管理など、多岐にわたる分野で不可欠な技術です。今日の知識を基に、株価データやセンサーデータなど、身近な時系列データで実践的な分析に挑戦してみてください。
明日からは、データに隠されたパターンを発見するための「教師なし学習」の世界に足を踏み入れていきます。その中でも、データ点をグループ分けする「クラスタリング」について詳しく学びましょう。
それでは、また明日!