見出し画像

【備忘録】機械学習ツールH2O.aiを用いた予測モデルの構築 -未来日付追加&精度改善編-(7/16更新)

!!!7/16 19:00現在検証中!!!
(本日一日中検証しているが、未来日付の予測精度がなかなか改善できない…)

前提:

● 1万レコードのサンプルデータで売上予測モデルを構築する。
● 売上予測モデルのデータソースを作成するために、自動機械学習を強みとする機械学習ツール:H2O.aiを選択した。
● データソースをビジュアライズするために、私が専門とするBIツール:Tableauデスクトップを選択した。

失敗ログ:

● 売上データのスケーリング手法として標準化「StandardScaler」を実行したが結果は小数という異常値になった。売上データを平均0、標準偏差1の分布に変換して各特徴量を同じスケールに調整することで、モデルが特定の特徴量に偏らず均等に学習することを狙った。

scaler = StandardScaler()
data_df[['売上']] = scaler.fit_transform(data_df[['売上']])

● 売上データのスケーリング手法として正規化「MinMaxScaler」を実行したが結果は小数という異常値になった。

scaler = MinMaxScaler()
data_df[['売上']] = scaler.fit_transform(data_df[['売上']])

● 季節性を考慮した時系列予測モデルとして「Prophet」をインストールし仮想環境を含めて実行を試みたが、Prophet パッケージが Numpy のバージョンと互換性がないなどのエラーを繰り返してうまくいかなかったため他手段を試すこととした。

● Prophet とよく似た API で Numpy 最新バージョンにも対応している「NeuralProphet」を実行したが結果は季節性があまり考慮されていない整数になった。また、NeuralProphet のハイパーパラメーター(例:バッチサイズ、エポック数、学習率など)を調整してモデルの精度向上を狙ったがほとんど変わらず。

model = NeuralProphet(batch_size=64, epochs=200, learning_rate=0.01)
model.fit(prophet_df, freq='D')

ステップ0:事前準備等

# 欠損値の確認
print(data_df.isnull().sum())

# 異常値の確認
print(data_df.describe())

# 平均値の比較
test_df = data_df[(data_df['オーダー日'] >= "2024-01-01") & (data_df['オーダー日'] <= "2024-12-31")]
comparison_df = pd.merge(test_df[['オーダー日', '売上']], forecast_df, on='オーダー日', how='left')
print(comparison_df)
print(f"実績データの平均売上: {test_df['売上'].mean()}")
print(f"予測データの平均売上: {forecast_df['予測売上'].mean()}")

ステップ1:データのインポートと前処理

Python
import h2o
import pandas as pd
from h2o.frame import H2OFrame

# H2Oの初期化
h2o.init()

# データのインポート
data = h2o.import_file("C:/data/sample_superstore.csv")

# Pandasデータフレームに変換
# フィルタリングを正常処理するためPandasフレームに一旦変換
data_df = data.as_data_frame(use_pandas=True)

# 行番号を追加
# ビジュアライズ時のデータソースの紐づけのため
data_df['行番号'] = range(len(data_df))

# 日付文字列を日付形式に変換
data_df['オーダー日'] = pd.to_datetime(data_df['オーダー日'], format='%Y/%m/%d')

# 新しい特徴量の追加
data_df['月'] = data_df['オーダー日'].dt.month
data_df['四半期'] = data_df['オーダー日'].dt.quarter
data_df['年'] = data_df['オーダー日'].dt.year

# トレーニングデータセットの抽出
# 2021年1月〜2023年12月の3年分でトレーニング
train_df = data_df[(data_df['オーダー日'] >= "2021-01-01") & (data_df['オーダー日'] <= "2023-12-31")]

# トレーニングデータをH2Oフレームに変換
# フィルタリングを正常処理したためH2Oフレームに戻す
train_h2o = H2OFrame(train_df)

ステップ2:モデルのトレーニングと予測

from h2o.automl import H2OAutoML

# 特徴量とターゲットの設定
x = ["オーダー日", "カテゴリ", "地域", "行番号", "月", "四半期", "年"]
y = "売上"

# AutoMLを使用したモデルのトレーニング
# H2O.aiを使用する一番の理由はこの自動機械学習
aml = H2OAutoML(max_runtime_secs=600, seed=1234, nfolds=5)
aml.train(x=x, y=y, training_frame=train_h2o)

# テストデータセットの抽出
# 2024年1月〜2024年12月の1年分でテスト
test_df = data_df[(data_df['オーダー日'] >= "2024-01-01") & (data_df['オーダー日'] <= "2024-12-31")]

# テストデータをH2Oフレームに変換
# フィルタリングを正常処理したためH2Oフレームに戻す
test_h2o = H2OFrame(test_df)

# 予測の実行
predictions_2024 = aml.leader.predict(test_h2o)

# 予測結果に行番号を追加
# ビジュアライズ時のデータソースの紐づけのため
predictions_2024 = predictions_2024.cbind(test_h2o["行番号"])

# 予測結果をCSVファイルにエクスポート
h2o.export_file(predictions_2024, path="C:/data/predictions_2024.csv", force=True)

# 2025年のダミーデータ生成
future_dates = pd.date_range(start="2025-01-01", end="2025-12-31", freq='D')
future_df = pd.DataFrame(future_dates, columns=['オーダー日'])
future_df['カテゴリ'] = 'カテゴリー' # 適切なカテゴリを使用
future_df['地域'] = '地域' # 適切な地域を使用
future_df['行番号'] = range(len(future_df))
future_df['月'] = future_df['オーダー日'].dt.month
future_df['四半期'] = future_df['オーダー日'].dt.quarter
future_df['年'] = future_df['オーダー日'].dt.year

# H2Oフレームに変換
# ダミーデータ生成を正常処理したためH2Oフレームに戻す
future_h2o = H2OFrame(future_df)

# 予測の実行
predictions_2025 = aml.leader.predict(future_h2o)

# 予測結果に行番号を追加
# ビジュアライズ時のデータソースの紐づけのため。なくてもいいかも?
predictions_2025 = predictions_2025.cbind(future_h2o[["オーダー日", "行番号"]])

# 予測結果をCSVファイルにエクスポート
h2o.export_file(predictions_2025, path="C:/data/predictions_2025.csv", force=True)

# 予測結果のデータフレームを取得
predictions_2025_df = pd.read_csv("C:/data/predictions_2025.csv")

# エポックタイムを日付形式に変換
# ビジュアライズに日付フィールドを使用するため
predictions_2025_df['オーダー日'] = pd.to_datetime(predictions_2025_df['オーダー日'], unit='ms')

# 修正後のデータを再度CSVに保存
predictions_2025_df.to_csv("C:/data/predictions_2025_fixed.csv", index=False)

以上


この記事が気に入ったらサポートをしてみませんか?