■ はじめに
現職で所属する部署において需要予測を行っており、今まで勘と経験に頼った予測部分があったため、可能な限りデータに基づいて意思決定・予測ができるようになるため受講を決断いたしました。
業務との並行のため、ぎりぎりになりましたがなんとか成果物を作成できたのはAidemyさんのご協力のおかげです。ありがとうございました。
データ分析初学者のため、記載内容に誤りがあった場合はご容赦願います。
※このブログはAidemy Premiumのカリキュラムの一環で、受講修了条件を満たすために公開しています。
■ 概要
・将来の売上げ予測(金額)
・活用データ:e-Stat(全国(二人以上の世帯限る)グロサリーカテゴリーデータ(加工済み))
・データの特徴確認
・特徴から実装モデルを選定
・モデル構築
・グラフ化
■ 実行環境
Google Colab
■ 手順
1 必要なライブラリをインポート
import warnings
import itertools
import pandas as pd
import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt
%matplotlib inline
2 データの読み込み
2000年1月から24年5月までの売上げデータ(数値加工分)読み込み。
sales_grocery = pd.read_csv("/content/monthly-grocery-sales-in-japan.csv", encoding="shift-jis")
3 読み込んだデータの整理
index = pd.date_range(start='2000/1/1', end='2024/6/1', freq='M')
sales_grocery.index = index
if 'Month' in sales_grocery.columns:
sales_grocery = sales_grocery.drop(columns=["Month"])
warnings.filterwarnings('ignore')
4 モデル選定
季節性とトレンドがあることを確認したため「SARIMAモデル」を選定。
※SARIMAモデル=S(季節性)+AR(自己相関)+I(トレンド加味のための階差)+MA(誤差)
5 モデルのパラメータ決定
「自己相関、差分、誤差」それぞれ何期前を見るか、また「自己相関、差分、誤差」の季節性は何期前まで見るか、「季節性の周期」の合計7つはハイパーパラメーター。
元データは月ごとのデータであることと、波形分解の「seasonal」で見えた波形から「季節性の周期」は12に。
その他のパラメータはselectparameter関数で最もBICが低くなる組み合わせを選ぶ。
def selectparameter(DATA, s):
p = d = q = range(0, 2)
pdq = list(itertools.product(p, d, q))
seasonal_pdq = [(x[0], x[1], x[2], s) for x in list(itertools.product(p, d, q))]
parameters = []
BICs = np.array([])
for param in pdq:
for param_seasonal in seasonal_pdq:
try:
mod = sm.tsa.statespace.SARIMAX(DATA,
order=param,
seasonal_order=param_seasonal)
results = mod.fit()
parameters.append([param, param_seasonal, results.bic])
BICs = np.append(BICs, results.bic)
except Exception as e:
print(f"モデルのフィッティングに失敗しました: {param}, {param_seasonal}, エラー: {e}")
continue
if BICs.size > 0:
return parameters[np.argmin(BICs)]
else:
raise ValueError("最適なパラメータが見つかりませんでした。")
6 モデル構築
5で決めたパラメータを使いSARIMAモデルにsales_groceryを学習させモデルを構築。
try:
best_params = selectparameter(sales_grocery, 12)
SARIMA_sales_grocery = sm.tsa.statespace.SARIMAX(sales_grocery,
order=best_params[0],
seasonal_order=best_params[1],
enforce_stationarity=False,
enforce_invertibility=False).fit()
except ValueError as e:
print(e)
best_params = None
7 構築したモデルによる売上げ予測
2024年6月から2028年1月までの売上げを予測。
pred = SARIMA_sales_grocery.predict(start='2024/6/1', end='2028/1/1')
plt.plot(pred, color='r', label='predict')
plt.plot(sales_grocery, label='actual')
plt.title('SARIMA model')
plt.xlabel('year')
plt.ylabel('proceeds')
plt.legend()
plt.show()
青は実際の数字、赤は予測値
pred.summary()
summaryの確認
■ 予測結果からの考察
1)2000年から2014年に向けてダウントレンド
2)2014年から2024年に向けてアップトレンド
3)2021年におけるノイズ
過去の記事を遡ったところ、2015年から円安に伴う値上げが実施されていることが確認された。
今回グロサリー(生活必需品)に限定していたため、消費以上に物価の高騰に伴ったアップトレンドであることが観測できた。
2021年の上昇はそれまでのトレンド以上の上昇が観測でき、これはコロナによって需要が集まったことと物価の上昇が相まったことによるデータであると考える。
今後も物価の上昇は継続すると考えるとグラフは肌感とも合う予測結果になったと思う。
■ 今後の課題
今回はデータを外部に出すことができないため、e-Statのデータをもとに予測を行った。
社内のデータでも実行してみたところ、また別のトレンドを見ることができた。
ただし、上記コードでは値上げや値下げの金額変動の影響を加味しきれていなかったため、カテゴリー内における商品性質を加味した上、数量ベースで予測を行っていきたい。
また、気温や県ごとの特性等の詳細部分の影響を加味できていないため、そういった外部要因を予測に追加していきたい。