回归分析
普通线性回归
原理
回归的目的是预测数值型的目标值,方程
y=wx+b
为回归方程,
w
为回归系数,求回归系数的过程就是回归。一旦有了这些系数,再给定输入,做预测就非常容易了。一般的回归都是线性回归,常用方法为最小二乘法:平方误差最小
用矩阵表示为 (y−xw)T(y−xw) 。如果对 w 求导,得到:
示例代码
# 标准线性回归
def standRegres(xArr, yArr):
xMat = mat(xArr); yMat = mat(yArr).T
xTx = xMat.T*xMat
if linalg.det(xTx) == 0.0:
print('This matrix is singular, cannot do inverse')
return
ws = xTx.I * (xMat.T*yMat)
return ws
标准线性最小二乘回归,在线性关系上表现较好,缺乏反映复杂映射的能力,出现欠拟合的现象
局部加权线性回归
线性回归的一个问题是有可能出现欠拟合现象,因为它求的是具有最小均方误差的无偏估计。一般情况可以在估计中引入一些偏差,从而降低预测的均方误差。其中一个方法是局部加权线性回归(LWLR
)。给待预测点附近的每个点赋予一定的权重。回归系数
w
的表示形式如下:
其中 w 为权矩阵。LWLR使用“核”(类似于SVM核函数)来对附近的点赋予更高的权重,核的类型可以自由选择,最常用的核是高斯核
公式中需要包含一个用户指定的参数k,它巨鼎了对附近的点赋予多大的权重。
示例代码
from numpy import *
def lwlr(testPoint, xArr, yArr, k = 1.0):
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
从图中可知k = 0.01效果最好,在实际情况中需要具体分析
岭回归
在数据的特征比样本点还多时,前面的回归方法会出现
XTX
为非满秩矩阵,不能对矩阵求逆。为了解决这种问题,引入岭回归的概念。岭回归就是在矩阵
XTX
上加一个
λI
从而使得矩阵非奇异,进而能对
XTX+λI
求逆,
I
为一个
ŵ =(XTX+λI)XTy
岭回归最先用来处理特征多余样本数的情况,现在也用于在估计中加入偏差,从而得到的较好的估计。通过引入 λ 来限制所有 w 之和,通过引入该惩罚项,能过减少不重要的参数。“岭”:岭回归使用了单位矩阵乘以常量
*示例程序*
from numpy import *
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
lasso
在增加如下约束时,普通的最小二乘回归会得到与岭回归一样的公式:
式中限定了多有回归系数的平方和不能大于 λ 。使用普通的最小二乘回归在当两个或更多的特征相关时会得出一个很大的系数和一个很大负系数。使用岭回归可以避免这个问题
和岭回归类似,另一个特征缩减方法lasso也对回归系数做了限定,对应的约束条件如下:
∑k=1n∣∣wk∣∣⩽λ
前向逐步回归
前向逐步回归算法可以得到与lasso差不多的效果,但更加简单。属于一种贪心算法,每一步都尽可能减少误差。一开始所有的权值都设置为1,然后每一步做的决策书对某个权重增加或较少一个很小的值
伪代码
数据标准化,使其满足N(0,1)分布
在每轮迭代过程中:
设置当前最小误差errorMin为正无穷
对每个特征
增大或缩小:
改变一个系数得到一个新的w
计算新w下的误差
如果误差小于当前最小误差,最小误差errorMin更新
w设置为新的最优w
示例代码
def regularize(xMat):
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