1.线性回归
1.1 优缺点
- 结果易于理解,计算不复杂
- 对非线性数据拟合效果不好,线性回归将数据视为线性的,可能会出现欠拟合现象,导致不能取得最好的预测效果.
1.2 回归的一般流程
(1) 收集数据
(2) 准备数据:回归需要数值型数据,标称型数据应该转换为二值型数据
(3) 分析数据: 给出数据的可视化二维图有助于对数据作出理解和分析,在采用缩减法得到新回归系数后,可以将新拟合线绘在图上作为对比.
(4) 训练算法: 找到回归系数
(5) 测试算法: 使用R的平方或者预测值和数据的拟合度来分析模型的效果
(6) 使用算法: 使用回归,可以在给定输入的时候预测出一个数值,这是对分类算法的提升,因为这样可以预测连续型数据而不仅仅是离散的类别标签.
1.3 标准线性回归
(1)误差函数为: 预测y值和真实y值之间的差值,该误差的平方和的累加
通过最小二乘法来求解回归系数w的计算公式如下:
此种求解方法只在XTX可逆的情况下有解.
(2) 实现函数如下:
<span style="font-size:18px;">#实现标准回归函数
def standardRegres(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
theta = xTx.I * (xMat.T * yMat)
return theta</span>
(3) 两个序列的相关系数,可以用来计算两个序列的匹配程度.即coefficient.2. 局部加权线性回归(locally weighted linear regression)
2.1 算法思想
给每个待预测点周围的点赋予一定的权重,越近的点权重越高,以此来选出该预测点对应的数据子集,然后在此数据子集上基于最小均方差进行普通的回归.
局部加权线性回归采用"核"对附近的点赋予权重,此处采用高斯核,其中参数k需要用户指定,其决定了对附近的点赋予多大的权重.W是对角矩阵.xi与x越近,w(i,i)越大.
2.2 实现代码
<span style="font-size:18px;">#局部加权线性回归
def lwlr(testPoint,xArr,yArr,k=1.0):
xMat = mat(xArr) ; yMat = mat(yArr).T
m = shape(xMat)[0]
weights = mat(eye((m)))
for i in range(m):
diffMat = testPoint - xMat[i,:]
weights[i,i] = exp(diffMat * diffMat.T/(-2.0*k**2))
xTx = xMat.T * (weights * xMat)
if linalg.det(xTx) == 0.0:
print "this matrix is singular "
return
theta = xTx.I * (xMat.T * (weights * yMat))
return testPoint * theta
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</span>
当k越大时,越多的数据参与到线性回归中,效果和标准线性回归类似;当k越小时,越少的数据参与到线性回归中,容易产生过拟合.因此合适的k非常重要. 下图的k逐渐增大:
2.3 优缺点
缺点: 增加了计算量, 因为其对每个点做预测时都必须使用整个数据集.在计算的过程中,发现大多数数据点的权重都接近0,如果避免这些计算将可以大大减少程序运行时间.
3. 岭回归(ridge regression)
3.1 定义
岭回归是一种缩减方法;
就是在矩阵XTX上加了一项从而使得矩阵非奇异,lamda由用户自己定义.
此时回归系数计算公式为:
3.2 训练过程
lamda用于限制所有w之和,通过引入该惩罚项,能够减少不重要的参数,因此能更好的理解数据.
确定lamda的过程:
数据获取之后,分为训练集和测试集,选取不同的lamda来重复上述过程,最后选择使得预测误差最小的lamda.
下图是回归系数与log(lamda)之间的关系,当lamda最小时,得到的结果和线性回归一样,在最右边,回归系数全部减为0,即最好的结果应该处于中间.
除此之外,为了判断哪些变量对结果更具影响力,观察其对应系数大小即可.
实现代码如下:
<span style="font-size:18px;">#岭回归
def ridgeRegres(xMat,yMat,lam=0.2):
xTx = xMat.T*xMat
m = shape(xMat)[1]
denom = xTx + eye(m)*lam
if linalg.det(denom) == 0.0:
print "this matrix is singular"
return
theta = denom.I * (xMat.T*yMat)
return theta
def ridgeTest(xArr,yArr):
xMat = mat(xArr); yMat = mat(yArr)
ymean = mean(yMat,0)
yMat = yMat - ymean
xmean = mean(xMat,0)
xvar = var(xMat,0)
xMat = (xMat - xmean)/xvar
testtimes = 30
wMat = zeros((testtimes,shape(xMat)[1]))
for i in range(testtimes):
theta = ridgeRegres(xMat,yMat,exp(i-10))
wMat[i,:] = theta.T
return wMat</span>
3.3 数据预处理
处理过程: 将所有特征减去各自的均值并除以其方差.测试时,也要将测试数据标准化处理,应该使用训练时的参数来对测试数据标准化.
3.4 tips
增加如下约束时,普通的最小二乘法回归会得到和岭回归一样的公式:
这个式子限制了所有回归系数的平方和不能大于lamda.
另外一种缩减方法lasso,其对应的回归系数约束条件为所有回归系数的绝对值之和不能大于lamda.
4. 前向逐步回归
4.1 前向逐步回归定义
一种贪心算法,每一步都尽可能减少误差.一开始, 所有的权重都设为1, 然后每一步所做的决策是对某个权重增加或减少一个很小的值,
4.2 算法过程
算法伪代码对应如下:
数据标准化,是其分布满足0均值和单位方差
在每轮迭代中:
设置当前最小误差为正无穷
对每个特征对应的系数:
增大或减小:
改变一个系数得到一个新的w
计算新w下的误差,若小于u当前最小误差,更新最小误差
更新w
真实代码如下:
<span style="font-size:18px;">def regularize(xMat):#regularize by columns
inMat = xMat.copy()
inMeans = mean(inMat,0) #calc mean then subtract it off
inVar = var(inMat,0) #calc variance of Xi then divide by it
inMat = (inMat - inMeans)/inVar
return inMat
#分别计算对每个w增加或减少特定的值后,读整体误差的影响
def stageWise(xArr,yArr,eps=0.01,numIt=100):
xMat = mat(xArr); yMat=mat(yArr).T
yMean = mean(yMat,0)
yMat = yMat - yMean #can also regularize ys but will get smaller coef
xMat = regularize(xMat)
m,n=shape(xMat)
#returnMat = zeros((numIt,n)) #testing code remove
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 #eps表示每次迭代需要调整的步长
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
</span>
4.3 算法评价
其主要优点在于可以帮助人们理解现有的模型并作出改进. 当构建了一个模型后, 可以运行该算法找出重要的特征, 可以及时的停止对不重要特征的收集.
5. 偏差与方差
误差: 模型与真实值之间存在差异,就存在误差
方差指的是模型之间的差异,偏差指的是模型预测值和数据之间的差异.