中階:咖啡摻偽 鑑別與定量

用 Coffee–Barley NIR 資料把 NIR 從成分預測推進到食品真偽:PLS-DA 判斷是否摻偽,PLS regression 預測 barley percentage。

158samples
1501NIR variables
PLS-DAauthenticity
PLSbarley %
Level 2 · 中階

Coffee–Barley NIR:食品摻偽鑑別與比例預測

這一章使用 Gruppo di Chemiometria 的 Coffee barley NIR dataset。你會用同一組 NIR 光譜同時做兩件事:判斷咖啡是否摻偽,並預測 barley 摻入比例。

樣本

158

咖啡與 coffee–barley 混合樣本。

NIR variables

1501

比 Tecator 更高維,更接近真實食品真偽資料。

兩種 y

class + %

分類:是否摻偽;回歸:barley percentage。

food authenticityadulterationPLS-DAPLS regression

資料集

同一組 X,可以回答兩種食品問題

咖啡摻入廉價 barley 是典型食品真偽案例。NIR 能快速取得粉末樣本的光譜指紋,chemometrics 則把微小光譜差異轉成「是否摻偽」與「摻多少」的答案。

矩陣 / 標籤意義問題型態
X_NIR1501 個 NIR 變數輸入特徵
y_classauthentic vs adulterated分類 / PLS-DA
y_barleybarley percentage回歸 / PLS
本章核心:分類模型回答「有沒有摻?」;回歸模型回答「摻了多少?」食品真偽分析常常需要兩者一起使用。
前處理比較

不要只跑一種前處理:比較 raw、SNV、derivative

摻偽訊號可能很微弱。不同前處理會改變 PCA 分群、PLS-DA 分類與 PLS regression 誤差,因此中階課要開始系統性比較前處理。

前處理目的可能風險
Raw保留原始光譜散射與基線可能主導結果
SNV / MSC降低散射差異若差異本身有用,可能被消除
First derivative凸顯斜率與細微峰形差異可能放大雜訊
Second derivative強化重疊峰解析更容易放大雜訊,需要 smoothing
from scipy.signal import savgol_filter

def first_derivative(X, window=15, poly=2):
    return savgol_filter(X, window_length=window, polyorder=poly, deriv=1, axis=1)

preprocess_sets = {
    "raw": X,
    "snv": snv(X),
    "snv_d1": first_derivative(snv(X)),
}
PCA

先看 barley percentage 是否形成梯度

用 barley percentage 幫 PCA score plot 上色。理想情況下,純咖啡會在一側,高比例 barley 會往另一側移動,中間比例形成連續梯度。

你要觀察

  • pure coffee 是否聚在一起?
  • barley % 是否沿 PC1 排列?
  • 低濃度摻偽是否和純咖啡重疊?

你要避免

  • 只挑最好看的 PCA 圖卻不驗證模型
  • 用全部資料決定前處理後再報告過度樂觀結果
  • 忽略 outlier 或 batch effect
PLS-DA

第一個任務:真咖啡 vs 摻偽咖啡

PLS-DA 是 supervised 方法,會利用類別標籤尋找最能分開 authentic 與 adulterated 的 latent variables。食品真偽問題中,最重要的是不要把摻偽樣本判成真品。

from sklearn.cross_decomposition import PLSRegression
from sklearn.model_selection import StratifiedKFold, cross_val_predict
from sklearn.preprocessing import LabelEncoder, OneHotEncoder, StandardScaler
from sklearn.metrics import classification_report, confusion_matrix

le = LabelEncoder()
y_int = le.fit_transform(y_class)
Y = OneHotEncoder(sparse_output=False).fit_transform(y_int.reshape(-1, 1))
Xs = StandardScaler().fit_transform(X_preprocessed)
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
y_score = cross_val_predict(PLSRegression(n_components=3), Xs, Y, cv=cv)
y_pred = y_score.argmax(axis=1)
print(classification_report(y_int, y_pred, target_names=le.classes_))
指標在食品真偽中的意義
Sensitivity for adulterated摻偽樣本被抓出來的比例;通常最重要。
Specificity for authentic真品不被誤判成摻偽的比例。
Confusion matrix直接看哪一種錯誤最常發生。
PLS Regression

第二個任務:預測 barley percentage

回歸模型能回答摻了多少。這對供應鏈稽核、品質管制和檢測限評估更有用。

from sklearn.model_selection import KFold, cross_val_predict
from sklearn.metrics import mean_squared_error, r2_score

cv = KFold(n_splits=5, shuffle=True, random_state=42)
for n_lv in range(1, 11):
    pls = PLSRegression(n_components=n_lv)
    y_cv = cross_val_predict(pls, Xs, y_barley, cv=cv).ravel()
    print(n_lv, mean_squared_error(y_barley, y_cv, squared=False), r2_score(y_barley, y_cv))
本章完成標準:你應該能比較不同前處理的 PCA、PLS-DA confusion matrix、PLS regression predicted vs measured,並說明哪個前處理最適合摻偽鑑別。
Orange

Orange workflow

分類:
File → Select Columns → Preprocess → PCA → Scatter Plot
     → Test and Score ← SVM / Random Forest / Logistic Regression
     → Confusion Matrix

回歸:
File → Select Columns(Target = barley %) → Preprocess
     → Test and Score ← SVR / Random Forest Regression
     → Predictions → Scatter Plot(measured vs predicted)
下一步

從單一光譜走向多儀器資料融合

如果你已經會做食品摻偽分類與比例預測,下一章會進入進階 chemometrics:不同儀器 blocks 如何融合?融合真的比較好,還是只是 overfitting?