COM6005 Statistical Modeling · Module 7
Principal Component Analysis (PCA)
COM6005 · Module 7 · Source: Lecture_PCA_L02_Complete.pdf (15 slides)
Contents · 7 sections
🎯 本講重點 (Learning outcomes)
- 分清 Feature selection(揀部分 predictors)同 Feature extraction(transform data,例如 PCA)。
- 明白 PCA 係將 data transform 去新嘅 coordinates (axes):PC1 variance 最大,PC2 次之……而且 axes 互相 perpendicular。
- 用 swarm of fireflies 嘅比喻理解 PC1、PC2。
- 知道 PCA 數學上係搵 covariance matrix 嘅 eigenvalues 同 eigenvectors,以及佢哋喺
sklearn對應邊個 attribute。 - 明白點解 PCA 之前要 Standardization,識用
StandardScaler。 - PCA + Regression:regress Y on 頭 k 個 PCs,用 CV error 揀 k。
⭐ 考試必溫 Top-5
- Feature selection = dump 一啲、keep 一啲 predictors;Feature extraction = transform data(例:用 internal score 代替 midterm + assignment + final)。PCA 屬 extraction。
- PC1 = maximum variance 方向(longest stretch);PC2 要 90° perpendicular to PC1,capture 下一個最大 variance。
- PCA = 搵 covariance matrix 嘅 eigenvalues(importance →
explained_variance_ratio_)同 eigenvectors(transform data →components_)。 - PCA 之前要 standardize(mean 0、SD 1),否則大 scale 嘅 feature(例如 income in dollars)會 dominate PC1。
- PCA regression:對 計 CV error,揀 CV error 最細嘅 k。
1. Feature extraction vs Feature selection(slide 2)
當 p 好大,好難將所有 predictors 都放入 regression model(Module 6:p = 20 已經有超過一百萬個 subsets)。有兩類處理方法:
| Feature selection | Feature extraction | |
|---|---|---|
| 做法 | 選擇 predictors:some are dumped, some are kept | Transform data,砌出新 variables |
| 例子 | Best subset、forward / backward selection(Module 6) | 用「internal score」代替 midterm + assignment + final 去 predict public exam score |
| 方法 | 、AIC、BIC、CV | Principal Component Analysis (PCA) |
| 結果嘅 variables | 原本嘅 predictors(易解釋) | 原本 predictors 嘅 combinations(較難解釋) |
midterm、assignment、final 三科分數通常高度相關(勤力嘅學生三樣都高)。與其三個都放入 model,不如合成一個 internal score,例如 。三個 variables 變一個,大部分資訊都保留。PCA 做嘅事類似,只不過 weights 由 data 自動決定,目標係保留最多 variance。
2. PCA 嘅概念(slides 3–5)
- PCA 係一個簡化複雜 data 嘅工具:搵出 data spread out the most(highest variance) 嘅方向。
- PCA = 將原本 data transform 去新 coordinates (axes)。
- 新嘅第 1 條 axis 最重要,第 2 條相對冇咁重要(in the sense of variance),第 3 條又冇第 2 條咁重要,如此類推。
- 新 axes 之間互相 perpendicular。
2.1 Swarm of Fireflies 比喻(slides 4–5)
想像一間房入面有一群螢火蟲,佢哋唔係亂飛,而係形成一個長形、傾斜、雪茄形嘅雲。每隻螢火蟲嘅位置由三個 coordinates 決定:Width (X)、Depth (Y)、Height (Z),即係 3D data。
想將 3D 簡化做較低 dimension 時,唔應該直接掉咗 Height (Z) 或者 Depth (Y),因為雪茄係斜放嘅,三個方向都有資訊。PCA 叫你轉換角度,喺房入面畫新嘅線。
- PC1:The Longest Stretch(largest variance)。沿住螢火蟲雲最長嘅部分畫一條直線,呢條線代表 direction of maximum variance(data points 最分散嘅方向)。
- PC2:The Next Best Direction。睇返剩低嘅 spread,畫第二條線,佢必須同 PC1 成 90 度(perpendicular),capture 下一個最大嘅 spread。
PC3 就係同 PC1、PC2 都垂直嘅方向,capture 剩低最少嘅 spread。如果雪茄好幼長,PC1 已經 capture 大部分 variance,只用 PC1(1D)或者 PC1 + PC2(2D)都唔會失去太多資訊,呢個就係 dimension reduction。
兩個 standardized variables ,covariance matrix:
Eigenvalues 係 、,對應 eigenvectors 、。
- PC1 方向係 (兩個 variables 一齊升嘅斜線),PC2 係 ,兩者垂直(dot product )。
- PC1 嘅 explained variance ratio ;PC2 。
- 一個 data point 嘅 PC1 score ,PC2 score 。
3. PCA in Python(slides 6–7)
3.1 Example code:Fireflies(slide 6)
import numpy as np
import pandas as pd
from sklearn.decomposition import PCA
swarm_df = pd.read_csv('fireflies.csv') # 3 columns:X, Y, Z
pca = PCA(n_components=3) # 保留 3 個 PCs
fireflies_3d = pca.fit_transform(swarm_df) # fit + 轉去新 coordinates
print(swarm_df.head())
print(f"PC1 (Longest stretch): {pca.explained_variance_ratio_[0]*100:.1f}%")
print(f"PC2: {pca.explained_variance_ratio_[1]*100:.1f}%")
print(f"PC3: {pca.explained_variance_ratio_[2]*100:.1f}%")
print(f"Total kept in 3D: {sum(pca.explained_variance_ratio_)*100:.1f}%") # 3 個 PCs 全保留 = 100%
pca.components_[0] # PC1 嘅 loadings / weights(eigenvector)
pca.explained_variance_[0] # PC1 嘅 variance magnitude(eigenvalue)
Slide 6 有 import plotly.graph_objects as go,但 extracted code 冇畫圖部分;fireflies.csv 亦唔喺 course folder。以下係一個可以自己 run 嘅版本,用 random data 模擬雪茄形雲。
import numpy as np
import pandas as pd
from sklearn.decomposition import PCA
rng = np.random.default_rng(0)
t = rng.normal(0, 5, 500) # 沿住雪茄長軸嘅位置(spread 大)
swarm_df = pd.DataFrame({
'X': t + rng.normal(0, 0.5, 500),
'Y': 0.8 * t + rng.normal(0, 0.5, 500), # 斜放:Y、Z 都跟住 t 變
'Z': 0.5 * t + rng.normal(0, 0.5, 500),
})
pca = PCA(n_components=3).fit(swarm_df)
print(pca.explained_variance_ratio_.round(3)) # PC1 大約 99%,PC2、PC3 好細
print(pca.components_[0].round(2)) # PC1 方向,大約同 (1, 0.8, 0.5) 成比例
3.2 數學:eigenvalues 同 eigenvectors(slide 7)
- PCA 數學上即係搵 covariance matrix 嘅 eigenvalues 同 eigenvectors。
- Eigenvalues 表示 transformed data 嘅 importance →
pca.explained_variance_ratio_ - Eigenvectors 用嚟 transform 原本 data →
pca.components_ - Python:
pca = PCA(n_components=3);pca_result = pca.fit_transform(x)
| Attribute | 內容 | 數學 |
|---|---|---|
explained_variance_ | 每個 PC 嘅 variance | Eigenvalue |
explained_variance_ratio_ | 每個 PC 佔 total variance 嘅比例 | |
components_ | 每一 row 係一個 PC 嘅 loadings / weights | Eigenvector |
fit_transform(X) | 每個 observation 喺新 axes 上嘅 scores |
- Slide 7 話 eigenvalues「given by
explained_variance_ratio_」。嚴格嚟講,explained_variance_先係 eigenvalues 本身,explained_variance_ratio_係將佢哋 normalize 成比例(加埋 = 1)。兩者都反映 importance,排序一樣。 components_嘅 row 係 PC(唔係 column):components_[0]係 PC1 嘅 weights,長度 = 原本 features 數目。- Eigenvectors 互相垂直,正好對應「新 axes are perpendicular」。
COM6004 Matrix Algebra Review 有 eigenvalue / eigenvector 嘅基本計法;Dimensionality Reduction 從 data mining 角度講 PCA、SVD(該兩章唔喺 COM6004 考試範圍,但對理解呢講有幫助)。
4. Standardization(slides 8–10)
- PCA 搵嘅係 maximize variance 嘅方向。
- 如果 features 嘅 scale / units 完全唔同(例如 income in dollars、age in years),numerical variance 大嘅 feature 會完全 dominate PC1。
- Standardizing(centering and scaling)將所有 features 變成 mean = 0、standard deviation = 1,確保每個 feature 公平貢獻。
Income 嘅 SD = 20,000 dollars → variance ;Age 嘅 SD = 10 years → variance = 100。PCA 會覺得 income 方向 spread 大到不得了,PC1 幾乎就係 income axis,age 嘅資訊被忽略。其實係因為「dollar」呢個單位數值大,唔係 income 真係重要啲。Standardize 之後,兩者 variance 都係 1,PCA 就會睇佢哋之間嘅 correlation 結構。
Python(slide 10):
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler() # get the object
X_scaled = scaler.fit_transform(X) # X_scaled:每個 column mean = 0、SD = 1
COM6001 學過嘅 scaling(standardization / normalization)同 COM6004 Ch 2 嘅 preprocessing 係同一件事。KNN、K-means 呢類用 distance 嘅方法,同樣需要先 standardize。
5. 用 PCs 做 regression(slides 11–15)
(Slide 11 同 slide 8 一樣係 section title;slide 12 係棒球員同 MLB pension 嘅插圖,作為 Baseball data 例子嘅引入,唔涉及考試內容。)
- Regress Y against 頭 k 個 principal components。
- 計 cross-validation error。
- 對 重複,揀 CV error 最細嘅 k。
sklearn 有現成 functions 做 PCA + Regression。
PCs 互相 uncorrelated(垂直),所以冇 multicollinearity 問題;而且頭幾個 PCs 已包含大部分 variance,用少數 PCs 代替大量 predictors 可以減少 overfitting。k 呢個「model size」點揀,就用返 Module 6 嘅 CV 諗法:k 太細會 underfit,太大就同用晒所有 predictors 差唔多。
5.1 Example:Hitters(Baseball)data(slides 14–15)
- ISLP package 嘅
Hittersdata:19 predictors(包括 categorical),。 - Response Y:球員嘅 Salary。
# pip install ISLP
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from ISLP import load_data
from sklearn.decomposition import PCA
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import StandardScaler
HC = load_data('Hitters')
HC = HC.dropna() # 刪走有 null 嘅 rows(Salary 有 missing)
X = HC.drop(columns=['Salary']) # 移除 target column
X = pd.get_dummies(X, drop_first=True) # categorical → dummy variables(statistics approach)
y = HC['Salary']
scaler = StandardScaler() # Standardization
X_scaled = scaler.fit_transform(X)
pca = PCA(n_components=10)
X_pca = pca.fit_transform(X_scaled)
cv_scores = cross_val_score(LinearRegression(), X_pca, y, cv=10,
scoring='neg_mean_squared_error')
plt.plot(range(1, len(cv_scores) + 1), -cv_scores, marker='o')
plt.xlabel('Number of Principal Components')
plt.ylabel('Mean Squared Error')
plt.title('Cross-validation result (MSEP)')
plt.show()
| Step | 作用 |
|---|---|
dropna() | Hitters 有部分 Salary 係 missing,刪走嗰啲 rows |
get_dummies(drop_first=True) | Categorical(League、Division、NewLeague)變 dummy;drop first category 做 baseline,同 Module 4b 嘅 dummy variable 做法一致 |
StandardScaler | PCA 前先 standardize(Section 4) |
cross_val_score(..., cv=10) | 10-fold CV,score 係負 MSE;-cv_scores 變返 MSE |
| MSEP | Mean Squared Error of Prediction,即 CV 估計嘅 prediction MSE |
- Slide 14 將結果存做
y_cv_pred,下一行就用cv_scores,變數名唔一致;跟 slide 15 用cv_scores就啱。 - Slide 15 嘅
cv_scores係 10 個 folds 嘅 score(全部用 10 個 PCs),所以 x-axis 其實係 fold number,唔係「Number of Principal Components」。要做到 slide 13 嘅「for k = 1, 2, 3, … 揀 k」,要 loop k,每次只用頭 k 個 PCs,再平均 10 個 folds:
msep = []
for k in range(1, 11):
s = cross_val_score(LinearRegression(), X_pca[:, :k], y, cv=10,
scoring='neg_mean_squared_error')
msep.append(-s.mean()) # 第 k 個點 = 用 k 個 PCs 嘅 CV MSE
best_k = int(np.argmin(msep)) + 1
plt.plot(range(1, 11), msep, marker='o')
plt.xlabel('Number of Principal Components'); plt.ylabel('CV MSE')
plt.show()
另外,scaler 同 PCA 係喺成個 dataset 上 fit 完先做 CV,test folds 嘅資訊會輕微漏入 preprocessing。更嚴謹嘅做法係將 StandardScaler、PCA、LinearRegression 放入同一個 Pipeline(Module 6 slide 23 嘅諗法)再做 CV。
Module 6 用 feature selection 揀 predictors;呢講用 feature extraction(PCA)。兩者都用 CV error 決定 model 大細(Module 6 揀 subset,呢度揀 k)。
自我測驗 Self-test
Q1. Feature selection 同 feature extraction 有咩分別?各舉一個例子。
Selection:保留部分原有 predictors,其餘 dump 走,例如 best subset、forward selection。Extraction:transform data 產生新 variables,例如用 internal score 代替 midterm + assignment + final,或者 PCA。
Q2. 用 fireflies 比喻解釋 PC1 同 PC2。
螢火蟲形成斜放嘅雪茄形雲。PC1 係穿過雲最長部分嘅直線,即 maximum variance 方向。PC2 係同 PC1 成 90° 嘅線,capture 剩低 spread 入面最大嘅方向。
Q3. 點解唔可以直接掉咗 Height (Z) 去將 3D 變 2D?
雪茄形雲係斜放,Z 同 X、Y 都有關,資訊分佈喺三個原本 axes 上。直接掉 Z 會失去部分 spread。PCA 換一套新 axes,令頭幾條 axes 集中最多 variance,再掉最唔重要嗰條。
Q4. 3 個 PCs 嘅 eigenvalues 係 6、3、1。計 explained variance ratio。用頭 2 個 PCs 保留幾多 variance?
Total = 10。PC1 = 60%,PC2 = 30%,PC3 = 10%。頭 2 個 PCs 保留 90%。
Q5. pca.components_、pca.explained_variance_、pca.explained_variance_ratio_ 分別係咩?
components_:eigenvectors(每 row 係一個 PC 嘅 loadings / weights),用嚟 transform data。explained_variance_:eigenvalues,每個 PC 嘅 variance。explained_variance_ratio_:eigenvalue ÷ 總和,即每個 PC 嘅 importance 比例。
Q6. 一個 dataset 有 income(dollars)同 age(years),唔 standardize 直接做 PCA 會點?
Income 嘅數值 variance 遠大於 age,PC1 幾乎完全由 income 決定,age 被忽略。呢個係單位造成,唔係真正重要性。要先 standardize(mean 0、SD 1)。
Q7. 一個 feature 嘅 mean = 50、SD = 8。x = 66 standardize 之後係幾多?
。
Q8. 描述 PCA + regression 點揀 k。
對 :用頭 k 個 PCs 做 regression,計 CV error(例如 10-fold CV MSE)。揀 CV error 最細嘅 k。
Q9. Slide 15 嘅 plot x-axis 寫「Number of Principal Components」,但 code 有咩問題?點改?
cross_val_score(..., X_pca, cv=10) 回傳嘅係 10 個 folds 嘅 score(每個都用 10 個 PCs),所以 x-axis 其實係 fold number。應該 loop k = 1…10,每次用 X_pca[:, :k],取 -scores.mean() 做該 k 嘅 MSEP。
Q10. PCs 互相垂直對 regression 有咩好處?
PCs 之間 uncorrelated,所以冇 multicollinearity;而且頭幾個 PCs 已包含大部分 variance,可以用較少 variables 建 model,減低 overfitting 風險。
一頁總結 Cheat sheet
- Large p → Feature selection(dump / keep predictors)或 Feature extraction(transform,例:internal score)。PCA = extraction。
- PCA:transform 去新 axes;PC1 = maximum variance(longest stretch),PC2 PC1 = next largest variance,PC3 …;axes 互相 perpendicular。
- Fireflies:3D 雪茄形雲,唔好直接掉 Z / Y,要換角度畫新線。
- 數學:covariance matrix 嘅 eigenvalues(importance →
explained_variance_ratio_;explained_variance_)同 eigenvectors(transform →components_,每 row 一個 PC)。 PCA(n_components=k).fit_transform(X)→ PC scores。- 先 standardize:,mean 0、SD 1;
StandardScaler().fit_transform(X)。否則大 scale feature dominate PC1。 - PCA regression:regress Y on 頭 k 個 PCs → CV error → 試 → 揀 CV error 最細。
- Hitters:19 predictors、、Y = Salary;
dropna→get_dummies(drop_first=True)→StandardScaler→PCA→cross_val_score(cv=10, scoring='neg_mean_squared_error')。