① 依序閱讀:每節先讀說明;遇到互動元件時,先預測結果,再操作驗證。 ② 對照程式範例:程式碼卡下方的「來源」標了課程練習筆記本(lab);需要實作時,再打開原始筆記本對照。 ③ 檢查理解:答錯時先看回饋,再回到相關說明;標為延伸的內容可留待第二輪。 ④ 最後翻關鍵詞彙卡自測術語,並用 重點速查與來源查閱。
教科書:An Introduction to Statistical Learning with Applications in Python(ISLP)。章節旁的來源標記可點到本頁書目。
Python 做統計建模有兩套主流工具,這門課兩套都會用到。它們算的東西常常一模一樣,
但回答的問題不同:statsmodels 給你係數、標準誤與 p 值,
是為了讓你解釋;scikit-learn 給你 fit/predict/
score,用來預測並核對模型表現。
fit_intercept=True 幫你處理。
sklearn_sm 把 statsmodels 的模型包成 sklearn 的估計器,好丟進 cross_validate。
intercept lstat 0 1.0 4.98 1 1.0 9.14 2 1.0 4.03 3 1.0 2.94
全是 1 的 intercept 欄用來表示截距。sm.OLS 不會自動加截距,忘了就是擬合一條過原點的線。
Ch03-linreg-lab-zh.ipynb
coef std err t P>|t| intercept 34.5538 0.563 61.415 0.0 lstat -0.9500 0.039 -24.528 0.0
四個欄位:係數、標準誤、t 值、p 值。下一節逐欄拆開講。
來源:Ch03-linreg-lab-zh.ipynb
你要在論文裡報告「每增加一個百分點的 lstat,medv 平均下降多少,這個估計有多確定」。該用哪一套?
先將資料整理成模型使用的設計矩陣 X:
第一欄通常是全 1 的截距,後面每一欄是一個預測變數。
類別變數要先展開成 0/1 的欄,交互作用要先乘起來變成新的一欄。
MS()(ModelSpec)就是幫你做這件事的。
MS([...]) 一步步把它變成 X。類別變數與交互作用都是在這一層處理掉的。
fit_transform 在訓練資料上學會「有哪些欄、類別有哪幾種」;之後對新資料一律用 transform,不要再 fit 一次——不然兩邊的欄可能對不起來。最後一節會用這個區分說明資料洩漏。
intercept lstat 0 1.0 4.98 1 1.0 9.14 2 1.0 4.03 3 1.0 2.94 intercept lstat 0 1.0 4.98 1 1.0 9.14 2 1.0 4.03 3 1.0 2.94
輸出跟上一節手工做的 X 完全一樣,差別是 MS 會記得規格,之後可以對新資料套用相同轉換。
Ch03-linreg-lab-zh.ipynb
intercept lstat 0 1.0 5 1 1.0 10 2 1.0 15
三筆新的 lstat 值,經過同一個 design 之後自動加入 intercept 欄。保留這個物件,就能對新資料套用相同規格。
Ch03-linreg-lab-zh.ipynb
array([29.80359411, 25.05334734, 20.30310057])
lstat = 5、10、15 對應的預測 medv。記住這三個數字,下一節 sklearn 會算出逐位相同的結果。
來源:Ch03-linreg-lab-zh.ipynb
summarize(results) 給你四個欄位。可以依序閱讀:係數告訴你效果多大,標準誤告訴你這個估計多穩,
p 值只是這兩者的比值換算出來的。
t = coef / std err。lstat 那一列是 −0.9500 ÷ 0.039 ≈ −24.5,跟表上的 −24.528 對得起來。所以四個欄位其實只有前兩個是獨立的資訊。
intercept 34.553841 lstat -0.950049 dtype: float64
results.params 回傳一個 Series,索引是欄名。要拿單一個係數就 results.params['lstat']。
Ch03-linreg-lab-zh.ipynb
這一格印出來很長(含 R²、F 統計量、殘差診斷),這裡不列,自己在 lab 裡跑一次看。四個核心欄位就是上面那張表。
來源:Ch03-linreg-lab-zh.ipynb
scikit-learn 的預測模型使用一致的介面。
線性迴歸、隨機森林、支持向量機,都是
fit(X, y) 學參數、predict(X) 給預測、score 算分數。
換模型只要換建構子那一行,後面完全不用改。
fit 用訓練資料的 y 學參數;predict 只吃 X,score 則需要 y 作為評分答案。
coef_、intercept_、classes_——sklearn 的慣例是「擬合之後才存在」的屬性結尾加底線。看到 NotFittedError 就是你還沒 fit 就想用它們。
(np.float64(34.5538408793831), array([-0.95004935]))
輸出是 (intercept_, coef_):34.5538408793831 與 −0.95004935。跟 statsmodels 的 34.5538 與 −0.9500 是同一組數字。另外注意 reshape(-1, 1)。sklearn 要的 X 一律是二維。
Ch03-linreg-lab-zh.ipynb
R2 : 0.5441462975864797 Ex. Var : 0.5441462975864798 MSE : 38.48296722989415
R² 0.544 與 MSE 38.48。這裡算的是訓練資料上的分數,所以一定偏樂觀——下一節就在講這件事。
來源:Ch03-linreg-lab-zh.ipynb
array([29.80359411, 25.05334734, 20.30310057])
跟 statsmodels 的 get_prediction 給出逐位相同的三個數字。兩套 API 算的是同一件事。
Ch03-linreg-lab-zh.ipynb
model.fit(X_train, y_train) 之後要在測試集評估,正確的寫法是?
上一節的 R² 0.544 是拿訓練資料自己考自己算出來的, 一定偏樂觀。模型可以把訓練資料背下來,那個分數不代表它對沒看過的資料有用。 解法是把資料切成兩份:一份學、一份考。
random_state=0 固定切法。不固定的話你今天的 MSE 跟明天的不一樣,就沒辦法比較模型了。
Ch05-resample-lab-zh.ipynb
np.float64(25.57387818968441)
25.57 是驗證資料上的誤差;後面會繼續用這個數字比較模型。
來源:Ch05-resample-lab-zh.ipynb
The MAE is: 3.9907 The MSE is: 25.574 The RMSE is: 5.0571
MAE 3.99、MSE 25.57、RMSE 5.06。RMSE 跟 y 同單位(每加侖英里),比 MSE 好解釋;MAE 對離群值比較不敏感。
來源:Ch05-resample-lab-zh.ipynb
array([25.57387819, 22.21802005, 22.66767544])
上面那張圖的三個數字就是這一格的輸出,逐字取用。
來源:Ch05-resample-lab-zh.ipynb
random_state,這三個數字都會變。lab 範例 就示範了換切法之後結果不同——所以才需要交叉驗證,下一節講。
比較兩個模型,先讓它們使用相同切分,再看每次分數的配對差異。各自的平均和標準差可以摘要結果,但不足以單獨判定哪個模型較好。
單切一刀有兩個問題:只用了一部分資料訓練,而且結果會隨著切法跳動。 交叉驗證把資料輪流當驗證集,每一筆都當過一次,結果穩定得多。 但用它之前得先弄清楚一件事——前處理要在切分的哪一邊做。
np.float64(24.231513517929226)
24.2315 是各留一折誤差的平均。固定資料下的留一切法唯一,仍有各筆誤差與抽樣不確定性;但要擬合 n 次,資料大的時候很貴。
來源:Ch05-resample-lab-zh.ipynb
(np.float64(23.802232661034168), np.float64(1.4218450941091842))
平均 23.80、標準差 1.42。1.42 描述不同切分下的分數變動。比較兩個模型時,需要查看相同切分下的配對差異,再判斷差距是否穩定。
來源:Ch05-resample-lab-zh.ipynb
| 順序 | 標準化參數從哪裡估 | 評估能否解讀 | 判定 |
|---|---|---|---|
| 先標準化 → 再切分 | 全部資料(含之後的測試資料) | 不能當成乾淨的 out-of-sample 表現 | ✗ 洩漏 |
| 先切分 → 訓練集 fit;測試集只 transform | 只有訓練集 | 可作為這次切分的測試表現 | ✓ |
Pipeline + cross_validate | 每一折各自的訓練部分 | 可彙整各折的驗證表現 | ✓ 最推薦 |
StandardScaler 與模型包成 Pipeline 之後丟進 cross_validate,sklearn 會在每一折內部重新 fit 那個 scaler。但放在 Pipeline 外的補值、選欄位或不當切分仍可能洩漏。第 6 章的收縮方法通常要標準化,練習那些模型時,也要維持相同的前處理順序。
你先對整份資料做 StandardScaler().fit_transform(X),再 train_test_split,最後回報測試 MSE。這個數字有什麼問題?
回顧本頁觀念與原 Lab 的程式,確認各個操作的意義與使用條件。
你要比較五個模型並挑一個,中間需要標準化與多項式展開。該用哪一套?
sm.OLS(y, Boston[['lstat']]).fit() 少做了一件事。少了什麼?
下列哪一個做法不會造成資料洩漏?
需要核對完整公式、比較表或實作時,再展開下方速查。
下表整理兩套 API 的用法與前處理順序。
| 你要做的事 | statsmodels | scikit-learn |
|---|---|---|
| 準備 X | MS([...]).fit_transform(df)(截距要自己有) | X.values.reshape(-1,1);截距用 fit_intercept=True |
| 擬合 | sm.OLS(y, X).fit() | model.fit(X, y) |
| 看係數 | summarize(results)、results.params | model.coef_、model.intercept_ |
| 標準誤與 p 值 | 有 | 沒有 |
| 預測 | results.get_prediction(newX) | model.predict(X) |
| 評分 | results.rsquared | model.score(X, y) |
| 交叉驗證 | 包成 sklearn_sm 才有 | cross_validate |
| 串前處理 | 沒有 | Pipeline |
| 估計器(Estimator) | 轉換器(Transformer) |
|---|---|
fit(X, y) — 學參數 | fit(X) — 學轉換的參數 |
predict(X) — 給預測 | transform(X) — 套用轉換 |
score(X, y) — 算分數 | fit_transform(X) — 兩步合一 |
| 例:LinearRegression、LogisticRegression | 例:StandardScaler、PCA、SimpleImputer |
| 誤差指標 | 公式的意思 | 什麼時候用 |
|---|---|---|
| MAE | 平均絕對誤差 | 對離群值不敏感;跟 y 同單位 |
| MSE | 平均平方誤差 | 數學上好處理,整門課的預設 |
| RMSE | MSE 開根號 | 跟 y 同單位,最好解釋 |
| R² | 被解釋的變異比例 | 跟其他模型比較時方便,但會隨變數增加而虛高 |
詞彙卡整理本頁引用的課程 lab中常用的統計或機器學習專有名詞,正面附英文名稱。 先看正面的術語,試著說出定義,再翻面核對。可以洗牌複習,也可以搭配本章例子練習解釋。