如果特征比样本点多,那么对于用矩阵求解的方式就不可行,因为矩阵不可逆,这时候可以通过岭回归的方法,在矩阵XTX上加一个λr,使得矩阵可逆,那么回归系数w = (xTx+λI)-1xTy,I是单位矩阵,lam是自己定义的一个系数,同时岭回归还可以用在估计中加入偏差,从而限制w的和,通过加入这个参数,可以减少不重要的参数。
这是不同的几个回归系数,横坐标是ln(lam)的值,纵坐标是回归系数,通过引进不同的lam,得到的回归系数不同,而随着lam的增大,w将衰减为0
另一种方法是lasso,限制条件是w的绝对值求和<=lam,在lam足够小的时候,一些系数会缩减到0,这里是用前向回归算法,它是通过谈心的思想,每一次迭代,尽可能减少误差。在每一次迭代中,对每一个系数,增大或缩小,然后重新计算新w的误差,如果误差小于当前最小误差,更新w
算法伪代码:
数据标准化,满足0均值和单位方差
在每轮的迭代过程中:
设置当前最小误差lowestError为正无穷
对每个特征:
增大或缩小:
改变一个系数得到一个新的W
计算新W下的误差
如果误差Error小于当前最小误差lowestError:设置Wbest等于当前W
将W设置为新的Wbest
如果用于测试,该算法每迭代100次就可以构建一个模型,可以通过类似10折交叉验证的方法比较这些模型,选择误差比较小的
这两种方法都是增加了偏差,减小了模型的方差。
from numpy import *
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 ridgeRegress(xMat,yMat,lam=0.2):
xTx = xMat.T * xMat
demon = xTx + eye(shape(xMat)[1]) * lam
if linalg.det(demon) == 0.0:
print("error")
return
ws = demon.I * (xMat.T * yMat)
return ws
#岭回归
def ridgeTest(xArr,yArr):
xMat = matrix(xArr)
yMat = mat(yArr).T
yMean = mean(yMat,0)
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 = ridgeRegress(xMat,yMat,exp(i-10))
wMat[i,:] = ws.T
return wMat
def rssError(yArr,yHatArr):
return ((yArr-yHatArr)**2).sum()
def regularize(xMat):#regularize by columns
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 = inf;
for j in range(n):
for sign in [-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
abx,aby = loadDataSet('abalone.txt')
a = stageWise(abx,aby,0.005,1000)
rw = ridgeTest(abx,aby)
# print(shape(rw))
import matplotlib.pyplot as plt
fig = plt.figure(1)
ax = fig.add_subplot(111)
ax.plot(a)
fig = plt.figure(2)
ax = fig.add_subplot(111)
ax.plot(rw)
plt.show()