ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

偏最小二乘回归(PLSR)原理与实战:从高维数据到稳健预测模型

偏最小二乘回归(PLSR)原理与实战:从高维数据到稳健预测模型 1. 从“维数灾难”到“降维打击”为什么我们需要偏最小二乘回归如果你做过数据分析或者机器学习项目大概率遇到过这样的场景手头有一堆自变量比如影响房价的几十个因素面积、地段、房龄、绿化率、周边学校数量……想要预测一个或多个因变量比如房价、租金。你兴冲冲地跑了个多元线性回归结果却可能让你大跌眼镜——模型要么过拟合严重在训练集上表现完美一到测试集就“见光死”要么干脆因为变量间高度相关统计学上称为多重共线性而无法求解软件直接报错。这背后的核心问题就是“维数灾难”在回归分析中的具体体现。当自变量数量多、样本量相对不足且变量间存在复杂相关性时传统的普通最小二乘回归就“失灵”了。它要求矩阵满秩而共线性会破坏这个前提。主成分回归算是前进了一步它先对自变量进行主成分分析降维用互不相关的主成分去回归。但这个方法有个“致命伤”它只考虑了自变量的方差结构完全没管因变量Y的感受。换句话说它找出的主成分是能最好解释X变异的但不一定是与Y最相关的。这就好比给一个饿肚子的人推荐食物你只根据“食物颜色最鲜艳”这个标准来选选出来的可能是一盘颜料而不是能填饱肚子的面包。偏最小二乘回归正是为了解决这个痛点而生的。你可以把它理解为一种“有监督的降维”技术。它的核心思想非常巧妙在降维时不仅要让新生成的成分称为潜变量或成分尽可能好地代表原始自变量X的信息还要让这些成分与因变量Y的相关性尽可能强。它像是在X和Y之间搭建了一座桥梁寻找的是能同时解释X和Y变异并且能最好地建立X与Y之间关系的那些“超级特征”。我第一次在工业数据中应用PLSR是为了分析一批化工产品的光谱数据自变量是数百个波长的吸光度与产品关键质量指标如纯度、粘度的关系。光谱数据维度极高且相邻波长高度相关用普通回归根本行不通。PLSR不仅成功构建了稳健的预测模型其提取出的潜变量还具备明确的物理意义对应着产品中特定化学键的振动为工艺优化提供了直接指导。这种“既降维又关联”的能力让PLSR在化学计量学、生物信息学、金融、社会科学等众多高维数据分析领域成为了不可或缺的工具。2. PLSR的核心算法逻辑一场X与Y的“共舞”理解PLSR关键在于理解它如何一步步提取出那些关键的潜变量。这个过程不像PCA那样是X的“独舞”而是X和Y的“双人舞”舞步的编排始终以最大化两者协方差为目标。2.1 从单因变量PLS1看起一个直观的迭代过程我们先从最简单的单因变量YPLS1算法入手把多因变量的情况PLS2看作是它的自然扩展。假设我们有自变量矩阵Xn个样本×p个变量和因变量向量yn个样本×1。第一步初始化。将X和y进行标准化处理中心化有时也进行缩放这是为了消除量纲影响让算法更稳定。然后我们从最简单的假设开始因变量y本身就可以作为对X进行“加权”的第一个方向参考。但更常见的稳健做法是将X的每一列与y求相关系数用相关系数向量作为初始权重w1。不过在标准算法描述中我们通常直接令第一个X的潜变量得分向量t1的初始值为X的某一列如与y相关性最强的那一列但这并不影响对本质的理解。第二步提取第一个潜变量。这是核心迭代中的第一步计算权重w1权重向量w1 X‘ * y / ||X’ * y||。这里X‘是X的转置。这个公式的意义是什么X’ * y 计算的是X的每一个变量与y的协方差因为已中心化。所以w1本质上是一个“协方差权重”它指向了X中那些与y协方差最大的综合方向。对w1进行归一化除以它的模长是为了保证后续计算的稳定性。计算得分t1得分向量t1 X * w1。t1就是我们提取的第一个潜变量它是一个n×1的向量代表了所有样本在这个新方向上的“坐标”。你可以把它想象成所有样本点在“与y最相关”的X投影轴上的位置。计算载荷p1和q1X的载荷p1 X‘ * t1 / (t1’ * t1)。这反映了原始X变量与这个新潜变量t1之间的相关性。用t1去回归X的每一列得到的回归系数就是p1。y的载荷q1 y‘ * t1 / (t1’ * t1)。这反映了y与这个新潜变量t1之间的相关性。用t1去回归y得到的回归系数就是q1。计算残差我们已经用t1解释了一部分X和y的信息现在要把这部分信息从原始数据中“扣除”以便寻找下一个不相关的方向。X的残差E1 X - t1 * p1‘。这里t1 * p1’ 就是用第一个潜变量及其载荷重构的X矩阵。E1是尚未被解释的X信息。y的残差f1 y - t1 * q1。这是尚未被解释的y信息。第三步重复迭代。将残差矩阵E1当作新的X残差向量f1当作新的y重复第二步的过程提取第二个权重w2、得分t2、载荷p2和q2并计算新的残差E2和f2。如此循环直到提取出足够多的潜变量比如A个。注意这里有一个关键点为了保证每次提取的潜变量得分t之间是正交的不相关在计算权重w时有一种更常见的算法变体称为NIPALS算法会要求权重w与之前所有潜变量的得分向量正交。但在最初的简化理解中我们可以认为算法通过不断对残差进行操作隐式地实现了这一点。最终模型当我们提取了A个潜变量后原始X和y可以表示为 X T * P‘ E y T * q f 其中T是得分矩阵n×A每一列是一个潜变量得分tP是X的载荷矩阵p×Aq是y的载荷向量A×1E和f是残差。而我们想要的从原始X预测y的回归系数β可以通过这些中间变量计算得到β W * (P‘ * W)^(-1) * q其中W是权重矩阵p×A。在实际应用中我们通常不需要手动推导这个公式软件会直接给出β或者给出用潜变量T建立的回归模型。2.2 扩展到多因变量PLS2从“单恋”到“多角关系”当因变量Y是一个矩阵n个样本×m个变量时算法思想完全一致只是“舞伴”变成了一个群体。核心目标仍然是寻找X的潜变量使其不仅能概括X还能同时概括Y注意是概括Y而不是单独某个Y变量。算法步骤与PLS1类似但初始化时需要为Y也设置一个初始的得分向量u通常取Y的第一列或与X相关性最强的列。在迭代中权重w的计算依赖于X和当前Y得分u的协方差w X‘ * u / ||X’ * u||。计算X得分t X * w。然后用t去计算Y的权重cc Y‘ * t / (t’ * t)。计算Y的得分u Y * c / (c‘ * c)。注意这里有一个归一化检查t和u是否收敛即变化很小如果收敛则计算载荷p和q并计算残差进入下一轮否则用新的u回到第1步迭代。PLS2提取的潜变量是能同时解释X和Y矩阵变异的方向。最终我们会得到一组潜变量T用于建立对所有m个Y变量的回归模型Y T * C‘ F其中C是Y的载荷矩阵。一个重要的实操心得在处理多因变量问题时如果各个Y变量之间尺度差异巨大或者量纲不同必须对Y矩阵进行标准化。否则量级大的Y变量会在计算协方差时占据绝对主导地位导致提取的潜变量主要服务于它而忽略了其他重要但量级小的Y变量。这和在处理X变量时进行标准化的道理是一样的。3. 手把手实战用Python/R实现PLSR建模与调优理论说得再多不如亲手跑一遍代码。这里我将分别用Python和R这两个最常用的数据分析语言演示一个完整的PLSR工作流从数据准备、模型训练、潜变量选择到模型评估与诊断。3.1 Python实战基于scikit-learnPython中我们主要使用scikit-learn库的PLSRegression模块。假设我们有一个数据集X是葡萄酒的光谱数据125个波长Y是葡萄酒的酒精度和酸度两个质量指标。import numpy as np import pandas as pd from sklearn.cross_decomposition import PLSRegression from sklearn.model_selection import train_test_split, cross_val_predict from sklearn.metrics import mean_squared_error, r2_score from sklearn.preprocessing import StandardScaler import matplotlib.pyplot as plt # 1. 加载数据并划分训练集/测试集 # 假设 df_X 是光谱数据DataFrame df_Y 是质量指标DataFrame X df_X.values Y df_Y.values X_train, X_test, Y_train, Y_test train_test_split(X, Y, test_size0.2, random_state42) # 2. 数据标准化 - 非常重要 # PLS对尺度敏感尤其是多Y变量时。使用StandardScaler进行中心化减均值和缩放除以标准差。 scaler_X StandardScaler(with_meanTrue, with_stdTrue) scaler_Y StandardScaler(with_meanTrue, with_stdTrue) X_train_scaled scaler_X.fit_transform(X_train) X_test_scaled scaler_X.transform(X_test) # 注意使用训练集的均值和标准差来转换测试集 Y_train_scaled scaler_Y.fit_transform(Y_train) Y_test_scaled scaler_Y.transform(Y_test) # 3. 确定最佳潜变量数n_components - 模型调优的核心 # 使用交叉验证计算不同成分数下的预测误差如RMSE n_comp_range range(1, 11) # 尝试1到10个成分 mse_cv [] for n_comp in n_comp_range: pls PLSRegression(n_componentsn_comp) # 使用交叉验证预测训练集 Y_cv_pred cross_val_predict(pls, X_train_scaled, Y_train_scaled, cv5) # 5折交叉验证 mse_cv.append(mean_squared_error(Y_train_scaled, Y_cv_pred)) # 绘制交叉验证误差曲线 plt.figure(figsize(8,5)) plt.plot(n_comp_range, mse_cv, markero, linestyle-) plt.xlabel(Number of PLS Components) plt.ylabel(Cross-Validated MSE) plt.title(PLS Component Number Selection) plt.grid(True) plt.show() # 选择误差最小或开始出现平台期的成分数 optimal_n_comp n_comp_range[np.argmin(mse_cv)] # 这里简单取MSE最小的实践中可结合“肘部法则” # 4. 用最优成分数训练最终模型 pls_optimal PLSRegression(n_componentsoptimal_n_comp) pls_optimal.fit(X_train_scaled, Y_train_scaled) # 5. 模型评估 Y_train_pred_scaled pls_optimal.predict(X_train_scaled) Y_test_pred_scaled pls_optimal.predict(X_test_scaled) # 将预测值反标准化回原始量纲 Y_train_pred scaler_Y.inverse_transform(Y_train_pred_scaled) Y_test_pred scaler_Y.inverse_transform(Y_test_pred_scaled) train_r2 r2_score(Y_train, Y_train_pred) test_r2 r2_score(Y_test, Y_test_pred) train_rmse np.sqrt(mean_squared_error(Y_train, Y_train_pred)) test_rmse np.sqrt(mean_squared_error(Y_test, Y_test_pred)) print(f最优潜变量数: {optimal_n_comp}) print(f训练集 R²: {train_r2:.4f}, RMSE: {train_rmse:.4f}) print(f测试集 R²: {test_r2:.4f}, RMSE: {test_rmse:.4f}) # 6. 获取模型系数对应于原始标准化前的数据 # 注意由于我们标准化了数据这里的系数是对应于标准化后数据的。 # 要得到原始数据的系数需要经过转换。sklearn的PLSRegression在拟合标准化数据后 # 其coef_属性给出的已经是基于原始输入X标准化前预测原始输出Y标准化前的系数矩阵吗不完全是。 # 更稳妥的方式是我们拟合的模型 pls_optimal 是在标准化数据上训练的。 # 对于一个新的、未标准化的样本 x_new (1×p)预测流程应为 # 1. x_new_scaled scaler_X.transform(x_new.reshape(1, -1)) # 2. y_new_scaled_pred pls_optimal.predict(x_new_scaled) # 3. y_new_pred scaler_Y.inverse_transform(y_new_scaled_pred) # 因此通常我们保存的是 scaler_X, scaler_Y 和 pls_optimal 这个管道而不是直接提取一个“原始系数”。关键点解析与避坑标准化是必须的StandardScaler的with_stdTrue确保了每个变量具有单位方差这对于PLS中基于协方差的权重计算至关重要。处理测试集时务必使用训练集拟合得到的scaler进行转换这是机器学习的基本准则但新手极易忘记导致数据泄露和错误的乐观评估。成分数选择交叉验证是金标准。单纯看训练集误差会倾向于选择更多的成分导致过拟合。交叉验证误差曲线上的“拐点”肘部通常是最佳选择。scikit-learn的cross_val_predict是进行这项工作的便捷工具。系数解释pls.coef_返回的系数矩阵其维度是 (p个X变量 × m个Y变量)。每一列对应一个Y变量的回归方程中所有X变量的系数。但请注意这些系数是模型内部的表示直接解释其大小时需谨慎因为变量间可能存在共线性尽管PLS缓解了它。更常见的解释工具是VIP值。3.2 R语言实战基于pls包R语言的pls包功能非常强大且用户友好特别适合化学计量学等领域。# 安装并加载包 # install.packages(pls) library(pls) library(ggplot2) # 1. 准备数据 # 假设 data 是一个数据框包含光谱变量 X1, X2, ..., X125 和质量变量 Y1, Y2 # 将自变量和因变量分开 X - as.matrix(data[, 1:125]) Y - as.matrix(data[, c(Y1, Y2)]) # 2. 建立PLSR模型并自动进行交叉验证 # plsr()函数会自动进行中心化scaleFALSE或标准化scaleTRUE # 这里我们对X和Y都进行标准化方法选择“oscorespls”一种稳健的算法 pls_model - plsr(Y ~ X, ncomp 10, validation LOO, # LOO留一交叉验证也可用“CV” scale TRUE, method oscorespls) # 3. 模型摘要与成分数选择 summary(pls_model) # 查看累计解释方差等 # 绘制交叉验证均方预测误差RMSEP图 validationplot(pls_model, val.type RMSEP, legendpos topright) # 通常选择RMSEP最小值或第一个局部最小值对应的成分数 optimal_comp - which.min(pls_model$validation$PRESS[1, ]) # PRESS是预测残差平方和 # 另一种更直观的方法使用selectNcomp()函数基于随机化检验或最小误差 optimal_comp_rand - selectNcomp(pls_model, method randomization, plot TRUE) optimal_comp_onesigma - selectNcomp(pls_model, method onesigma, plot TRUE) print(paste(根据最小PRESS建议成分数:, optimal_comp)) print(paste(根据随机化检验建议成分数:, optimal_comp_rand)) print(paste(根据‘one-sigma’法则建议成分数:, optimal_comp_onesigma)) # 4. 使用选定成分数重新拟合或提取最终模型 # pls_model已经包含了所有成分的信息我们只需要在预测时指定成分数即可。 final_ncomp - optimal_comp_onesigma # 举例使用 one-sigma 法则的结果 # 5. 模型评估 # 获取拟合值 Y_fitted - predict(pls_model, ncomp final_ncomp, newdata X) # 计算R2和RMSE R2 - 1 - sum((Y - Y_fitted)^2) / sum((Y - colMeans(Y))^2) RMSE - sqrt(mean((Y - Y_fitted)^2)) # 6. 绘制诊断图 # 观测值 vs 预测值图 plot(Y_fitted[,1], Y[,1], xlab Predicted Y1, ylab Observed Y1, main Y1: Fit Plot) abline(0, 1, colred) # 添加yx的参考线 # 载荷图 (Loadings Plot) - 查看每个潜变量中原始变量的贡献 plot(pls_model, loadings, comps 1:2, legendpos topleft) # 解释图中点代表原始X变量其坐标是它们在潜变量1和2上的载荷(p1, p2)。 # 位置靠近的变量在潜变量空间中行为相似。远离原点的变量对当前潜变量贡献大。 # 7. 计算并绘制变量重要性投影VIP值 # pls包没有内置VIP函数但可以手动计算或使用其他包如ropls。 # 这里提供一个手动计算VIP for Y的第一个变量的示例函数 get_vip - function(pls_model) { W - pls_model$loading.weights # 权重矩阵 W P - pls_model$loadings # 载荷矩阵 P T - pls_model$scores # 得分矩阵 T Q - pls_model$Yloadings # Y载荷矩阵 Q ncomp - ncol(T) p - nrow(W) VIP - matrix(0, nrowp, ncolncomp) for (i in 1:ncomp) { # 计算第i个成分对Y的解释方差权重 weight (Q[i,]^2 * sum(T[,i]^2)) / sum(Q^2 * colSums(T^2)) # 计算第i个成分的VIP VIP[,i] sqrt(p * weight * (W[,i]^2) / sum(W[,i]^2)) } # 通常报告的是所有成分的VIP总和 vip_scores - sqrt(rowSums(VIP^2)) return(vip_scores) } vip_scores - get_vip(pls_model) # 绘制VIP图 barplot(vip_scores, names.arg colnames(X), las2, cex.names0.7, mainVariable Importance in Projection (VIP), ylabVIP Score) abline(h1, colred, lty2) # VIP1通常被认为是重要的变量R实战要点pls包的便利性plsr()函数一句命令就能完成建模和交叉验证validationplot()和selectNcomp()让模型选择非常直观。算法选择method参数有多种选项如 “kernelpls”, “widekernelpls”, “simpls”, “oscorespls”。对于大多数情况“kernelpls”或“oscorespls”是稳健的选择。“simpls”计算更快但数值性质可能稍差。当变量数远大于样本数时“widekernelpls”更高效。VIP值VIP是PLSR中用于变量筛选的黄金指标。它衡量了一个X变量在解释Y变异的全过程中在所有潜变量上的综合重要性。VIP 1 是一个常用的经验阈值大于1的变量被认为对模型有显著贡献。这在光谱分析中用于筛选关键波长在金融中用于筛选关键因子非常实用。4. 模型诊断、解释与进阶应用场景构建出PLSR模型只是第一步如何诊断模型是否健康、如何解释模型结果、以及将它用在哪些特色场景才是真正体现分析功力的地方。4.1 核心诊断图洞察模型健康状况一个可靠的PLSR分析离不开以下几张关键的诊断图预测误差 vs. 成分数图如前所述这是选择最佳潜变量数的根本依据。一个健康的模型其交叉验证误差会随着成分数增加先迅速下降然后进入一个平缓区或开始轻微上升。选择平缓区的起点肘部作为成分数。观测值 vs. 预测值散点图无论是训练集还是测试集数据点应均匀分布在yx参考线两侧。如果出现明显的弯曲模式可能意味着数据中存在非线性关系或者需要对Y进行变换如取对数。如果测试集散点明显比训练集分散说明模型存在过拟合或测试集与训练集分布不一致。残差图绘制预测残差Y_obs - Y_pred against 预测值Y_pred或观测值Y_obs。健康的残差图应该像一个随机的“毛球”没有任何明显的趋势或模式如漏斗形、弧形。如果存在趋势同样暗示模型可能遗漏了重要变量或存在非线性。得分图Score Plot绘制样本在前两个潜变量t1 vs. t2上的得分。这张图用于发现异常样本离群点远离样本云中心的点需要重点关注可能是测量错误、录入错误或者是具有特殊性质的样本。观察样本聚类结构如果数据本身存在类别如不同产地的葡萄酒得分图上通常能清晰地看到类别分离这说明潜变量抓住了区分类别的关键信息。评估模型稳定性如果测试集样本的得分点落在训练集样本云的范围之内说明模型外推能力较好。载荷图Loading Plot绘制变量在前两个潜变量p1 vs. p2上的载荷。这张图用于理解潜变量的含义落在同一象限且距离原点较远的变量它们对当前潜变量的贡献大且方向一致。例如在光谱分析中如果某些波长在t1上有高的正载荷可能对应着某种官能团的吸收。识别共线变量组位置非常接近的变量说明它们在潜变量空间中提供的信息高度冗余可以考虑剔除一部分。关联X与Y在双标图中同时画出X的载荷和Y的载荷或Y的权重可以直观看到哪些X变量与哪个Y变量关系密切。靠近某个Y变量的X变量通常是对预测该Y有重要影响的变量。4.2 变量重要性评估从VIP到回归系数除了直观的图形我们还需要定量的指标来判断每个自变量的重要性。变量重要性投影VIP如前所述VIP是PLSR中最综合、最常用的变量重要性指标。它考虑了变量在所有潜变量上对解释Y的累计贡献。VIP 1是筛选重要变量的黄金准则。在实际项目中我经常用VIP值来指导特征选择先建立包含所有变量的PLSR模型然后剔除VIP 0.8更严格或 1 的变量重新建模往往能在不损失预测精度甚至提升精度的情况下得到一个更简洁、更易解释的模型。标准化回归系数虽然PLSR的回归系数β因为共线性问题其大小和符号在传统回归中难以直接解释但在PLS模型中由于潜变量是正交的其系数的稳定性相对更好。我们可以通过观察系数绝对值的大小来粗略判断影响力。一个重要的技巧是绘制系数图Coefficient Plot按系数大小排序。这能一目了然地看到正负影响最大的变量是哪些。但解释时仍需结合领域知识因为高度相关的变量在PLSR中可能会被分配相似的系数。权重w与载荷p权重向量w的方向决定了潜变量t的提取方向它直接反映了X变量与Y的协方差关系。载荷p反映了X变量与潜变量t的相关性。比较同一潜变量下的w和p如果两者差异很大可能暗示数据中存在一些“干扰”变量或者该潜变量提取的信息比较复杂。4.3 进阶应用场景与技巧PLSR远不止于做回归预测它在许多特定场景下大放异彩。多元校正与定量分析这是PLSR在分析化学中的经典应用。例如近红外光谱分析中光谱X与样品浓度Y之间关系复杂且光谱波段多、共线性强。PLSR可以建立光谱与浓度之间的稳健校正模型用于未知样品的快速、无损定量检测。这里的核心是模型的稳健性和可转移性需要关注模型在时间推移、仪器更换后的表现常常需要用到模型更新或标准化的技术。处理缺失值PLSR的迭代算法如NIPALS天然能够处理数据中的少量缺失值。算法会在迭代过程中基于现有数据来估计缺失值。但这并非万能缺失太多或非随机缺失仍然会导致严重问题。分类问题PLS-DA偏最小二乘判别分析是PLSR用于分类问题的变体。其思路是将类别标签如0/1或经过虚拟编码的多个类别作为Y矩阵然后进行PLSR建模。提取出的潜变量空间能够最大化地区分不同类别的样本。随后可以在潜变量得分空间中使用线性判别分析、最近邻等分类器进行分类。PLS-DA在代谢组学、基因组学等高维分类问题中非常流行。一个关键注意事项PLS-DA容易过拟合必须使用严格的交叉验证来评估分类性能并且潜变量数的选择至关重要。多块数据融合当你有来自不同来源或技术的多组自变量数据例如同时有光谱数据、色谱数据和工艺参数数据想要共同预测一个质量指标Y时可以使用多块PLSR或分层PLSR。这些方法能同时分析多个X块与Y的关系并揭示不同数据块之间的协同或互补信息。非线性PLSR标准的PLSR是线性的。当X与Y之间存在明显的非线性关系时可以通过引入核函数核PLSR或将X的平方项、交互项作为新变量加入来捕捉非线性效应。但这样会增加模型复杂度和过拟合风险需谨慎使用。在我处理的一个发酵过程优化项目中我们就使用了多块PLSR。我们将在线传感器数据温度、pH、溶氧等和离线检测的代谢物浓度数据两个X块共同建模预测最终产物效价Y。PLSR不仅给出了高精度的预测模型其载荷图还清晰地揭示出在发酵前期在线传感器数据块是主要预测因子而在发酵中后期离线代谢物数据块变得至关重要。这个发现直接指导了我们优化采样策略将有限的离线检测资源集中到了最关键的时间点。
返回列表