STEP 36:トレンド分析と予測精度の評価

📈 STEP 36: トレンド分析と予測精度の評価

様々なトレンドパターンを理解し、予測の精度を正しく評価しよう

📋 このステップで学ぶこと

  • 線形トレンド・指数トレンド・S字カーブの違い
  • データに最適なトレンドの選び方
  • 予測誤差の評価指標(MAE、RMSE、MAPE)
  • Excelとpythonでの精度評価の実装
  • トレンド転換の検出と対応
  • 実務でよくある間違いと対策

学習時間の目安: 3時間

📌 前のステップとのつながり

STEP 35(移動平均と季節調整)では、データの平滑化と季節性の除去を学びました。

このSTEP 36では、平滑化したデータからトレンド(傾向)を把握し、
予測の精度を定量的に評価する方法を学びます。

また、STEP 34(高度な予測手法)で学んだARIMAやProphetの
予測結果を評価する際にも、このSTEPの知識が必要になります。

🔍 1. トレンドの種類と特徴

なぜトレンドの種類を理解するのか?

💡 適切なトレンドモデルを選ばないと予測が大きく外れる
例: 急成長するスタートアップの売上予測

実績: 1年目100万円 → 2年目150万円 → 3年目225万円

線形トレンドで予測した場合:
4年目 = 275万円(毎年50万円増加と仮定)

指数トレンドで予測した場合:
4年目 = 337万円(毎年50%成長と仮定)

62万円の差!
→ 設備投資や採用計画に大きな影響

正しいトレンドを選ぶことで、より精度の高い予測が可能になります。

線形トレンド(直線的な成長)

📌 一定のペースで増加または減少

数式: y = a + bx(a: 切片、b: 傾き)

特徴:
・毎期、同じ量だけ増加/減少
・例: 毎月10万円ずつ増加
・グラフは直線

どんな時に使う?
・安定成長期の企業売上
・人口増加(短期的に)
・設備の減価償却

計算例:
y = 100 + 5x(切片100、傾き5)
・1ヶ月目: 100 + 5×1 = 105万円
・2ヶ月目: 100 + 5×2 = 110万円
・3ヶ月目: 100 + 5×3 = 115万円
毎月5万円ずつ一定額で増加

指数トレンド(加速度的な成長)

💡 一定の割合で増加または減少

数式: y = a × b^x(a: 初期値、b: 成長率)

特徴:
・毎期、一定の割合(%)で増加/減少
・例: 毎月5%ずつ成長
・グラフは曲線(上昇または下降)

どんな時に使う?
・急成長するスタートアップ
・ウイルス感染者数
・複利計算

計算例:
y = 100 × 1.05^x(初期値100、月次5%成長)
・1ヶ月目: 100 × 1.05 = 105.0万円
・2ヶ月目: 100 × 1.05² = 110.3万円
・12ヶ月目: 100 × 1.05¹² = 179.6万円
増加額が徐々に大きくなる(複利効果)

S字カーブ(ロジスティック成長)

📌 初期は緩やか、中期は急成長、後期は飽和
3つのフェーズ:

1. 導入期: 認知度低い、成長は緩やか
2. 成長期: 口コミ効果、急激な成長
3. 成熟期: 市場飽和、成長鈍化

実例:
・スマートフォンの普及率
・SNSユーザー数
・電気自動車の販売台数

3種類のトレンド比較(視覚的理解)

