线性回归
那么对于给定的数据x1,即矩阵X的第一列数据,预测结果u1将会通过如下公式给出:
现在的问题是,手里有数据矩阵X和对应的标签向量y,怎么才能找到w呢?一个常用的方法就是找出使误差最小的w。这里的误差是指预测u值和真实y值之间的差值,使用该误差的简单累加将使得正差值和负差值相互抵消,所以我们采用平方误差。
平方误差和可以写做:
为啥能这么变化,记住一个前提:若x为向量,则默认x为列向量,x^T为行向量。将上述提到的数据矩阵X和标签向量y带进去,就知道为何这么变化了。
在继续推导之前,我们要先明确一个目的:找到w,使平方误差和最小。因为我们认为平方误差和越小,说明线性回归拟合效果越好。
现在,我们用矩阵表示的平方误差和对w进行求导:
得到w
局部加权线性回归
多了一个权重矩阵
随着样本点与待测点距离的增加,权重将以指数级衰减。
岭回归
岭回归即我们所说的L2正则线性回归,在一般的线性回归最小化均方误差的基础上增加了一个参数w的L2范数的罚项,从而最小化罚项残差平方和:
简单说来,岭回归就是在普通线性回归的基础上引入单位矩阵。回归系数的计算公式变形如下:
图中绘制了回归系数与log(λ)的关系。在最左边,即λ最小时,可以得到所有系数的原始值(与线性回归一致);而在右边,系数全部缩减成0;在中间部分的某个位置,将会得到最好的预测结果。想要得到最佳的λ参数,可以使用交叉验证的方式获得
Lasso:
对回归系数做出限定,使回归系数的和小于一个数,,这样当这个数足够小时,一些系数就被压缩到零了
向前逐步回归
一开始把所有的权重都设为一,然后进行迭代在对每一个权重移动一个很小的值。
缩减方法(逐步线性回归或岭回归),就是将一些系数缩减成很小的值或者直接缩减为0。这样做,就增大了模型的偏差(减少了一些特征的权重),通过把一些特征的回归系数缩减到0,同时也就减少了模型的复杂度。消除了多余的特征之后,模型更容易理解,同时也降低了预测误差。但是当缩减过于严厉的时候,就会出现过拟合的现象,即用训练集预测结果很好,用测试集预测就糟糕很多。
正则化的目的就是防止过拟合!
一般,正则化项就是一些L1范数和L2范数(因为L0范数用的少,所以不作讨论)。
L1范数——各参数的绝对值之和(稀疏规则算子)
L2范数——各参数的平方和的开方(权重衰减)
代码
from numpy import *
def loadDataSet(fileName):
numFeat=len (open(fileName).readline().split('/t'))-1
dataMat=[];labelMat=[]
fr=open(fileName)
for line in fr.redlines():
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 standRegres(xArr,yArr):
xMat=mat(xArr);yMat=mat(yArr).T
xTx=xMat.T*xMat
if linalg.det(xTx)==0.0:
print('this matrix is singular ,cannot do inverse')
return
ws=xTx.I*(xMat.T*yMat)
return ws
def lwlr(testPoint,xArr,yArr,k=1.0):
xMat=mat(xArr);yMat=mat(yArr).T
m=shape(xMat)[0]
weights=mat(eye((m)))
for j in range(m):
diffMat=testPoint-xMat[j,:]
weights[j,j]=exp(diffMat*diffMat.T/(-2.0*k**2))
xTx=xMat.T*(weights*xMat)
if linalg.det(xTx)==0.0:
print ('this matrx is singular ,cannot do inverse')
return
ws=xTx.I*(xMat.T*(weights*yMat))
return testPoint*ws
def lwlrTest(testArr,xArr,yArr,k=0.0):
m=shape(testArr)[0]
yHat=zeros(m)
for i in range(m):
yHat[i]=lwlr(testArr[i],xArr,yArr,k)
return yHat
def lwlrTestPlot(xArr,yArr,k=1.0):
yHat=zeros(shape(yArr))
xCopy=mat(xArr)
xCopy.sort(0)
for i in range(shape(xArr)[0]):
yHat[i]=lwlr(xCopy[i],xArr,yArr,k)
return yHat,xCopy
def rssError (yArr,yHatArr):
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,0)
yMat=yMat-yMean
xMeans=mean(xMat,0)
xVar=var(xMat,0)
xMat=(xMat-xMeans)/xVar
numTestPts=30
wMat=zeros((numTestPts,shape(xMat)[1]))
for i in range(numTestPts):
ws=ridgeRegres(xMat,yMat,exp(i-10))
wMat[i,:]=ws.T
return wMat
def regularize(xMat):
inMat=xMat.copy()
inMeans=mean(inMat,0)
inVar=var(inMat,0)
inMat=(inMat-inMeans)/inVar
return inMat
def stageWise(xArr,yArr,eps=0.01,numIt=100):
xMat=mat(xArr);yMat=mat(yArr).T
yMean=mean(yMat,0)
yMat=yMat-yMean
xMat=regularize(xMat)
m,n=shape(xMat)
returnMat=zeros((numIt,n))
ws=zeros((n,1));wsTest=ws.copy();wsMax=ws.copy()
for i in range(numIt):
print (ws.T)
lowestError=float(inf)
for j in range (n):
for sign in range [-1,1]:
wsTest=ws.copy()
wsTest[j]+=eps*sign
yTest=xMat*wsTest
rssE=rssError(yMat.A,yTest.A)
if rssE<lowestError:
lowestError=rssE
wsMax=wsTest
ws=wsMax.copy()
returnMat[i,:]=ws.T
return returnMat