跳到正文
格致开物MATHWIKI

偏最小二乘回归

偏最小二乘回归(partial least squares regression,PLS)用与响应共同变化的预测方向形成少量得分,再基于得分进行回归。它是一种有监督降维:选择方向时已经使用响应数据。不同PLS变体在标准化、响应数目和逐步残差化上有所区别;以下先完整讲解单响应的一成分PLS1。

与主成分回归的区别

设样本量 n≥2,中心化预测矩阵 X∈ℝn×p、响应 y∈ℝn,第一得分为 t=Xw。PCA只考虑预测得分的方差;PLS1则寻找与响应协方差绝对值最大的方向。固定欧氏长度 ‖w‖2=1,协方差除常数 n−1 外等于 w𝖳X𝖳y。Cauchy–Schwarz不等式给出 |w𝖳X𝖳y|≤‖X𝖳y‖2. 当 X𝖳y≠0,可取 w=X𝖳y‖X𝖳y‖2,t=Xw. 方向正负可同时翻转,不改变最终回归。协方差最大与相关系数最大使用不同归一化;后者是典型相关分析所强调的目标。[1]

在交叉内积非零的上述情形,t 也非零:若 Xw=0,则 w𝖳X𝖳y=0,但按所取方向该内积等于 ‖X𝖳y‖2>0,矛盾。因此下面的分母为正。将 y 对得分回归,最小化 ‖y−tq‖2,求导得到 q=t𝖳y/(t𝖳t)。一成分预测为 y^=tq=X(wq),所以原变量系数是 wq。权重 w、得分 t、响应载荷 q 是不同对象,维数分别为 p,n,1。

大方差方向可能无助预测

取四个教学观测 X=(−10−1−10110−1101),y=(−3,3,−3,3)𝖳. 两列正交,平方和分别四百与四,所以未经标准化的第一主成分沿第一列;但该列与响应内积为零。PLS使用 X𝖳y=(0,12)𝖳,w=(0,1)𝖳,t=(−1,1,−1,1)𝖳. 响应载荷为 q=12/4=3,故系数 (0,3)𝖳,训练预测恰好等于 y。高方差的第一方向在此特定构造中对响应没有线性预测作用,低方差第二方向却包含完整信号。

四个预测点在横向大幅变化,响应正负却只随纵坐标改变,PCA沿横向而PLS沿纵向
坐标轴标出原始尺度。本例没有先标准化,因此横向方差大;响应标签说明有监督方向与仅看预测方差的方向可以不同。

变式。 保持 X 不变,将响应改为 yi=Xi1Xi2。此时两个预测列与响应的内积都为零,第一成分公式没有非零方向可用;然而响应显然由二者的交互决定。没有线性协方差信号,不等于完全没有关系,线性PLS并不会自动识别这个非线性结构。

残差化与后续成分

一个常见PLS1步骤先计算预测载荷 p=X𝖳t/(t𝖳t),再更新 Xnew=X−tp𝖳,ynew=y−tq. 代入载荷公式可得 t𝖳Xnew=0、t𝖳ynew=0:已由当前得分解释的部分被移除,后续成分在残差上继续寻找。多成分预测要把每一步的残差坐标映回原始变量,不能把不同步骤权重直接相加。本文代码只计算一成分,避免把这一点藏在软件输出中。[1]

一成分的可运行实现

输入是有限、非空的二维预测数组与同长响应;函数自行中心化但不缩放,返回原尺度截距和系数,不改变输入。若交叉内积为零,返回仅含均值的预测,并不伪造一个有解释力的方向。单条观测时中心化后也按此规则仅预测其均值,不把它称为一个有定义的样本协方差估计。需要NumPy。

Python 3
import numpy as np

def pls1_one_component(x, y):
    x, y = np.asarray(x, dtype=float), np.asarray(y, dtype=float)
    if not (x.ndim == 2 and y.ndim == 1 and x.shape[0] == len(y)
            and min(x.shape) > 0 and np.all(np.isfinite(x)) and np.all(np.isfinite(y))):
        raise ValueError("finite nonempty paired data required")
    xm, ym = x.mean(axis=0), y.mean()
    xc, yc = x - xm, y - ym
    cross = xc.T @ yc
    size = np.linalg.norm(cross)
    if size == 0:
        return float(ym), np.zeros(x.shape[1])
    w = cross / size
    score = xc @ w
    loading = score @ yc / (score @ score)
    beta = w * loading
    return float(ym - xm @ beta), beta

x = [[-10, -1], [-10, 1], [10, -1], [10, 1]]
print(pls1_one_component(x, [-3, 3, -3, 3]))

输出为截距零、系数 [0. 3.]。一成分时间为 O(np),含中心化副本的存储为 O(np+n+p);近零交叉内积在浮点下需按数据尺度评估,而非无条件宣称统计信号恰为零。

PLS各成分使用响应,所以选成分数时必须在训练折内重新拟合,不能先用全体响应降维再交叉验证。标准化会改变协方差目标,训练精确拟合也不保证留出预测优秀;高维情况下仍需控制成分数并检查外部验证误差。

参考文献

  1. ↑ 1.0 1.1 scikit-learn 官方文档:Cross decomposition,“PLSRegression”及PLS投影、权重、得分和残差化的说明。