机器学习实战第8章预测数值型数据:回归

1.简单的线性回归

假定输入数据存放在矩阵X中,而回归系数存放在向量W中,则对于给定的数据X1,预测结果将会是

                

这里的向量都默认为列向量

现在的问题是手里有一些x和对应的y数据,怎样才能找到W呢?一个常用的方法是找到使误差最小的W,这里的误差是指预测y值与真实y值之间的差值,使用该误差的简单累加将使得正差值和负差值相互抵消,所以我们采用平方误差。

平方误差可以写做:

                

用矩阵表示可以写成

                

使用上式对w进行求导:

                

具体可参考https://blog.csdn.net/nomadlx53/article/details/50849941

令上述导数为0,即可得

                

2. 局部加权线性回归

  线性回归的一个问题是有可能出现欠拟合现象,因为它求的是具有小均方误差的无偏估计。显而易见,如果模型欠拟合将不能取得好的预测效果。所以有些方法允许在估计中引入一 些偏差,从而降低预测的均方误差。

  其中的一个方法是局部加权线性回归(Locally Weighted Linear Regression,LWLR)。在该方法中,我们给待预测点附近的每个点赋予一定的权重。与kNN一样,这种算法每次预测均需要事先选取出对应的数据子集。该算法解除回归系数W的形式如下:

                      

  LWLR使用"核"(与支持向量机中的核类似)来对附近的点赋予更高的权重。核的类型可以自由选择,最常用的核就是高斯核,高斯核对应的权重如下:

                    

  其中k需要用户设定,它决定了对附近的点赋予多大的权重,控制衰减速度

下面是代码

from numpy import mat,linalg,corrcoef,shape,eye,exp,zeros
import matplotlib.pyplot as plt
import numpy as np

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

"""
    函数说明:线性回归
    ParameterS:
        xArr - x数据集
        yArr - y数据集
    Returns:
        ws  - 回归系数
"""
def standRegres(xArr, yArr):
    xMat = mat(xArr); yMat = mat(yArr).T
    xTx = xMat.T*xMat
    # linalg.det()计算行列式,若为0,则不可逆
    if linalg.det(xTx) == 0.0:
        print("This matrix is singular, cannot do inverse")
        return
    #回归系数ws = (X^TX)^-1X^Ty
    ws = xTx.I * (xMat.T * yMat)
    return ws

def plotStandRegres(xMat, yMat, ws):
    fig = plt.figure()
    ax = fig.add_subplot(111)
    xCopy = xMat.copy()
    yHat = xCopy * ws
    # flatten()函数Return a copy of the array collapsed into one dimension.
    # .A将矩阵转化为数组
    ax.scatter(xMat[:, 1].flatten().A[0], yMat.T[:, 0].flatten().A[0])
    ax.plot(xCopy[:, 1], yHat,‘r‘)
    plt.show()

"""
    函数说明:局部加权线性回归
    Parameters:
        testPoint - 测试点,xArr -  x数据集,yArr - y数据集,
        k   - 高斯核的参数,自定义,控制衰减速度
    Returns:
        测试点y值
"""
def lwlr(testPoint, xArr, yArr, k=1.0):
    xMat = mat(xArr)    # m * n
    yMat = mat(yArr).T  # m * 1
    m = shape(xMat)[0]
    weights = mat(eye(m))   #生成对角矩阵,对角线上元素全为1,其他为0
    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

"""
    函数说明:局部加权线性回归测试函数
    Parameters:
        testPoint - 测试x数据集,xArr -  x数据集,yArr - y数据集,
        k - 高斯核的参数,自定义,控制衰减速度
    Returns:
        yHat - 预测y数据集
"""
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

def plotLwlr(xMat, yMat):
    plt.rcParams[‘font.sans-serif‘] = [‘SimHei‘]
    plt.rcParams[‘axes.unicode_minus‘] = False
    strInd = xMat[:,1].argsort(0)   #对x进行排序,并返回排序下标
    xSort = xMat[strInd][:,0,:]
    yHat1 = lwlrTest(xArr, xArr, yArr, 1.0)
    yHat2 = lwlrTest(xArr, xArr, yArr, 0.01)
    yHat3 = lwlrTest(xArr, xArr, yArr, 0.003)
    fig, axs = plt.subplots(nrows=3, ncols=1, sharex=False, sharey=False, figsize=(10, 8))
    axs[0].plot(xSort[:, 1], yHat1[strInd], c=‘red‘)
    axs[1].plot(xSort[:, 1], yHat2[strInd], c=‘red‘)
    axs[2].plot(xSort[:, 1], yHat3[strInd], c=‘red‘)
    axs[0].scatter(xMat[:, 1].flatten().A[0], yMat.T[:, 0].flatten().A[0])
    axs[1].scatter(xMat[:, 1].flatten().A[0], yMat.T[:, 0].flatten().A[0])
    axs[2].scatter(xMat[:, 1].flatten().A[0], yMat.T[:, 0].flatten().A[0])
    #设置标题,x轴y轴label
    axs0_title_text = axs[0].set_title(u‘局部加权回归曲线,k=1.0‘)
    axs1_title_text = axs[1].set_title(u‘局部加权回归曲线,k=0.01‘)
    axs2_title_text = axs[2].set_title(u‘局部加权回归曲线,k=0.003‘)
    plt.setp(axs0_title_text, size=8, weight=‘bold‘, color=‘red‘)
    plt.setp(axs1_title_text, size=8, weight=‘bold‘, color=‘red‘)
    plt.setp(axs2_title_text, size=8, weight=‘bold‘, color=‘red‘)
    plt.xlabel(‘X‘)
    plt.ylabel(‘Y‘)
    plt.show()