# ============================================ # 3種類のトレンドパターンの比較と可視化 # ============================================ import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression from sklearn.metrics import r2_score # サンプルデータ作成(3年分) np.random.seed(42) months = np.arange(1, 37) # 1. 線形トレンド: y = 100 + 5x linear_trend = 100 + 5 * months + np.random.normal(0, 5, len(months)) # 2. 指数トレンド: y = 100 × 1.05^x exponential_trend = 100 * (1.05 ** months) + np.random.normal(0, 10, len(months)) # 3. S字カーブ(ロジスティック) logistic_trend = 500 / (1 + np.exp(-0.2 * (months – 18))) + np.random.normal(0, 10, len(months)) # トレンドラインのフィッティング X = months.reshape(-1, 1) # 線形トレンドのフィット model_linear = LinearRegression() model_linear.fit(X, linear_trend) y_pred_linear = model_linear.predict(X) r2_linear = r2_score(linear_trend, y_pred_linear) # 指数トレンドのフィット(対数変換) y_log = np.log(exponential_trend) model_exp = LinearRegression() model_exp.fit(X, y_log) y_pred_exp = np.exp(model_exp.predict(X)) growth_rate = (np.exp(model_exp.coef_[0]) – 1) * 100 r2_exp = r2_score(exponential_trend, y_pred_exp) print(“【トレンドの特徴】”) print(f”線形: y = {model_linear.intercept_:.1f} + {model_linear.coef_[0]:.2f}x (R²={r2_linear:.3f})”) print(f”指数: 月次成長率 {growth_rate:.2f}% (R²={r2_exp:.3f})”) # ============================================ # 3種類のトレンドの可視化 # ============================================ fig, axes = plt.subplots(1, 3, figsize=(15, 5)) # 線形トレンド axes[0].scatter(months, linear_trend, alpha=0.6, label=’実績’) axes[0].plot(months, y_pred_linear, ‘r-‘, linewidth=2, label=’線形トレンド’) axes[0].set_title(f’線形トレンド\ny = {model_linear.intercept_:.0f} + {model_linear.coef_[0]:.1f}x\nR² = {r2_linear:.3f}’) axes[0].set_xlabel(‘月’) axes[0].set_ylabel(‘売上(万円)’) axes[0].legend() axes[0].grid(True, alpha=0.3) # 指数トレンド axes[1].scatter(months, exponential_trend, alpha=0.6, label=’実績’) axes[1].plot(months, y_pred_exp, ‘r-‘, linewidth=2, label=’指数トレンド’) axes[1].set_title(f’指数トレンド\n月次成長率: {growth_rate:.1f}%\nR² = {r2_exp:.3f}’) axes[1].set_xlabel(‘月’) axes[1].set_ylabel(‘売上(万円)’) axes[1].legend() axes[1].grid(True, alpha=0.3) # S字カーブ axes[2].scatter(months, logistic_trend, alpha=0.6, label=’実績’) axes[2].axhline(y=500, color=’gray’, linestyle=’–‘, label=’上限(500)’) axes[2].set_title(‘S字カーブ(ロジスティック)\n初期→急成長→飽和’) axes[2].set_xlabel(‘月’) axes[2].set_ylabel(‘ユーザー数’) axes[2].legend() axes[2].grid(True, alpha=0.3) plt.tight_layout() plt.savefig(‘trend_comparison.png’, dpi=150, bbox_inches=’tight’) plt.show() print(“\n→ グラフを ‘trend_comparison.png’ に保存しました”)

トレンド判断の早見表

📌 データの特徴からトレンドを見分ける
確認項目 線形 指数 S字
増加幅 一定
(毎月+10万円)
拡大
(+10→+15→+22)
山型
(小→大→小)
増加率 低下
(10%→8%→6%)
一定
(毎月+5%)
山型
(低→高→低)
上限の有無 なし なし あり
グラフの形状 直線 上向き曲線 S字
典型例 安定企業の売上 スタートアップ 新製品の普及

🎯 2. どのトレンドを選ぶべきか?

トレンド選択の判断基準

⚠️ 正しいトレンドを選ぶための3つのステップ
ステップ1: データの特徴を確認
・増加幅: 一定(線形)、拡大(指数)、変動(S字)
・増加率: 低下(線形)、一定(指数)、山型(S字)
・上限: なし(線形・指数)、あり(S字)

ステップ2: R²(決定係数)で比較
・R² > 0.9: 非常に良いフィット
・R² > 0.7: 良いフィット
→ 複数のトレンドを試して、R²が最も高いものを選択

ステップ3: ビジネス知識で検証
・市場に上限はあるか?(あればS字)
・成長は加速しているか?(していれば指数)
・安定成長か?(していれば線形)

トレンド選択の実装

