1. 线性回归
根据已有的数据点拟合出回归系数。
1)普通最小二乘法(OLS)
找出使误差最小的w(使用平方误差),即最小化:

求一阶导,得其解为:

python代码为:
def loadDataSet(filename):
numFeat = len(open(filename).readline().split('\t')) - 1
#numFeat的值是2,因为文件一行有三个特征
dataMat = []
labelMat = []
fr = open(filename)
for line in fr.readlines():
lineArr = []
curLine = line.strip().split('\t')
#一个有三个元素的list
for i in range(numFeat):#(0,2)
lineArr.append(float(curLine[i]))
#提取前两个元素,最后一元素为标签
dataMat.append(lineArr)
#dataMat为一个list,每个元素是数据集前两项的list
labelMat.append(float(curLine[-1]))
#-1代表最后一行
return dataMat, labelMat
def standRegres(xArr, yArr):
xMat = mat(xArr)
#mat()使每个元素单独成行,向量形式
yMat = mat(yArr).T
xTx = xMat.T*xMat
#x转置乘x
if linalg.det(xTx) == 0.0:
print("this matrix is singular, cannot do inverse")
return
ws =xTx.I * (xMat.T*yMat)
#回归系数
return ws
尝试绘制图表
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], s=2, c='red')
#[a:b, n]代表从a开始到b行,输出list的第n-1列
#flatten() 将矩阵的每一个元素提取出来成为list的单独元素
ax.plot(xSort[:, 1], yHat[srtInd])
plt.show()
数据松散与否都有可能拟合出相同的曲线,所以要引进计算相关系数的办法,相关系数越大匹配越完美。
2. 局部加权线性回归
目的:解决线性回归欠拟合的问题
解的形式:

而使用的核为高斯核,其权重为:

而我们只需要确定一个合理的k值即可。
局部加权线性回归函数的代码如下:
def lwlr(testPoint, xArr, yArr, k=1.0):
xMat = mat(xArr)
yMat = mat(yArr).T
m = shape(xMat)[0]
#shape得出来是一个元祖:(行数, 列数)
#这里m取了行数
weights = mat(eye((m)))
#生成一个m行m列对角线为1的对角矩阵
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
若k值过小会产生过拟合现象。
3. 缩减系数方法
目的:防止特征多于样本点数,出现矩阵不满秩的情况,这会在求逆时出现问题。解决方法:
1) 岭回归
加入一些东西让矩阵非奇异

实现代码如下:
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 cannot 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
xMean = mean(xMat, 0)
xVar = var(xMat, 0)
xMat = (xMat - xMean)/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
λ越小,越接近普通回归;越大,则回归系数缩减为0.
2) lasso
普通最小二乘法回归加入如下约束

因为计算太复杂了所以选用一个简单的方法:前向逐步回归,从1开始,每一步对某个权重增加或者减少一个很小的值
伪代码如下:
数据标准化,使其分布满足0均值和单位方差
在每轮迭代过程中:
设置当前最小误差lowestError为正无穷
对每个特征:
增大或缩小:
改变一个系数得到一个新的时
计算新时下的误差
如果误差Error小于当前最小误差lowestError:设置Wbest等于当前的W
将W设置为新的Wbest
其代码如下:
def stageWise(xArr, yArr, eps=0.01, numIt=100):
xMat = mat(xArr)
yMat = mat(yArr).T
yMean = mean(yMat, 0)
#压缩行,对各列求值。如果是1则反过来
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
注:今天遇到的error
IndexError:list out of range
第一,可能是访问越界
第二,可能是list本身为空,访问list[0]的时候会发生错误
网友评论