岭回归

1、 解决问题

2、 原理

3、 算法

4、 实现代码

5、 交叉验证

  • 1、 当数据的特征比样本点还要多怎么办?即:n>m。也就是说输入数据的矩阵不是满秩矩阵,非满秩矩阵求逆就会出现问题。——这是《机器学习实战》上的问题
    除此之外,在其他大佬的博客和研究生论文到看到岭回归是主要解决复共线问题。
    秩:将矩阵进行行列变换成梯形矩阵,不为0的行(列)的行(列)数称为矩阵的秩
  • 2、 简单来说岭回归就是在矩阵XTX上加一个λI从而使得矩阵奇异,进而能对XTX+λI求逆,其实I是一个n*n的单位矩阵,对角线全为1,其他元素全为0,而λ是一个用定义的数值,那么回归系数就变成了:w^=(XTX+λI)−1XTy
    岭回归是对最小二乘回归的一种补充,它损失了无偏性,来换取高的数值稳定性,从而得到较高的计算精度。
    岭回归最先用来处理特征数对于样本数的情况,现在也用于在估计中加入偏差,从而得到更好的估计,这里通过引入λ来限制所有w之和,通过引入该惩罚项,能够减少不重要的参数,这个技术在统计学中也叫缩减。
  • 3、(1)将特征值处理,数据标准化
    (2)规定一组λ值
    (3)循环求出w在不同情况下的数据建立矩阵
    (4)交叉验证找出最佳的λ值
  • 4、代码
# coding=utf-8 

from numpy import *
import numpy as np
import pylab as pl
#处理数据
def loadDataSet(fileName):
numFeat = len(open(fileName).readline().split('\t')) - 1
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 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 show(ws):
pl.plot(ws)
pl.show()

def main():
xArr,yArr = loadDataSet(r"C:\Users\l\Desktop\abalone.txt")
ws = ridgeTest(xArr,yArr)
#print ws
show(ws)

if __name__ == '__main__':
main();

岭回归_数据

  • 5、交叉验证求最佳系数
def rssError(yArr,yHatArr):
return ((yArr-yHatArr)**2).sum()

def crossValidation(xArr, yArr, numFold = 10):
m = len(yArr)
indexList = range(m)
errorMat = zeros((numFold, 30))# 每一行都有30个λ得到的结果
for i in range(numFold):
trainX = []; trainY = []
testX = []; testY = []
random.shuffle(indexList)# 把indexList打乱获得随机的选择效果
for j in range(m):# 划分测试集和训练集
if j < 0.9*m:
trainX.append(xArr[indexList[j]])
trainY.append(yArr[indexList[j]])
else:
testX.append(xArr[indexList[j]])
testY.append(yArr[indexList[j]])
# 30组系数,返回维度为30*8的数组
wMat = ridgeTest(trainX, trainY)

# 对每一组系数求误差
# 训练数据做了怎么的处理,新的查询数据就要做怎样的处理才能带入模型
for k in range(30):
matTestX = mat(testX)
matTrainX = mat(trainX)
meanTrainX = mean(trainX, 0)
varTrainX = var(matTrainX, 0)
meanTrainY = mean(trainY, 0)
matTestX = (matTestX - meanTrainX)/varTrainX
yEst = matTestX * mat(wMat[k, :]).T + mean(trainY)
errorMat[i, k] = rssError(yEst.T.A, array(testY))
print errorMat
meanErrors = mean(errorMat, 0) # 每个λ对应的平均误差
minErrors = float(min(meanErrors))
# 找到最优的λ之后,选取最后一轮迭代的wMat的对应的λ的权重作为最佳权重
bestWeights = wMat[nonzero(meanErrors == minErrors)]
xMat = mat(xArr)
yMat = mat(yArr)
meanX = mean(xMat, 0)
varX = var(xMat, 0)
# 为了和标准线性回归比较需要对数据进行还原
print varX
unReg = bestWeights/varX
print unReg
print -1*sum(multiply(meanX,unReg)) + mean(yMat)