100本ノック / 機械学習 / 実務機械学習100本ノック

製造業の需要予測を強くする特徴量設計10選|Python実践100本ノック

製造業の需要予測を強くする特徴量設計 ― 受注履歴を意思決定情報へ変える10本ノック

本記事では、架空の部品メーカーの受注履歴を題材に、予測時点で本当に利用できる情報だけから特徴量を設計します。曜日や祝日、過去需要、顧客・商品特性を、在庫・要員・生産計画に使える形へ変換することが目的です。

対象は「機械学習100本ノック」第6章の No.051〜No.060 です。コードを動かすだけでなく、特徴量の業務上の意味、作り方、結果の読み方、データリークを防ぐ運用まで確認します。

[!NOTE] 本資料は、数理工房 (もしくは代表である和山個人) が過去に企業研修において使用した notebook を企業様の許可を得て再構成・編集のうえ公開しています。 掲載データはすべて架空のものであり、実在する企業・工場・数値とは一切関係ありません。

はじめに:この記事で扱う製造業の実務課題

部品メーカーでは、翌週の受注数量を予測し、材料手配、設備枠、残業、外注を決めます。しかし受注量の生データだけでは、月末集中、休日、顧客ごとの発注周期、商品ごとの需要水準をモデルへ伝えられません。本記事では「履歴を、予測に使える説明変数へ翻訳する」工程に焦点を当てます。

現場でよくある状況

  • ERPから日付・顧客・商品・数量を抽出したが、そのままモデルへ入れている
  • 全期間平均を特徴量にして、検証時だけ精度が高くなる
  • 欠損したラグをゼロで埋め、休業日と履歴不足を混同する
  • 特徴量の定義や利用可能時点が属人化している

なぜこの問題は判断が難しいのか

特徴量は予測精度だけで評価できません。計画確定時点に取得可能か、将来も同じ定義で生成できるか、現場が意味を説明できるかも重要です。とくに時系列では、未来の実績をわずかに混ぜただけで検証値が過大になります。

今回扱うノックの全体像

No.テーマ計画業務への接続
051日付特徴量曜日・月・四半期の周期
052祝日・営業日稼働可能日と休日影響
053ラグ直近・同曜日の需要
054移動平均基準需要と変動
055顧客別集計顧客固有の発注水準
056商品別集計品目固有の需要水準
057比率能力負荷・構成比
058交互作用条件の組合せ効果
059ターゲットエンコーディング高カーディナリティの数値化
060データリーク防止本番再現性の確保

Python 環境の準備

numpypandasmatplotlibscikit-learnを使います。乱数シードは固定し、グラフはMarkdown変換後も読みやすい設定にします。

import numpy as np
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
from sklearn.compose import ColumnTransformer
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_absolute_error
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder

SEED = 42
rng = np.random.default_rng(SEED)
plt.rcParams["figure.figsize"] = (9, 4.5)
plt.rcParams["axes.unicode_minus"] = False

print("numpy:", np.__version__)
print("pandas:", pd.__version__)
print("matplotlib:", matplotlib.__version__)
numpy: 2.5.1
pandas: 3.0.3
matplotlib: 3.11.0

架空データの作成

2024年1月から2025年6月まで、8顧客×5商品の日次レコードを作ります。目的変数は受注数量 order_qty。曜日、月末、顧客規模、商品人気、販促、休日の影響を含めます。capacity_qty はその日に割り当て可能な標準能力です。外部データは使いません。

dates = pd.date_range("2024-01-01", "2025-06-30", freq="D")
customers = [f"C{i:02d}" for i in range(1, 9)]
products = [f"P{i:02d}" for i in range(1, 6)]
idx = pd.MultiIndex.from_product([dates, customers, products], names=["date", "customer_id", "product_id"])
df = idx.to_frame(index=False)

customer_scale = {c: v for c, v in zip(customers, [0.75, 0.9, 1.05, 1.25, 1.5, 0.85, 1.15, 1.35])}
product_base = {p: v for p, v in zip(products, [18, 25, 34, 43, 55])}
product_capacity = {p: v for p, v in zip(products, [52, 58, 68, 78, 90])}
df["promotion"] = (rng.random(len(df)) < 0.045).astype(int)
df["unit_price"] = df["product_id"].map(dict(zip(products, [1280, 1650, 2100, 2480, 3150])))

