[机器学习]线性回归和局部加权线性回归

首先先了解清楚线性回归的概念,需要掌握一些高等数学,概率论和线性代数的知识作为基础。我从不同的书籍资料中看到各种证明方法,有些易懂但不易想到,总之我们最后要得出的结论


这是多元线性回归得到y= β1x1 + β2x2 + … + βkxk这条最佳拟合直线参数的方法。

先来看一下数据:

图片图片

我们假定了x0=1,最终会得到y=ws[0]+ws[1]*x1,ws就是对应于上面所说的β。这里只是使用了一元线性回归作为一个基本的例子,程序可以应用与多元,只是我们希望可以用数据可视化工具matplotlib呈现出来,而多维数据难以呈现。

直接上源码:

from numpy import *
import matplotlib.pyplot as plt
def figure(xArr,yArr,ws ):#数据可视化
    xMat = mat(xArr)
    yMat = mat(yArr)
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xMat[:,1].flatten().A[0],yMat.T[:,0].flatten().A[0])
    xCopy = xMat.copy()
    xCopy.sort(0)
    yHat = xCopy*ws
    ax.plot(xCopy[:,1],yHat)
    plt.show()


def loadDataSet(fileName):读入数据,先把txt文件放入当前文件夹
    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

def standRegres(xArr,yArr):求解ws
    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

def Corrcoef(xArr,yArr,ws ):#计算相关系数
    yMat = mat(yArr)
    xMat = mat(xArr)
    yHat = xMat*ws
    return corrcoef(yHat.T,yMat)

def main():
    xArr,yArr=loadDataSet('ex0.txt')
    ws = standRegres(xArr,yArr)
    print(ws)
    cor = Corrcoef(xArr,yArr,ws)
    print(cor)
    figure(xArr,yArr,ws)


if __name__ == '__main__':
    main()
看一下效果图:


线性回归的一个问题是有可能出现欠拟合的现象,因为他求的是具有最小均方误差的无偏差估计。比如说,一个远离直线的异常点可能会对直线造成巨大的影响,所以有些方法允许在估计中引入一些偏差,从而减低预测的均方误差。其中一个方法是局部加权线性回归(LWLR)在该算法中我们给待预测点附近的每个点赋予一定的权重。

下面的理论公式zhuanzaihttp://blog.csdn.net/herosofearth/article/details/51969517转载

本算法依然使用损失函数J,只不过是加权的J函数:

这里写图片描述

该函数称为指数衰减函数,其中k为波长参数,它控制了权值随距离下降的速率,该函数形式上类似高斯分布(正态分布),但并没有任何高斯分布的意义。该算法解出回归系数如下: 

这里写图片描述

在使用这个算法训练数据的时候,不仅需要学习线性回归的参数,还需要学习波长参数。这个算法的问题在于,对于每一个要预测的点,都要重新依据整个数据集计算一个线性回归模型出来,使得算法代价极高。

这里写图片描述

看看源码:

from numpy import *
from linearRegression import * #就是导入上面的py文件
import matplotlib.pyplot as plt
def figure(xArr,yArr,yHat):#数据可视化
    xMat = mat(xArr)
    srtInd = xMat[:,1].argsort(0)
    xSort = xMat[srtInd][:,0,:]
    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()

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 singualr sannot do inverse")
        return
    ws = xTx.I*(xMat.T*(weights*yMat))
    return testPoint*ws

def lwlrTest(testArr,xArr,yArr,k=1.0):#获得只含对角元素的权重矩阵w
    m = shape(testArr)[0]
    yHat = zeros(m)
    for i in range(m):
        yHat[i] = lwlr(testArr[i],xArr,yArr,k)
    return yHat
def main():
    xArr,yArr = loadDataSet("ex0.txt")
    print(yArr[0])
    test1 = lwlr(xArr[0],xArr,yArr,1.0)
    print(test1)
    test2 = lwlr(xArr[0], xArr, yArr, 0.001)
    print(test2)
    yHat1 = lwlrTest(xArr,xArr,yArr,1.0)
    figure(xArr,yArr,yHat1)
    yHat2 = lwlrTest(xArr, xArr, yArr, 0.01)
    figure(xArr, yArr, yHat2)
    yHat3 = lwlrTest(xArr, xArr, yArr, 0.003)
    figure(xArr, yArr, yHat3)
if __name__ == '__main__':
    main()

看看结果:

图片1

图片2

图片3图片1图片2图片3





使用三种不同的平滑值绘出的局部加权线性回归结果表明了k=1.0时的模型效果与最小二乘法差不多,即上面的普通线性回归,k=0.01时该模型可以挖出数据的潜在规律,而k=0.003时则考虑了太多的噪声,进而导致过拟合的现象。

猜你喜欢

转载自blog.csdn.net/sinat_33487968/article/details/70482454
今日推荐