# ============================================ # トレンド選択: どのモデルが最適か判断する # ============================================ import numpy as np from sklearn.linear_model import LinearRegression from sklearn.metrics import r2_score from sklearn.preprocessing import PolynomialFeatures # 実際の売上データ(例) months = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) sales = np.array([100, 108, 118, 127, 139, 152, 166, 180, 197, 214, 233, 254]) X = months.reshape(-1, 1) # 増加幅と増加率を確認 increases = np.diff(sales) print(f”増加額の傾向: {increases[0]:.0f} → {increases[-1]:.0f}万円”) if increases[-1] > increases[0] * 1.2: print(” → 増加額が拡大 → 指数トレンドの可能性”) # 3種類のトレンドをフィット # 線形トレンド model_linear = LinearRegression() model_linear.fit(X, sales) r2_linear = r2_score(sales, model_linear.predict(X)) # 指数トレンド(対数変換) model_exp = LinearRegression() model_exp.fit(X, np.log(sales)) r2_exp = r2_score(sales, np.exp(model_exp.predict(X))) # 2次多項式 poly = PolynomialFeatures(degree=2) model_poly = LinearRegression() model_poly.fit(poly.fit_transform(X), sales) r2_poly = r2_score(sales, model_poly.predict(poly.transform(X))) print(f”\n【R²の比較】”) print(f”線形: R² = {r2_linear:.4f}”) print(f”指数: R² = {r2_exp:.4f}”) print(f”多項式: R² = {r2_poly:.4f}”) # 最適モデルの判定 results = {‘線形’: r2_linear, ‘指数’: r2_exp, ‘多項式’: r2_poly} best = max(results, key=results.get) print(f”\n【結論】最適: {best}トレンド (R²={results[best]:.4f})”) # ============================================ # 将来予測の実行 # ============================================ future_months = np.array([13, 14, 15]) # 来期3ヶ月 future_X = future_months.reshape(-1, 1) # 指数トレンドで予測(この例では指数が最適) future_pred = np.exp(model_exp.predict(future_X)) print(f”\n【来期の売上予測(指数トレンド)】”) for m, pred in zip(future_months, future_pred): print(f”{m}ヶ月目: {pred:.0f}万円”) # ============================================ # トレンド比較の可視化 # ============================================ import matplotlib.pyplot as plt fig, ax = plt.subplots(figsize=(10, 6)) # 実績データ ax.scatter(months, sales, s=100, color=’blue’, label=’実績’, zorder=5) # 各トレンドライン x_line = np.linspace(1, 15, 100).reshape(-1, 1) ax.plot(x_line, model_linear.predict(x_line), ‘–‘, label=f’線形 (R²={r2_linear:.3f})’, alpha=0.7) ax.plot(x_line, np.exp(model_exp.predict(x_line)), ‘-‘, label=f’指数 (R²={r2_exp:.3f})’, linewidth=2) ax.plot(x_line, model_poly.predict(poly.transform(x_line)), ‘:’, label=f’多項式 (R²={r2_poly:.3f})’, alpha=0.7) # 将来予測点 ax.scatter(future_months, future_pred, s=100, color=’red’, marker=’*’, label=’予測’, zorder=5) ax.axvline(x=12.5, color=’gray’, linestyle=’–‘, alpha=0.5) ax.text(12.7, ax.get_ylim()[0] + 20, ‘← 実績 | 予測 →’, fontsize=10) ax.set_xlabel(‘月’, fontsize=12) ax.set_ylabel(‘売上(万円)’, fontsize=12) ax.set_title(‘トレンド比較と将来予測’, fontsize=14) ax.legend(loc=’upper left’) ax.grid(True, alpha=0.3) plt.tight_layout() plt.savefig(‘trend_selection.png’, dpi=150, bbox_inches=’tight’) plt.show() print(“\n→ グラフを ‘trend_selection.png’ に保存しました”)

Excelでのトレンド分析

💡 Excelでトレンドラインを追加する方法
手順:
1. データを選択 → 挿入 → 散布図
2. グラフのデータ点を右クリック → 「近似曲線の追加」
3. トレンドの種類を選択(線形/指数/多項式)
4. 「グラフに数式を表示する」「R-2乗値を表示する」にチェック

Excel数式:
・R²: =RSQ(実績範囲, 予測範囲)
・傾き: =SLOPE(Y範囲, X範囲)
・切片: =INTERCEPT(Y範囲, X範囲)
・指数成長率: =LOGEST(Y範囲, X範囲)

📊 3. 予測精度の評価指標

3つの主要な評価指標

