解决线性回归算法的过拟合问题-----LARS算法

上一次写的机器学习算法是使用线性回归算法实现的,但是线性回归算法不可避免的会出现过拟合问题,训练的越多你的模型就越匹配你的训练数据而逐渐丧失了对新数据的“预测性”,为了解决这个问题提出了岭回归,lars算法,惩罚线性回归等方案。
岭回归:通过添加额外的项来制约过拟合问题

关于稳定性再补充一下。当回归变量不是列满秩的时候,我们固然需要通过正则化来获得唯一解()。但即使列满秩,我们来看看当有其中两列相关程度很高时,会发生什么。比方说一个自变量是身高,一个自变量是体重,假设因变量是某种性激素的水平(或者别的什么跟身体发育相关的东西,随便举的例子)。虽然我们拟合后能得到唯一解,但由于和高度相关,所以和之间存在互相抵消的效应:你可以把弄成一个很大的正数,同时把弄成一个绝对值很大的负数,最终可能不会改变多少。这会导致用不同人群拟合出来的和差别可能会很大,模型的可解释性就大大降低了。怎么办?最简单就是给一个限制,令,这正好就是岭回归。

作者:知乎用户
链接:https://www.zhihu.com/question/28221429/answer/53858036

这里使用lars算法来查看350步的逼近过程中,这11个属性列对结果影响的系数的变化情况
代码:

# -*- coding:utf-8 -*-
import urllib.request
import numpy
from sklearn import datasets,linear_model
from math import sqrt
import matplotlib.pyplot as plot

#从网页中读取数据
url="http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv"
data=urllib.request.urlopen(url)

#将数据中第一行的属性读取出来放在names列表中,将其他行的数组读入row中,并将row中最后一列提取
#出来放在labels中作为标签,并使用pop将该列从row去去除掉,最后将剩下的属性值转化为float类型存入xList中
xlist=[]
labels=[]
names=[]
firstline=True
for line in data:
    if firstline:
        names=line.strip().split(b';')
        firstline=False
    else:
        row=line.strip().split(b';')
        labels.append(float(row[-1]))
        row.pop()
        floatrow=[float(num) for num in row]
        xlist.append(floatrow)

#计算几行几列
nrows=len(xlist)
ncols=len(xlist[1])
#print("rows:"+nrows)
#print("cols"+ncols)

#计算均值和方差
xmeans=[]
xsd=[]
for i in range(ncols):
    col=[xlist[j][i] for j in range(nrows)]
    mean=sum(col)/nrows
    xmeans.append(mean)
    coldiff=[(xlist[j][i]-mean) for j in range(nrows)]
    sumsq=sum([coldiff[j]*coldiff[j] for j in range(nrows)])
    stddev=sqrt(sumsq/nrows)
    xsd.append(stddev)

#数值减去平均数再除以标准差得到标准分数,反映了各数值的相对位置,也就是书中说的归一化
#对数值进行归一化
xnormalized=[]
for i in range(nrows):
    rownormalized=[(xlist[i][j]-xmeans[j])/xsd[j] for j in range(ncols)]
    xnormalized.append(rownormalized)

#对标签进行归一化
meanlabel=sum(labels)/nrows
sdlabel=sqrt(sum([(labels[i]-meanlabel)*(labels[i]-meanlabel) for i in range(nrows)])/nrows)
labelnormalized=[(labels[i]-meanlabel)/sdlabel for i in range(nrows)]

#初始化初始化向量系数β
beta=[0.0]*ncols
#初始化矩阵β的每一步
betamat=[]
betamat.append(list(beta))
#设置走多少步
nsteps=350
#设置每一步系数变化多少
stepsize=0.004

#计算每列与最终结果的关系系数β
for i in range(nsteps):
#计算残差
    residuals=[0.0]*nrows
    for j in range(nrows):
#labelshat=每行的各个标准差*相应β系数后的和(预测标准差)
        labelshat=sum([xnormalized[j][k]*beta[k] for k in range(ncols)])
#residuals是列表,记录每行的实际标准差与预测标准差的差值
        residuals[j]=labelnormalized[j]-labelshat


#通过标准分数和残差值计算列的相关属性
    corr=[0.0]*ncols

    for j in range(ncols):
#corr列表初始化为各列的数值*他所在行的差值后的和再除以行数=各列对残差值减小的贡献数值
#2个属性的关联值=两者归一化的乘积
        corr[j]=sum([xnormalized[k][j]*residuals[k] for k in range(nrows)])/nrows

#寻找刚刚计算的关联值中最大的那一列(正负)
    istar=0
    corrstar=corr[0]

    for j in range(1,(ncols)):
        if abs(corrstar)<abs(corr[j]):
            istar=j
            corrstar=corr[j]
#对残差值减小关联最大的这列β进行增大或减小(corrstar/abs(corrstar)控制正负)
    beta[istar]+=stepsize*corrstar/abs(corrstar)
    betamat.append(list(beta))

#显示共11条线,分表代表没个属性对结果影响的系数,随着步数增大各个系数趋近准确
for i in range(ncols):
    coefcurve=[betamat[k][i] for k in range(nsteps)]
    xaxis=range(nsteps)
    plot.plot(xaxis,coefcurve)

plot.xlabel("steps taken")
plot.ylabel(("coefficient values"))
plot.show()

运行结果如下
解决线性回归算法的过拟合问题-----LARS算法_第1张图片

你可能感兴趣的:(python,机器学习,机器学习,算法)