CONTENTS コンテンツ

ChatGPTを使ってPythonを学ぼう!(53)

ChatGPTを使ってPythonを学ぼう!

2024.03.23

 Python学習編53回目です。

 scikit-learnライブラリで実際にデータをいじってみる。題材は金利と株価。データは財務省の国債金利とTOPIX終値。前回は。同日付のデータを使って微妙な感じになったので、日付をずらしてみよう。

入力:scikit-learnライブラリを使って時系列分析を考えています。 データは日付昇順で格納されています。 データAとn日後のデータBの相関関係を分析したい場合、どうすればよいですか

出力:

Scikit-learnを使用して時系列データの分析を行う場合、データAとn日後のデータBの相関関係を調べるにはいくつかのステップが必要です。以下に基本的な手順を示します。

  1. データの準備: 時系列データを正しく準備し、特徴量とターゲット変数を定義します。このケースでは、データAを特徴量として、n日後のデータBをターゲット変数として使用します。
  2. ラグ特徴量の作成: n日後の相関を調べたい場合、データAからn日分のラグ特徴量を作成します。つまり、各日付のデータポイントに対して、n日後のデータBの値をターゲットとして関連付けます。
  3. データの分割: モデルの訓練とテストのためにデータセットを訓練セットとテストセットに分割します。時系列データの場合、ランダムな分割ではなく、時間に基づいて順序を保ったまま分割することが重要です。
  4. モデルの選択と訓練: 相関関係を分析するためのモデルを選択し、訓練セットを使用してモデルを訓練します。Scikit-learnには多くの回帰モデルが用意されていますが、線形回帰やランダムフォレスト回帰などが一般的に使用されます。
  5. 評価: 訓練されたモデルをテストセットに適用し、モデルの性能を評価します。性能評価のためには、R^2値、平均絶対誤差(MAE)、平均二乗誤差(MSE)などの指標を使用できます。
  6. 相関の分析: モデルの係数や特徴量の重要度を分析することで、データAとn日後のデータBとの相関関係を理解します。

実際のコード例を示します。この例では、データAをfeaturesとし、n日後のデータBをtargetとして、線形回帰モデルを使用しています。

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score

# データの読み込み(例)
df = pd.read_csv('your_data.csv')

# ラグ特徴量の作成
n = 5  # n日後のデータとの相関を見たい場合
df['target'] = df['B'].shift(-n)

# 欠損値の削除(ラグ特徴量作成により発生する可能性がある)
df.dropna(inplace=True)

# 特徴量とターゲット変数の定義
X = df[['A']]  # ここで複数の特徴量を使用する場合は、適宜調整してください。
y = df['target']

# データの分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)

# モデルの訓練
model = LinearRegression()
model.fit(X_train, y_train)

# モデルの評価
y_pred = model.predict(X_test)
print(f'MSE: {mean_squared_error(y_test, y_pred)}')
print(f'R^2: {r2_score(y_test, y_pred)}')

なるほど、.shift(-n)でn行先を指定しているのか。これでnを動かして、一番フィットするnを求めるコードにするとこんな感じか

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score

# データの読み込み(例)
df = pd.read_csv('10年債とTOPIX.csv')

#MSE値の格納
MSEs = []

for n in range(0,30): # n=0~30日後のTOPIX変化値との相関を見る
  # ラグ特徴量の作成
  df['target'] = df['TOPIX変化率'].shift(-n)

  # 欠損値の削除(ラグ特徴量作成により発生する可能性がある)
  df.dropna(inplace=True)

  # 特徴量とターゲット変数の定義
  X = df[['10年債利回り変化値']]  # ここで複数の特徴量を使用する場合は、適宜調整してください。
  y = df['target']

  # データの分割
  X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)

  # モデルの訓練
  model = LinearRegression()
  model.fit(X_train, y_train)

  # モデルの評価
  y_pred = model.predict(X_test)
  MSEs.append(f'MSE: {mean_squared_error(y_test, y_pred)}')

print(MSEs)
print(min(MSEs))
print(MSEs.index(min(MSEs)))

結果
MSE: 0.00010045796678755276
3

3日後が最もMSEが小さいらしい。3日後を指定して散布図見るか。

import numpy as np
import matplotlib.pyplot as plt
# データの読み込み
df = pd.read_csv('10年債とTOPIX.csv')
# ラグ特徴量の作成
df['target'] = df['TOPIX変化率'].shift(-n)

# 欠損値の削除(ラグ特徴量作成により発生する可能性がある)
df.dropna(inplace=True)

# 特徴量とターゲット変数の定義
X = df[['10年債利回り変化値']]  # ここで複数の特徴量を使用する場合は、適宜調整してください。
y = df['target']

# 訓練データとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)

model=LinearRegression() # 線形回帰モデル
model.fit(X_train,y_train) # モデルを訓練データに適合
y_predicted=model.predict(X_test) # テストデータで予測
print(mean_squared_error(y_test,y_predicted)*10000) # 予測精度(平均二乗誤差)の評価。%の2乗の単位
coefficient = model.coef_[0] # 係数を取得
intercept = model.intercept_ # 切片を取得
print(f"回帰式: y = {intercept} + {coefficient}x") #回帰式を表示
x_plot=np.linspace(-0.1,0.1) # xの値の範囲を設定
X_plot=x_plot[:,np.newaxis] #モデルのpredictメソッドに適合する形式にするため、xの値を2次元配列に変換
y_plot=model.predict(X_plot) # 生成したxの値に対する予測値yを計算
plt.scatter(X,y, s = 2) # 元のデータ点を散布図としてプロット
plt.plot(x_plot,y_plot); # 線形回帰モデルに基づく予測値を直線としてプロット

結果
MSE = 1.0034811734145876
回帰式: y = 0.0004621142092594879 + 0.001611311967620051x

 平均二乗誤差1.00%、傾き約0.16%(前回:平均二乗誤差1.36%、傾き約1.95%)。うーん。平均二乗誤差は小さくなったが、「10年国債金利が0.1%上昇すると3日後のTOPIXが0.016%上昇する傾向にある」って、誤差みたいな結果見せられても何の役にも立たんな。まぁ役に立つならとっくに研究されて3日経つ前に値上がりという形で調整されてるか。

次回に続く

この記事をシェアする