💡 MAE(平均絶対誤差)
計算式: MAE = Σ|実績 – 予測| ÷ n

意味: 予測が平均してどれくらいズレているか(金額)
特徴: 単位が元データと同じ、解釈しやすい

計算例:
実績: 100, 110, 120 / 予測: 105, 108, 118
MAE = (5 + 2 + 2) ÷ 3 = 3.0万円
💡 RMSE(二乗平均平方根誤差)
計算式: RMSE = √(Σ(実績 – 予測)² ÷ n)

意味: 大きな誤差を重視した評価(金額)
特徴: 外れ値に敏感、MAEより常に大きい

計算例:
二乗誤差: 25, 4, 4
RMSE = √(33 ÷ 3) = 3.3万円
💡 MAPE(平均絶対パーセント誤差)
計算式: MAPE = Σ(|実績 – 予測| ÷ 実績) ÷ n × 100%

意味: 予測が平均して何%ズレているか
特徴: スケールに依存しない、経営報告に最適

計算例:
%誤差: 5%, 1.8%, 1.7%
MAPE = (5 + 1.8 + 1.7) ÷ 3 = 2.8%

評価指標の使い分け

📌 目的と相手に応じて選択
指標 報告先 メリット
MAE 現場担当者 金額で分かりやすい
RMSE データ分析者 外れ値を重視
MAPE 経営層 %で直感的

精度評価の完全実装

# ============================================ # 予測精度の完全評価 # ============================================ import numpy as np import pandas as pd import matplotlib.pyplot as plt # データの準備 actual = np.array([100, 110, 105, 115, 120, 125, 118, 130, 135, 140]) forecast = np.array([102, 108, 107, 113, 122, 123, 120, 128, 137, 138]) # 評価指標の計算 def calculate_metrics(actual, forecast): errors = forecast – actual abs_errors = np.abs(errors) pct_errors = abs_errors / actual * 100 mae = np.mean(abs_errors) rmse = np.sqrt(np.mean(errors ** 2)) mape = np.mean(pct_errors) bias = np.mean(errors) return {‘MAE’: mae, ‘RMSE’: rmse, ‘MAPE’: mape, ‘Bias’: bias} metrics = calculate_metrics(actual, forecast) print(“【評価指標】”) print(f”MAE: {metrics[‘MAE’]:.2f}万円”) print(f”RMSE: {metrics[‘RMSE’]:.2f}万円”) print(f”MAPE: {metrics[‘MAPE’]:.2f}%”) # 精度の評価基準 if metrics[‘MAPE’] < 5: print("\n【評価】非常に良い") elif metrics['MAPE'] < 10: print("\n【評価】良好") elif metrics['MAPE'] < 20: print("\n【評価】普通") else: print("\n【評価】要改善") # バイアス分析 print(f"\n【バイアス】{metrics['Bias']:+.2f}万円") if abs(metrics['Bias']) < 1: print("→ バイアスなし(良好)") elif metrics['Bias'] > 0: print(“→ 過大予測の傾向あり”) else: print(“→ 過小予測の傾向あり”) # ============================================ # 精度評価の可視化(4つのグラフ) # ============================================ fig, axes = plt.subplots(2, 2, figsize=(12, 10)) months = np.arange(1, len(actual) + 1) errors = forecast – actual # 1. 実績 vs 予測の推移 ax1 = axes[0, 0] ax1.plot(months, actual, ‘o-‘, label=’実績’, linewidth=2, markersize=8) ax1.plot(months, forecast, ‘s–‘, label=’予測’, linewidth=2, markersize=8) ax1.fill_between(months, actual, forecast, alpha=0.3, color=’orange’) ax1.set_xlabel(‘月’) ax1.set_ylabel(‘売上(万円)’) ax1.set_title(‘① 実績 vs 予測の推移’) ax1.legend() ax1.grid(True, alpha=0.3) # 2. 誤差の棒グラフ ax2 = axes[0, 1] colors = [‘#e74c3c’ if e > 0 else ‘#3498db’ for e in errors] ax2.bar(months, errors, color=colors, alpha=0.7, edgecolor=’black’) ax2.axhline(y=0, color=’black’, linewidth=1) ax2.axhline(y=metrics[‘Bias’], color=’red’, linestyle=’–‘, label=f’バイアス: {metrics[“Bias”]:+.1f}’) ax2.set_xlabel(‘月’) ax2.set_ylabel(‘誤差(万円)’) ax2.set_title(‘② 月別誤差(赤=過大、青=過小)’) ax2.legend() ax2.grid(True, alpha=0.3, axis=’y’) # 3. 散布図(45度線付き) ax3 = axes[1, 0] ax3.scatter(actual, forecast, s=100, alpha=0.7, edgecolors=’black’) min_val = min(min(actual), min(forecast)) – 5 max_val = max(max(actual), max(forecast)) + 5 ax3.plot([min_val, max_val], [min_val, max_val], ‘r–‘, linewidth=2, label=’完全一致線’) ax3.set_xlabel(‘実績(万円)’) ax3.set_ylabel(‘予測(万円)’) ax3.set_title(‘③ 実績 vs 予測 散布図’) ax3.legend() ax3.grid(True, alpha=0.3) ax3.set_xlim(min_val, max_val) ax3.set_ylim(min_val, max_val) # 4. 誤差分布のヒストグラム ax4 = axes[1, 1] ax4.hist(errors, bins=7, color=’steelblue’, alpha=0.7, edgecolor=’black’) ax4.axvline(x=0, color=’red’, linestyle=’–‘, linewidth=2, label=’誤差0’) ax4.axvline(x=metrics[‘Bias’], color=’orange’, linestyle=’-‘, linewidth=2, label=f’バイアス: {metrics[“Bias”]:+.1f}’) ax4.set_xlabel(‘誤差(万円)’) ax4.set_ylabel(‘頻度’) ax4.set_title(‘④ 誤差の分布’) ax4.legend() ax4.grid(True, alpha=0.3, axis=’y’) plt.tight_layout() plt.savefig(‘accuracy_evaluation.png’, dpi=150, bbox_inches=’tight’) plt.show() print(“\n→ グラフを ‘accuracy_evaluation.png’ に保存しました”)

