本章介绍了不同场景下使用的线性回归方法
一般情况:简单的线性回归
欠拟合:局部加权线性回归
特征数大于样本数:岭回归 或 lasso法
最后引出交叉验证,用来定量地找到最佳参数值
# _*_ coding:utf-8_*_ # 8-1 标准回归函数和数据导入函数
from numpy import *
# 将数据格式化
def loadDataSet(fileName):
numFeat = len(open(fileName).readlines()[0].split('\t')) - 1
dataMat = []
labelMat = []
fr = open(fileName)
for line in fr.readlines():
lineArr = []
curLine = line.strip().split('\t')
for i in range(numFeat): # float()不能将整个list中的元素进行类型转换,所以用一个循环,一个元素一个元素地转换
lineArr.append(float(curLine[i]))
dataMat.append(lineArr)
labelMat.append(float(curLine[-1]))
return dataMat, labelMat # 计算系数向量w的最佳估计,其中要求xTx的逆,所以先要判断它是否为满秩矩阵(行列式不为0),
# 若否,则不能进一步计算。这里并没有提供伪逆矩阵的做法
def standRegres(xArr, yArr): # 矩阵相乘要把结构改成matrix,否则array的*只能对元素进项相乘
xMat = mat(xArr)
yMat = mat(yArr).T
xTx = xMat.T * xMat
if linalg.det(xTx) == 0.0: # numpy提供了一个线性代数库linalg(linear algebra),
# 其中包含计算行列式(determinant)的方法det(),
# 为什么可以用==比较浮点数?????????????
print "This matrix is singular, cannot do inverse"
return
ws = xTx.I * (xMat.T * yMat)
return ws # 效果 xArr,yArr = loadDataSet('ex0.txt')
print xArr[0:2] ws = standRegres(xArr,yArr) xMat=mat(xArr)
yMat=mat(yArr)
yHat=xMat*ws #y的预测值 import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(xMat[:,1].flatten().A[0],yMat.T[:,0].flatten().A[0],10) # flatten()方法能将matrix的元素变成一维的,
# .A能使matrix变成array .A[0]能少一个[] 虽然我不明白到底什么意思,以后注意一下
# 另外,为什么前两个参数需要转变成array?明明matrix也能画出来
print (corrcoef(yHat.T, yMat)) xCopy = xMat.copy()
xCopy.sort(0)
yHat = xCopy *ws
ax.plot(xCopy[:,1],yHat,'red') plt.show() # 8-2 局部加权线性回归函数
def lwlr(testPoint, xArr, yArr, k=1.0): # 参数k控制衰减速度; testPoint为输入,函数返回根据加权线性回归得出的预测值
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 matrix is singular, cannot do inverse"
return
ws = xTx.I*(xMat.T*(weights*yMat))
return testPoint * ws def lwlrTest(testArr, xArr, yArr, k=1.0):
m = shape(testArr)[0]
yHat = zeros(m)
for i in range(m):
yHat[i] = lwlr(testArr[i], xArr, yArr, k)
return yHat xArr,yArr = loadDataSet('ex0.txt')
yHat = lwlrTest(xArr, xArr, yArr, 0.01)
xMat = mat(xArr)
srtInd = xMat[:,1].argsort(0) # argsort()方法返回的是排序后个元素排序前的下标
xSort = xMat[srtInd][:,0,:] # 这个功能看懂了 但是语法没搞懂??????? import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(xSort[:,1], yHat[srtInd])
ax.scatter(xMat[:,1].flatten().A[0], mat(yArr).T.flatten().A[0], s=2, c='red')
plt.show() # 8-3 岭回归(xTx肯定不是满秩矩阵,加上一个lam*I使其变为满秩的,I是单位矩阵) def ridgeRegres(xMat, yMat, lam=0.2):
xTx = xMat.T * xMat
denom = xTx+lam*eye(len(xTx[0]))
if linalg.det(denom) == 0.0:
print "this matrix is not 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 # 在30个不同的lambda下调用ridgeRegres()函数
wMat = zeros((numTestPts, shape(xMat)[1]))
for i in range(numTestPts):
ws = ridgeRegres(xMat, yMat, exp(i-10)) # lambda以指数级变化,这样能看出lambda在去非常小的值时和取非常大的值时对结果造成的影响
wMat[i,:]=ws.T
return wMat # 8-4 前向逐步线性回归 # 标准化特征(书上漏了这部分)
def regularize(xMat):
inMat = xMat.copy()
inMeans = mean(inMat,0)
inVar = var(inMat,0)
inMat = (inMat - inMeans)/inVar
return inMat def rssError(yArr, yHatArr):
return ((yArr-yHatArr)**2).sum() # 对每个特征,将他的系数从一个初始值开始以特定步长增大或减少,一旦误差变小就用lowestError来记录最小误差,用wsMax来记录最优权重。
def stageWise(xArr, yArr, eps=0.01, numIt=100): # eps表示每次迭代需要调整的步长
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