if __name__ == ‘__main__‘:
    xArr, yArr = loadDataSet(‘ex0.txt‘)
    ws = standRegres(xArr, yArr)
    xMat = mat(xArr)
    yMat = mat(yArr)
    yHat = xMat * ws  # 预测y值
    plotStandRegres(xMat, yMat, ws)
    #计算相关系数
    print(corrcoef(yHat.T, yMat))
    plotLwlr(xMat, yMat)

简单线性回归的运行结果:

    

相关系数:

      

  

局部加权回归:

  

从图中可以看出在三种k的取值中,k=0.01的结果相对更好一些,k=0.003时会出现过拟合的情况。

局部加权回归存在一个问题:增加了计算量,每次必须在整个数据集上运行

3.示例:预测鲍鱼的年龄

"""
    函数说明:计算误差
"""
def rssError(yArr,yHatArr): #yArr and yHatArr both need to be arrays
    return ((yArr-yHatArr)**2).sum()

if __name__ == ‘__main__‘:
    xArr, yArr = regression.loadDataSet(‘abalone.txt‘)
    print(‘训练集与测试集相同:局部加权线性回归,核k的大小对预测的影响:‘)
    yHat01 = regression.lwlrTest(xArr[0:99], xArr[0:99], yArr[0:99], 0.1)
    yHat1 = regression.lwlrTest(xArr[0:99], xArr[0:99], yArr[0:99], 1)
    yHat10 = regression.lwlrTest(xArr[0:99], xArr[0:99], yArr[0:99], 10)
    print(‘k=0.1时,误差大小为:‘,rssError(yArr[0:99], yHat01.T))
    print(‘k=1时,误差大小为:‘,rssError(yArr[0:99], yHat1.T))
    print(‘k=10.1时,误差大小为:‘,rssError(yArr[0:99], yHat10.T))
    print(‘‘)
    print(‘训练集与测试集不同:局部加权线性回归,核k的大小对预测的影响:‘)
    yHat01 = regression.lwlrTest(xArr[100:199], xArr[0:99], yArr[0:99], 0.1)
    yHat1 = regression.lwlrTest(xArr[100:199], xArr[0:99], yArr[0:99], 1)
    yHat10 = regression.lwlrTest(xArr[100:199], xArr[0:99], yArr[0:99], 10)
    print(‘k=0.1时,误差大小为:‘,rssError(yArr[100:199], yHat01.T))
    print(‘k=1时,误差大小为:‘,rssError(yArr[100:199], yHat1.T))
    print(‘k=10时,误差大小为:‘,rssError(yArr[100:199], yHat10.T))
    print(‘‘)
    print(‘训练集与测试集不同:简单的线性归:‘)
    ws = regression.standRegres(xArr[0:99], yArr[0:99]) # 8 * 1
    yHat = xArr[100:199] * ws
    print(rssError(yArr[100:199],yHat.T.A))

  

  从中可以看出使用训练数据集做测试集时,k=0.1时的误差最小,但使用不同训练集的数据做测试数据集时,k=0.1的误差最大,说明了可能出现了过拟合的情况,因此在选取k值时应选择使测试误差最小的值。同时我们可以看到,当k=1时,局部加权线性回归和简单的线性回归得到的效果差不多。这也表明一点,必须在未知数据上比较效果才能选取到最佳模型。

参考:

《机器学习实战第8章》

http://cuijiahua.com/blog/2017/11/ml_11_regression_1.html

原文地址:https://www.cnblogs.com/weiququ/p/9526515.html

时间: 2024-10-19 14:04:48

机器学习实战第8章预测数值型数据:回归的相关文章

机器学习实战第8章预测数值型数据:回归2