ホールドアウト検証(テストデータでの評価)

⚠️ 学習データとテストデータを分ける重要性
問題: 学習に使ったデータで精度を測ると、過度に良い結果が出る

解決策: データを分割して「未知のデータ」でテスト

推奨分割:
・学習データ: 70-80%(例: 1-30ヶ月目)
・テストデータ: 20-30%(例: 31-36ヶ月目)
# ============================================ # ホールドアウト検証の実装 # ============================================ import numpy as np from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_absolute_error, mean_squared_error # 36ヶ月分のデータ np.random.seed(42) months_all = np.arange(1, 37) sales_all = 100 + 8 * months_all + np.random.normal(0, 10, 36) # データ分割(80%学習、20%テスト) split_point = 30 # 30ヶ月目で分割 # 学習データ X_train = months_all[:split_point].reshape(-1, 1) y_train = sales_all[:split_point] # テストデータ X_test = months_all[split_point:].reshape(-1, 1) y_test = sales_all[split_point:] print(f”学習データ: {len(y_train)}件(1-{split_point}ヶ月目)”) print(f”テストデータ: {len(y_test)}件({split_point+1}-36ヶ月目)”) # モデル学習(学習データのみ使用) model = LinearRegression() model.fit(X_train, y_train) # 学習データでの精度 y_pred_train = model.predict(X_train) mae_train = mean_absolute_error(y_train, y_pred_train) # テストデータでの精度(重要!) y_pred_test = model.predict(X_test) mae_test = mean_absolute_error(y_test, y_pred_test) print(f”\n【精度比較】”) print(f”学習データ MAE: {mae_train:.2f}万円”) print(f”テストデータ MAE: {mae_test:.2f}万円”) # 過学習チェック if mae_test > mae_train * 1.5: print(“\n⚠️ 警告: 過学習の可能性あり”) print(” → モデルを単純化するか、データを増やす”) else: print(“\n✓ 過学習なし(テスト精度が妥当)”) # 可視化 import matplotlib.pyplot as plt fig, ax = plt.subplots(figsize=(12, 6)) # 学習データ ax.scatter(X_train, y_train, color=’blue’, s=60, label=’学習データ’, alpha=0.7) # テストデータ ax.scatter(X_test, y_test, color=’green’, s=80, marker=’s’, label=’テストデータ(実績)’, alpha=0.7) # テスト予測 ax.scatter(X_test, y_pred_test, color=’red’, s=80, marker=’^’, label=’テストデータ(予測)’, alpha=0.7) # トレンドライン x_line = np.linspace(1, 36, 100).reshape(-1, 1) ax.plot(x_line, model.predict(x_line), ‘r-‘, linewidth=2, label=’トレンドライン’) # 分割線 ax.axvline(x=split_point + 0.5, color=’gray’, linestyle=’–‘, linewidth=2) ax.text(split_point – 5, ax.get_ylim()[1] – 20, ‘学習期間’, fontsize=11) ax.text(split_point + 1, ax.get_ylim()[1] – 20, ‘テスト期間’, fontsize=11) ax.set_xlabel(‘月’, fontsize=12) ax.set_ylabel(‘売上(万円)’, fontsize=12) ax.set_title(f’ホールドアウト検証\n学習MAE: {mae_train:.1f}万円 / テストMAE: {mae_test:.1f}万円’, fontsize=14) ax.legend(loc=’upper left’) ax.grid(True, alpha=0.3) plt.tight_layout() plt.savefig(‘holdout_validation.png’, dpi=150, bbox_inches=’tight’) plt.show() print(“\n→ グラフを ‘holdout_validation.png’ に保存しました”)

