📋 このステップで学ぶこと
- 残差(ざんさ)とは何か – 基本概念の理解
- 残差プロットの見方と解釈
- 正規性の確認(Q-Qプロット、ヒストグラム)
- 等分散性の確認と異常値の検出
- モデルの問題点の診断と改善方法
学習時間の目安:3時間
📊 1. 残差とは
残差の基本概念
📌 残差(Residual)とは
実際の値と予測値の差
計算式:
残差 = 実際の値 – 予測値
e = y – ŷ
意味:
・残差が0に近い → 予測が正確
・残差が大きい → 予測が外れている
・残差がプラス → 実際の値の方が大きい(過小評価)
・残差がマイナス → 予測値の方が大きい(過大評価)
具体例
📋 残差の計算例
| X(広告費) |
Y(実際の売上) |
ŷ(予測売上) |
残差(Y – ŷ) |
| 50 | 310 | 320 | -10 |
| 60 | 380 | 370 | +10 |
| 70 | 430 | 420 | +10 |
| 80 | 470 | 470 | 0 |
| 90 | 520 | 520 | 0 |
解釈:
・広告費50万円:予測より10万円低い(過大評価)
・広告費60万円:予測より10万円高い(過小評価)
・広告費80, 90万円:予測がぴったり!
なぜ残差分析が重要か
💡 残差分析の目的
R²が高くても、モデルに問題があることがあります。残差分析で、以下をチェックします:
- 残差がランダムか → パターンがあれば問題
- 残差が正規分布か → 偏っていれば問題
- 残差の大きさが一定か → バラつきが変化すれば問題
- 外れ値がないか → 極端な値は要注意
これらを確認することで、予測精度の向上やモデルの改善ができます!
📈 2. 残差プロット
残差プロットとは
📌 残差プロット(Residual Plot)
横軸:予測値(ŷ)、縦軸:残差(e)のグラフ
目的:
残差にパターン(規則性)がないかを視覚的に確認
→ パターンがなければ、モデルは適切
良い残差プロット vs 悪い残差プロット
【良い残差プロット】
残差
|
+20| ● ●
+10| ● ● ●
0|●─────●─────●───────● ← 0の周りにランダムに散らばる
-10| ● ● ●
-20| ● ●
└────────────────────
予測値
✓ 残差が0の周りにランダムに散らばっている
✓ パターンや傾向が見られない
✓ バラつきの大きさが一定
→ モデルは適切!
【悪い残差プロット – パターン1:曲線パターン】
残差
|
+20| ●
+10| ● ●
0|●─────────●─────────● ← U字型の曲線
-10| ● ●
-20| ●
└────────────────────
予測値
✗ 曲線的なパターンが見える
→ 非線形の関係がある
→ 対策:多項式回帰(X²を追加)、対数変換など
【悪い残差プロット – パターン2:扇形パターン】
残差
|
+30| ●
+20| ● ●
+10| ● ●
0|●─────●─────●───────
-10| ●
-20| ● ●
-30| ● ●
└────────────────────
予測値
✗ 右に行くほど残差のバラつきが大きくなる(扇形)
→ 等分散性が満たされていない
→ 対策:対数変換、加重最小二乗法など
Excelでの残差プロット作成
【Excelの分析ツールで残差プロットを作成】
1. 「データ」タブ → 「データ分析」 → 「回帰」
2. 入力Y範囲、入力X範囲を設定
3. ☑ 残差プロット にチェック
4. OK → 新しいシートに残差プロットが自動生成される
結果:
・各説明変数ごとに残差プロットが作成される
・パターンがないかを目視で確認
Pythonでの残差プロット作成
# ============================================
# 残差分析の実装
# ============================================
# 残差(Residual)= 実際の値 – 予測値
# → モデルが予測できなかった部分
# → 残差の傾向を分析してモデルの問題点を発見
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
# ============================================
# サンプルデータの準備
# ============================================
data = {
‘広告費’: [50, 60, 70, 55, 80, 90, 85, 75, 65, 70, 95, 100],
‘売上’: [310, 370, 420, 330, 480, 530, 500, 450, 390, 430, 560, 590]
}
df = pd.DataFrame(data)
# ============================================
# 回帰分析の実行
# ============================================
X = df[[‘広告費’]]
y = df[‘売上’]
model = LinearRegression()
model.fit(X, y)
# ============================================
# 予測値と残差の計算
# ============================================
# model.predict(X): 学習済みモデルで予測
y_pred = model.predict(X)
# 残差 = 実際の値 – 予測値
# 正の残差: モデルが過小評価(実際の方が大きい)
# 負の残差: モデルが過大評価(実際の方が小さい)
残差 = y – y_pred
print(“【残差の確認】”)
print(f”残差の平均: {残差.mean():.4f}(0に近いほど良い)”)
print(f”残差の標準偏差: {残差.std():.2f}(モデルの誤差の大きさ)”)
# ============================================
# 残差プロットの作成
# ============================================
# 残差プロット: X軸=予測値、Y軸=残差
# なぜ残差プロットを作るか?
# → モデルの仮定が満たされているか確認
# → 系統的なパターンがないかチェック
plt.figure(figsize=(10, 6))
# plt.scatter(): 散布図を描画
plt.scatter(y_pred, 残差, s=100, alpha=0.6, color=’blue’)
# plt.axhline(): 水平線を描画
# y=0の線を引く(残差が0のライン)
plt.axhline(y=0, color=’red’, linestyle=’–‘, linewidth=2)
plt.xlabel(‘予測値’, fontsize=12)
plt.ylabel(‘残差’, fontsize=12)
plt.title(‘残差プロット’, fontsize=14)
plt.grid(True, alpha=0.3)
plt.show()
print(“\n【残差プロットの読み方】”)
print(“✓ 良い状態: 点がランダムに散らばっている”)
print(“✗ 悪い状態: U字型、扇型などのパターンがある”)
📌 残差プロットのチェックポイント
- 点が0の線の周りにランダムに散らばっているか?
- U字型やS字型のパターンがないか?
- 扇形(右に行くほど広がる)になっていないか?
- 極端に外れた点がないか?
📊 3. 正規性の確認
なぜ正規性が重要か
📌 正規性(Normality)の仮定
回帰分析では、残差が正規分布に従うことを仮定しています
正規分布:
平均を中心に、左右対称な釣り鐘型の分布
多くの自然現象や測定誤差は正規分布に従う
正規性が満たされないと:
・p値が正しく計算されない
・信頼区間が正確でない
・予測区間が信頼できない
方法1:ヒストグラム
# ============================================
# 残差のヒストグラム
# ============================================
# ヒストグラム: データの分布を視覚化
# なぜ作るか?
# → 残差が正規分布(釣り鐘型)に従うか確認
# → 正規分布なら、回帰分析の仮定を満たしている
plt.figure(figsize=(10, 6))
# plt.hist(): ヒストグラムを描画
# bins=10: 棒の数(データを10個の区間に分ける)
# edgecolor=’black’: 棒の枠線
# alpha=0.7: 透明度
plt.hist(残差, bins=10, color=’skyblue’, edgecolor=’black’, alpha=0.7)
# 残差=0の位置に縦線を追加
plt.axvline(x=0, color=’red’, linestyle=’–‘, linewidth=2)
plt.xlabel(‘残差’, fontsize=12)
plt.ylabel(‘頻度’, fontsize=12)
plt.title(‘残差のヒストグラム’, fontsize=14)
plt.grid(True, alpha=0.3)
plt.show()
print(“【ヒストグラムの見方】”)
print(“✓ 良い状態: 左右対称の釣り鐘型”)
print(“✗ 悪い状態: 左右に偏っている、複数の山がある”)
方法2:Q-Qプロット(最も重要)
📌 Q-Qプロット(Quantile-Quantile Plot)
残差が正規分布に従うかを確認する最も信頼できる方法
見方:
・点が直線上に並ぶ → 正規分布に従う ✓
・点が直線から大きく外れる → 正規分布に従わない ✗
対処:
正規性が満たされない場合 → 対数変換、平方根変換などを検討
# ============================================
# Q-Qプロット(正規性の視覚的確認)
# ============================================
# Q-Qプロット: 理論的な正規分布と実際のデータを比較
# なぜQ-Qプロットか?
# → ヒストグラムより正確に正規性を判断できる
# → 端の部分(裾)の違いも確認できる
import scipy.stats as stats
plt.figure(figsize=(10, 6))
# stats.probplot(): Q-Qプロットを作成
# 残差: 分析対象のデータ
# dist=”norm”: 比較する分布(正規分布)
# plot=plt: グラフ描画に使用するライブラリ
stats.probplot(残差, dist=”norm”, plot=plt)
plt.title(‘Q-Qプロット(正規性の確認)’, fontsize=14)
plt.xlabel(‘理論的分位数(正規分布の場合の期待値)’, fontsize=12)
plt.ylabel(‘標本分位数(実際のデータ)’, fontsize=12)
plt.grid(True, alpha=0.3)
plt.show()
print(“【Q-Qプロットの見方】”)
print(“✓ 良い状態: 全ての点が赤い直線に沿っている”)
print(“✗ 悪い状態: 端の点が直線から外れている(裾が重い/軽い)”)
方法3:シャピロ・ウィルク検定
# ============================================
# シャピロ・ウィルク検定(正規性の統計的検定)
# ============================================
# なぜ統計検定を使うか?
# → グラフだけでは主観的な判断になりがち
# → p値で客観的に判断できる
from scipy.stats import shapiro
# shapiro(): シャピロ・ウィルク検定を実行
# 帰無仮説: データは正規分布に従う
# 対立仮説: データは正規分布に従わない
#
# 戻り値:
# statistic: 検定統計量
# p_value: p値
statistic, p_value = shapiro(残差)
print(“【シャピロ・ウィルク検定】”)
print(f”検定統計量: {statistic:.4f}”)
print(f”p値: {p_value:.4f}”)
# p値による判定
# p > 0.05: 帰無仮説を棄却できない → 正規分布と見なせる
# p < 0.05: 帰無仮説を棄却 → 正規分布ではない
print("\n【判定】")
if p_value > 0.05:
print(f”p値({p_value:.4f}) > 0.05″)
print(“→ 残差は正規分布に従うと見なせる ✓”)
else:
print(f”p値({p_value:.4f}) < 0.05")
print("→ 残差は正規分布に従わない可能性がある ✗")
print("→ 対数変換などを検討してください")
# 出力例
シャピロ・ウィルク検定
統計量: 0.9723
p値: 0.9234
→ 残差は正規分布に従う(p > 0.05)
📏 4. 等分散性の確認
等分散性とは
📌 等分散性(Homoscedasticity)
残差のバラつきが、予測値によらず一定であること
問題(不等分散性):
予測値が大きくなるにつれて、残差のバラつきも大きくなる
→ 「扇形パターン」
影響:
・予測の信頼性が一定でない
・標準誤差が正しく計算されない
・p値が信頼できない
残差プロットで確認
【等分散性のチェック – 残差プロットを見る】
良い例(等分散):
残差
|
+20| ● ● ● ●
+10| ● ● ●
0|●─────●─────●─────●
-10| ● ● ●
-20| ● ● ●
└────────────────────
予測値
✓ 残差のバラつきが一定
悪い例(不等分散):
残差
|
+30| ●
+20| ● ●
+10| ● ●
0|●─●─●─●───────
-10| ●
-20| ● ●
-30| ● ●
└────────────────────
予測値
✗ 右に行くほどバラつきが大きい
対処方法
🔧 不等分散性の対処法
1. 対数変換
目的変数Yを対数変換 → log(Y)で回帰
特に、Yの値が大きいほどバラつきが大きい場合に有効
2. 平方根変換
目的変数Yを平方根変換 → √Yで回帰
カウントデータ(来客数、クリック数など)で有効
3. 加重最小二乗法
バラつきが大きいデータの重みを下げる
高度な手法(statsmodelsで実装可能)
# ============================================
# 対数変換の例(等分散性の改善)
# ============================================
# なぜ対数変換を使うか?
# → 右に裾が長い分布(売上データなど)を正規分布に近づける
# → 等分散性を改善(残差のバラつきを均一にする)
# → 外れ値の影響を軽減
import numpy as np
# np.log(): 自然対数を計算
# → 大きな値の差が縮まる
# → 例: log(100)=4.6, log(1000)=6.9 (差が10倍→1.5倍に圧縮)
df[‘売上_log’] = np.log(df[‘売上’])
print(“【対数変換の効果】”)
print(f”売上(元データ): 最小={df[‘売上’].min()}, 最大={df[‘売上’].max()}”)
print(f”売上(対数変換): 最小={df[‘売上_log’].min():.2f}, 最大={df[‘売上_log’].max():.2f}”)
# ============================================
# 対数変換後のデータで回帰分析
# ============================================
X = df[[‘広告費’]]
y_log = df[‘売上_log’]
model_log = LinearRegression()
model_log.fit(X, y_log)
# 残差を計算
y_log_pred = model_log.predict(X)
残差_log = y_log – y_log_pred
# ============================================
# 残差プロットで改善を確認
# ============================================
plt.figure(figsize=(10, 6))
plt.scatter(y_log_pred, 残差_log, s=100, alpha=0.6, color=’blue’)
plt.axhline(y=0, color=’red’, linestyle=’–‘, linewidth=2)
plt.xlabel(‘予測値(対数変換後)’, fontsize=12)
plt.ylabel(‘残差’, fontsize=12)
plt.title(‘残差プロット(対数変換後)’, fontsize=14)
plt.grid(True, alpha=0.3)
plt.show()
print(“\n【対数変換のポイント】”)
print(“・元データと変換後の残差プロットを比較”)
print(“・扇形パターンが改善されていれば成功”)
print(“・解釈時は変換を考慮(係数の意味が変わる)”)
🎯 5. 異常値(外れ値)の検出
異常値とは
📌 異常値(Outlier)
他のデータと大きく異なる極端な値
問題:
・回帰式が大きくズレる
・R²が下がる
・予測精度が悪化
原因:
・データ入力ミス
・特殊なイベント(キャンペーン、災害など)
・測定ミス
残差で検出
# ============================================
# 残差が大きい点を検出(異常値の発見)
# ============================================
# 異常値検出の基本ルール:
# → 残差が±2標準偏差を超える点 = 要注意
# → 残差が±3標準偏差を超える点 = 異常値の可能性大
# 残差の標準偏差を計算
# np.std(): 標準偏差を計算(データのバラつきの指標)
残差の標準偏差 = np.std(残差)
# 異常値の閾値を設定(2標準偏差)
異常値の閾値 = 2 * 残差の標準偏差
# np.where(): 条件を満たすインデックスを取得
# np.abs(): 絶対値を計算(正負両方の外れ値を検出)
異常値インデックス = np.where(np.abs(残差) > 異常値の閾値)[0]
print(“【異常値の検出】”)
print(f”残差の標準偏差: {残差の標準偏差:.2f}”)
print(f”異常値の閾値: ±{異常値の閾値:.2f}(2標準偏差)”)
print(f”\n異常値の数: {len(異常値インデックス)}件”)
# 異常値があれば詳細を表示
if len(異常値インデックス) > 0:
print(“\n【異常値の詳細】”)
for idx in 異常値インデックス:
print(f” データ{idx+1}: 広告費={df.iloc[idx][‘広告費’]}万円, ”
f”売上={df.iloc[idx][‘売上’]}万円”)
print(f” 残差={残差.iloc[idx]:.2f}(予測から{abs(残差.iloc[idx]):.1f}万円ズレ)”)
else:
print(“\n→ 異常値は検出されませんでした”)
スチューデント化残差
📌 スチューデント化残差(Studentized Residual)
標準化された残差
基準:
・|スチューデント化残差| > 2 → 要注意
・|スチューデント化残差| > 3 → 異常値の可能性が高い
利点:
データのバラつきを考慮した、より正確な異常値検出
# ============================================
# スチューデント化残差(より正確な異常値検出)
# ============================================
# なぜスチューデント化残差を使うか?
# → 単純な残差は、各データ点の影響力を考慮していない
# → スチューデント化残差は、標準化されているため比較しやすい
# → |値| > 2 で要注意、|値| > 3 で異常値と判断
import statsmodels.api as sm
# statsmodelsで回帰分析を実行
X_with_const = sm.add_constant(df[[‘広告費’]])
model_sm = sm.OLS(df[‘売上’], X_with_const)
results = model_sm.fit()
# .outlier_test(): スチューデント化残差と関連統計を取得
# student_resid: スチューデント化残差
# unadj_p: 調整前p値
# bonf(p): ボンフェローニ補正後のp値
student_resid = results.outlier_test()
print(“【スチューデント化残差】”)
print(student_resid)
# 異常値の検出(|t| > 3)
異常値 = student_resid[np.abs(student_resid[‘student_resid’]) > 3]
print(“\n【異常値判定(|スチューデント化残差| > 3)】”)
if len(異常値) > 0:
print(“⚠ 異常値が検出されました:”)
print(異常値)
print(“\n→ これらのデータの原因を調査してください”)
else:
print(“✓ 異常値は検出されませんでした”)
異常値への対処
🔧 異常値の対処フロー
ステップ1:原因を調査
- データ入力ミス? → 修正
- 測定ミス? → 削除
- 特殊なイベント? → 残すか判断
ステップ2:削除 or 残す
- 明らかなミス → 削除
- ビジネス的に意味がある → 残す
- 判断できない → ダミー変数で対応
ステップ3:再分析
異常値を除いて、回帰分析を再実行
結果が大きく変わるかを確認
ステップ4:報告
「〇件の異常値を除外して分析」と明記
📝 6. モデル診断のチェックリスト
回帰分析の前提条件
📌 回帰分析の4つの仮定
- 線形性:XとYの関係が直線的
- 独立性:残差同士が独立(時系列相関がない)
- 正規性:残差が正規分布に従う
- 等分散性:残差のバラつきが一定
診断手順
✅ 完全なモデル診断チェックリスト
1. 残差プロット
- ☑ パターンがないか(曲線、扇形など)
- ☑ 残差が0の周りにランダムに散らばっているか
2. 正規性の確認
- ☑ Q-Qプロットで点が直線上にあるか
- ☑ ヒストグラムが釣り鐘型か
- ☑ シャピロ・ウィルク検定(p > 0.05)
3. 等分散性の確認
- ☑ 残差プロットで扇形パターンがないか
- ☑ 残差のバラつきが一定か
4. 異常値の検出
- ☑ スチューデント化残差 > 3 の点がないか
- ☑ 散布図で極端な点がないか
5. 多重共線性の確認(重回帰の場合)
- ☑ VIF < 10(STEP 15で学習)
- ☑ 説明変数同士の相関 < 0.8
Pythonでの総合診断
# 総合的なモデル診断
import matplotlib.pyplot as plt
import scipy.stats as stats
def モデル診断(y_actual, y_pred, 残差):
“””回帰モデルの診断を行う”””
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# 1. 残差プロット
axes[0, 0].scatter(y_pred, 残差, alpha=0.6)
axes[0, 0].axhline(y=0, color=’red’, linestyle=’–‘)
axes[0, 0].set_xlabel(‘予測値’)
axes[0, 0].set_ylabel(‘残差’)
axes[0, 0].set_title(‘残差プロット’)
axes[0, 0].grid(True, alpha=0.3)
# 2. Q-Qプロット
stats.probplot(残差, dist=”norm”, plot=axes[0, 1])
axes[0, 1].set_title(‘Q-Qプロット’)
axes[0, 1].grid(True, alpha=0.3)
# 3. ヒストグラム
axes[1, 0].hist(残差, bins=10, color=’skyblue’, edgecolor=’black’)
axes[1, 0].axvline(x=0, color=’red’, linestyle=’–‘)
axes[1, 0].set_xlabel(‘残差’)
axes[1, 0].set_ylabel(‘頻度’)
axes[1, 0].set_title(‘残差のヒストグラム’)
axes[1, 0].grid(True, alpha=0.3)
# 4. 実測値 vs 予測値
axes[1, 1].scatter(y_actual, y_pred, alpha=0.6)
min_val = min(y_actual.min(), y_pred.min())
max_val = max(y_actual.max(), y_pred.max())
axes[1, 1].plot([min_val, max_val], [min_val, max_val], ‘r–‘)
axes[1, 1].set_xlabel(‘実測値’)
axes[1, 1].set_ylabel(‘予測値’)
axes[1, 1].set_title(‘実測値 vs 予測値’)
axes[1, 1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 正規性検定
stat, p_value = stats.shapiro(残差)
print(f”\n【正規性検定(シャピロ・ウィルク)】”)
print(f”p値: {p_value:.4f}”)
if p_value > 0.05:
print(“→ 正規性OK(p > 0.05)”)
else:
print(“→ 正規性に問題あり(p < 0.05)")
# 実行
モデル診断(y, y_pred, 残差)
📝 STEP 13 のまとめ
✅ このステップで学んだこと
1. 残差の基本
- 残差 = 実際の値 – 予測値(e = y – ŷ)
- 残差が0に近いほど予測が正確
2. 残差プロット
- パターンがなければモデルは適切
- 曲線パターン → 非線形の関係
- 扇形パターン → 不等分散性
3. 正規性の確認
- Q-Qプロット:点が直線上なら正規分布
- ヒストグラム:釣り鐘型なら正規分布
- シャピロ・ウィルク検定:p > 0.05なら正規分布
4. 異常値の検出と対処
- スチューデント化残差 > 3 で検出
- 原因を調査してから削除 or 残す
💡 最も大切なポイント
R²が高くても、残差分析で問題が見つかることがあります。必ず以下を確認しましょう:
- 残差プロット:パターンがないか
- Q-Qプロット:正規性が満たされているか
- 異常値:極端な値がないか
問題が見つかったら:
- 変数変換(対数、平方根など)
- 異常値の除去(原因を調査してから)
- 多項式回帰(X²を追加)
- 別のモデルの検討
次のSTEP 14では、予測モデルの構築と評価を学びます!
🎯 次のステップの予告
STEP 14では、「予測モデルの構築と評価」を学びます。過学習を防ぎ、実用的な予測モデルを作る方法を習得します!
📝 練習問題
問題 1
基礎
残差とは何ですか?また、残差が0に近いことは何を意味しますか?
【解答】
残差とは:
実際の値と予測値の差
残差 = 実際の値 – 予測値
e = y – ŷ
残差が0に近い意味:
・予測が正確
・実際の値と予測値がほぼ一致している
・モデルの説明力が高い
逆に、残差が大きい場合:
・予測が外れている
・モデルで説明できていない要因がある
問題 2
基礎
残差プロットで「良いパターン」と「悪いパターン」の違いを説明してください。
【解答】
良いパターン:
- 残差が0の線の周りにランダムに散らばっている
- 特定の傾向やパターンが見られない
- バラつきの大きさが一定
- → モデルは適切!
悪いパターン:
- 曲線パターン(U字型、S字型) → 非線形の関係がある
- 扇形パターン → 等分散性が満たされていない
- 傾斜パターン → モデルに問題がある
- → 対策が必要!
問題 3
応用
残差プロットを見たところ、右に行くほど残差のバラつきが大きくなる「扇形パターン」が見られました。これはどういう問題で、どう対処すべきですか?
【解答】
問題:
不等分散性(Heteroscedasticity)の問題
残差のバラつきが予測値によって変化している。
予測値が大きいほど、残差も大きくなる傾向。
影響:
・予測の信頼性が一定でない
・標準誤差、p値が正しく計算されない
・信頼区間が不正確
対処法:
- 対数変換:目的変数Yを log(Y) に変換して再分析
- 平方根変換:√Y に変換
- 加重最小二乗法:バラつきが大きいデータの重みを下げる
- ロバスト標準誤差:不等分散に対応した標準誤差を使う
まずは対数変換を試すのが最も簡単でおすすめです!
問題 4
応用
Q-Qプロットを見たところ、点が右端で直線から大きく上に外れていました。これは何を意味していますか?どう対処すべきですか?
【解答】
意味:
残差の分布が右に長い裾を持つ(右裾が重い)
これは:
・正規分布よりも、極端に大きい値が多い
・異常値が存在する可能性
・右に歪んだ分布(右偏)
対処法:
- 異常値の確認:スチューデント化残差で異常値を検出、散布図で極端な点がないか確認
- 異常値の除去:明らかなミスなら削除、ビジネス的に意味があるなら残す
- 変数変換:目的変数Yを log(Y) に変換(右に長い分布を正規分布に近づける効果)
- 再分析:変換後、または異常値除去後に、再度Q-Qプロットを確認
問題 5
実践
あなたは売上予測モデルを作成しました。R² = 0.85で良好な結果でしたが、残差分析を行う前にモデルを本番運用することに上司が決定しました。この決定の問題点を説明し、どのような残差分析を行うべきか提案してください。
【解答】
問題点:
- R²が高くても、モデルに隠れた問題がある可能性がある
- 残差分析なしでは、予測が特定の条件で大きく外れるかもしれない
- 異常値の影響で、R²が見かけ上高くなっている可能性
- 本番運用後に問題が発覚すると、ビジネス上の損失につながる
行うべき残差分析:
- 残差プロット:曲線パターン、扇形パターンがないか確認
- Q-Qプロット:正規性が満たされているか確認
- シャピロ・ウィルク検定:統計的に正規性を検証
- 異常値の検出:スチューデント化残差 > 3 の点を確認
- 実測値 vs 予測値プロット:予測が系統的にズレていないか確認
上司への説明:
「R²=0.85は良好ですが、残差分析で問題が見つかった場合、予測精度が大きく改善する可能性があります。また、問題を見逃したまま運用すると、特定の条件で予測が大きく外れるリスクがあります。1〜2日の追加分析で、モデルの信頼性を大幅に高められます。」
❓ よくある質問
Q1: 残差がすべて0になることはありますか?
理論的にはあり得ますが、現実ではほぼありません。
残差がすべて0 = R² = 1.0 = 完璧な予測
現実では:
・測定誤差、ランダムな変動が必ずある
・人間の行動は予測が難しい
・すべてのデータ点が回帰直線上にピッタリ並ぶことはまずない
もし残差がすべて0なら:
・データ数が非常に少ない
・目的変数と説明変数が完全に一致している(間違い)
・何かがおかしい可能性が高いので、再確認しましょう
Q2: 残差プロットで少しパターンが見えますが、問題ですか?
完璧にランダムでなくても、実務上は問題ないことが多いです。
判断基準:
・明確なパターン(U字型、扇形など)が見える → 問題
・なんとなくパターンっぽいが微妙 → 実務上は許容範囲
重要なのは:
・ビジネス的に予測精度が十分か
・R²が十分に高いか
・テストデータでも予測が当たるか
統計的には完璧でなくても、ビジネス的に使えるなら問題ありません。ただし、限界は認識して使いましょう。
Q3: 異常値は必ず除去すべきですか?
いいえ、必ずしも除去する必要はありません。
除去すべき場合:
・データ入力ミス(例:1000万円が10000万円)
・測定ミス
・明らかにあり得ない値
残すべき場合:
・ビジネス的に意味がある(例:大型キャンペーン)
・将来も起こり得るイベント
・その異常値から学べることがある
判断できない場合:
・ダミー変数で対応(例:キャンペーンダミー=1)
・異常値を含む場合と除く場合の両方を分析
・どちらも報告して、判断を委ねる
重要:異常値を除去した場合は、必ず報告に明記しましょう。
Q4: 正規性が満たされない場合、回帰分析は使えませんか?
使えますが、注意が必要です。
正規性が満たされない場合の影響:
・p値が正しくない可能性
・信頼区間が不正確
・仮説検定の結果が信頼できない
ただし:
・予測には大きな影響はない
・サンプルサイズが大きい(n>30)と、正規性の仮定は緩和される
・R²、回帰係数の推定値は影響を受けにくい
対処:
1. 変数変換(対数、平方根など)を試す
2. 異常値を除去
3. ノンパラメトリック手法を検討
4. サンプルサイズを増やす
実務では:
正規性が完璧でなくても、ビジネス的に使えるなら問題ありません。ただし、「正規性が完全には満たされていない」と明記しましょう。
Q5: Excelでも残差分析はできますか?
はい、Excelでも基本的な残差分析は可能です。
Excelでできること:
・残差プロットの作成(分析ツール)
・残差のヒストグラム
・基本的な異常値の検出
Excelで難しいこと:
・Q-Qプロット
・スチューデント化残差
・シャピロ・ウィルク検定
推奨:
・基本的な確認はExcelで十分
・詳細な診断が必要ならPythonを使う
・両方を組み合わせるのが最も効率的
まずはExcelの残差プロットで、明らかなパターンがないかを確認しましょう!
Q6: 残差分析で問題が見つかったら、モデルは使えませんか?
必ずしも使えないわけではありません。
問題の程度による判断:
・軽微な問題(少しパターンがある程度)→ そのまま使用可能
・中程度の問題(明確なパターン)→ 改善を試みてから使用
・重大な問題(完全に前提を満たさない)→ モデルの再構築が必要
実務的な対応:
1. 問題を認識した上で使う(限界を明記)
2. 予測区間を広めに設定
3. 定期的にモニタリングして、問題が悪化したら対処
4. 重要な意思決定には、複数のモデルを比較
ポイント:
完璧なモデルは存在しません。問題を認識した上で、ビジネス的に許容できる範囲なら使用可能です。