1. Shrinkage(缩减) Methods 当特征比样本点还多时(n>m),输入的数据矩阵X不是满秩矩阵,在求解(XTX)-1时会出现错误.接下来主要介绍岭回归(ridge regression)和前向逐步回归(Foward Stagewise Regression)两种方法. 1.1 岭回归(ridge regression) 简单来说,岭回归就是在矩阵XTX上加上一个从而使得矩阵非奇异,进而能进行求逆.其中矩阵I是一个单位矩阵,是一个调节参数. 岭回归的回归系数计算公式为: 岭回归最先

机器学习——预测数值型数据:回归

线性回归 优点:结果易于理解,计算上不复杂 缺点:对非线性的数据拟合不好 适用数据类型:数值型和标称型数据 回归的目的就预测数值型的目标值.最直接的办法就是依据输入写一个目标值的计算公式.这个计算公式就是所谓的回归方程(regression equation),其中的参数就是回归系数,求这些回归系数的过程就是回归. 说道回归,一般都是指线性回归(linear regression). 一元线性回归的矩阵形式可以写成,其中 是噪声,b是回归系数(斜率) 或者 ,其中y.X.a.都是n维向量,而b是

回归:预测数值型数据

何为回归? “回归”一词是由达尔文的表兄弟Francis Galton发明的.Galton于1877年完成了第一次回归预测,目的是根据上一代豌豆种子(双亲)的尺寸来预测下一代豌豆种子(孩子)的尺寸. Galton在大量对象上应用了回归分析,甚至包括人的身高预测.他注意到,如果双亲的高高度比平均高度高,他们的子女也倾向于比平均高度高,但尚不及双亲(笔者感觉未必,Galton并未考虑物质条件的发展会带来整体身高的增加,至少笔者感觉80,90的人普遍比父母高).孩子的高度向着平均高度“回归”. 在软件

第八章:预测数值型数据:回归

本章内容□ 线性回归□ 局部加权线性回归□ 岭回归和逐步线性回归□ 预测鲍鱼年龄和玩具售价  8.1用线性回归找到最佳拟合直线

机器学习实战之第一章 机器学习基础

第1章 机器学习基础 机器学习 概述 机器学习就是把无序的数据转换成有用的信息. 获取海量的数据 从海量数据中获取有用的信息 我们会利用计算机来彰显数据背后的真实含义,这才是机器学习的意义. 机器学习 场景 例如:识别动物猫 模式识别(官方标准):人们通过大量的经验,得到结论,从而判断它就是猫. 机器学习(数据学习):人们通过阅读进行学习,观察它会叫.小眼睛.两只耳朵.四条腿.一条尾巴,得到结论,从而判断它就是猫. 深度学习(深入数据):人们通过深入了解它,发现它会'喵喵'的叫.与同类的猫科动物

预测数值型数据-回归(Regression)

===================================================================== <机器学习实战>系列博客是博主阅读<机器学习实战>这本书的笔记也包含一些其他python实现的机器学习算法 算法实现均采用python github 源码同步:https://github.com/Thinkgamer/Machine-Learning-With-Python ==================================

机器学习实战第7章——利用AdaBoost元算法提高分类性能

将不同的分类器组合起来,这种组合结果被称为集成方法或元算法(meta-algorithm). 使用集成方法时会有多种形式:(1)可以是不同算法的集成(2)可以是同一种算法在不同设置下的集成(3)数据集不同部分分配给不同分类器之后的集成,等等 接下来介绍基于同一种分类器多个不同实例的两种不同计算方法bagging和boosting 1. bagging 原理:从原始数据集选择S次后得到S个新数据集的一种技术.新数据集和原数据集的大小相等.每个数据集都是通过在原始数据集中随机选择一个样本来进行替换而

机器学习--标称型和数值型数据

在监督学习(supervised learning)的过程中,只需要给定输入样本集,机器就可以从中推演出指定目标变量的可能结果.监督学习相对比较简单,机器只需从输入数据中预测合适的模型,并从中计算出目标变量的结果. 监督学习一般使用两种类型的目标变量:标称型和数值型 标称型:标称型目标变量的结果只在有限目标集中取值,如真与假(标称型目标变量主要用于分类) 数值型:数值型目标变量则可以从无限的数值集合中取值,如0.100,42.001等 (数值型目标变量主要用于回归分析)-------------

机器学习实战之第二章 k-近邻算法

第2章 k-近邻算法 KNN 概述 k-近邻(kNN, k-NearestNeighbor)算法主要是用来进行分类的. KNN 场景 电影可以按照题材分类,那么如何区分 动作片 和 爱情片 呢? 动作片:打斗次数更多 爱情片:亲吻次数更多 基于电影中的亲吻.打斗出现的次数,使用 k-近邻算法构造程序,就可以自动划分电影的题材类型. 现在根据上面我们得到的样本集中所有电影与未知电影的距离,按照距离递增排序,可以找到 k 个距离最近的电影. 假定 k=3,则三个最靠近的电影依次是, He's Not