Excelでの精度計算

💡 Excelで評価指標を計算する数式
データ配置: B列=実績、C列=予測

指標 Excel数式
MAE =AVERAGE(ABS(B2:B11-C2:C11))
RMSE =SQRT(AVERAGE((B2:B11-C2:C11)^2))
MAPE =AVERAGE(ABS(B2:B11-C2:C11)/B2:B11)*100
バイアス =AVERAGE(C2:C11-B2:B11)

※Excel 365以前は配列数式(Ctrl+Shift+Enter)が必要

実務での精度目標

⚠️ 業界・用途別のMAPE目標
精度 MAPE 用途例
非常に高精度 < 5% 電力需要、金融
高精度 5-10% 売上予測、在庫管理
中精度 10-20% 新商品、中期計画
低精度 > 20% 長期予測、新規事業

🔄 4. トレンド転換の検出

トレンド転換の兆候

💡 5つの早期警戒サイン
サイン 具体例
1. 成長率の変化 前年比+20%→+5%
2. 移動平均の傾き 上昇→横ばい
3. 予測誤差の拡大 MAPE 5%→15%
4. バイアスの発生 常に過大予測に
5. 外部環境の変化 競合参入、規制変更

トレンド転換の検出実装

# ============================================ # トレンド転換の検出 # ============================================ import pandas as pd import numpy as np import matplotlib.pyplot as plt # トレンド転換があるデータ生成 np.random.seed(42) months = np.arange(1, 37) trend_change_point = 18 # 18ヶ月目で転換 # 前半:上昇、後半:下降 trend1 = 100 + 5 * months[:trend_change_point] + np.random.normal(0, 3, trend_change_point) trend2 = trend1[-1] – 3 * np.arange(1, len(months) – trend_change_point + 1) + np.random.normal(0, 3, len(months) – trend_change_point) sales = np.concatenate([trend1, trend2]) df = pd.DataFrame({‘month’: months, ‘sales’: sales}) df[‘MA_6’] = df[‘sales’].rolling(window=6).mean() df[‘MA_change’] = df[‘MA_6’].diff() # トレンド転換点の検出 def detect_trend_change(data, window=6): ma = data.rolling(window=window).mean() ma_change = ma.diff() signs = np.sign(ma_change.dropna()) changes = [] for i in range(1, len(signs)): if signs.iloc[i] != signs.iloc[i-1] and signs.iloc[i] != 0: changes.append(signs.index[i]) return changes change_points = detect_trend_change(df[‘sales’]) print(“【検出された転換点】”) for cp in change_points: print(f” {cp}ヶ月目”) print(“\n【対応策】”) print(“1. 転換点以降のデータで再学習”) print(“2. 複数シナリオを準備”) print(“3. モニタリング強化”)

⚠️ 5. 実務でよくある間違い

間違い①: 精度指標を1つしか見ない

❌ 問題: 「MAPEが8%なので良好です」

