見出し画像

動的配車管理へのアプローチ

機械学習プロフェッショナルシリーズをチクチクと読んでいく。

1)前処理

異なる時系列を持つデータをJSONデータで入手して、それを高階テンソルで構造化データにする。ここでテンソル分解を用いる。

import numpy as np
import tensorly as tl
from tensorly.decomposition import parafac, tucker

# サンプルデータ(各IDごとに複数の時系列データがあるリスト)
data = {
    'ID_1': [
        [1, 2, 3, 4, 5],  # 時系列1
        [2, 3, 4, 5, 6],  # 時系列2
    ],
    'ID_2': [
        [5, 6, 7, 8, 9],  # 時系列1
        [6, 7, 8, 9, 10],  # 時系列2
    ]
}

# 1. データをテンソル形式に変換
# ID × 時系列データ × 時間の3次元テンソルを作成
max_time_length = max(max(len(ts) for ts in id_data) for id_data in data.values())  # 最大の時系列長
tensor_data = []

for id_data in data.values():
    padded_data = [ts + [0] * (max_time_length - len(ts)) for ts in id_data]  # ゼロ埋めで揃える
    tensor_data.append(padded_data)

tensor_data = np.array(tensor_data)  # (ID, 時系列, 時間)
print("Tensor Shape:", tensor_data.shape)

# 2. テンソル分解 (CP分解)
rank = 3  # ランクを指定
cp_decomposition = parafac(tensor_data, rank=rank)

print("CP Decomposition Factors:")
for i, factor in enumerate(cp_decomposition):
    print(f"Factor {i + 1} shape: {factor.shape}")

# 3. テンソル分解 (Tucker分解)
core, tucker_factors = tucker(tensor_data, ranks=[2, 2, 3])  # ランクを指定
print("Tucker Decomposition Core Shape:", core.shape)
for i, factor in enumerate(tucker_factors):
    print(f"Tucker Factor {i + 1} shape: {factor.shape}")

2)本処理

ガウス過程で行う。(ベイズよりも複雑なモデルを扱えるしノイズに強い)

import GPy

# データ準備
X = np.linspace(0, 1, 10)[:, None]
Y = np.sin(2 * np.pi * X) + np.random.randn(*X.shape) * 0.1

# カーネル定義
kernel = GPy.kern.RBF(input_dim=1)

# モデル作成
m = GPy.models.GPRegression(X, Y, kernel)

# 最適化
m.optimize()

# 予測
X_new = np.linspace(0, 1, 100)[:, None]
mean, var = m.predict(X_new)

# 可視化
plt.plot(X, Y, 'kx', mew=2)
plt.plot(X_new, mean, 'C0')
plt.fill_between(X_new[:, 0], mean[:, 0] - 2*np.sqrt(var[:, 0]), mean[:, 0] + 2*np.sqrt(var[:, 0]), alpha=0.2)
plt.show()

3)因果関係の可視化

ベイジアンネットワークを視覚化するツール。
結果を視るのに良さそうだ。

import pygraphviz as pgv

# グラフオブジェクトの作成
G = pgv.AGraph(directed=True)

# ノードの追加
G.add_node('A', label='A')
G.add_node('B', label='B')
G.add_node('C', label='C')

# エッジの追加
G.add_edge('A', 'B', label='P(B|A)')
G.add_edge('A', 'C', label='P(C|A)')

# グラフのレイアウト
G.layout(prog='dot')

# グラフの描画
G.draw('bayes_network.png')

4)まとめ

因果関係を調べるのに役立つ。非線形の重回帰分析みたいなもんだ。

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from pycausal.inference import CausalImpact
from pycausal.estimation import LinearRegressionEstimator
from pycausal.synthetic import generate_data

# データの生成 (例)
X = generate_data(num_samples=1000, num_features=3, sem_type='linear')
X_train, X_test = train_test_split(X, test_size=0.2, random_state=42)

# LiNGAMモデルの作成と学習
from pycausal.inference.nonparametric import LiNGAM

model = LiNGAM()
model.fit(X_train)

# 因果効果の推定
treatment = 'X1'
outcome = 'X2'
control = ['X0']  # 共変量

# 効果の推定
effect = model.estimate_treatment_effect(X_test, treatment, outcome, control)
print(effect)

XAIは人間に説明する為のテクニック。

LIME

import lime
import lime.lime_tabular
from sklearn.ensemble import RandomForestClassifier

# データの準備
X = ...  # 説明変数
y = ...  # 目的変数

# モデルの構築
clf = RandomForestClassifier()
clf.fit(X, y)

# 説明したいデータのインデックス
index = 15

# LIMEの説明器を作成
explainer = lime.lime_tabular.LimeTabularExplainer(
    X_train,
    feature_names=feature_names,
    class_names=class_names,
    mode='classification'
)

# 説明を生成
exp = explainer.explain_instance(X_test[index], clf.predict_proba, num_features=5)

# 説明を表示
exp.as_list()

SHAP

import shap
from sklearn.ensemble import RandomForestClassifier

# モデルの構築
clf = RandomForestClassifier()
clf.fit(X, y)

# SHAPの計算
explainer = shap.TreeExplainer(clf)
shap_values = explainer.shap_values(X)

# 特徴量の重要度をプロット
shap.summary_plot(shap_values, X)


いいなと思ったら応援しよう!