前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >岭回归(ridge regression)

岭回归(ridge regression)

作者头像
用户6021899
发布2019-08-14 17:20:05
3.5K0
发布2019-08-14 17:20:05
举报
文章被收录于专栏:Python编程 pyqt matplotlib

回归分析中最常用的最小二乘法是一种无偏估计, 回归系数矩阵为

当X不是列满秩矩阵时,即特征数n比样本数m还多,则X.T*X的行列式为0,逆不存在。或者X的某些列的线性相关比较大时,则X.T*X的行列式接近0,X.T*X为病态矩阵(接近于奇异),此时计算其逆矩阵误差会很大,传统的最小二乘法缺乏稳定性与可靠性。

为了解决这个问题,统计学家引入岭回归的概念。简单来说,岭回归就是在矩阵X.T*X上加上一个λI从而使矩阵非奇异,进而能对 X.T*X + λI 求逆。其中,λ是一个用户给定的参数,I是一个nxn的单位矩阵(像是在0构成的平面上有条1组成的“岭”)。

在这种情况下,回归系数的计算公式为:

本篇的样例使用数据集如下(只显示了很小一部分),它使用8个特征预测一种海洋动物的年龄,部分特征间线性相关度比较高。样本总数为4177。

对于本数据集,回归系数矩阵中各项回归系数随λ的变化规律如下:

图左边λ很小,接近0时,回归系数与最小二乘法一致;图右边,λ非常大时,各项回归系数向0靠近;λ取在中间部分的某值将可以取得较好的预测效果。

示例代码如下:

代码语言:javascript
复制
from numpy import *

def loadDataSet(fileName):      #general function to parse tab -delimited floats
    numFeat = len(open(fileName).readline().split('\t')) - 1 #get number of fields 
    dataMat = []; labelMat = []
    fr = open(fileName)
    for line in fr.readlines():
        lineArr =[]
        curLine = line.strip().split('\t')
        for i in range(numFeat):
            lineArr.append(float(curLine[i]))
        dataMat.append(lineArr)
        labelMat.append(float(curLine[-1]))
    return dataMat,labelMat

def rssError(yArr,yHatArr): #yArr and yHatArr both need to be arrays
    return ((yArr-yHatArr)**2).sum()
    
def ridgeRegres(xMat,yMat,lam=0.2):
    xTx = xMat.T*xMat
    denom = xTx + eye(shape(xMat)[1])*lam
    if linalg.det(denom) == 0.0:
        print ("This matrix is singular, cannot do inverse")
        return
    ws = denom.I * (xMat.T*yMat)
    return ws
    
def ridgeTest(xArr,yArr):
    xMat = mat(xArr)
    yMat=mat(yArr).T
    #数据标准化(归一化)
    yMean = mean(yMat,axis =0)
    yMat = yMat - yMean     #to eliminate X0 take mean off of Y
    print(yMat.shape)
    #regularize X's
    xMat = regularize(xMat)
    
    numTestPts = 30 ###
    wMat = zeros((numTestPts,shape(xMat)[1]))
    for i in range(numTestPts): # 测试不同的lambda时求得的系数矩阵
        ws = ridgeRegres(xMat,yMat,exp(i-10)) #让 labmda 指数变化,广覆盖
        #Y_predict = xMat*ws +yMean
        wMat[i,:]=ws.T #保存不同的lambda时求得各个系数矩阵
    return wMat
    
def regularize(xMat):#regularize by columns
    inMat = xMat.copy()
    inMeans = mean(inMat,axis=0)   #calc mean then subtract it off
    inVar = var(inMat,0)      #calc variance of Xi then divide by it
    inMat = (inMat - inMeans)/inVar #减去均值,再除以标准差
    return inMat

X,Y = loadDataSet("abalone.txt")
ridgeWeights = ridgeTest(X,Y)
print(ridgeWeights.shape)
import matplotlib.pyplot as plt
n = ridgeWeights.shape[1]#特征数
numTestPts = 30 ###
for i in range(n):
    plt.plot(arange(numTestPts)-10, ridgeWeights[:,i], label = "W(%s)"%i)
plt.legend(loc="upper right")
#$\lambda\ $ 注意这里的空格符
plt.title(r"岭回归 回归系数随$\lambda\ $变化规律""\n基于数据集'abalone.txt'", fontsize=16)
plt.xlabel(r"ln($\lambda\ $)")
plt.grid(ls="--",lw =1)
plt.show()

xMat_normilized = regularize(mat(X))
rssErrorList=[]
for i in range(numTestPts):
    Y_predict = xMat_normilized*ridgeWeights[i].reshape(n,1) +mean(mat(Y).T,axis =0)
    RSS = rssError(array(Y).T, array(Y_predict))
    rssErrorList.append(RSS)
plt.plot(arange(numTestPts)-10, rssErrorList)
plt.xlabel(r"ln($\lambda\ $)")
plt.ylabel(r"RSS")
plt.show()
for i in range(20,25):
    Y_predict = xMat_normilized*ridgeWeights[i].reshape(n,1) +mean(mat(Y).T,axis =0)
    RSS = rssError(array(Y).T, array(Y_predict))
    #rssErrorList.append(RSS)
    plt.plot(array(Y)[1000:1100],label= "Y_True(train set)")
    plt.plot(Y_predict[1000:1100], label="Y_Predict")
    plt.title("ln("r"$\lambda\ $"")=%d, RSS =%.1f "%(i-10, RSS))
    plt.legend()
    plt.show()
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python可视化编程机器学习OpenCV 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档