何が問題か?
・バイアスが隠れている可能性
・外れ値の影響が見えない

✅ 正しいアプローチ:
・MAE、RMSE、MAPEの3つを確認
・バイアスを確認
・誤差の分布を可視化

間違い②: 過去データだけで評価する

❌ 問題: 「全データで学習し、同じデータで評価したらMAPE=3%!」

何が問題か?
・過学習の可能性
・未知データに対する精度が不明

✅ 正しいアプローチ:
・データを学習用とテスト用に分割
・例: 1-30ヶ月目で学習、31-36ヶ月目でテスト

間違い③: 精度目標を決めずに進める

❌ 問題: 「とりあえずモデルを作って、精度を見てから考えよう」

✅ 正しいアプローチ:
・事前に目標を設定: 「MAPEを10%以下に」
・業界標準を参考にする
・費用対効果を考慮

間違い④: 外れ値を無視する

❌ 問題: 「12月は特需で2倍だけど、そのままモデルに入れよう」

✅ 正しいアプローチ:
1. 外れ値を検出(平均±3σの範囲外)
2. 原因を特定(特需?入力ミス?)
3. 適切に処理(除外or補正)

間違い⑤: モデルを更新しない

❌ 問題: 「去年作ったモデルをそのまま今年も使おう」

✅ 正しいアプローチ:
・月次: 精度モニタリング
・四半期: パラメータ調整
・年次: モデル全体の見直し

✅ 6. 精度評価チェックリスト

💡 予測精度を評価する前に確認!
【データの確認】
□ 十分なデータ量があるか(最低24ヶ月推奨)
□ 外れ値は処理したか
□ 欠損値は適切に補完したか
□ 季節調整は必要か(→STEP 35参照)

【トレンドの選択】
□ 複数のトレンドを試したか
□ R²で比較したか
□ ビジネス知識と整合性があるか

【精度評価】
□ 学習データとテストデータを分けたか
□ MAE、RMSE、MAPEの3つを確認したか
□ バイアスを確認したか

【運用準備】
□ 精度目標を設定したか
□ 更新スケジュールを決めたか
□ 複数シナリオを準備したか

📝 STEP 36 のまとめ

✅ このステップで学んだこと
  • 3種類のトレンド: 線形(一定額)、指数(一定率)、S字(飽和あり)
  • トレンドの選択: R²で比較、ビジネス知識で検証
  • 評価指標: MAE(金額)、RMSE(外れ値重視)、MAPE(%)
  • バイアス分析: 過大/過小予測の傾向を確認
  • トレンド転換: 移動平均の変化率で早期検出
  • よくある間違い: 単一指標、過学習、更新忘れなど
💡 実務での重要ポイント

予測精度評価の鉄則!

1. 複数の指標で総合判断
・MAPE: 経営報告向け
・MAE: 実務判断向け
・バイアス: 傾向の確認

2. テストデータで評価
・学習データと分離する
・時系列は時間順に分割

3. 継続的にモニタリング
・精度の低下を早期検出
・トレンド転換に注意

完璧な予測は不可能!
でも、精度を正しく評価し、
継続的に改善することで
意思決定の質は確実に向上します!

📌 次のステップへのつながり

このSTEPで学んだ精度評価の手法は、
STEP 37(ABC分析・パレート分析)でも活用します。

また、STEP 34(高度な予測手法)で学んだ
ARIMA、Prophet、指数平滑法などのモデルを
比較する際にも、このSTEPの知識が必要です。

📝 練習問題

問題 1 基礎

以下の予測結果について、MAE、RMSE、MAPEを計算してください。

実績: 100, 110, 120, 130, 140 (万円)
予測: 105, 108, 125, 128, 145 (万円)

【解答】MAE = 3.8万円、RMSE = 4.1万円、MAPE = 3.2%
計算手順:

誤差: +5, -2, +5, -2, +5
絶対誤差: 5, 2, 5, 2, 5
二乗誤差: 25, 4, 25, 4, 25
%誤差: 5.0%, 1.8%, 4.2%, 1.5%, 3.6%

MAE = (5+2+5+2+5) ÷ 5 = 3.8万円
RMSE = √(83÷5) = 4.1万円
MAPE = (5.0+1.8+4.2+1.5+3.6) ÷ 5 = 3.2%

