3.4 The Marketing Plan

📖 ISLP §3.4 📄 pp. 109–111 ⭐⭐ 基礎應用 ⏱️ 約 15 分鐘
線性迴歸 行銷分析 模型診斷 假設檢定 預測區間 交互作用
← 3.3 Other Considerations 📑 課程首頁 3.5 Linear Regression vs KNN →

📚 理論基礎

James, G., Witten, D., Hastie, T., & Tibshirani, R. (2023). An Introduction to Statistical Learning with Applications in Python. Springer. §3.4, pp. 109–111.

在本章開頭(§3.0),我們提出了關於 Advertising 資料集的七個關鍵問題。經過 §3.1(簡單線性迴歸)、§3.2(多元線性迴歸)和 §3.3(回歸模型的其他考量)的學習後,我們現在可以完整回答這七個問題。本節是一個整合性的案例研究,展示如何將統計學習工具應用於真實的商業決策。

🎯 本節核心:以 Advertising 資料集為例,示範如何用多元線性迴歸回答「銷售額與廣告預算之間的關係」這一完整的商業分析問題。這是從統計理論到實際決策的橋樑。

七個行銷問題的完整解答

問題 1:銷售額與廣告預算之間是否存在關係?

要回答這個問題,我們需要建立一個多元迴歸模型,將銷售額(sales)對三個廣告媒介預算(TV、radio、newspaper)進行回歸:

\[ \text{sales} = \beta_0 + \beta_1 \times \text{TV} + \beta_2 \times \text{radio} + \beta_3 \times \text{newspaper} + \epsilon \]
公式 3.20 — Advertising 多元迴歸模型

我們使用 F 統計量來檢定虛無假設 \(H_0: \beta_{\text{TV}} = \beta_{\text{radio}} = \beta_{\text{newspaper}} = 0\)。在 §3.2.2 中,我們知道 F 統計量可以判斷是否應拒絕此虛無假設。Advertising 資料的 F 統計量對應的 p 值非常小,提供了銷售額與廣告預算之間存在關係的明確證據。

📊 表 3.6 關鍵數據:F 統計量的 p 值極低(< 0.0001),強烈拒絕「所有斜率為零」的虛無假設。這意味著至少有一個廣告媒介與銷售額之間存在顯著關係。

問題 2:關係有多強?

我們使用兩個指標來衡量模型的準確度:

殘差標準誤(RSE):估計總體迴歸線的標準差。對 Advertising 資料而言,RSE = 1.69 單位,而銷售額的平均值為 14.022,百分比誤差約為 12%

\[ \text{Percentage Error} = \frac{\text{RSE}}{\bar{y}} = \frac{1.69}{14.022} \approx 12\% \]

決定係數 \(R^2\):記錄預測變數解釋了多少反應變數的變異性。預測變數解釋了銷售額近 90% 的變異。

\[ R^2 \approx 0.897 \quad \Rightarrow \quad \text{廣告預解釋了約 90\% 的銷售額變異} \]

問題 3:哪些媒介與銷售額有關?

檢查每個預測變數的 t 統計量對應的 p 值(§3.1.2)。根據 Table 3.4 的多元迴歸結果:

預測變數p 值顯著性
TV< 0.0001✅ 高度顯著
radio< 0.0001✅ 高度顯著
newspaper0.860❌ 不顯著

只有 TV 和 radio 與銷售額相關。newspaper 的 p 值不顯著,表示在控制 TV 和 radio 後,newspaper 對銷售額沒有額外的解釋力。

問題 4:每個媒介與銷售額的關聯有多大?

利用 §3.1.2 中 \(\hat{\beta}_j\) 的標準誤,我們可以構建 \(\beta_j\) 的 95% 信賴區間。根據 Table 3.4 的結果:

預測變數95% 信賴區間解讀
TV(0.043, 0.049)窄且遠離零 → 顯著正向影響
radio(0.172, 0.206)窄且遠離零 → 顯著正向影響
newspaper(−0.013, 0.011)包含零 → 統計上不顯著

