National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 80 24°C PM2.5 21
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 16

特徵工程與 Pipeline

類別編碼、縮放、缺值,把流程接起來
Interaction實作 30 minute(s)

Learning Objectives

  • 用 One-Hot 編碼處理類別欄,並處理測試資料出現沒看過的類別
  • 用訓練資料算補值,說明為什麼不能用全部資料
  • 依資料的現象做新特徵,用交叉驗證確認有沒有幫助
  • 用 ColumnTransformer 與 Pipeline 把前處理和模型接起來,並說明它怎麼避免資料洩漏

真實的資料不會直接餵得進模型

前面幾課大多只用數值特徵,而且先把缺值的列丟掉。實際的資料表長得不是這樣。students.csv(程式產生的模擬資料,不是任何學校的真實資料)就有這些情況:

  • 類別欄:系所(dept)是文字,模型只吃數字;
  • 缺值:期中考有 18 筆、小考平均有 6 筆是空的;
  • 尺度不同:通勤分鐘數和睡眠小時數的數字範圍差很多;
  • 非線性:讀書時數增加到某個程度後,成績的增加變慢。

把原始資料整理成模型能用、而且有用的特徵,就是特徵工程(feature engineering)。這一課先學每一步,最後用 Pipeline 把所有步驟接成一個物件。第 14、15 課看到的資料洩漏,大多是前處理做在錯的地方;Pipeline 就是解決這件事的工具。

逐步看:類別欄怎麼變成數字

比較三種寫法。特別注意最後一行:測試資料出現訓練資料沒有的系所「物理」時會怎樣。

什麼時候不用 One-Hot

情況 做法
類別之間沒有順序(系所、宿舍) One-Hot
類別之間有順序(年級、滿意度) 可以直接用數字或 OrdinalEncoder,但要確認間距合理
類別很多(例如上千個課程代碼) One-Hot 會多出太多欄,可以合併少見的類別(min_frequency),或想想這個欄位真的需要嗎
只有兩類(住宿 Y/N) One-Hot 或 0/1 都可以

決策樹與隨機森林不看距離,對編號的大小比較不敏感;羅吉斯迴歸與 k 近鄰則會把編號當成真的數值,一定要處理。

逐步看:補值

SimpleImputer 預設用平均補值(strategy="mean")。這裡改用中位數,比較不受極端值影響。第二個補值器多加了「這筆原本是不是缺值」的欄位。

自己做新特徵

模型只能用你給它的欄位。如果你知道某種關係存在,可以把它算成新欄位,線性模型就學得到:

現象 新特徵
增加到某個程度效果變小(飽和)、或資料右偏 取對數:np.log1p(x)
兩個特徵一起才有意義 相乘或相除,例如「每學分的讀書時數」
非線性 平方項(PolynomialFeatures),或切成區間
日期 拆成星期幾、是不是週末、距離考試幾天

新特徵要用交叉驗證確認有沒有幫助,不要只看訓練分數:特徵越多訓練分數幾乎一定不會變差,這不代表真的比較好。另外,如果新特徵要用到其他資料列的統計量(例如「該系的平均」),就要放進 Pipeline,只用訓練資料算。

逐步看:讀書時數取對數

用四個特徵預測期末成績(迴歸),比較 study_hours 原始值和取對數之後的差別。線性迴歸只能畫直線,取對數相當於讓它能學到「一開始增加很快、後面變慢」的曲線。

把流程接起來:ColumnTransformer 與 Pipeline

不同的欄要做不同的處理,而且每一步都只能看訓練資料。手寫很容易出錯,scikit-learn 提供兩個工具:

  • Pipeline:把步驟依序接起來。前面的步驟是轉換器,最後一步是模型。
  • ColumnTransformer:分欄處理,數值欄走一條路、類別欄走另一條路,結果併起來。沒有列出的欄預設丟掉(remainder="drop")。
                ┌ 數值欄:補值 → 標準化 ┐
原始資料表 ──→  │                        ├─→ 羅吉斯迴歸
                └ 類別欄:One-Hot      ┘

接好之後它就像一個模型,只有 fit、predict、score。

