食品分析實驗 · W12
← → / 空白鍵切頁 · F 全螢幕 · 點兩側翻頁
食品分析實驗 · W12

主成分分析 PCA:食用油分類

Principal Component Analysis — Classifying Edible Oils by Spectra
食品分析實驗 · 4 小時課程
六種食用油 × Raman 785nm /各組 NIR · Orange PCA(Data→Scatter, Components→Spectra) · Colab/R
PCA scores/loadingsmean-centering不做 autoscalescree plotOrange PCA
開始前,先看三支工廠影片
貼錯標籤的「橄欖油」,
光譜看得出來嗎?

橄欖油產線(12:20–13:44,特級初榨分級,容易被摻偽)↗ 芥花油產線(12:02–13:31,脫臭精製/酸價/過氧化價)↗ 大豆油產線(08:00–09:28,己烷萃取)↗

影片裡的小提醒:特級初榨橄欖油(EVOO)分級除了看感官,法規上也需要 K232/K270 等指標,而且很容易被摻偽或貼錯標籤——這正是今天的問題。

今天的問題: 如果有一瓶油被貼錯標籤(例如標「特級初榨橄欖油」但其實摻了精製橄欖油或其他油), 光譜 + PCA 看得出來嗎?(待會看分數圖時回來討論——但也會看到,PCA 有時候會被一個離群點騙)

W12 / PCA COURSE TOUR

食用油 PCA:從分群到證據

完整旁白與字幕;使用本課模擬光譜。 獨立播放器與下載 · 互動實驗

W12 / PREDICT · OBSERVE · EXPLAIN

六幕互動:投影、PCA 與離群點重算

今天的學習目標

上完 W12,你應該會…

  • 知道光譜資料其實就是一張樣品 × 波數的數字表;PCA 在找資料變異最大的方向,PC1 ⟂ PC2
  • 知道score(分數)是 loadings 的加權總和——分清楚 scores(樣品位置)與 loadings(哪些波長在驅動)分別回答什麼問題
  • 親手算過一次 mean-centering 與 autoscale,說出為什麼光譜資料通常只做前者
  • 看懂特徵值(eigenvalue)與解釋變異(explained variance)怎麼算,說出 scree plot 的 elbow 在哪裡
  • 在 Orange 裡把 PCA 的 Data(不是 Transformed Data)接到 Scatter Plot 依類別上色,Components 接到 Spectra 看 loadings
  • 從分數圖判讀重複性與離群樣品,並知道一個離群點可以綁架一整個 PC——遇到要回頭查光譜、記錄原因、重做一次 PCA
資料表 X

一列=一條光譜,一欄=一個波數

樣品900 cm⁻¹915 cm⁻¹931 cm⁻¹946 cm⁻¹961 cm⁻¹…
EVOO_r10.0050.013-0.0110.0040.004…
COC_r10.0150.048-0.002-0.0210.048…
SOY_r1-0.018-0.041-0.0460.007-0.016…
PEA_r30.0840.073-0.0260.0770.095…
…(共 18 條)…(共 60 個波數欄)
  • 今天的資料:18 條光譜 × 60 個波數 = 1080 個數字(6 種油 × 3 重複,每條光譜在 900–1800 cm⁻¹ 間取 60 個點)
  • 每一條光譜=表格裡的一列;每一個波數=表格裡的一欄;每個樣品其實是60 維空間裡的一個點
  • 我們的眼睛跟螢幕只能看 2~3 個維度——PCA 要做的事,就是把這個 60 維的點雲,投影到幾個「最有代表性」的方向上來看

表格數字取自 Colab NB10 用的同一份 CSV(nb10_demo_spectra.csv),不是另外編的。

資料・小例子

兩個波數放一起看:它們一起變

  • 只挑 1655 cm⁻¹ 跟 1265 cm⁻¹(都跟不飽和有關)畫成散佈圖:椰子油兩個都低,大豆油兩個都高
  • 18 個點幾乎排成一條斜線:相關係數 r ≈ 0.99(算法同 W04 ↗,只是這裡是兩個波數,不是兩個變數)
  • 因為兩個波數一起變(相關),PCA 可以只用一個方向就同時描述兩者——這個方向就是「不飽和度」,也就是 PC1

數字取自同一份光譜資料的第 50 欄(1647 cm⁻¹)與第 25 欄(1266 cm⁻¹),非另外編造。

原理

