邏輯回歸像一個「機率翻譯機」:你把信用卡餘額(X)丟進去,它輸出違約機率 p(X),永遠落在 0 到 1 之間。秘密在於 logistic 函數——這個 S 形曲線保證無論 X 多大或多小,預測值都不會超出 [0,1]。不同於線性回歸直接預測 Y,邏輯回歸預測的是「事件發生的機率」,再用 0.5 門檻做分類。
這個公式解決了線性回歸最大的問題:預測值可能 <0 或 >1。Logistic 函數的 S 形狀保證輸出永遠在 0 到 1 之間。稍微整理一下,得到更直觀的形式:
勝算是邏輯回歸最核心的概念。勝算 2 代表「發生的可能性是不發生的 2 倍」。取 log 後,我們回到線性:
這三條公式是理解邏輯回歸的關鍵:線性組合 → 勝算 → 機率,像一個三層翻譯系統。
線性回歸用最小平方法(OLS)找 β。邏輯回歸用最大概似估計(Maximum Likelihood Estimation, MLE):找到一組 β̂ 使得「觀察到眼前這筆資料的機率」最大化。
直觀理解:對於每個違約者,我們希望模型預測的違約機率接近 1;對於每個正常客戶,希望預測機率接近 0。MLE 沒有閉式解,需要用數值方法(如 Newton-Raphson)迭代求解——這也是為什麼 sklearn 的 LogisticRegression 比 LinearRegression 稍慢。
表 4.1 — Default 資料集:balance 預測違約機率
β̂₁ = 0.0055 的解讀:balance 每增加 $1,違約的 log-odds 增加 0.0055。更直觀的講法:勝算比 e0.0055 ≈ 1.0055——balance 每增加 $1,違約勝算變為原來的 1.0055 倍。聽起來很小,但 balance 增加 $1000 就是 e5.5 ≈ 245 倍。
# §4.3 Logistic Regression — 完整 Python 示範
import numpy as np
import pandas as pd
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix, classification_report
# === 資料載入(Colab 相容) ===
try:
from google.colab import drive
drive.mount('/content/drive')
DATA_PATH = '/content/drive/MyDrive/ISLP_data/'
except ImportError:
DATA_PATH = '/tmp/'
# 讀取 Default 資料集
url = 'https://www.statlearning.com/s/Default.csv'
df = pd.read_csv(url)
print(f'資料形狀: {df.shape}')
# === 準備訓練資料 ===
X = df[['balance']].values
y = (df['default'] == 'Yes').astype(int).values
# === 訓練邏輯回歸模型 ===
model = LogisticRegression()
model.fit(X, y)
beta0 = model.intercept_[0]
beta1 = model.coef_[0][0]
print(f'\n估計係數: β₀ = {beta0:.4f}, β₁ = {beta1:.6f}')
print(f'勝算比: e^β₁ = {np.exp(beta1):.6f}')
# === 視覺化 S 形曲線 ===
X_range = np.linspace(X.min(), X.max(), 300).reshape(-1, 1)
probs = model.predict_proba(X_range)[:, 1]
plt.figure(figsize=(10, 6))
jitter = np.random.uniform(-0.02, 0.02, len(y))
plt.scatter(X, y + jitter, alpha=0.3, s=10, c=['blue' if v==0 else 'red' for v in y])
plt.plot(X_range, probs, 'g-', linewidth=2, label='Logistic 回歸')
plt.axhline(y=0.5, color='gray', linestyle='--', label='決策邊界 (p=0.5)')
plt.xlabel('信用卡餘額 (Balance)')
plt.ylabel('違約機率')
plt.title('§4.3 邏輯回歸:Balance → 違約機率')
plt.legend()
plt.savefig('/tmp/logistic_regression_default.png', dpi=100, bbox_inches='tight')
plt.close()
# === 模型評估 ===
y_pred = model.predict(X)
print(f'\n準確率: {model.score(X, y):.4f}')
print(classification_report(y, y_pred, target_names=['No Default', 'Default']))
# 多變量邏輯回歸 — 觀察 confounding 現象
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
url = 'https://www.statlearning.com/s/Default.csv'
df = pd.read_csv(url)
# === 單變量:student 看起來增加違約風險 ===
X_student = (df['student'] == 'Yes').astype(int).values.reshape(-1, 1)
y = (df['default'] == 'Yes').astype(int).values
m1 = LogisticRegression().fit(X_student, y)
print(f'單變量 student: β₁ = {m1.coef_[0][0]:.4f}')
print(f' 解讀:學生身分 → 違約勝算 e^{m1.coef_[0][0]:.4f} = {np.exp(m1.coef_[0][0]):.2f} 倍')
print(f' ⚠️ 看起來學生風險較高...但等等!')
# === 多變量:加入 balance 後,student 係數反轉 ===
X_multi = df[['balance', 'income', 'student']].copy()
X_multi['student'] = (X_multi['student'] == 'Yes').astype(int)
m2 = LogisticRegression().fit(X_multi, y)
print(f'\n多變量模型係數:')
for name, coef in zip(['balance', 'income', 'student'], m2.coef_[0]):
print(f' {name}: {coef:.6f} (勝算比 = {np.exp(coef):.4f})')
print(f'\n 🔍 關鍵洞察:student 係數從正變負!')
print(f' 這是 confounding — 學生傾向有較高 balance(可能是學貸)')
print(f' 控制 balance 後,學生的違約風險其實低於非學生!')
# === 驗證 confounding:學生平均 balance 較高 ===
student_mean = df[df['student'] == 'Yes']['balance'].mean()
nonstudent_mean = df[df['student'] == 'No']['balance'].mean()
print(f'\n學生平均 balance: ${student_mean:.0f}')
print(f'非學生平均 balance: ${nonstudent_mean:.0f}')
print(f'差距: ${student_mean - nonstudent_mean:.0f} — 學生確實持有較高餘額')
銀行用邏輯回歸評估每個申請人的違約機率。輸入特徵包括收入、債務比、信用歷史長度,輸出一個 0~1 的分數。
急診室需要快速判斷昏迷病人的病因。邏輯回歸輸入生命徵象(血壓、心率、體溫)、年齡、病史,輸出各病因的機率。
Gmail 用邏輯回歸判斷一封郵件是否為垃圾郵件。特徵包括關鍵字頻率、發信人信譽、HTML 比例等。
Hermes 的 skill 系統本質上是一個技能記憶庫。§4.3 教了我們 logistic function 的核心洞見:一個壓縮函數把不設限的線性組合 βX 對應到 (0,1) 機率空間。這和 Hermes 架構的設計哲學很像:原始的 LLM token 輸出是無界的(任何文字都可能),但 skill prompt 壓縮了行為空間——它把無邊界的語言生成對應到結構化的操作(部署、驗證、Git push)。
此外,confounding 現象提醒我:當技能之間有相關性(如 deploy 和 verify 常常一起觸發),只看單一技能的成功率會誤判——需要考慮聯合效果。正如 logistic regression 加入 balance 後 student 符號反轉,加入 deploy 成功率作為控制變數後,某些 skill 的邊際貢獻才會顯現。