机器学习实战线性回归局部加权线性回归笔记
2015-10-18 08:49
656 查看
线性回归
用线性回归找到最佳拟合直线
回归的目的是预测数值型数据,根据输入写出一个目标值的计算公式,这个公式就是回归方程(regression equation),变量前的系数(比如一元一次方程)称为回归系数(regression weights)。求这些回归系数的过程就是回归。
假设输入数据存放在矩阵X 中,回归系数存放在向量w 中,那么对于数据X 1 的预测结果可以用Y 1 =X T 1 w 得出。我们需要找到使误差最小的w ,但是如果使用误差之间的累加的话,那么正负误差将会抵消,起不到效果,所以采用平方误差。如下:∑ i=1 n (y i −x T i w) 2 用矩阵表示:(Y−Xw) T (Y−Xw) 。对W 求导得到X T (Y−Xw) ,令其等于零得到w 的最佳估计:w ^ =(X T X) −1 X T y 首先我们导入数据,代码如下:
这部分数据是由tap分隔,并且最后一个值是目标值。接下来计算回归系数:
该函数首先读入x 和y 数组,然后将它们转换成矩阵,之后根据公式计算平方误差,注意,需要对X T X 求逆,此时需要判断它的行列式是否为0,行列式等于0的矩阵无法求逆,可以直接使用
我们先看看前两条数据:
第一个值总是等于1.0,也就是x 0 ,假定偏移量是一个常数,第二个值是x 1 。
现在看看计算回归系数函数效果:
现在得到了回归系数,那么我们可以通过回归方程进行预测yHat:
为方便观察,我们画出数据集散点图:
现在绘制最佳拟合直线,那么需要画出预测值yHat,如果直线上数据点次序混乱,绘图时将会出现问题,所以要将点按照升序排序:
我们来看看效果:
最佳拟合直线方法将数据视为直线进行建模,但图中的数据集似乎还有更好的拟合方式。
局部加权线性回归
线性回归可能出现欠拟合的现象,如上图所示,因为它求的是具有最小均方误差的无偏差估计。所以有些方法允许在估计中引入一些偏差,从而降低预测的均方误差。其中一个方法就是使用局部加权线性回归(Locally Weighted Linear Regression,LWLR),我们给待测点附近的每个点赋予一定的权重,是用此方法解出的回归系数如下:w ^ =(X T WX) −1 X T Wy 其中W 是一个矩阵,用来给每个数据点赋予权重。
LWLR使用“核”来对附近的点赋予更高的权重,核的类型可以自由选择,最常用的核就是高斯核,高斯核对应的权重如下:w(i,i)=exp(|x i −x|−2k 2 ) 下面来编写局部加权线性回归:
lwlr()函数得到的是单点的估计,为得到所有点的估计,可以调用lwlrTest()函数。
下面绘出估计值和原始值,看看yHat的拟合效果。需要将数据点按序排列。
然后使用Matplotlib绘图:
当k=1.0时,权重很大,相当于将所有数据视为等权重,得出的最佳拟合直线与标准线性回归一致:
当使用k=0.01时:
结果如下:
当使用k=0.003时:
结果如下:
由上三种结果可以看出,在k=1.0时,得出的拟合曲线欠拟合,k=0.01时,曲线拟合效果不错,而k=0.003时,又有些过拟合。
用线性回归找到最佳拟合直线
回归的目的是预测数值型数据,根据输入写出一个目标值的计算公式,这个公式就是回归方程(regression equation),变量前的系数(比如一元一次方程)称为回归系数(regression weights)。求这些回归系数的过程就是回归。
假设输入数据存放在矩阵X 中,回归系数存放在向量w 中,那么对于数据X 1 的预测结果可以用Y 1 =X T 1 w 得出。我们需要找到使误差最小的w ,但是如果使用误差之间的累加的话,那么正负误差将会抵消,起不到效果,所以采用平方误差。如下:∑ i=1 n (y i −x T i w) 2 用矩阵表示:(Y−Xw) T (Y−Xw) 。对W 求导得到X T (Y−Xw) ,令其等于零得到w 的最佳估计:w ^ =(X T X) −1 X T y 首先我们导入数据,代码如下:
from numpy import * def loadDataSet(fileName): numFeat = len(open(fileName).readline().split('\t'))-1 dataMat = []; labelMat = [] fr = open(fileName) 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
这部分数据是由tap分隔,并且最后一个值是目标值。接下来计算回归系数:
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
该函数首先读入x 和y 数组,然后将它们转换成矩阵,之后根据公式计算平方误差,注意,需要对X T X 求逆,此时需要判断它的行列式是否为0,行列式等于0的矩阵无法求逆,可以直接使用
linalg.det()来计算行列式。好了,我们来看看效果,首先读入数据:
xArr,yArr=loadDataSet('ex0.txt')
我们先看看前两条数据:
print xArr[0:2] [[1.0, 0.067732], [1.0, 0.42781]]
第一个值总是等于1.0,也就是x 0 ,假定偏移量是一个常数,第二个值是x 1 。
现在看看计算回归系数函数效果:
ws = standRegres(xArr,yArr) print ws [[ 3.00774324] [ 1.69532264]]
现在得到了回归系数,那么我们可以通过回归方程进行预测yHat:
xMat = mat(xArr) yMat = mat(yArr) yHat = xMat*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])
现在绘制最佳拟合直线,那么需要画出预测值yHat,如果直线上数据点次序混乱,绘图时将会出现问题,所以要将点按照升序排序:
xCopy = xMat.copy() xCopy.sort(0) yHat=xCopy*ws ax.plot(xCopy[:,1], yHat) plt.show()
我们来看看效果:
最佳拟合直线方法将数据视为直线进行建模,但图中的数据集似乎还有更好的拟合方式。
局部加权线性回归
线性回归可能出现欠拟合的现象,如上图所示,因为它求的是具有最小均方误差的无偏差估计。所以有些方法允许在估计中引入一些偏差,从而降低预测的均方误差。其中一个方法就是使用局部加权线性回归(Locally Weighted Linear Regression,LWLR),我们给待测点附近的每个点赋予一定的权重,是用此方法解出的回归系数如下:w ^ =(X T WX) −1 X T Wy 其中W 是一个矩阵,用来给每个数据点赋予权重。
LWLR使用“核”来对附近的点赋予更高的权重,核的类型可以自由选择,最常用的核就是高斯核,高斯核对应的权重如下:w(i,i)=exp(|x i −x|−2k 2 ) 下面来编写局部加权线性回归:
def lwlr(testPoint, xArr, yArr, k = 1.0): xMat = mat(xArr); yMat = mat(yArr).T m = shape(xMat)[0] # eye()返回一个对角线元素为1,其他元素为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 "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
lwlr()函数得到的是单点的估计,为得到所有点的估计,可以调用lwlrTest()函数。
yHat = lwlrTest(xArr,xArr,yArr,1.0)
下面绘出估计值和原始值,看看yHat的拟合效果。需要将数据点按序排列。
xMat = mat(xArr) srtInd = xMat[:,1].argsort(0) xSort = xMat[srtInd][:,0,:]
然后使用Matplotlib绘图:
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()
当k=1.0时,权重很大,相当于将所有数据视为等权重,得出的最佳拟合直线与标准线性回归一致:
当使用k=0.01时:
yHat = lwlrTest(xArr,xArr,yArr,0.01)
结果如下:
当使用k=0.003时:
yHat = lwlrTest(xArr,xArr,yArr,0.003)
结果如下:
由上三种结果可以看出,在k=1.0时,得出的拟合曲线欠拟合,k=0.01时,曲线拟合效果不错,而k=0.003时,又有些过拟合。