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 19

PCA

降維與視覺化:主成分與解釋變異
Interaction實作 30 minute(s)

Learning Objectives

  • 說明主成分是投影後變異最大的方向,並用 numpy 算出來
  • 從解釋變異比例判斷可以保留幾個主成分
  • 說明 PCA 為什麼通常要先標準化
  • 用 PCA 把資料投影到兩維來視覺化,並說明它不看標籤帶來的限制

特徵太多,畫不出來

兩個特徵可以畫散布圖,三個勉強可以。上一課的生活習慣資料有 4 個特徵,等一下要用的手寫數字有 64 個,畫不出來,也很難看出資料的結構。

主成分分析(principal component analysis,PCA)的做法是換一組座標軸:

  • 第一主成分:把所有點投影到一條軸上,讓投影後的變異最大的那個方向;
  • 第二主成分:和第一主成分垂直的方向裡,變異最大的那個;
  • 依此類推,有幾個特徵就有幾個主成分。

變異大表示點在這個方向上散得開,保留了比較多資料之間的差異。只留前面幾個主成分,就能用比較少的數字描述每一筆資料,這叫降維。

這個方法的歷史很長:Pearson 在 1901 年從「找最貼近資料點的直線與平面」的角度提出,Hotelling 在 1933 年發展出現在的代數形式,並使用「主成分」這個名稱。

先從兩個特徵開始,用 numpy 算一次。

逐步看:用 numpy 算主成分

八筆模擬資料:讀書時數與小考分數,兩者高度相關。程式分成四步,注意 values 與解釋變異比例。

互動練習:轉動投影軸

綠色的線是投影軸,每一點垂直投影到軸上(綠色小點)。在圖上拖動或用滑桿轉動它,看投影後的點散得多開。資料都是程式產生的模擬資料。

主成分與 scikit-learn

剛才看到的幾件事,正好是使用 PCA 要記得的重點:

  • 主成分是原本特徵的加權組合,不是挑掉某些特徵。每個主成分都用到所有特徵。
  • 主成分之間互相垂直,投影後的資料彼此不相關。
  • 方向不分正反:轉 180 度是同一條軸。主成分向量的正負號沒有意義,不同軟體可能相反,解讀時要看正負相對的關係。
  • 解釋變異比例:每個主成分占總變異的比例,全部加起來是 1。
  • 幾乎沒有相關的資料,轉到哪個方向變異都差不多,第一主成分也解釋不了多少,這時降維的效果有限。

scikit-learn 的寫法:

pca = PCA(n_components=2).fit(X)
scores = pca.transform(X)            # 每一筆投影後的座標
pca.explained_variance_ratio_        # 解釋變異比例
pca.components_                      # 每一列是一個主成分(特徵的權重)

PCA 會置中,但不會縮放,要標準化得自己先做。n_components 不設時保留所有主成分。接下來用 habits.csv(程式產生的模擬資料,不是任何學校的真實資料)看標準化的差別。

逐步看:標準化前後的差別

四個特徵的生活習慣資料。比較沒有標準化與標準化之後的解釋變異比例,再看前兩個主成分用了哪些特徵。

手寫數字:64 個特徵的資料

接下來用 sklearn.datasets.load_digits()。這不是本課程產生的模擬資料,而是真實的公開資料集:UCI 機器學習資料庫(UCI Machine Learning Repository)的 Optical Recognition of Handwritten Digits,scikit-learn 內建的是其中的測試資料。

  • 共 1797 筆,類別是數字 0~9;
  • 原本是 32×32 的黑白點陣圖,每 4×4 一格數有幾個黑點,變成 8×8、每格 0~16 的整數;
  • 攤平成一列就是 64 個特徵。

每張圖是 64 維空間裡的一個點。它們在 64 維裡是怎麼分布的?PCA 可以把它投影到兩維畫出來看。

逐步看:64 維投影到 2 維

注意兩個地方:PCA.fit 只給 X,沒有給 y;畫圖時才用 y 上色。這份資料每一格的範圍相同(0~16),所以這裡沒有先標準化。

逐步看:留幾個主成分才夠

累加解釋變異比例,看留幾個主成分能保留多少變異;再把第一張圖壓縮後還原,用眼睛看差別。

PCA 不看標籤

PCA 是非監督式的:它只管變異,不知道你要預測什麼。這帶來一個常被忽略的問題:變異最大的方向,不一定對預測有用。 丟掉變異小的主成分時,可能剛好把最有用的資訊丟掉。下面的範例故意做出這種情況。

逐步看:變異大不等於有用

兩個特徵的模擬資料:第 1 個特徵變異很大但是純雜訊,第 2 個變異很小卻決定類別。分別用原始特徵、只留第一主成分、只留第二主成分來分類。

把 PCA 當前處理時

PCA 也常放在模型前面,減少特徵數量。這時候要照第 8 課與第 14 課的規矩:只用訓練資料 fit,測試資料用同一個 PCA 轉換,否則就是資料洩漏。放進第 16 課的 Pipeline 最不容易出錯,交叉驗證時每一折也會自動重新 fit:

model = make_pipeline(StandardScaler(), PCA(n_components=20), LogisticRegression(max_iter=2000))
model.fit(X_train, y_train)
model.score(X_test, y_test)

留幾個主成分是超參數,要用交叉驗證比較,不要用測試資料挑,也不要只看解釋變異比例決定。

另外,主成分是所有特徵的加權組合,模型的係數因此不容易對應回原本的特徵。需要解釋模型時,這是降維的代價。

實作:寫一個 explained_ratio 函數

完成 explained_ratio(X):回傳每個主成分的解釋變異比例,由大到小。步驟:置中、算共變異數矩陣、算特徵值、由大到小排、除以總和。

np.linalg.eigvalsh(cov) 只回傳特徵值,由小到大排,這裡用它就夠了。

你的輸出
預期輸出

小測驗:PCA

1.

下面程式會印出什麼?

import numpy as np
values = np.array([6.0, 3.0, 1.0])
ratio = values / values.sum()
print(np.cumsum(ratio).round(1).tolist())
2.

第一主成分是什麼樣的方向?

3.

PCA().fit(df) 的 df 有「年收入(元)」和「年齡」兩欄,沒有先標準化,最可能得到什麼?

4.

某個分類問題,第一主成分解釋 95% 的變異,你只留它來訓練模型,測試準確率卻接近亂猜。最可能的原因是?

5.

把 PCA 當作模型的前處理,下面哪一個做法正確?

6.

兩台電腦算出的第一主成分,一個是 [0.6, 0.8],另一個是 [-0.6, -0.8],代表什麼?

第 1 次作答

重點整理

  • 主成分是投影後變異最大的方向,彼此垂直;數學上是共變異數矩陣的特徵向量,特徵值就是投影後的變異。
  • 解釋變異比例告訴你每個主成分保留多少變異,累加後可以幫助決定留幾個,但不能單獨決定。
  • PCA 只置中、不縮放:特徵單位不同時通常要先標準化,否則數字範圍大的特徵會主導結果。
  • 投影到兩維適合用來看資料的結構,但可能丟掉大部分變異(手寫數字只留 28.5%)。
  • PCA 不看標籤:變異大不等於對預測有用。當前處理時只用訓練資料 fit,留幾個主成分用交叉驗證比較。
  • 下一課開始進入神經網路,從只有一個神經元的感知器開始。
這一課完成了!
Next lesson:感知器與活化函數
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。