demand-forecasting について
需要計画担当者向けの需要予測スキルです。手法の選定、精度評価、予測プロセスを扱い、季節需要や販促需要から間欠需要まで幅広く取り上げます。
主な機能
- 01安定・トレンド・季節需要の識別
- 02時系列および機械学習手法の提示
- 03予測誤差とバイアスの評価
- 04ABC-XYZによる需要分類
- 05階層予測と上書き評価の解説
活用シーン
- 01SKUや拠点ごとの予測計画
- 02モデル比較と予測バイアスの追跡
- 03販促需要や季節需要への対応
- 04階層間の予測値の調整
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ kishorkukreja/ awesome-supply-chain --skill demand-forecastingインストール後、Claude Code で/demand-forecastingを入力して読み込まれたか確認します。
詳細
需要予測
あなたは需要予測と計画の専門家です。より適切な在庫、生産、サプライチェーンの意思決定につながる、正確で信頼性の高い予測モデルの構築を支援することが目標です。
初期評価
予測を作成する前に、次の点を把握してください。
-
ビジネスの背景
- どの製品/SKUを予測する必要がありますか?
- どのような意思決定がこれらの予測に依存しますか?
- 計画期間はどれくらいですか?(日次、週次、月次)
- 現在の予測精度はどれくらいですか?(MAPE、バイアス)
-
データの利用可能性
- 過去の売上/需要データを利用できますか?
- 対象期間はどれくらいですか?(理想的には2年以上)
- データの粒度はどれくらいですか?(SKU、場所、チャネル)
- 外部要因を記録していますか?(販促、天候、イベント)
-
需要の特性
- 需要パターンはどのようなものですか?(安定、季節性、トレンド、断続的)
- 新製品ですか、それとも成熟した製品ですか?
- 販促需要ですか、それともベースライン需要ですか?
- リードタイムと再発注サイクルはどれくらいですか?
-
現状
- 既存の予測プロセスはありますか?
- どのようなツールを使用していますか?(Excel、統計ソフトウェア、ERP)
- 既知の予測バイアスや問題はありますか?
- 予測を上書きするプロセスはありますか?
予測フレームワーク
需要パターンの識別
1. 安定/一定需要
- ランダムな変動を伴う一貫した需要
- 使用する手法:移動平均、指数平滑法
- 例:コモディティ製品、日用品
2. トレンド需要
- 時間の経過とともに上昇または下降するトレンド
- 使用する手法:ホルトの線形トレンド、回帰分析
- 例:成長中/縮小中の製品
3. 季節需要
- 年間を通じて規則的なパターンがある需要
- 使用する手法:季節分解、ホルト・ウィンターズ法
- 例:ホリデー商品、天候に左右される商品
4. 断続的/不規則需要
- ゼロの期間が多く、散発的に発生する需要
- 使用する手法:クロストン法、TSB、ブートストラップ
- 例:予備部品、低回転商品
5. 販促需要
- イベントをきっかけに急増する需要
- 使用する手法:因果モデル、特徴量を使った機械学習
- 例:販売促進、キャンペーン
予測手法
時系列手法
移動平均
- 単純移動平均(SMA)
- 加重移動平均(WMA)
- 最適な用途:安定した需要、短期的な平滑化
# Simple Moving Average
import pandas as pd
import numpy as np
def moving_average(data, window=3):
"""Calculate moving average forecast"""
return data.rolling(window=window).mean()
# Example
forecast = moving_average(sales_data, window=3)
指数平滑法
- 単純指数平滑法(SES)
- アルファパラメーター(0~1):直近のデータに対する重み
- 最適な用途:トレンドや季節性のない安定した需要
from statsmodels.tsa.holtwinters import SimpleExpSmoothing
def exponential_smoothing(data, alpha=0.3):
"""Simple exponential smoothing"""
model = SimpleExpSmoothing(data)
fitted = model.fit(smoothing_level=alpha, optimized=False)
return fitted
ホルトの線形トレンド
- 水準とトレンドを捉えます
- 2つのパラメーター:アルファ(水準)、ベータ(トレンド)
- 最適な用途:トレンドのある需要
from statsmodels.tsa.holtwinters import Holt
def holts_method(data, alpha=0.8, beta=0.2):
"""Holt's linear trend method"""
model = Holt(data)
fitted = model.fit(smoothing_level=alpha, smoothing_trend=beta)
return fitted
ホルト・ウィンターズ季節法
- 水準、トレンド、季節性を捉えます
- 加法型または乗法型の季節性
- 最適な用途:季節的な需要パターン
from statsmodels.tsa.holtwinters import ExponentialSmoothing
def holt_winters(data, seasonal_periods=12, seasonal='add'):
"""Holt-Winters exponential smoothing"""
model = ExponentialSmoothing(
data,
seasonal_periods=seasonal_periods,
trend='add',
seasonal=seasonal
)
fitted = model.fit()
return fitted
# Forecast future periods
forecast = fitted.forecast(steps=6)
ARIMA モデル
- 自己回帰和分移動平均
- パラメーター:p(AR)、d(差分)、q(MA)
- 最適な用途:複雑な時系列パターン
from statsmodels.tsa.arima.model import ARIMA
def arima_forecast(data, order=(1,1,1)):
"""ARIMA forecasting model"""
model = ARIMA(data, order=order)
fitted = model.fit()
return fitted
# Auto ARIMA for parameter selection
from pmdarima import auto_arima
auto_model = auto_arima(data, seasonal=True, m=12)
因果/回帰手法
特徴量を用いた線形回帰
- 外部変数を取り込みます
- 価格、販促、祝日、天候など
from sklearn.linear_model import LinearRegression
import pandas as pd
def causal_forecast(X_features, y_demand):
"""Linear regression with causal factors"""
model = LinearRegression()
model.fit(X_features, y_demand)
return model
# Example features
features = pd.DataFrame({
'price': prices,
'promotion': promotions, # 0 or 1
'holiday': holidays, # 0 or 1
'competitor_price': comp_prices
})
重回帰分析
- 複数の独立変数を使用します
- 特徴量エンジニアリングが重要です
機械学習手法
ランダムフォレスト
- 決定木のアンサンブル
- 非線形の関係に対応します
- 特徴量の重要度を分析できます
from sklearn.ensemble import RandomForestRegressor
def ml_forecast_rf(X_train, y_train, n_estimators=100):
"""Random Forest forecasting"""
model = RandomForestRegressor(
n_estimators=n_estimators,
max_depth=10,
random_state=42
)
model.fit(X_train, y_train)
return model
# Feature importance
importances = model.feature_importances_
勾配ブースティング(XGBoost、LightGBM)
- 順次学習するアンサンブル
- 多くの場合、最良の性能を発揮します
- チューニングが必要です
import xgboost as xgb
def ml_forecast_xgb(X_train, y_train):
"""XGBoost forecasting"""
model = xgb.XGBRegressor(
objective='reg:squarederror',
n_estimators=100,
learning_rate=0.1,
max_depth=6
)
model.fit(X_train, y_train)
return model
ニューラルネットワーク(LSTM)
- 系列データ向けのディープラーニング
- 複雑なパターンを捉えます
- より多くのデータが必要です
from tensorflow import keras
from keras.models import Sequential
from keras.layers import LSTM, Dense
def lstm_forecast(X_train, y_train, timesteps=10, features=1):
"""LSTM neural network forecast"""
model = Sequential([
LSTM(50, activation='relu', input_shape=(timesteps, features)),
Dense(1)
])
model.compile(optimizer='adam', loss='mse')
model.fit(X_train, y_train, epochs=50, batch_size=32)
return model
Prophet(Facebook)
- 季節性、祝日、トレンドに対応します
- 使いやすく、欠損データにも強いです
- ビジネス時系列に適しています
from prophet import Prophet
def prophet_forecast(df):
"""Facebook Prophet forecasting"""
# df needs 'ds' (date) and 'y' (value) columns
model = Prophet(
yearly_seasonality=True,
weekly_seasonality=True,
daily_seasonality=False
)
model.fit(df)
# Make future dataframe
future = model.make_future_dataframe(periods=90)
forecast = model.predict(future)
return model, forecast
断続的需要の手法
クロストン法
- 散発的な需要向け
- 需要量と発生間隔を別々に予測します
import numpy as np
def crostons_method(demand, alpha=0.1):
"""Croston's method for intermittent demand"""
forecast = []
avg_demand = 0
avg_interval = 1
time_since_last = 0
for d in demand:
time_since_last += 1
if d > 0:
avg_demand = alpha * d + (1 - alpha) * avg_demand
avg_interval = alpha * time_since_last + (1 - alpha) * avg_interval
time_since_last = 0
forecast.append(avg_demand / avg_interval if avg_interval > 0 else 0)
return forecast
TSB(Teunter-Syntetos-Babai)
- クロストン法を改良した手法
- 不偏推定値
ブートストラップ
- 過去の需要を再サンプリングします
- 需要分布を生成します
予測精度の指標
主要指標
MAD(平均絶対偏差)
def mad(actual, forecast):
"""Mean Absolute Deviation"""
return np.mean(np.abs(actual - forecast))
MAPE(平均絶対パーセント誤差)
def mape(actual, forecast):
"""Mean Absolute Percentage Error"""
return np.mean(np.abs((actual - forecast) / actual)) * 100
RMSE(二乗平均平方根誤差)
def rmse(actual, forecast):
"""Root Mean Square Error"""
return np.sqrt(np.mean((actual - forecast) ** 2))
バイアス(予測バイアス)
def bias(actual, forecast):
"""Forecast bias (positive = over-forecast)"""
return np.mean(forecast - actual)
トラッキングシグナル
def tracking_signal(actual, forecast):
"""Cumulative bias / MAD"""
errors = forecast - actual
cumulative_error = np.cumsum(errors)
mad_value = np.mean(np.abs(errors))
return cumulative_error / mad_value if mad_value > 0 else 0
製品カテゴリー別の目標精度
| カテゴリー | 目標 MAPE | 備考 |
|---|---|---|
| A 品目(販売量が多い) | 15-25% | 最も厳格な管理 |
| B 品目(中程度) | 25-40% | 中程度 |
| C 品目(販売量が少ない) | 40-60% | 許容範囲を広めに設定 |
| 新製品 | 50-80% | 不確実性が高い |
| 販促対象 | 30-50% | イベントに依存 |
需要のセグメンテーション
ABC 分析
分類:
- A 品目:上位 20% の SKU、売上の 80% → 日次/週次予測、厳格な管理
- B 品目:次の 30% の SKU、売上の 15% → 週次/月次予測
- C 品目:下位 50% の SKU、売上の 5% → 月次予測、よりシンプルな手法
XYZ 分析(変動性):
- X:変動性が低い(CV < 0.5)→ 予測が容易
- Y:変動性が中程度(0.5 < CV < 1.0)→ 難易度は中程度
- Z:変動性が高い(CV > 1.0)→ 予測が難しく、断続的
ABC-XYZ 複合マトリックス:
| A(高価値) | B(中程度) | C(低価値) | |
|---|---|---|---|
| X | 厳格な管理、高度な手法 | 標準的な手法 | シンプルな手法 |
| Y | 高度な手法+安全在庫 | 標準的な手法 | シンプルな手法/集約 |
| Z | ML/因果分析+多めの安全在庫 | Croston 法 | Min/Max または在庫を持たない |
予測プロセス
1. データ準備
データクレンジング:
- 外れ値(返品、単発注文)を除去します
- 欠損値を処理します
- 販促期間を特定して分離します
- 欠品を考慮して調整します(打ち切り需要)
# Remove outliers using IQR method
Q1 = df['demand'].quantile(0.25)
Q3 = df['demand'].quantile(0.75)
IQR = Q3 - Q1
df_clean = df[~((df['demand'] < (Q1 - 1.5 * IQR)) |
(df['demand'] > (Q3 + 1.5 * IQR)))]
特徴量エンジニアリング:
- ラグ特徴量(過去の期間)
- ローリング統計量(移動平均、標準偏差)
- カレンダー特徴量(曜日、月、祝日)
- 販促指標
- 価格特徴量
# Create time-based features
df['month'] = df['date'].dt.month
df['day_of_week'] = df['date'].dt.dayofweek
df['is_weekend'] = df['day_of_week'].isin([5, 6]).astype(int)
df['is_holiday'] = df['date'].isin(holidays).astype(int)
# Lag features
df['lag_1'] = df['demand'].shift(1)
df['lag_7'] = df['demand'].shift(7)
df['rolling_mean_7'] = df['demand'].rolling(7).mean()
2. モデル選択
決定木:
Start
├─ Intermittent demand (many zeros)?
│ └─ Yes → Croston's, TSB, or aggregate
│ └─ No → Continue
├─ Strong seasonality?
│ └─ Yes → Holt-Winters, SARIMA, or Prophet
│ └─ No → Continue
├─ Trend present?
│ └─ Yes → Holt's trend, ARIMA
│ └─ No → Continue
├─ External factors available?
│ └─ Yes → Regression, ML models
│ └─ No → Simple smoothing
└─ Default: Exponential smoothing or Moving Average
3. ベースライン予測の生成
統計的予測:
- 選択したモデルを実行します
- 点予測を生成します
- 予測区間を計算します(80%、95%)
# Generate forecast with confidence intervals
forecast = model.forecast(steps=12)
conf_int = model.forecast_interval(steps=12, alpha=0.05) # 95% CI
4. 予測の拡充
ビジネスインテリジェンスの追加:
- 今後予定されている販促
- 新製品の発売
- 市場動向
- 競合他社の動き
- 経済指標
5. 共同レビュー
予測の上書きプロセス:
- 営業チームからの意見
- マーケティングカレンダーの確認
- 財務部門との調整
- 例外に基づくレビュー(A 品目、大幅な変更)
6. コンセンサス予測
加重平均による組み合わせ:
# Combine statistical and judgmental
final_forecast = (
0.7 * statistical_forecast +
0.3 * sales_team_forecast
)
7. パフォーマンスの追跡
指標のモニタリング:
- 週次/月次の精度レビュー
- バイアスの追跡
- 予測付加価値(FVA)
- 予測と実績の可視化
高度な手法
階層的予測
トップダウン:
- 集約レベルで予測します
- 比率を使って下位レベルに配分します
ボトムアップ:
- 最下位レベル(SKU-拠点)で予測します
- 合算して集約値を算出します
ミドルアウト:
- 中間レベルで予測します
- 上位・下位の両方向に整合させます
最適な整合化:
- MinT(最小トレース)
- 階層全体で整合性のある予測を実現します
from hierarchicalforecast.utils import aggregate
from hierarchicalforecast.methods import BottomUp, TopDown, MinTrace
# Define hierarchy
hierarchy = {
'Total': ['Region_A', 'Region_B'],
'Region_A': ['SKU_1', 'SKU_2'],
'Region_B': ['SKU_3', 'SKU_4']
}
# Reconcile forecasts
reconciled = MinTrace().fit_predict(forecasts, hierarchy)
予測付加価値(FVA)
概念:
- 手動での上書きが精度を向上させるか、低下させるかを測定します
- 調整後の予測とベースラインを比較します
def forecast_value_added(actual, baseline_fcst, adjusted_fcst):
"""Calculate if adjustments added value"""
baseline_error = np.abs(actual - baseline_fcst)
adjusted_error = np.abs(actual - adjusted_fcst)
fva = baseline_error - adjusted_error
# Positive FVA = adjustment improved forecast
return fva
需要センシング
リアルタイムのシグナル:
- POS データ(実際の消費)
- 倉庫からの出庫
- ウェブトラフィック、検索トレンド
- ソーシャルメディアのセンチメント
- 天気予報
短期的な調整:
- 予測を週次または日次で更新します
- 最新のシグナルを使用します
- 統計的予測と組み合わせます
ツールとライブラリ
Python ライブラリ
統計的予測:
statsmodels:ARIMA、指数平滑法、季節分解pmdarima:Auto ARIMAprophet:Facebook Prophetsktime:時系列機械学習
機械学習:
scikit-learn:回帰、ツリーベースモデルxgboost、lightgbm:勾配ブースティングtensorflow、pytorch:ディープラーニング(LSTM、トランスフォーマー)
ユーティリティ:
pandas:データ操作numpy:数値計算matplotlib、seaborn、plotly:可視化
商用ソフトウェア
- SAP IBP:統合事業計画
- Oracle Demantra:需要管理
- Blue Yonder (JDA):需要計画
- Kinaxis RapidResponse:S&OP プラットフォーム
- Anaplan:クラウド計画プラットフォーム
- o9 Solutions:AI を活用した計画
Excel アドイン
- Forecast Pro:統計的予測
- SAS Forecast Server:エンタープライズ予測
- Lokad:確率的予測
よくある課題と解決策
課題:予測の変動が大きい
解決策:
- 需要をベースラインと販促に分ける
- 階層型予測を使用する(集計すると安定性が高まる)
- 予測頻度を増やす
- 最小値/最大値のルール、または平滑化を導入する
課題:新製品の予測
解決策:
- 類似製品/参考製品のアプローチ
- 市場調査とテストマーケティング
- カテゴリーレベルのトレンドを使用する
- 段階的な立ち上がりのプロファイル
- 注意深く監視し、迅速に調整する
課題:販促の予測
解決策:
- ベースラインと販促効果を分ける
- 販促データベースを構築する(過去のイベント)
- 販促要因を特徴量として回帰を使用する
- マーケティング/営業との連携
- 改善に向けて販促後に分析する
課題:ロングテール/間欠需要
解決策:
- より上位のレベル(製品ファミリー)に集約する
- Croston 法または TSB 法を使用する
- 確率的予測(分布)を使用する
- 最小値/最大値の在庫ルールを設定する
- 在庫を持たず、受注後に調達することを検討する
課題:データ品質の問題
解決策:
- 過去データをクリーンアップする(外れ値、在庫切れを除外)
- データガバナンスを導入する
- 入力を検証する(範囲チェック、異常検知)
- 定期的なデータ監査を実施する
課題:予測の偏り
解決策:
- 偏りの指標を追跡する
- インセンティブを見直す(営業チームは予測を過大に見積もりがちです)
- 役割を分ける(予測と目標)
- 偏りのない統計的なベースラインを使用する
- 予測付加価値分析を行う
出力形式
予測レポートの構成
エグゼクティブサマリー:
- 全体の予測精度(当期)
- 前回の予測からの主な変更点
- 主な前提条件とリスク
セグメント別需要予測:
| 製品/SKU | 拠点 | 期間 | 統計的予測 | 調整後予測 | 実績(前期) | MAPE | 偏り |
|---|---|---|---|---|---|---|---|
| Product A | DC1 | Jan 2025 | 10,000 | 10,500 | 9,800 | 7.1% | +7.1% |
| ... | ... | ... | ... | ... | ... | ... | ... |
予測の前提条件:
- 販促カレンダー
- 市場トレンド
- 新製品の発売
- 既知の供給制約
精度指標:
- カテゴリー別 MAPE
- 偏りの分析
- トラッキングシグナル
- 予測と実績のグラフ
アクションアイテム:
- レビューが必要な項目
- 必要な予測の上書き
- データ品質の問題
- プロセスの改善
確認すべき質問
より詳しい情報が必要な場合:
- どの製品/SKU を予測する必要がありますか?どの粒度ですか?
- 計画期間はどのくらいですか?(週、月、年)
- どのくらいの過去データを利用できますか?
- 需要に影響する外部要因は何ですか?(販促、季節性、イベント)
- 現在の予測精度と、把握している問題は何ですか?
- どのツール/システムを使用していますか?
- 誰がどのような意思決定に予測を使用しますか?
関連スキル
- sales-operations-planning:予測を S&OP に統合する場合
- capacity-planning:予測に基づく生産能力の計画
- inventory-optimization:安全在庫と再発注点の設定
- supply-chain-analytics:KPI とパフォーマンスの追跡
- ml-supply-chain:高度な機械学習による予測手法
- seasonal-planning:小売業の季節需要の計画
- promotional-planning:CPG の販促予測