TV 和 radio 的信賴區間窄且遠離零,提供了這些媒介與銷售額相關的強力證據。newspaper 的信賴區間包含零,表示在 TV 和 radio 存在的情況下,newspaper 統計上不顯著。

🔍 共線性檢查:VIF 分數為 TV=1.005、radio=1.145、newspaper=1.145,遠低於警戒值 5 或 10,表示沒有共線性問題。因此 newspaper 不顯著不是因為共線性。

為了個別評估每個媒介對銷售額的影響,我們可以執行三個簡單線性迴歸。結果顯示 TV 和 radio 與銷售額之間存在極強的關聯,而 newspaper 與銷售額之間只有微弱的關聯(當忽略 TV 和 radio 時)。

問題 5:我們能多準確地預測未來的銷售額?

使用多元迴歸模型進行預測時,預測的準確度取決於我們想要預測的是什麼:

預測目標使用工具寬度
個別反應值 \(Y = f(X) + \epsilon\)預測區間(Prediction Interval)較寬
平均反應值 \(f(X)\)信賴區間(Confidence Interval)較窄
📐 關鍵區別:預測區間一定比信賴區間寬,因為預測區間還需考慮不可約誤差 \(\epsilon\) 的不確定性。信賴區間只衡量模型參數估計的不確定性。

問題 6:關係是線性的嗎?

在 §3.3.3 中,我們學到殘差圖可以用來識別非線性關係。如果關係是線性的,殘差圖應該呈現隨機散布、無明顯模式。

對 Advertising 資料,Figure 3.5 觀察到一些非線性效應。這種非線性效應也可以在殘差圖中觀察到。在 §3.3.2 中,我們討論了如何在線性迴歸模型中加入預測變數的轉換(如多項式項)來處理非線性關係。

問題 7:廣告媒介之間是否存在協同效應?

標準線性迴歸模型假設預測變數與反應變數之間是加法關係(additive relationship)。加法模型容易解釋,因為每個預測變數與反應變數的關聯與其他預測變數的值無關。

然而,加法假設可能不切實際。Figure 3.5 暗示 Advertising 資料可能不是加法的。加入交互作用項後,\(R^2\) 從約 90% 大幅提升到近 97%

\[ \text{sales} = \beta_0 + \beta_1 \times \text{TV} + \beta_2 \times \text{radio} + \beta_3 \times (\text{radio} \times \text{TV}) + \epsilon \]
含交互作用項的模型
💡 商業洞察:radio 和 TV 之間存在協同效應(synergy)——同時在 TV 和 radio 上投放廣告的效果,大於兩者個別效果的簡單加總。這意味著行銷預算的分配策略應該考慮媒介間的互動,而非獨立優化每個管道。

完整 Python 實作

以下程式碼完整回答 Advertising 資料集的七個行銷問題:

try:
    from google.colab import drive
    drive.mount('/content/drive')
    DATA_PATH = '/content/drive/MyDrive/ISLP_data/'
except ImportError:
    DATA_PATH = '/tmp/'

import numpy as np
import pandas as pd
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import statsmodels.api as sm
from statsmodels.stats.outliers_influence import variance_inflation_factor as VIF
from itertools import combinations

# 載入 Advertising 資料
try:
    adv = pd.read_csv(DATA_PATH + 'Advertising.csv')
except FileNotFoundError:
    import urllib.request
    urllib.request.urlretrieve(
        'https://www.statlearning.com/s/Advertising.csv',
        '/tmp/Advertising.csv'
    )
    adv = pd.read_csv('/tmp/Advertising.csv')

print("=== Advertising 資料集前 5 筆 ===")
print(adv.head())
print(f"\n資料筆數: {len(adv)}")
print(f"\n基本統計量:\n{adv.describe()}")

# === 問題 1 & 2 & 3 & 4: 多元迴歸分析 ===
print("\n" + "="*60)
print("問題 1~4: 多元迴歸分析")
print("="*60)

