线性回归LR和局部加权线性回归LWLR算法简介

1.线性回归(LinearRegression)


        回归模型可以使用一个回归方程(regressionequation)来描述,其中求解回归系数(regression weights)的过程即称为回归。

        线性回归使用最小二乘法(ordinaryleast squares),即基于均方误差最小化模型的求解:


用矩阵表示可以写成


对sita求偏导可得


令偏导等于零,解出sita的最优估计解为:

 

则预测输出为:


        然而,现实任务中XTX往往不满秩,如样例的特征数目大,甚至超过样例数时,此时可解出多组sita使得均方误差最小化。当XTX不满秩时,常见的做法是引入正则化(regularization)项,将不适定的问题转化为适定问题,如岭回归(ridge regression)和lasso算法等。

        参数学习算法(Parametriclearning algorithm)是指有固定数目的参数用于进行数据拟合的算法,如线性回归有固定参数集合sita;非参数学习算法(Non-parametric learning algorithm)是指没有固定数目的参数用于进行数据拟合的算法,其参数随着样本集合的增大而线性正变化,如局部加权线性回归有非固定的权重参数W。

 

2.局部加权线性回归(LocallyWeighted Linear Regression,LWLR)


        线性回归求的是具有最小均方误差的无偏估计,因而可能出现欠拟合现象;有些方法允许在估计中引入一些偏差,从而降低预测的均方误差,比如局部加权线性回归(Locally Weighted Linear Regression,LWLR),如典型的住房价格预测(housingprice prediction)问题。

        局部加权线性回归根据预测样例与训练样例的距离给予权重,距离越近权重越大,然后应用最小二乘法拟合,即基于加权的均方误差最小化模型的求解:


用矩阵表示可以写成


其中权重使用核函数来赋予,核的类型可以自由选择,常用高斯核:


权重矩阵W则是对角矩阵


对sita求偏导可得


令偏导等于零,解出sita的最优估计解为:

 

则预测输出为:

 

        局部加权线性回归使用高斯核函数时,可调的参数只有波长参数k;当k越大时,表示各个实例具有相近的权重,得出的最佳拟合直线与标准回归一致,有可能出现欠拟合现象;当k越小时,表示与预测值相近的实例具有较大的权重,导致对噪声点敏感,拟合的直线与数据点过于贴近,可能出现过拟合现象。

        局部加权线性是典型的非参数学习算法,每计算一个预测值都要遍历一遍训练集或其局部样本。而对于样本非常大时,则存在计算量大的问题,算法应该进行调整,如使用kNN算法的kd树获取预设的若干个最近邻,并赋予合适的权重,如此减少计算量。

 

'''
Created on 2017年2月17日
线性回归LR和局部加权线性回归LWLR算法
@author: Administrator
'''

import numpy as np
import matplotlib.pyplot as plt

# 数据载入函数
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

# 标准回归函数
def standRegres(xArr, yArr):
    xMat = np.mat(xArr); yMat = np.mat(yArr).T
    xTx = xMat.T * xMat
    
    # 判断行列式是否可以求逆
    if abs(np.linalg.det(xTx)) < 1e-10:
        print('This matrix is singular, cannot do inverse')
        return
    
    # 求回归系数向量
    ws = xTx.I * (xMat.T * yMat)
    return ws

# 局部加权线性回归函数
def lwlr(testPoint, xArr, yArr, k=1.0):
    xMat = np.mat(xArr); yMat = np.mat(yArr).T
    m = np.shape(xMat)[0]
    weights = np.mat(np.eye((m)))
    
    # 根据高斯核函数构造权重矩阵
    for j in range(m):
            diffMat = testPoint - xMat[j,:]
            weights[j,j] = np.exp(diffMat * diffMat.T / (-2.0 * k ** 2))
    
    # 判断行列式是否可以求逆
    xTx = xMat.T * (weights * xMat)
    if abs(np.linalg.det(xTx)) < 1e-10:
        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 = np.shape(testArr)[0]
    yHat = np.zeros(m)
    for i in range(m):
        yHat[i] = lwlr(testArr[i], xArr, yArr, k)
    return yHat

# 计算样本实际值序列和预测值序列的均方误差
def rssError(yArr, yHatArr):
    return ((yArr - yHatArr) ** 2).sum()

# 绘制原始数据散点图和回归线
def scatterPlot(xArr, yArr, yHat):
    # 预处理数据,yMat和yHatMat为列向量
    xMat = np.mat(xArr)
    yMat = np.mat(yArr).T
    yHatMat = np.mat(yHat).T
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    
    # 根据输入数据的特征选取xMat的下标为1的列和yMat绘制散点图
    ax.scatter(xMat[:,1], yMat, s=30, c='blue', marker='o')
    
    # 对xMat递增排序,绘制回归线
    srtInd = xMat[:,1].argsort(0)
    xSort = xMat[srtInd][:,0,:]
    ax.plot(xSort[:,1], yHatMat[srtInd][:,0])
    
    # 计算模型的均方差
    print('模型的均方误差:\n', np.sum((yArr - yHatMat.A) ** 2))
    
    # 计算实际序列和预测序列的相关系数
    print('实际值和预测值的相关系数:\n', np.corrcoef(yHatMat.T, yMat.T))
    
    plt.show()


if __name__ == '__main__':
    xArr,yArr = loadDataSet('Datas/ex0.txt')
    print(xArr[0:10])
    
    # 标准回归
    ws = standRegres(xArr, yArr)
    print(ws)    
    yHat = (np.mat(xArr) * ws).T    
    scatterPlot(xArr, yArr, yHat)
    
    # 局部加权线性回归
    k = 0.01
    yHat = lwlrTest(xArr, xArr, yArr, k).T
    scatterPlot(xArr, yArr, yHat)
    
    # 预测鲍鱼的年龄
    xArr,yArr = loadDataSet('Datas/abalone.txt')
    print(xArr[0], yArr[0])
    yHat01 = lwlrTest(xArr[0:99], xArr[0:99], yArr[0:99], 0.1)
    yHat1 = lwlrTest(xArr[0:99], xArr[0:99], yArr[0:99], 1)
    yHat10 = lwlrTest(xArr[0:99], xArr[0:99], yArr[0:99], 10)
    print(rssError(yArr[0:99], yHat01.T))
    print(rssError(yArr[0:99], yHat1.T))
    print(rssError(yArr[0:99], yHat10.T))
    scatterPlot(xArr[0:99], yArr[0:99], yHat10)
    
    yHat01 = lwlrTest(xArr[100:199], xArr[0:99], yArr[0:99], 0.1)
    yHat1 = lwlrTest(xArr[100:199], xArr[0:99], yArr[0:99], 1)
    yHat10 = lwlrTest(xArr[100:199], xArr[0:99], yArr[0:99], 10)
    print(rssError(yArr[100:199], yHat01.T))
    print(rssError(yArr[100:199], yHat1.T))
    print(rssError(yArr[100:199], yHat10.T))
    scatterPlot(xArr[100:199], yArr[100:199], yHat10)


代码参考《机器学习实战》


你可能感兴趣的:(机器学习)