它怎麼避免資料洩漏:呼叫 model.fit(X_train, y_train) 時,每個步驟只用這份 X_train 算統計量(中位數、平均、標準差、有哪些類別);呼叫 model.predict(X_new) 時,只用已經算好的數字做轉換。把整個 model 傳給 cross_val_score 或 GridSearchCV,每一折都會從頭 fit 一次,驗證資料就不會參與任何統計量。

相對地,如果你先對全部資料 fit_transform,再把結果傳給交叉驗證,前處理就已經看過驗證資料了。除此之外,把整個 model 存起來就可以直接用在新資料上,不用記得要先做哪些處理。

逐步看:完整的 Pipeline

用缺值的欄、類別欄一起預測是否及格。這次不需要 dropna,也不用自己 One-Hot。特徵裡沒有放 final,原因等一下會談。

逐步看:連前處理一起搜尋

補值要用平均還是中位數,也是一種超參數。第 14 課的「兩個底線」可以一層一層往裡指。

最難發現的洩漏:特徵裡藏著答案

Pipeline 能防止前處理的洩漏,但擋不住另一種:特徵本身就包含答案。這叫標籤洩漏(target leakage)。

判斷方法是問自己一句話:真正要預測的那個時間點,這個欄位已經存在了嗎?

要在期中考之後預測誰會不及格,就不能把期末成績當特徵,因為那時期末考還沒考,而且及格與否就是由期末成績決定的。訓練時分數會非常漂亮,真正要用的時候這個欄位卻拿不到。分數好得不合理時,先懷疑洩漏,不要先高興。

逐步看:把答案放進特徵

同樣的模型,只差在有沒有多一個 final。這裡有用 Pipeline,也有用交叉驗證,流程沒有問題,問題在欄位。

實作:接一條迴歸的 Pipeline

用 students.csv 預測期末成績(final),特徵是三個數值欄 study_hours、quiz_avg、midterm 和類別欄 dept。

數值欄:中位數補值,再標準化。類別欄:One-Hot(handle_unknown="ignore")。模型:LinearRegression,步驟名稱用 prep 與 reg。

依序印出兩行:5 折交叉驗證 R² 的平均(四捨五入到小數 2 位)、用全部資料 fit 後轉換出的特徵個數。

你的輸出
預期輸出

小測驗:特徵工程與 Pipeline

1.

下面程式會印出什麼?

import pandas as pd
from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder(handle_unknown="ignore", sparse_output=False)
enc.fit(pd.DataFrame({"c": ["a", "b", "c"]}))
print(enc.transform(pd.DataFrame({"c": ["b", "z"]})).sum(axis=1).tolist())
2.

把系所編成 0、1、2、3 直接餵給 k 近鄰,主要的問題是?

3.

下面哪一種做法有資料洩漏的風險?

4.

ColumnTransformer 預設怎麼處理你沒有列出的欄?

5.

預測「新生第一學期會不會被二一」的模型,交叉驗證準確率 0.99,特徵裡有「第一學期不及格學分數」。最可能的原因是?

6.

GridSearchCV 的參數名稱 prep__num__impute__strategy 表示什麼?

第 1 次作答

重點整理

  • 類別欄:沒有順序用 One-Hot;OneHotEncoder(handle_unknown="ignore") 記得住類別,也能處理沒看過的值。
  • 缺值:SimpleImputer 只用訓練資料算補值;add_indicator=True 可以保留「這筆原本是缺值」的資訊。
  • 新特徵要依資料的現象來做,並用交叉驗證確認有沒有幫助。
  • ColumnTransformer 分欄處理,Pipeline 依序接步驟;整條傳給交叉驗證或 GridSearchCV,每一折都重新 fit,前處理不會洩漏。
  • 標籤洩漏 Pipeline 擋不住:問自己,要預測的時間點這個欄位存在嗎?
  • 到這裡,監督式學習的工具已經完整:選模型、評估、調參數、接流程。下一課開始看沒有標籤的資料,第一個是 k-means 分群。
這一課完成了!
Next lesson:k-means
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。