PCA 在找什麼:變異最大的方向

PCA 找的是「資料變異最大」的方向 原始波數 1 的強度 → ↑ 原始波數 2 的強度 PC1(最大變異方向) PC2(與 PC1 垂直,次大變異) 每個點=一條光譜;PCA 完全不看標籤,只根據光譜本身的變異找方向(非監督式)
  • PC1:資料變異量最大的方向;PC2:與 PC1 垂直、次大變異的方向——彼此互相垂直(⟂)
  • PCA 是非監督式(unsupervised)方法——它完全不知道樣品是哪一種油,只根據光譜本身的變異來分
  • 所以如果分數圖上不同油真的分開,代表輸入光譜存在差異;但差異是否真的來自化學組成,還須結合 loadings、原始光譜與量測條件一起確認——等一下也會看到,這個差異也可能只是被一個離群點誤導
原理

分數(score) = loadings 的加權總和

t = p₁(x₁−x̄₁) + p₂(x₂−x̄₂) + p₃(x₃−x̄₃) + …

t=樣品在這個 PC 上的分數;pⱼ=第 j 個波長的loading(權重);xⱼ−x̄ⱼ=該波長先做完 mean-centering 的值

p=[0.6, 0.6, 0.53],centred x=[0.5, 0.4, 0.3]
t = 0.6×0.5 + 0.6×0.4 + 0.53×0.3 = 0.30+0.24+0.159 ≈ 0.70
  • loading(負荷量):每個波長對這個 PC 的「權重」——決定「為什麼」樣品會分開
  • score(分數):把每個波長的(去平均後)訊號乘上它的權重再加總——就是樣品畫在圖上的座標
  • loading 越大(不管正負),那個波長對這個 PC 的影響越大;loading 接近 0,代表那個波長幾乎不影響這個 PC
小遊戲 ①這個問題該看 scores 還是 loadings?0 / 8
把下面 8 個問題,分到「scores 回答的問題」或「loadings 回答的問題」。
前處理・算一次

中心化(mean-centering)與autoscale算一次

波長原始值 xx − x̄(中心化)÷ SD 後(autoscale)
訊號波長0.8 / 1.0 / 1.2−0.2 / 0 / 0.2−1 / 0 / 1
雜訊波長1.001 / 0.999 / 1.0000.001 / −0.001 / 01 / −1 / 0

兩列都用樣本標準差 SD(算法同 W01 ↗;訊號列 SD=0.2,雜訊列 SD=0.001)。

  • 中心化:三個值各減掉自己的平均值 1.0——這樣 PCA 才是在找「相對平均光譜」的變異,幾乎是必要的前處理
  • autoscale:中心化後再除以自己的標準差——訊號波長跟雜訊波長,中心化後都變成 −1/0/1 這種量級
  • 問題來了:雜訊波長本來訊號很小(SD=0.001),除完之後卻跟訊號波長一樣「顯眼」——雜訊被放大了,這就是光譜資料通常不做 autoscale 的原因
前處理選項

SNV/導數:要不要先做,PCA 之前

📐
SNV(標準常態變量轉換)
先做一次 SNV(見 W11 ↗),能去除粒徑散射造成的截距/斜率差異,PCA 找到的變異更接近真正的化學差異
📉
一階/二階導數
先做導數(見 W11 ↗),能去掉基線飄移,但也會放大高頻雜訊——用前多想一下
🧪
今天示範:只做 mean-centering
今天分數圖/loadings 都是對原始強度做 PCA,只做 mean-centering,沒有另外做 SNV/導數——留給作業比較
本示範只做 mean-centering、不做 autoscale;在 Orange PCA 節點裡要記得取消勾選「Normalize variables」(它預設是打開的)。
原理

特徵值(eigenvalue) 與 解釋變異

λₐ = 第 a 個 PC 分數的變異數(eigenvalue)
解釋變異% = λₐ / Σλᵢ × 100%

λₐ 越大,代表樣品在第 a 個 PC 方向上分散得越開——這個 PC 就越「重要」。

  • 今天六種油的資料:PC1 ≈ 46.3%、PC2 ≈ 28.3%、PC3 ≈ 23.0%、PC4 之後只剩 0.53%
  • scree plot(陡坡圖):把每個 PC 的解釋變異畫成長條圖,用來決定「看幾個 PC 才夠」
  • ⚠️ 這個 λ 跟 W11 ↗ ALS 基線校正用的 λ(平滑度參數)完全是兩件事,只是剛好都借用希臘字母 λ