# 日本の祝日を模した架空カレンダー(外部カレンダーには依存しない)
holiday_dates = pd.to_datetime([
    "2024-01-01", "2024-01-08", "2024-02-12", "2024-02-23", "2024-04-29",
    "2024-05-03", "2024-05-06", "2024-07-15", "2024-08-12", "2024-09-16",
    "2024-10-14", "2024-11-04", "2025-01-01", "2025-01-13", "2025-02-11",
    "2025-02-24", "2025-04-29", "2025-05-05", "2025-05-06"
])
weekday = df["date"].dt.dayofweek
is_holiday = df["date"].isin(holiday_dates)
business = ((weekday < 5) & ~is_holiday).astype(int)
month_end = (df["date"].dt.day >= 25).astype(int)
season = 1 + 0.10 * np.sin(2 * np.pi * (df["date"].dt.month - 1) / 12)
mu = (df["product_id"].map(product_base) * df["customer_id"].map(customer_scale)
      * season * (1 + 0.18 * month_end) * (1 + 0.28 * df["promotion"])
      * np.where(business == 1, 1.0, 0.16))
df["order_qty"] = rng.poisson(mu).astype(int)
df["capacity_qty"] = df["product_id"].map(product_capacity)
df["revenue"] = df["order_qty"] * df["unit_price"]

print("形状:", df.shape)
display(df.head())
形状: (21880, 8)
date customer_id product_id promotion unit_price order_qty capacity_qty revenue
0 2024-01-01 C01 P01 0 1280 4 52 5120
1 2024-01-01 C01 P02 0 1650 4 58 6600
2 2024-01-01 C01 P03 0 2100 3 68 6300
3 2024-01-01 C01 P04 0 2480 7 78 17360
4 2024-01-01 C01 P05 0 3150 7 90 22050

No.051:日付から曜日・月・四半期を作る

実務での意味

日付は単なる識別子ではなく、生産・出荷の周期を表します。曜日は配車や締め、月は季節需要、四半期は予算・棚卸の周期をモデルへ伝えます。

分析・モデル化の考え方

日付 tt から曜日 d(t)d(t)、月 m(t)m(t)、四半期 q(t)=(m(t)1)/3+1q(t)=\lfloor(m(t)-1)/3\rfloor+1 を作ります。番号には大小関係を誤学習する余地があるため、モデルによってはカテゴリとして扱います。

Pythonで確認する