X = adv[['TV', 'radio', 'newspaper']]
X_const = sm.add_constant(X)
y = adv['sales']

model = sm.OLS(y, X_const).fit()
print(model.summary())

# F 統計量 (問題 1)
print(f"\n【問題 1】F 統計量 = {model.fvalue:.2f}, p 值 = {model.f_pvalue:.2e}")
print(f"  → p 值極低,拒絕 H0,至少有一個預測變數與 sales 相關")

# RSE 和 R² (問題 2)
rse = np.sqrt(model.mse_resid)
r2 = model.rsquared
print(f"\n【問題 2】RSE = {rse:.4f}, R² = {r2:.4f}")
print(f"  → 百分比誤差 = {rse/adv['sales'].mean()*100:.1f}%")
print(f"  → 預測變數解釋了 {r2*100:.1f}% 的 sales 變異")

# p 值 (問題 3)
print(f"\n【問題 3】各預測變數的 p 值:")
for var in ['TV', 'radio', 'newspaper']:
    pval = model.pvalues[var]
    sig = "顯著" if pval < 0.05 else "不顯著"
    print(f"  {var}: p = {pval:.4f} → {sig}")

# 95% 信賴區間 (問題 4)
print(f"\n【問題 4】95% 信賴區間:")
ci = model.conf_int(alpha=0.05)
for var in ['TV', 'radio', 'newspaper']:
    lo, hi = ci.loc[var]
    contains_zero = "包含零 (不顯著)" if lo <= 0 <= hi else "不含零 (顯著)"
    print(f"  {var}: ({lo:.4f}, {hi:.4f}) → {contains_zero}")

# VIF 檢查
print(f"\n  VIF 值:")
for i, var in enumerate(['const', 'TV', 'radio', 'newspaper']):
    if var == 'const':
        continue
    vif_val = VIF(X_const.values, list(X_const.columns).index(var))
    print(f"  {var}: VIF = {vif_val:.3f}")

# === 問題 5: 預測 ===
print("\n" + "="*60)
print("問題 5: 預測新觀測值")
print("="*60)

# 預測 TV=100, radio=20, newspaper=0
new_obs = pd.DataFrame({'TV': [100], 'radio': [20], 'newspaper': [0]})
new_obs_const = sm.add_constant(new_obs, has_constant='add')

pred = model.get_prediction(new_obs_const)
pred_summary = pred.summary_frame(alpha=0.05)
print(f"\n預測條件: TV=100, radio=20, newspaper=0")
print(f"預測值 (mean): {pred_summary['mean'].values[0]:.4f}")
print(f"信賴區間 (CI): ({pred_summary['mean_ci_lower'].values[0]:.4f}, {pred_summary['mean_ci_upper'].values[0]:.4f})")
print(f"預測區間 (PI): ({pred_summary['obs_ci_lower'].values[0]:.4f}, {pred_summary['obs_ci_upper'].values[0]:.4f})")
print(f"\n→ 預測區間比信賴區間寬,因為包含了不可約誤差 ε")

# === 問題 6: 非線性檢查 ===
print("\n" + "="*60)
print("問題 6: 殘差圖檢查線性假設")
print("="*60)

fig, axes = plt.subplots(1, 3, figsize=(14, 4))
for ax, var in zip(axes, ['TV', 'radio', 'newspaper']):
    ax.scatter(adv[var], model.resid, alpha=0.5, s=15)
    ax.axhline(0, c='red', linestyle='--')
    ax.set_xlabel(var)
    ax.set_ylabel('Residual')
    ax.set_title(f'Residuals vs {var}')
plt.tight_layout()
plt.savefig('/tmp/residual_plots_adv.png', dpi=100, bbox_inches='tight')
plt.show()
print("殘差圖已儲存 → 若殘差呈現隨機散布則線性假設成立")

# === 問題 7: 交互作用效應 ===
print("\n" + "="*60)
print("問題 7: 交互作用效應 (radio × TV)")
print("="*60)