數據・Scree

Scree Plot:解釋變異隨 PC 遞減

資料來自 NB10 同一份光譜的實際 PCA。前 3 個 PC 共 97.7%,PC4 只剩 0.53%(<1%):elbow 明顯在 PC3 之後。
分數圖 Score Plot

PC1 vs PC2:六種油分數散佈圖

  • PC1(46.3%):主要由 1655/1265 cm⁻¹(不飽和相關)驅動——椰子油(飽和度最高)落在最負的一端
  • PC2(28.3%):看起來初榨橄欖油分得開,但算一下平方和才發現——74% 的 PC2 變異來自花生油第 3 重複這一個點,loading 峰值在 1159 cm⁻¹ 附近,剛好是量測異常留下的人工訊號,不是乾淨的化學訊號
  • QC:五種油的重複都緊緊聚在一起;花生油有一個重複明顯跑到最上面——先懷疑量測(氣泡?對準?),不要急著說「花生油自成一群」
  • 回應開場問題:貼錯標籤能不能被 PCA 抓到,要先確定看的那個 PC 沒被單一離群點綁架——下一頁把這個點拿掉重做一次

資料來自 Colab NB10 用的同一份模擬拉曼光譜(nb10_demo_spectra.csv),PCA 是建置本頁時即時算的,數字保證跟 NB10 一致。點色=油品,同色三點=三次重複。

動手重做一次

移除 PEA-3 後重做 PCA

  • 拿掉花生油第 3 重複這一個點:PC1 = 63.5%、PC2 = 33.2%(比移除前的 28.3%還高,不減反增)、PC3 只剩 0.74%——原本被 PEA-3 一個點撐起的 74% PC2 平方和不見了,剩下的變異重新集中成一個乾淨的方向
  • 現在 PC2 loading 最高在 1525 cm⁻¹ 附近=類胡蘿蔔素譜帶:初榨橄欖油(EVOO)平均 PC2 = 0.99,其他油都在 −0.39~0.03 之間——這才是「乾淨」的類胡蘿蔔素分離
  • 教訓:一個離群點可以綁架一整個 PC;找到離群樣品後,先回頭查原始光譜、記錄原因(見 W08 ↗),再重新做一次 PCA 確認故事有沒有變
  • NB10 預覽:這個點的 Hotelling T² = 12.7,超過 95% 界線 7.7——T²/Q 殘差的正式定義留給 W14 ↗

同一份資料,拿掉那一條光譜後即時重新跑一次 PCA(Colab NB10 第 3、7 節有完整版本)。

數據・Loadings

PC1 Loading:哪些波數驅動了這個主成分

PC1 loading 在約 1655 cm⁻¹(C=C stretching)與約 1265 cm⁻¹(=C–H bending)附近是正值的高峰——這兩個都是不飽和相關的拉曼譜帶,也正好解釋了椰子油(高度飽和)為什麼在 PC1 上差最遠。波段歸屬請視為約略指認,實際樣品仍須以標準品或文獻圖譜比對確認。
正負荷的意思:loading 是正值的波段,強度越高的樣品在這個 PC 的分數也越高;loading 是負值,訊號越強分數反而越低。 兩群重疊怎麼辦:可以看 PC3,或換一種前處理(如二階導數)。
Orange OR12 一步步

從光譜到分數圖與 loadings的實際點法

對照 tools.html 的說明:Orange 流程 OR12 ↗

Orange 工作流程

從光譜到分數圖與 loadings

下方 Colab/R 程式碼是進階選項——不寫程式,用上一頁的 Orange 步驟就能完成今天的分析。

Orange 工作流程(OR12) File 匯入光譜;oil=target PCA mean-centering 內建;不勾 Normalize Data 輸出 原始資料+PC分數+類別 Components 輸出 = loadings Scatter Plot 依油品類別上色=分數圖 Data Table 框選可疑點,檢視原始數值 Spectra(Loadings) loading vs 波數(波長) 關鍵地雷:① Scatter Plot 要接「Data」不是「Transformed Data」 ② PCA 記得取消勾選「Normalize variables」

進階:Colab(scikit-learn,5 行):

from sklearn.decomposition import PCA import numpy as np X = np.loadtxt("oils_X.csv", delimiter=",") # 每列一條光譜(一個樣品) pca = PCA(n_components=5).fit(X - X.mean(axis=0)) scores = pca.transform(X - X.mean(axis=0)) # scores[:, :2] 拿來畫分數圖

進階:R(prcomp):

X <- as.matrix(read.csv("oils_X.csv", header=FALSE)) pca <- prcomp(X, center=TRUE, scale.=FALSE) scores <- pca$x[, 1:2] loadings <- pca$rotation[, 1] summary(pca)$importance[2, ] # 各 PC 解釋變異比例

Colab NB10:在 Colab 開啟 NB10 ↗。備用資料集:五種糖 NIR 備用資料集(chemometrics-teaching)→

樣品、儀器與安全

六種食用油 × Raman 785 + 各組 NIR

  • 六種油:特級初榨橄欖油、精製橄欖油、大豆油、芥花油、椰子油、花生油——每組全部都要測,各 3 次重複(重新裝填/取樣)
  • Raman 785 nm(輪站量測):初榨橄欖油若用 532 nm 會有強烈螢光干擾——回想 W10 教訓,今天固定用 785 nm
  • 各組 NIR:依組別使用 Avantes(300–1100/900–1650 nm;600–1100 nm 待到貨)、InnoSpectra NIR-S-G1/T1/T11/R14、NeoSpectra Scanner/Micro Dev Kit/光纖模組 或 Spectral Engines NIRONE S2.0/S2.2/S2.5 其中一台
  • 椰子油:室溫(約24°C以下)會凝固,需先微溫加熱融化成液態才能量測
🔴
拉曼雷射(532/785nm)
不可直視光源或讓光束射向他人眼睛,依儀器說明配戴適當護目措施
🔥🛢️
熱油與地板濕滑
椰子油只需微溫加熱到液態即可,勿過度加熱;發現油漬溢漏立即擦拭,避免滑倒
4 小時課程時間表

測光譜 → 前處理 → PCA → 跨儀器比較

時間內容
0:00–0:45講解:資料表、scores/loadings、mean-centering/autoscale、解釋變異、一個離群點怎麼綁架一個 PC
0:45–2:05六種油 × 3 重複:Raman 785 輪站量測+各組 NIR 量測(椰子油先加熱融化)
2:05–2:30用 SpectraView 前處理(選用 SNV/導數),匯出成一列一樣品的 X 矩陣
2:30–3:30Orange 執行 PCA:分數圖(依油品上色)、loadings(vs 波數)、解釋變異;發現離群點先查原始光譜與量測紀錄,確認異常並記錄理由後再剔除或重測、重做 PCA
3:30–4:00各組交換、比較不同儀器(NIR)測出的分數圖是否一致
小遊戲 ②PCA 分析工作流程排序— / 6
用 ▲▼ 把「從光譜到 PCA 結果」的 6 個步驟排成正確順序。
小遊戲 ③PCA 觀念 即時測驗0 / 5
小遊戲 ④這個前處理決定,會不會影響 PCA 結果?0 / 6
把 6 個決定分到「會影響 PCA 結果」或「不影響 PCA 結果」。
小遊戲 ⑤決策挑戰:分數圖判讀0 / 5
小遊戲 ⑥計算闖關:PC1+PC2 解釋變異 (%)未作答
已知 5 個主成分的特徵值(eigenvalues)分別為 8.2, 3.1, 0.9, 0.5, 0.3。求 PC1 與 PC2 合計解釋了全部變異的百分之多少?公式:(λ₁+λ₂)/Σλᵢ×100%。
%
課後作業

Colab NB10

📊
分數圖+解讀
附上本組數據的 PC1 vs PC2 分數圖,說明哪些油分得開、哪些重疊,以及是否有離群點
🧬
Loading 圖+化學指認
附上 loading 圖,指出 1–2 個波段並嘗試給出化學官能基指認(記得標「約」)
🚩
離群點練習
仿照今天的 PEA-3:找一個(或刻意標記一個)離群樣品,移除後重做 PCA,比較解釋變異與 loadings 的變化
📡
跨儀器比較
找另一組交換分數圖,比較用不同 NIR 測出的結果是否一致,討論可能原因

Colab NB10:在 Colab 開啟 NB10 ↗ ・入門(不用寫程式):Orange 流程 OR12 ↗。備用資料集:五種糖 NIR 備用資料集(chemometrics-teaching)→

自我檢核

今天結束,你應該會…

點一下打勾——確認自己真的會了。

EN