df["day_of_week"] = df["date"].dt.dayofweek
df["day_name"] = df["date"].dt.day_name()
df["month"] = df["date"].dt.month
df["quarter"] = df["date"].dt.quarter
calendar_summary = df.groupby("day_name", observed=True)["order_qty"].mean().reindex(
    ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"])
display(calendar_summary.rename("mean_order_qty").round(2).to_frame())
calendar_summary.plot(kind="bar", color="#4472C4")
plt.title("Average order quantity by day of week")
plt.xlabel("Day of week"); plt.ylabel("Average order quantity"); plt.grid(axis="y", alpha=.3); plt.tight_layout(); plt.show()
mean_order_qty
day_name
Monday 35.70
Tuesday 39.81
Wednesday 40.99
Thursday 41.38
Friday 40.45
Saturday 6.64
Sunday 6.51

png

結果の読み取り

平日と週末の水準差が明確です。曜日特徴量により、モデルは休日直前の生産量や週明けの出荷負荷を区別できます。ただし「曜日が原因」と断定せず、締め時刻や配送便との対応を現場確認します。

No.052:祝日・営業日フラグを作る

実務での意味

カレンダー日数と実際の稼働可能日数は一致しません。休日を明示すると、需要減と設備停止を通常日の変動から分離できます。

分析・モデル化の考え方

祝日集合への所属を HtH_t、週末を WtW_t とすると、営業日フラグは Bt=1[(Ht=0)(Wt=0)]B_t=1[(H_t=0)\land(W_t=0)] です。本番では会社カレンダー、臨時稼働、顧客別休日も管理します。

Pythonで確認する

df["is_holiday"] = df["date"].isin(holiday_dates).astype(int)
df["is_business_day"] = ((df["day_of_week"] < 5) & (df["is_holiday"] == 0)).astype(int)
business_summary = df.groupby("is_business_day")["order_qty"].agg(["mean", "median", "count"])
business_summary.index = ["non-business", "business"]
display(business_summary.round(2))
business_summary["mean"].plot(kind="bar", color=["#A5A5A5", "#70AD47"])
plt.title("Orders on business and non-business days")
plt.xlabel("Calendar class"); plt.ylabel("Average order quantity"); plt.grid(axis="y", alpha=.3); plt.tight_layout(); plt.show()
mean median count
non-business 6.57 6.0 7000
business 41.35 38.0 14880

png

結果の読み取り

非営業日の平均受注は営業日より大幅に小さくなりました。営業日フラグは材料・人員計画の前提になります。受注日と希望納期のどちらのカレンダーを使うかは、目的変数に合わせて定義します。

No.053:ラグ特徴量を作る

実務での意味

昨日や前週同曜日の受注量は、短期計画の強い手掛かりです。急な増減を捉え、購買・生産担当者の経験則を再現します。

分析・モデル化の考え方

系列ごとに Lt,k=ytkL_{t,k}=y_{t-k} を作ります。ここでは顧客×商品単位で1日前と7日前を参照します。shiftを先に行うことが、当日の実績混入を防ぐ要点です。

Pythonで確認する

df = df.sort_values(["customer_id", "product_id", "date"]).copy()
series_keys = ["customer_id", "product_id"]
df["lag_1"] = df.groupby(series_keys)["order_qty"].shift(1)
df["lag_7"] = df.groupby(series_keys)["order_qty"].shift(7)
sample = df.query("customer_id == 'C05' and product_id == 'P05'").tail(12)
display(sample[["date", "order_qty", "lag_1", "lag_7"]])
plt.plot(sample["date"], sample["order_qty"], marker="o", label="actual")
plt.plot(sample["date"], sample["lag_7"], marker="s", label="lag 7")
plt.title("Actual orders and 7-day lag"); plt.xlabel("Date"); plt.ylabel("Order quantity")
plt.grid(alpha=.3); plt.legend(); plt.xticks(rotation=30); plt.tight_layout(); plt.show()
date order_qty lag_1 lag_7
21424 2025-06-19 86 94.0 80.0
21464 2025-06-20 81 86.0 61.0
21504 2025-06-21 11 81.0 15.0
21544 2025-06-22 12 11.0 15.0
21584 2025-06-23 95 12.0 71.0
21624 2025-06-24 89 95.0 89.0
21664 2025-06-25 103 89.0 94.0
21704 2025-06-26 100 103.0 86.0
21744 2025-06-27 94 100.0 81.0
21784 2025-06-28 19 94.0 11.0
21824 2025-06-29 16 19.0 12.0
21864 2025-06-30 105 16.0 95.0

png

結果の読み取り

7日前の値は同じ曜日の水準を追随します。欠損は系列先頭で履歴がない印なので、機械的なゼロ補完ではなく、学習対象から外すか「履歴不足」フラグを併用します。

No.054:移動平均特徴量を作る

実務での意味

単日の受注は偶然変動します。移動平均は基準需要を安定させ、安全在庫や能力計画の判断を支えます。

分析・モデル化の考え方

直近 ww 日の平均は MAt,w=1wi=1wytiMA_{t,w}=\frac{1}{w}\sum_{i=1}^{w}y_{t-i}。当日を含めないため shift(1).rolling(w) の順で計算します。

Pythonで確認する

g = df.groupby(series_keys)["order_qty"]
df["rolling_mean_7"] = g.transform(lambda s: s.shift(1).rolling(7, min_periods=3).mean())
df["rolling_mean_28"] = g.transform(lambda s: s.shift(1).rolling(28, min_periods=7).mean())
sample = df.query("customer_id == 'C05' and product_id == 'P05'").tail(60)
plt.plot(sample["date"], sample["order_qty"], alpha=.45, label="actual")
plt.plot(sample["date"], sample["rolling_mean_7"], label="7-day mean")
plt.plot(sample["date"], sample["rolling_mean_28"], label="28-day mean")
plt.title("Short- and medium-term demand baselines"); plt.xlabel("Date"); plt.ylabel("Order quantity")
plt.grid(alpha=.3); plt.legend(); plt.xticks(rotation=30); plt.tight_layout(); plt.show()

png

結果の読み取り

7日平均は直近変化へ速く反応し、28日平均は安定しています。短期配員には前者、月次購買には後者など、意思決定のリードタイムに合わせて窓幅を選びます。

No.055:顧客別の集計特徴量を作る

実務での意味

顧客ごとに発注規模や変動性が異なります。過去平均とばらつきは、重点顧客の負荷見込みや予測区間の設計に使えます。

分析・モデル化の考え方

各顧客について予測日より前の累積統計を使います。拡張窓平均は yˉc,t1\bar y_{c,t-1} であり、全期間平均を一括結合しない点が重要です。

Pythonで確認する

customer_daily = df.groupby(["date", "customer_id"], as_index=False)["order_qty"].sum()
customer_daily = customer_daily.sort_values(["customer_id", "date"])
customer_daily["customer_past_mean"] = customer_daily.groupby("customer_id")["order_qty"].transform(
    lambda s: s.shift(1).expanding().mean())
customer_profile = customer_daily.groupby("customer_id").agg(
    latest_past_mean=("customer_past_mean", "last"), observed_std=("order_qty", "std"))
display(customer_profile.round(2).sort_values("latest_past_mean", ascending=False))
customer_profile["latest_past_mean"].sort_values().plot(kind="barh", color="#ED7D31")
plt.title("Historical demand level by customer"); plt.xlabel("Past mean daily quantity"); plt.ylabel("Customer")
plt.grid(axis="x", alpha=.3); plt.tight_layout(); plt.show()
latest_past_mean observed_std
customer_id
C05 206.99 115.22
C08 184.89 102.48
C04 171.93 95.56
C07 158.00 87.48
C03 144.15 79.93
C02 122.89 68.19
C06 116.22 64.75
C01 102.44 57.00

png

結果の読み取り

C05など高水準顧客を識別できました。平均だけでなく標準偏差や最終発注からの日数を併用すると、能力確保と営業フォローを分けて判断できます。

No.056:商品別の集計特徴量を作る

実務での意味

商品ごとの需要規模・変動性は、材料所要量や段取り計画の基本情報です。品目コードを数値化するだけでは、この水準差を直接表せません。

分析・モデル化の考え方

商品別日次需要を作り、過去のみの累積平均を計算します。新商品では履歴が少ないため、商品群平均へ縮約する運用も検討します。

Pythonで確認する

product_daily = df.groupby(["date", "product_id"], as_index=False)["order_qty"].sum()
product_daily = product_daily.sort_values(["product_id", "date"])
product_daily["product_past_mean"] = product_daily.groupby("product_id")["order_qty"].transform(
    lambda s: s.shift(1).expanding().mean())
product_profile = product_daily.groupby("product_id").agg(
    latest_past_mean=("product_past_mean", "last"), max_daily=("order_qty", "max"))
display(product_profile.round(2))
product_profile["latest_past_mean"].plot(kind="bar", color="#5B9BD5")
plt.title("Historical demand level by product"); plt.xlabel("Product"); plt.ylabel("Past mean daily quantity")
plt.grid(axis="y", alpha=.3); plt.tight_layout(); plt.show()
latest_past_mean max_daily
product_id
P01 124.02 228
P02 172.20 318
P03 235.02 428
P04 296.70 555
P05 379.57 672

png

結果の読み取り

P05はP01より大きな需要水準です。この差を特徴量化するとモデルは品目別の基準線を持てます。ただし廃番・価格改定後も古い履歴を同じ重みで使うかは見直しが必要です。

No.057:比率特徴量を作る

実務での意味

絶対数量だけでは「能力に対して重いか」を判断できません。負荷率や顧客内構成比は、逼迫と重要度を共通尺度で比較できます。

分析・モデル化の考え方

負荷率を rt=yt/ctr_t=y_t/c_t とします。分母がゼロまたは未確定なら欠損として扱い、微小値で無理に割らないことが重要です。ここでは予測用として7日平均需要を能力で割ります。

Pythonで確認する

df["demand_capacity_ratio"] = df["rolling_mean_7"].div(df["capacity_qty"].replace(0, np.nan))
ratio_summary = df.groupby("product_id")["demand_capacity_ratio"].agg(["mean", "median", "max"])
display(ratio_summary.round(3))
plot_data = df.dropna(subset=["demand_capacity_ratio"]).sample(2500, random_state=SEED)
plt.hist(plot_data["demand_capacity_ratio"], bins=30, color="#FFC000", edgecolor="white")
plt.axvline(1.0, color="red", linestyle="--", label="capacity threshold")
plt.title("Distribution of expected load ratio"); plt.xlabel("7-day mean / standard capacity"); plt.ylabel("Frequency")
plt.grid(axis="y", alpha=.3); plt.legend(); plt.tight_layout(); plt.show()
mean median max
product_id
P01 0.298 0.291 0.585
P02 0.371 0.362 0.687
P03 0.433 0.422 0.845
P04 0.476 0.462 0.842
P05 0.528 0.514 0.941

png

結果の読み取り

1.0超は標準能力を上回る見込みです。高負荷の頻度を品目別に見ることで、残業・外注・前倒しの検討対象を絞れます。能力値の更新頻度と単位整合は必ず管理します。

No.058:交互作用特徴量を作る

実務での意味

販促効果は一律ではなく、月末や特定商品で強まることがあります。単独特徴量だけでは表しにくい「組合せ条件」を明示します。

分析・モデル化の考え方

2変数 x1,x2x_1,x_2 の積 x1x2x_1x_2 を追加します。ここでは promotion × month_endbusiness_day × lag_7 を作り、販促集中と営業日上の前週需要を表現します。

Pythonで確認する

df["is_month_end"] = (df["date"].dt.day >= 25).astype(int)
df["promotion_month_end"] = df["promotion"] * df["is_month_end"]
df["business_lag_7"] = df["is_business_day"] * df["lag_7"]
interaction_summary = df.groupby(["promotion", "is_month_end"])["order_qty"].mean().unstack()
interaction_summary.columns = ["not_month_end", "month_end"]
display(interaction_summary.round(2))
interaction_summary.plot(kind="bar", color=["#A5A5A5", "#C00000"])
plt.title("Interaction of promotion and month-end"); plt.xlabel("Promotion flag"); plt.ylabel("Average order quantity")
plt.grid(axis="y", alpha=.3); plt.legend(); plt.tight_layout(); plt.show()
not_month_end month_end
promotion
0 28.57 34.89
1 36.13 41.03

png

結果の読み取り

販促かつ月末の組合せで平均数量が最大です。交互作用は施策効果の仮説をモデルへ渡せますが、候補を無制限に増やすと過学習するため、現場仮説と検証で絞ります。

No.059:ターゲットエンコーディングを使う

実務での意味

顧客・商品・設備などカテゴリ数が多い場合、One-Hot Encodingは列数を増やします。過去の目的変数水準でカテゴリを1列に要約できます。

分析・モデル化の考え方

カテゴリ cc の値を平滑化平均 TEc=(ncyˉc+mμ)/(nc+m)TE_c=(n_c\bar y_c+m\mu)/(n_c+m) に置換します。ここでは各行より前だけで、顧客×商品の累積和・件数と全体事前平均から計算します。mm は少数カテゴリを全体平均へ寄せる強さです。

Pythonで確認する

df = df.sort_values("date").copy()
cat_key = df["customer_id"] + "_" + df["product_id"]
past_sum = df.groupby(cat_key)["order_qty"].cumsum() - df["order_qty"]
past_count = df.groupby(cat_key).cumcount()
global_past_sum = df["order_qty"].cumsum() - df["order_qty"]
global_past_count = np.arange(len(df))
global_prior = global_past_sum.div(pd.Series(global_past_count, index=df.index).replace(0, np.nan))
smoothing = 30
df["target_encoding"] = (past_sum + smoothing * global_prior) / (past_count + smoothing)
te_summary = df.groupby(["customer_id", "product_id"])["target_encoding"].last().unstack()
display(te_summary.round(2))
plt.imshow(te_summary, aspect="auto", cmap="Blues")
plt.colorbar(label="Past target mean"); plt.xticks(range(len(te_summary.columns)), te_summary.columns)
plt.yticks(range(len(te_summary.index)), te_summary.index)
plt.title("Leakage-safe target encoding"); plt.xlabel("Product"); plt.ylabel("Customer")
plt.grid(False); plt.tight_layout(); plt.show()
product_id P01 P02 P03 P04 P05
customer_id
C01 11.62 15.37 20.65 25.38 31.95
C02 13.37 17.92 24.23 30.20 38.64
C03 15.59 21.16 28.28 34.99 44.49
C04 18.31 25.00 33.46 41.62 52.44
C05 21.55 29.67 39.95 49.89 63.02
C06 12.86 17.41 22.76 28.41 36.60
C07 17.20 22.92 30.61 38.53 48.38
C08 19.65 26.36 35.42 44.82 56.87

png

結果の読み取り

顧客×商品の需要水準を1列で表せました。新規カテゴリは全体平均へフォールバックします。学習・検証を無作為分割してから全体平均を計算するとリークするため、時系列順またはfold外で算出します。

No.060:データリークを防ぐ

実務での意味

検証精度が高くても、本番時点で未知の情報を使っていれば計画には使えません。リーク防止はアルゴリズム選定より前の品質要件です。

分析・モデル化の考え方

時点 TT で学習し、TT より後を検証します。危険な特徴量 leaky_target は結合ミスで残った当日の目的変数そのもの、安全な safe_roll は1日シフト後の移動平均です。両者のMAE差から過大評価を確認します。

Pythonで確認する

daily = df.groupby("date", as_index=False)["order_qty"].sum().sort_values("date")
daily["leaky_target"] = daily["order_qty"]  # 予測時には未知。説明用の典型的リーク
daily["safe_roll"] = daily["order_qty"].shift(1).rolling(7, min_periods=7).mean()
daily = daily.dropna().copy()
cutoff = pd.Timestamp("2025-04-01")
train = daily[daily["date"] < cutoff]
test = daily[daily["date"] >= cutoff]

results = []
predictions = {}
for feature in ["leaky_target", "safe_roll"]:
    model = RandomForestRegressor(n_estimators=150, min_samples_leaf=4, random_state=SEED, n_jobs=1)
    model.fit(train[[feature]], train["order_qty"])
    pred = model.predict(test[[feature]])
    predictions[feature] = pred
    results.append({"feature": feature, "MAE": mean_absolute_error(test["order_qty"], pred)})
display(pd.DataFrame(results).set_index("feature").round(2))
view = test.iloc[:45]
plt.plot(view["date"], view["order_qty"], label="actual", color="black")
plt.plot(view["date"], predictions["leaky_target"][:45], label="leaky feature")
plt.plot(view["date"], predictions["safe_roll"][:45], label="safe feature")
plt.title("Apparent accuracy caused by target leakage"); plt.xlabel("Date"); plt.ylabel("Total order quantity")
plt.grid(alpha=.3); plt.legend(); plt.xticks(rotation=30); plt.tight_layout(); plt.show()
MAE
feature
leaky_target 3.34
safe_roll 613.13

png

結果の読み取り

目的変数そのものを残した特徴量は不自然に良いMAEを示しますが、予測時には作れません。特徴量ごとに「発生時刻・確定時刻・取得時刻」を記録し、時系列分割で検証し、学習と推論で同じ生成処理を使うことが必要です。

対象ノックを通して見える実務上の示唆

特徴量設計は、データを増やす作業ではなく、業務の時間軸と意思決定をモデルへ写す作業です。暦特徴量は操業周期、ラグと移動平均は需要の記憶、顧客・商品集計は構造差、比率は制約、交互作用は業務仮説を表します。

精度改善の優先順位は、まず利用可能時点を守ること、次に意思決定のリードタイムと粒度を揃えること、その後に特徴量を増やすことです。検証値だけでなく、欠品、残業、在庫、計画変更回数といった業務KPIへの効果で採否を決めます。

実務導入する場合に必要なこと

  1. 予測仕様:対象、粒度、予測日、予測期間、計画確定時刻を定義する
  2. データ時刻管理:各項目の発生・確定・取得時刻と訂正ルールを管理する
  3. 特徴量台帳:定義、単位、窓幅、欠損処理、責任者を残す
  4. 再現可能な処理:学習と推論で同じコードを使い、履歴スナップショットを保存する
  5. 時系列検証:繁忙期・休暇期を含む複数期間で、MAEと業務KPIを評価する
  6. 監視と更新:新商品、顧客構成、能力、カレンダー変更による分布変化を監視する

まとめ

No.051〜060では、生の日付・受注履歴を製造計画に意味のある特徴量へ変換しました。最重要ポイントは、すべての特徴量を予測時点より前の情報で作ることです。小さく始めるなら、営業日、7日ラグ、7日移動平均、顧客・商品別の過去平均から導入し、時系列検証で効果を確認するとよいでしょう。

法人向けのご相談

需要予測や在庫・生産計画では、モデルそのものより、データ定義、特徴量、検証、現場運用の接続が成果を左右します。数理工房では、課題整理、データ診断、PoC、業務実装、企業研修まで、保有データと意思決定プロセスに合わせてご支援します。

📩 お問い合わせ: surikobo.co.jp/contact まずはお気軽にご相談ください。