adv['radio_TV'] = adv['radio'] * adv['TV']
X_interact = adv[['TV', 'radio', 'radio_TV']]
X_interact_const = sm.add_constant(X_interact)

model_interact = sm.OLS(y, X_interact_const).fit()
print(f"\n無交互作用模型 R² = {model.rsquared:.4f}")
print(f"含交互作用模型 R² = {model_interact.rsquared:.4f}")
print(f"R² 提升: {(model_interact.rsquared - model.rsquared)*100:.2f}%")
print(f"\n交互作用項係數: {model_interact.params['radio_TV']:.6f}")
print(f"交互作用項 p 值: {model_interact.pvalues['radio_TV']:.4e}")
print(f"\n→ 交互作用項高度顯著,表示 radio 和 TV 之間存在協同效應")
print(f"→ R² 從 {model.rsquared*100:.1f}% 提升到 {model_interact.rsquared*100:.1f}%")

# 視覺化交互作用
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
tv_levels = [10, 50, 100, 200]
for tv_val in tv_levels:
    radio_range = np.linspace(0, 50, 100)
    pred_sales = (model_interact.params['const'] +
                  model_interact.params['TV'] * tv_val +
                  model_interact.params['radio'] * radio_range +
                  model_interact.params['radio_TV'] * tv_val * radio_range)
    axes[0].plot(radio_range, pred_sales, label=f'TV={tv_val}')
axes[0].set_xlabel('Radio Budget')
axes[0].set_ylabel('Predicted Sales')
axes[0].set_title('Interaction Effect: Sales vs Radio at different TV levels')
axes[0].legend()

# 殘差圖
axes[1].scatter(model_interact.fittedvalues, model_interact.resid, alpha=0.5, s=15)
axes[1].axhline(0, c='red', linestyle='--')
axes[1].set_xlabel('Fitted values')
axes[1].set_ylabel('Residuals')
axes[1].set_title('Residuals: Interaction Model')
plt.tight_layout()
plt.savefig('/tmp/interaction_effect.png', dpi=100, bbox_inches='tight')
plt.show()
print("交互作用圖已儲存")

應用場景

🏢 場景:企業行銷預算分配

一家電商公司有年度行銷預算 500 萬,需要分配到 TV、radio 和社群媒體三個管道。利用多元迴歸分析:

🏥 場景:醫療資源配置

醫院想要了解不同治療方案(藥物 A、藥物 B、物理治療)對患者復原時間的影響。類似的分析框架:

優缺點對照

✅ 優點

❌ 缺點

方法比較

分析步驟使用的工具替代方法適用情境
關係存在性F 統計量ANOVA、卡方檢定多個預測變數的整體檢定
模型強度RSE, R²Adjusted R², AIC, BIC模型選擇與比較
個別顯著性t 統計量Likelihood Ratio Test單一預測變數的檢定
效應大小信賴區間效果量 (Cohen's d)量化影響幅度
預測預測/信賴區間Bootstrap、Cross-validation新觀測值的預測
非線性偵測殘差圖成分殘差圖、GAM模型假設驗證
交互作用交互作用項樹模型、MARS非加法關係

關鍵回顧:七個問題的答案摘要

#問題答案關鍵證據
1是否存在關係?F 檢定 p 值 < 0.0001
2關係多強?R² ≈ 90%RSE = 1.69 (12% 誤差)
3哪些媒介相關?TV, radionewspaper p 值 = 0.86
4關聯多大?CI 不含零 (TV, radio)VIF ≈ 1,無共線性
5預測準確度?PI 比 CI 寬包含不可約誤差 ε
6線性關係?輕微非線性殘差圖有模式
7協同效應?是 (radio × TV)R² 從 90% → 97%
統計學習不是終點,而是決策的起點。從「是否存在關係」到「如何優化資源分配」,迴歸分析提供了從數據到行動的完整路徑。 — ISLP §3.4 核心精神
← 3.3 Other Considerations 📑 課程首頁 3.5 Linear Regression vs KNN →