Coffee–Barley NIR:食品摻偽鑑別與比例預測
這一章使用 Gruppo di Chemiometria 的 Coffee barley NIR dataset。你會用同一組 NIR 光譜同時做兩件事:判斷咖啡是否摻偽,並預測 barley 摻入比例。
樣本
咖啡與 coffee–barley 混合樣本。
NIR variables
比 Tecator 更高維,更接近真實食品真偽資料。
兩種 y
分類:是否摻偽;回歸:barley percentage。
food authenticityadulterationPLS-DAPLS regression
同一組 X,可以回答兩種食品問題
咖啡摻入廉價 barley 是典型食品真偽案例。NIR 能快速取得粉末樣本的光譜指紋,chemometrics 則把微小光譜差異轉成「是否摻偽」與「摻多少」的答案。
| 矩陣 / 標籤 | 意義 | 問題型態 |
|---|---|---|
X_NIR | 1501 個 NIR 變數 | 輸入特徵 |
y_class | authentic vs adulterated | 分類 / PLS-DA |
y_barley | barley 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)),
}先看 barley percentage 是否形成梯度
用 barley percentage 幫 PCA score plot 上色。理想情況下,純咖啡會在一側,高比例 barley 會往另一側移動,中間比例形成連續梯度。
你要觀察
- pure coffee 是否聚在一起?
- barley % 是否沿 PC1 排列?
- 低濃度摻偽是否和純咖啡重疊?
你要避免
- 只挑最好看的 PCA 圖卻不驗證模型
- 用全部資料決定前處理後再報告過度樂觀結果
- 忽略 outlier 或 batch effect
第一個任務:真咖啡 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 | 直接看哪一種錯誤最常發生。 |
第二個任務:預測 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))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?