岭回归(ridge regression)

收缩方法

通过选择自变量的一个子集产生新的线性模型,这个模型是可解释的并且可能具有比完整模型更低的预测误差,然而,由于它是一个离散过程(变量或者保留,或者丢弃),使得子集选择方法常常表现出高方差,因此不能降低整个模型的预测误差。收缩方法更加连续,并且不会因为变量多而过多的降低性能

岭回归(Ridge Regression)

岭回归通过对系数向量的长度平方添加处罚来收缩系数。
算法极小化如下表达式:
β^ridge=argminβNi=1(yiβ0pj=1xijβj)2+λpj=1β2)
λ值越大,收缩量越大。
表达岭回归的一个等价方法是
β^ridge=argminβNi=1(yiβ0pj=1xijβj)2
subject topj=1β2jt
当线性回归模型中存在多个相关变量时,它们的系数确定性变差并呈现高方差。比如说,在一个变量上的一个很大的正系数可能被在其相关变量上的类似大小的负系数抵消,岭回归就是通过在系数上施加约束来避免这种现象的发生。此外当特征数p>>样本数量时,矩阵X^TX不可逆,此时不可以直接使用最小二乘法,而岭回归没有这个限制。

注意到,岭回归在不同自变量的不同度量下的解是不同的,因此在进行岭回归的时候,要先将X和Y标准化。残差平方和对β求偏导并置为零,可以得到岭回归的解
β^ridge=(XTX+λI)1XTy
可以注意到,岭回归的解仍然是y的线性函数。特殊的,如果X是正交的,那么岭回归相当于最小二乘法的缩放。

为了观察岭回归解的特点,考虑对X进行奇异值分解,
X=UDVT
这里,U和V是N*p和p*p的正交矩阵,那么经过岭回归得到的y的拟合值为
y^=X(XTX+λI)1XTy
=UD(D2+λI)1DUTy
=pj=1ujd2jd2j+λIuTjy
di是X的奇异值。
可以看出,对应di值越小的方向被收缩的量越大。这也可以看出岭回归的作用,收缩X的主成分,并优先收缩其中方差小的方向。

贝叶斯理论角度来看岭回归

从贝叶斯理论的角度来看岭回归问题,选择先验分布,岭回归也可以作为后验分布的均值(或众数)导出。
事实上,在高斯先验分布β ~ N(0,γI)和高斯选样模型y N(xβ,σ2I),岭回归估计是后验分布的均值(和众数),而且可以证明
λ=σ2γ2
现在简单的证明一下这个结论:
根据贝叶斯理论,我们得到
P(β|D)P(D|β)P(β)
=N(Xβ,σ2I)N(0,γ2I)
P(β|D)实际上也是一个正态分布
更进一步,
log(P(β|D))=C1/2(yXβ)T(yXβ)σ21/2βTβγ2
其中C是一个与\beta无关的常数,这个正态分布的众数和平均值是使得它的概率密度函数的极大值,即
β^=arg minβ(log(P(β|D)))
=arg minβ(2σ2log(P(β|D)))
=arg minβ((yXβ)T(yXβ)σ2γ2βTβ)

可以看到,这和岭回归的
β^ridge=argminβNi=1(yiβ0pj=1xijβj)2+λpj=1β2)
等价,其中
λ=σ2γ2

岭回归的求解与代码

除了上面说的利用
β^ridge=(XTX+λI)1XTy
得到岭回归的解以外,还可以通过向构造人工数据来讲岭回归问题转化为普通最小二乘法(OLS)来求解,具体来说,用p个附加的行添加到原始的X下面,对应的响应值y都为0。
代码如下:

from numpy import *


# 预处理数据
def loadData(filename):
    dataSet = []
    labels = []
    fr = open(filename)
    for line in fr.readlines():
        curLine = line.strip().split('\t')
        fltLine = list(map(float, curLine))
        dataSet.append(fltLine[:-1])
        labels.append(fltLine[-1])
    return dataSet, l


# 岭回归
def ridgeRegres(xArr, yArr, lam=0.2):
    xMat = mat(xArr); yMat = mat(yArr).T
    m, n = shape(xMat)
    xMean = mean(xMat, 0)
    xStd = std(xMat, 0)
    xMat = (xMat-xMean)/xStd
    yMean = mean(yMat)
    yMat -= yMean
    xTx = xMat.T*xMat+lam*mat(eye(n))
    if linalg.det(xTx) == 0.0:
        print('xTx is not invertible')
        return
    beta = xTx.I * (xMat.T) * yMat
    print(xMat*beta-yMat)
    return beta, xMean, xStd, yMean



你可能感兴趣的:(机器学习)