評価: MAPE 3.2% → 非常に良い精度!
問題 2 応用

ある商品の売上が以下のように推移しています。
線形トレンドと指数トレンドのどちらが適切か判断してください。

1ヶ月目: 100万円
6ヶ月目: 130万円
12ヶ月目: 170万円
18ヶ月目: 220万円
24ヶ月目: 285万円

【解答】指数トレンド
判断の根拠:

増加幅の確認:
1-6ヶ月: +30万円
6-12ヶ月: +40万円
12-18ヶ月: +50万円
18-24ヶ月: +65万円
増加幅が拡大している

増加率の確認:
各期間: 約30%, 31%, 29%, 30%
増加率がほぼ一定

→ 指数トレンドの特徴に合致!

予測への影響:
30ヶ月目予測:
・線形: 約331万円
・指数: 約374万円
43万円の差!
問題 3 応用

2つの予測モデルの結果があります。
どちらを採用すべきか判断し、理由を説明してください。

モデルA: MAE = 8万円、MAPE = 6%、バイアス = +7万円
モデルB: MAE = 10万円、MAPE = 8%、バイアス = -1万円

【解答】モデルBを採用すべき
判断の根拠:

一見するとモデルAが良さそう:
・MAE: A(8) < B(10)
・MAPE: A(6%) < B(8%)

しかしバイアスを見ると:
・モデルA: +7万円(常に過大予測)
・モデルB: -1万円(ほぼバイアスなし)

モデルAの問題点:
・バイアス+7万円 = MAE 8万円の87.5%
・誤差のほとんどが系統的な過大予測
・モデルに構造的な問題がある

結論:
バイアスがないモデルBの方が信頼性が高い!
問題 4 発展

月次売上予測の精度改善プロジェクトを任されました。

現状: MAPE = 18%
目標: MAPE = 10%
データ: 過去24ヶ月の売上実績

精度改善のためのアクションプランを3つ提案してください。

【解答例】精度改善アクションプラン
アクション1: データ品質の向上
・外れ値の検出と処理
・季節調整の実施(STEP 35参照)
・データ期間の延長(可能なら36ヶ月以上)
期待効果: MAPE 2-3%改善

アクション2: 特徴量の追加
・休日フラグ(祝日、大型連休)
・プロモーション情報
・天候データ
期待効果: MAPE 3-5%改善

アクション3: モデルの高度化
・ARIMA、Prophet等を試行(STEP 34参照)
・複数モデルのアンサンブル
期待効果: MAPE 2-4%改善

プロジェクト計画:
1. データ品質向上(2週間)→ MAPE 15%
2. 特徴量追加(3週間)→ MAPE 12%
3. モデル高度化(3週間)→ MAPE 10%

❓ よくある質問

Q1: MAE、RMSE、MAPE、どれを使えばいいですか?
目的と相手に応じて使い分けます。

・経営層への報告 → MAPE(%で分かりやすい)
・現場での実務 → MAE(金額で具体的)
・モデル比較 → RMSE(外れ値を重視)

推奨: 基本はMAPEをメインに、MAEも併記
Q2: R²(決定係数)とMAPEの違いは何ですか?
目的が異なります。

・R²: トレンドの当てはまりの良さ(0〜1)
 → トレンド選択時に使用

・MAPE: 予測の精度(%)
 → 予測評価時に使用

両方確認するのがベスト!
Q3: 予測精度が目標に達しない場合、どうすればいいですか?
段階的にアプローチします。

1. 現状分析(どの月の誤差が大きいか)
2. データ改善(外れ値処理、データ量増加)
3. モデル改善(トレンド変更、特徴量追加)
4. 目標の見直し(費用対効果を考慮)

MAPE 20%→10%は努力で可能、10%→5%は極めて困難
Q4: トレンド転換をどう見極めますか?
複数の兆候から総合的に判断します。

数値的な兆候:
・移動平均の傾きが変化
・成長率の急変
・予測誤差の拡大

定性的な兆候:
・競合の動き
・市場環境の変化

対応策: 予測期間を短縮、モデル更新、複数シナリオ準備
📝

学習メモ

ビジネスデータ分析・意思決定 - Step 36

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE