紅外光譜,讀出咖啡的品種指紋

用真實的即溶咖啡 MIR-DRIFT FTIR 資料,學會兩個化學計量學核心方法:
PCA 探索結構、PLS-DA 鑑別 Arabica vs Robusta。

56即溶咖啡樣本
286FTIR 波數
2品種(Arabica / Robusta)
100%品種鑑別準確率
為什麼是紅外光譜

最快速的「化學掃描儀」

傅立葉轉換紅外光譜(Fourier-Transform Infrared Spectroscopy, FTIR)依分子鍵振動吸收特定波長的紅外光, 幾秒內就能在一個樣本上同時量得數百個波數的吸收值——形成獨一無二的化學指紋。 MIR-DRIFT 模式(漫反射紅外轉換光譜)特別適合粉末食品(咖啡、麵粉、奶粉),無需破壞樣品。

快速無損

幾秒出一條光譜,粉末樣品直接量,不需化學前處理。

指紋區

810–1911 cm⁻¹ 中紅外「指紋區」——分子骨架振動,任何化學差異都有痕跡。

但是…

一條光譜是 286 個高度相關的數字,必須靠化學計量學才能解讀。
  咖啡粉 ──▶ FTIR-DRIFT 掃描 ──▶ 286 個波數的吸收值 ──▶ 整理成「樣本 × 波數」資料矩陣
本課兩步走: 先用 PCA(非監督)看光譜指紋裡有什麼品種結構,再用 PLS-DA(監督)建立能鑑別 Arabica / Robusta 的模型。
資料集

即溶咖啡 MIR-DRIFT FTIR(公開資料)

Mendeley Data frrv2yd9rg(Briandet et al.):56 支即溶凍乾咖啡, 以 MIR-DRIFT FTIR 量得 286 個波數(810–1911 cm⁻¹ 指紋區)的吸收值, 並標註品種 Arabica / Robusta。屬公開資料。

即溶咖啡 FTIR 原始光譜
每支咖啡的原始 FTIR 光譜。每條線是一支咖啡、286 個波數——teal = Arabica,coral = Robusta。注意基線高低不同,需要 SNV 前處理。
品種 variety樣本數本課用途
Arabica29PLS-DA 類別 A
Robusta27PLS-DA 類別 B

前處理:SNV(標準正常變量)

DRIFT 模式的光譜受顆粒大小和填充密度影響,造成基線漂移和乘法散射效應。 SNV(Standard Normal Variate) 對每條光譜逐條計算均值和標準差後標準化, 消除散射干擾,讓化學資訊凸顯出來——這是 MIR-DRIFT 分析的標準前處理, 作用等同近紅外光譜中廣泛採用的 SNV。

SNV 前處理後光譜
SNV 後,基線對齊、兩品種的差異帶清晰可見。相同顏色代表相同品種,光譜間一致性大幅提高。
方法一 · 非監督

PCA:把 286 個波數壓成幾個方向

主成分分析(Principal Component Analysis)在資料最分散的方向上建立新座標軸: PC1 是變異最大的方向、PC2 與它垂直且次大……少數幾個主成分,就能描述最重要的品種結構。

🎬 教學影片(一)PCA · 渲染後可在此播放
$X \approx T\,P^{\top}$  —  分數 $T$ 是樣本位置、負荷量 $P$ 是波數如何組成新方向

要保留幾個主成分?

PCA 陡坡圖
陡坡圖:PC1 = 44.5%,前兩個累積 67.6%,前三個達 76.3%。 FTIR 光譜中相鄰波數高度相關,資訊比代謝組學更集中——前 2 個成分已足以「看見」品種結構。

品種自己浮現

PCA 分數圖(依品種上色)
把每支咖啡畫在 PC1、PC2 上,顏色為品種。PCA 從沒看過品種,Arabica(teal)與 Robusta(coral)卻自動分群,主要靠 PC2 區分——結構自己浮現。
核心觀念: PCA 是非監督的——只看光譜、不用任何標籤,卻能讓品種結構自己浮現。它擅長探索、分群、找異常,但不會直接告訴你「這支是 Arabica 還是 Robusta」。

負荷量回連紅外化學

PCA 負荷量
PC1 貢獻最大的波段集中在 1714 / 1710 / 1706 cm⁻¹——羰基與脂質 C=O 伸縮振動區。 Arabica 和 Robusta 的脂質組成不同,紅外光譜把這個差異翻譯出來了。
方法二 · 監督

PLS-DA:用指紋「鑑別」Arabica vs Robusta

偏最小二乘判別分析(PLS Discriminant Analysis)給模型看過品種標籤,找出的潛在變量 同時解釋光譜的變異、又對齊 Arabica / Robusta 的分界。這就是它和 PCA 的關鍵差異: PCA 只看 X,PLS-DA 一手抓光譜、一手抓品種標籤。

🎬 教學影片(二)PLS-DA · 渲染後可在此播放
$\max\ \operatorname{cov}(Xw,\ y)$  —  每個潛在變量(LV)最大化光譜與品種 $y$ 的共變異

監督式分數:LV1 直接分開兩品種

PLS-DA 分數圖
29 支 Arabica 對上 27 支 Robusta,LV1 就已乾淨地把兩品種分開。監督式學習讓模型直接「衝著品種方向去找」。

該用幾個潛在變量?用交叉驗證

CV 準確率 vs 潛在變量
只用 1 個 LV,5 折交叉驗證準確率已達 98.2%;再加到 2 個 LV,達到 100%。 加更多不會更好,只會開始背雜訊(過度擬合)。停在夠用的地方。

成果:交叉驗證下的混淆矩陣

PLS-DA 混淆矩陣
對角線全中:29 支 Arabica、27 支 Robusta 沒有一支認錯。在誠實的 5 折交叉驗證下,兩品種可由 FTIR 光譜指紋完美區分。

準確率 100%

5 折交叉驗證,56 支咖啡全部分類正確。

2 個 LV

但 1 個 LV 已達 98.2%——複雜度夠用就好。
0 誤判
Arabica / Robusta 互不混淆。

哪些波段在做決定?

PLS-DA 回歸係數
PLS-DA 回歸係數排前面的是 1007 / 957 / 903 cm⁻¹——醣類 C–O 伸縮振動區。 Arabica 與 Robusta 的咖啡因、綠原酸、碳水化合物組成不同,模型挑出的全是真實咖啡化學。
應用: 把品種換成別的標籤,同一套 PLS-DA 就是食品真偽鑑別的主力——品種鑑別、摻偽偵測、產地溯源。FTIR 給指紋,PLS-DA 給答案。
交叉驗證 · 真實成分

光譜的差異,是真實的咖啡化學

FTIR 把 Arabica 和 Robusta 分開了——但這是真的化學差異,還是光譜的巧合? 我們換一份完全不同的資料來檢驗:R 語言 pgmm 套件的 coffee 資料,43 支咖啡, 直接用濕式化學量了 12 種成分(脂肪、咖啡因、葫蘆巴鹼、綠原酸…)。

真實成分 PCA
光對這 12 種真實成分做 PCA,Arabica 與 Robusta 一樣自己分兩群(PC1 37.7%)。
哪些成分在分
脂肪、葫蘆巴鹼 Arabica 較高;咖啡因、綠原酸 Robusta 較高——都是公認的品種標記。

用這份真實成分做 PLS-DA,留一法交叉驗證準確率一樣是 100%——和 FTIR 光譜結果完全一致。 而且這些「會分」的成分,每一個在紅外光譜裡都有對應吸收:

真實成分差異(pgmm)哪邊較高對應的 FTIR 吸收
脂肪 Fat(15.4% vs 9.1%)Arabica酯基 C=O ~1745、C–H ~2920 / 2855 cm⁻¹
咖啡因 Caffeine(1.2% vs 1.9%)RobustaC=O / C=N ~1700–1600 cm⁻¹
綠原酸類 Chlorogenic acidsRobusta芳香 C=C、C–O ~1600–1000 cm⁻¹
葫蘆巴鹼 TrigonellineArabica環 C=N / C–N ~1600–1500 cm⁻¹
碳水化合物 / 醣類1007 / 957 / 903 cm⁻¹(C–O,PLS-DA 鑑別波段)
結論: 兩份完全不同的資料——一份 FTIR 光譜、一份直接量的化學成分——都把 Arabica 與 Robusta 分得一樣乾淨(皆 100%)。 這說明 FTIR 看到的,不是巧合,而是真實、已知的品種化學差異。光譜,是化學的影子。
怎麼算的

Python 程式(scikit-learn)

整套分析用 numpy / pandas / scikit-learn 完成,可重現。完整檔案見 python/ 目錄。

前處理 — SNV 散射校正(python/ftir_utils.py

def snv(X):
    """Standard Normal Variate — per-spectrum scatter correction (standard for IR/DRIFT)."""
    Xv = np.asarray(X, float)
    mu = Xv.mean(axis=1, keepdims=True)
    sd = Xv.std(axis=1, ddof=1, keepdims=True); sd[sd == 0] = 1.0
    return (Xv - mu) / sd

PCA — 主成分分析 + 品種分群(python/02_pca.py

from sklearn.decomposition import PCA

Xs = snv(X)                              # SNV 散射校正
Xc = Xs - Xs.mean(0)                     # mean-center for PCA
pca = PCA(n_components=8).fit(Xc)
T = pca.transform(Xc)                    # 樣本在新軸上的位置(分數)
# PC1=44.5%, PC2=23.1% -> 前兩個累積 67.6%; 品種依 PC2 主要分開
# 負荷量 P = pca.components_; top PC1 bands: 1714, 1710, 1706 cm⁻¹ (C=O 區)

PLS-DA — 鑑別 Arabica vs Robusta(python/03_plsda.py

from sklearn.cross_decomposition import PLSRegression
from sklearn.model_selection import StratifiedKFold, cross_val_predict
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, FunctionTransformer

y = (meta["variety"].values == "Arabica").astype(int)   # 1=Arabica, 0=Robusta

def pipe(k):
    return Pipeline([("snv", FunctionTransformer(snv)),
                     ("center", StandardScaler(with_std=False)),
                     ("pls", PLSRegression(n_components=k))])

cv = StratifiedKFold(5, shuffle=True, random_state=42)
# 1 LV: 98.2%, 2 LV: 100% — 停在 2 LV 即可
yhat = cross_val_predict(pipe(2), X.values, y.astype(float), cv=cv).ravel()
acc = ((yhat >= 0.5).astype(int) == y).mean()   # 5 折 CV 準確率 = 100%
# 鑑別波段: 1007 / 957 / 903 cm⁻¹ (醣類 C–O 區)
▶ 如何在本機重跑
pip install numpy pandas scipy scikit-learn matplotlib
cd python
python 01_explore.py     # 下載資料 + 原始 / SNV 光譜圖
python 02_pca.py         # 陡坡 / 分數 / 負荷量
python 03_plsda.py       # 監督分數 / 選 LV / 混淆矩陣 / 鑑別係數
# 所有圖輸出到 python/figures/
不寫程式的版本

用 Orange Data Mining 親手拉一遍

課堂可用 Orange 的拖拉式 widget,不寫一行程式就重現上面的 PCA 與品種鑑別。 開啟 orange/coffee_ftir_workflow.ows,把 File 指向 data/coffee_orange.tab 即可。

          ┌─ Data Table        (檢視原始 FTIR 光譜矩陣)
          │
 File ────┼─ PCA ──Transformed Data──▶ Scatter Plot          ← PCA 分支(Color = variety)
(coffee_  │
 orange)  └─ Logistic Regression ──▶ Test & Score ──▶ Confusion Matrix
                (Arabica vs Robusta,PLS-DA 的 Orange 對應,無需 Select Rows)

關於 PLS-DA:Orange 內建的 PLS widget 只做數值回歸,故分類分支改用 Logistic Regression——同樣是監督式線性鑑別,能直接輸出混淆矩陣,教學概念與 PLS-DA 完全相通。本資料已只有 Arabica / Robusta 兩類,無需 Select Rows,比質譜課更簡潔。

對應概念Python 圖Orange widget
FTIR 光譜(原始)ft01File → Data Table
主成分數量ft03PCA 視窗內變異曲線
分數圖(依品種上色)ft04PCA → Scatter Plot(Color=variety)
分類 + 混淆矩陣ft08Logistic Regression → Test&Score → Confusion Matrix
哪些波段在分類ft09Rank widget(information gain / ANOVA)
學術文獻 · 參考比對

把 FTIR 的脂質訊號,接回 GC 的脂肪酸數字

本頁的 FTIR 是非目標式振動指紋,PC1 主要落在羰基/脂質 C=O(~1714–1706 cm⁻¹)區。那「脂質差異」具體是哪些分子?兩篇用 GC 測脂肪酸 的同儕審查研究給了答案,正好和本頁的「交叉驗證」段落互相印證。

Martín 等 (2001) · Talanta

毛細管 GC-FID 測 40 支咖啡(27 Arabica / 13 Robusta,生豆+烘焙豆)的 10 種脂肪酸,以 PCA + LDA 判別:

  • PCA PC1 40.7%;主要判別成分為油酸 (C18:1)、次亞麻油酸 (C18:3)、亞麻油酸 (C18:2)、肉豆蔻酸 (C14:0)
  • 「油酸 vs 次亞麻油酸」散布圖即可完全分開兩品種
  • LDA 品種辨識率 100%

Romano 等 (2014) · J. Food Compos. Anal.

更進一步——以 HRGC/FID 脂肪酸標記定量混合比例防摻假:

  • 標記:ΣMUFA、次亞麻油酸 (18:3n-3)、18:0/18:1 比值、ΣMUFA/ΣSFA
  • PCA PC1 97.56%;標記與 Arabica 含量的線性迴歸 r=0.98
  • 能抓出標示與實際不符的市售咖啡(如標 80%、實測約 58%)

關鍵化學:Arabica 與 Robusta 的脂肪酸差異

脂肪酸ArabicaRobusta判別意義
油酸 Oleic (C18:1)~7.7–8.3%~12.1–12.3%Robusta 明顯較高
次亞麻油酸 Linolenic (C18:3)~1.4–1.5%~0.7–0.9%Arabica 較高
亞麻油酸 Linoleic (C18:2)~43.6%~39.3%主成分、Arabica 略高
棕櫚酸 Palmitic (C16:0)~33–36%~36%主要飽和脂肪酸

數值整理自 Martín 等 (2001) 與 Romano 等 (2014)。本頁 PC1 的 C=O/C–H 脂質吸收,反映的正是這些脂肪酸的總體差異——FTIR 看「整體脂質」,GC 解析「個別脂肪酸」。

三條獨立證據,同一結論: 本頁(FTIR 光譜)、「交叉驗證」段(濕式化學成分)、與這兩篇(GC 脂肪酸)——都把 Arabica / Robusta 分得一樣乾淨。FTIR 的優勢是快、整譜、免前處理;GC-FAME 的優勢是分子層級、可定量。互補而非取代。
面向本頁 FTIRMartín 2001Romano 2014
測什麼286 波數(整譜)10 種脂肪酸脂肪酸 + 比值標記
樣本數56 即溶咖啡4011 純品 + 多組混合
方法PCA + PLS-DAPCA + LDAPCA + 多元迴歸
目標分類 A / R分類 A / R(+生/熟)定量混合比例
關鍵結果5 折 CV 100%LDA 100%r=0.98、抓出標示不符
延伸思考: 本頁停在「Arabica 還是 Robusta」(二元分類);Romano 等 (2014) 用脂肪酸標記定量混合比例、抓出標示不符的市售咖啡——把分類升級成真偽與摻假定量,也是 FTIR + 化學計量學常見的下一步。

引用文獻

1. Martín, M.J., Pablos, F., González, A.G., Valdenebro, M.S., León-Camacho, M. (2001). Fatty acid profiles as discriminant parameters for coffee varieties differentiation. Talanta 54(2), 291–297.
2. Romano, R., Santini, A., Le Grottaglie, L., Manzo, N., Visconti, A., Ritieni, A. (2014). Identification markers based on fatty acid composition to differentiate between roasted Arabica and Canephora (Robusta) coffee varieties in mixtures. Journal of Food Composition and Analysis 35(1), 1–9.

總結

PCA 與 PLS-DA,一張表看懂

面向PCAPLS-DA
學習方式非監督(只看光譜 X)監督(用光譜 X 與品種 y)
目的探索結構、分群、找異常分類鑑別(Arabica vs Robusta)
找方向的準則最大化 X 的變異最大化 X 與品種的共變異
本課結果PC1=44.5%,兩品種自動分群(PC2 主要)2 LV,5 折 CV 準確率 100%
關鍵圖陡坡圖、分數圖、負荷量CV 曲線、混淆矩陣、回歸係數
關鍵波段1714 / 1710 / 1706 cm⁻¹(羰基 C=O)1007 / 957 / 903 cm⁻¹(醣類 C–O)
何時用先用它「看」光譜資料確定要鑑別時用它建模
帶走兩句話: PCA 把 286 個波數壓縮成看得懂的方向;PLS-DA 一手抓光譜、一手抓答案,讓 FTIR 直接說出「這,是 Arabica,還是 Robusta」。