回归
回归
线性回归
回归系数求解方法:常用最小二乘法
缺点:由于采用具有最小均方误差的无偏估计,可能出现欠拟合现象
解决办法: 局部加权线性回归
局部加权线性回归(Locally Weighted Linear Regression, LWLR)
思想:给待测点附近每一个点赋予一定的权重,在这个子集上基于最小均方差进行普通回归
与KNN一样这种算法每次预测都需要事先选取对应数据子集
LWLR: 使用了“核”(与支持向量机中的核类似)来对附近的点赋予更高的权重。核的类型可以
自由选择,最常用的核是高斯核:
\[高斯核公式
\]
缺点:增加了计算量,由于对每个点最预测时,都必须使用数据集。
解决方式:缩减技术
缩减技术
缩减系数来“理解”数据
特征比样点多,即不是矩阵不是满秩矩阵,则求解矩阵的秩时会出问题
则无法使用线性回归和之前的方法来做预测,解决方法如下:
1 岭回归
使用场景:特征数多于样本数情况
普通回归方法可能产生错误,岭回归仍然可以正常工作,但同时也需要对数据进行检查
所以,使用岭回归和缩减技术,首先需要对特征做标准化处理
2 lasso
普通的最小二乘法会得到与岭回归一样的公式
所有回归系数平方和不能大于lambda,lasso也类似对回归系数有限定,回归系数的绝对值之和不大于lambda
缺点:计算复杂,因为需要求出回归系数,要使用二次规划算法
3 前向逐步回归
优点:可以得到与lasso差不多效果,但更加简单,属于贪心算法
每一步尽可能减少误差
缺点:使用缩减技术时,模型增加了偏差,此时也减小了模型的方差,处理方法如下
权衡偏差和方差
树回归
代码实践
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
"""
回归
"""
from numpy import *
def loadDataSet(fileName):
fr = open(fileName)
numFeat = len(fr.readline().split('\t')) - 1
dataMat = []
labelMat = []
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 standRegres(xArr, yArr):
xMat = mat(xArr)
yMat = mat(yArr).T
xTx = xMat.T * xMat
if linalg.det(xTx) == 0:
print(f'This matrix is singular, cannot do inverse')
return
ws = xTx.I * (xMat.T * yMat)
return ws
def lwlr(testPoint, xArr, yArr, k=1.0):
"""
局部加权线性回归
:param testPoint:
:param xArr:
:param yArr:
:param k:
:return:
"""
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:
print(f'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):
"""
局部加权回归测试
:param testArr:
:param xArr:
:param yArr:
:param k:
:return:
"""
m = shape(testArr)[0]
yHat = zeros(m)
for i in range(m):
yHat[i] = lwlr(testArr[i], xArr, yArr, k)
return yHat
def ridgeRegres(xMat, yMat, lam=0.2):
"""
岭回归,计算回归系数
:param xMat:
:param yMat:
:param lam:
:return:
"""
xTx = xMat.T * xMat
denom = xTx + eye(shape(xMat)[1]) * lam
if linalg.det(denom) == 0:
print(f'This matrix is singular, cannot do inverse')
return
ws = denom.I * (xMat.T * yMat)
return ws
def ridgeTest(xArr, yArr):
"""
岭回归测试, 用于一组lambda下岭回归求解
:param xArr:
:param yArr:
:return:
"""
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 stageWise(xArr, yArr, eps=0.01, numIt=100):
"""
逐步向前
:param xArr:
:param yArr:
:param eps:
:param numIt:
:return:
"""
xMat = mat(xArr)
yMat = mat(yArr).T
yMean = mean(yMat, 0)
yMat = yMat - yMean
# 数据标准化
# xMat = regularize(xMat)
xMeans = mean(xMat, 0)
xVar = var(xMat, 0)
xMat = (xMat - xMeans) / xVar
m, n = shape(xMat)
returnMat = zeros((numIt, n))
ws = zeros((n , 1))
wsTest = ws.copy()
wsMax = ws.copy()
for i in range(numIt):
print(f'{ws.T}')
lowerError = inf
for j in range(n):
wsTest = ws.copy()
wsTest[j] += eps * sign
yTest = xMat * wsTest
rssE = rssError(yMat.A, yTest.A)
if rssE < lowerError:
lowerError = rssE
wsMax = wsTest
ws = wsMax.copy()
returnMat[i, :] = ws.T
return returnMat