机器学习实战-8预测数值型数据-回归

来源:互联网 发布:汽车行业数据报告 编辑:程序博客网 时间:2024/05/20 23:56

回归和分类是机器学习两个主要的类别,通常会在面试的时候,被询问这两者之间的区别。对于我,有时候我也无法说清,虽然我感觉我已经弄懂了,但是这里还是说一说自己的理解。首先,我们学过一本书《随机过程》,这里面讲到了马尔科夫链等,这是一种在时间、位置等有序列属性的数据,也就是说,这些说句不仅仅存在关系,而且存在一种序列上的前后关系,如时间、地理位置等。而分类一般核心不在于此。所以,回归问题就是一种序列预测问题,比如预测房价-时间、房间-面积、股票-时间等序列关系,通过模拟之前的序列来预测之后的序列。最简单,如线性回归,这就像我们解一元方程y=ax一样,解出a就可以了。但是,存在一个问题,这个直线是不是太直了,可能是个曲线了?或者说,更应该是是一个近似曲线的波浪线了?所以,回归的问题就开始复杂了,此时,我们开始了一些波动预测。采用的一种方式就是,对于每一个数据都有一个权重,而不是只有一个。即我们不是求单个方程,而是求解整个片段的方程,每一个点都有权值,遮掩,我们就将这个权值序列向后移动,以此来预测后来的值,即已有[1-100],那么就可以预测[2-101]来得出x=101的值,以此类推。


一、线性回归

通俗一定,线性回归就是多元以此方程组,多元指的就是多个特征值。回归最早是由达尔文的表兄弟发明的,当时他的目的是为了通过豌豆上一代的尺寸来预测下一代的尺寸,这正是回归问题。为什么叫做回归?是因为当时他发现一般人的身高虽然遗传来自父母,但是整体上还是会向均值靠近,即回归(即便他的父母很高),这个名词和这里的意义不大,但是还是有那么点意思,即任何数据都会靠近正常预测水平,不会太不靠谱(强行解释–)

  1. 原理
    一般使用平方误差计算(因为单减误差会互相抵消):
    这里写图片描述
    对w求导,等于0,得:
    这里写图片描述

  2. 衡量分离的好坏,有一个方式就是通过corrcoef函数来求解相关系数,越接近0,相关性越大,说明预测越好

![enter description here][3]

二、局部加权回归

线性回归有个很大的缺点,即欠拟合,太直了,不知道转弯,就是一条直线(它求得是最小均方误差的无偏估计);所以,为了防止这种情况,引入一些偏差进来,相当于做一个缓冲作用,从而降低均方误差。局部加权回归LWLR就是其中的一种

  1. 对每一个数据都加入一个权重系数W,最终的回归系数w就是:
    这里写图片描述

  2. 这里的核类似于支持向量机中的核,通过这个核来对附近的点赋予更高的权重,一般使用的是高斯核:
    这里写图片描述
  3. 注意,这里的代码和线性回归不同,因为它不是一条直线,而是每个点都是一个单独计算的,所以最后的划线是片段性的。

这里写图片描述

**三、缩减系数来“理解”数据

对于分类还是回归问题,我们时常遇到数据特征比样本数量还多的情况。如果是这种情况,由于(xTx)^-1不能计算,所以是无法解决的。为了解决这个问题,我们想到了在矩阵中加入一个额外的数据,类似于补充特征。这里讲述两种方式:岭回归lasso法(本文采用类的前向逐步回归)

  1. 岭回归
    • 岭回归就是在上面提到的矩阵上加一个λI 从而使矩阵非奇异(参考奇异值分解),这样就可以求逆了。之后的公式为:
      这里写图片描述
    • 为什么叫做缩减?因为通过引入惩罚项后,可以限制所有w的和,这样就能够减少不重要的参数,在统计学上就叫做缩减,这样能更好的理解数据(奇异值分解就是这个作用,提取出关键的信息点)
    • 标准化问题:这里对特征进行了标准化处理,以使特征具有相同的重要性(这里的处理类似于归一化,但是在归一化的基础上又除以了跨度值);而对于结果y只有归一化。
      这里写图片描述
  2. lasso

    • 这种方式通过对每一个点进行上下浮动取值,来定点优化;从而遍历优化所有的w
      这里写图片描述
      四、代码
  3. regression.py

""" @author: zoutai@file: regression.py @time: 2017/11/24 @description:逻辑回归"""# 相对于分类所不同的是,逻辑回归更适合处理数据之间有连续关系的数据# 线性回归就像是近似拟合直线,比如房价的走势等,找到一条最近似的直接来进行模拟,以便于能够预测将来的数据from math import *from numpy import *def loadDataSet(fileName):      #general function to parse tab -delimited floats    numFeat = len(open(fileName).readline().split('\t')) - 1 #get number of fields    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# 1、线性回归-最小二乘法# 求解线性回归的权重参数w,求导解,公式为:w=(X.T * X)^(-1) * (X.T * Y)def standRegres(xArr,yArr):    xMat = mat(xArr);yMat = mat(yArr).T    xtx = xMat.T * xMat    # 这里需要保证xtx的秩不能为0,否则没有逆矩阵-1    if linalg.det(xtx) == 0.0:        print("This matrix is single,cannot do inverse")        return    w = xtx.I * (xMat.T * yMat)    return w# 2、局部加权回归LWLR# 1中的线性回归有个问题,就是欠拟合,太老实了;不知道转个弯变通一下。因为它求的是最小均方误差的无偏估计(即保证整个过程是条直线,不转弯)# 因此引入一定的偏差,从而降低预测的均方误差# 与线性回归有一点差别,这里面主要是引入了回归系数w# 公式为:w=(X.T * W * X)^(-1) * (X.T * W * Y)def lwlr(testPoint,xArr,yArr,k=1.0):    xMat = mat(xArr)    yMat = mat(yArr).T    m = shape(xMat)[0]    weight = mat(eye(m))    for i in range(m):        diffI = testPoint - xMat[i,:]        weight[i,i] = exp(diffI * diffI.T/(-2.0*k**2))    xtx = xMat.T * weight * xMat    if linalg.det(xtx) == 0.0:        print("This matrix is single,cannot do inverse")        return    w = xtx.I * (xMat.T * weight * yMat)    return testPoint * w # 注意矩阵相乘是的前后顺序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 yHatdef rssError(yArr,yHatArr):    return ((yArr - yHatArr)**2).sum()# 3、岭回归def ridgeRegres(xMat, yMat, lam=0.2):    xTx = xMat.T * xMat    denom = xTx + eye(shape(xMat)[1]) * lam    if linalg.det(denom) == 0.0:        print("This matrix is singular, cannot do inverse")        return    ws = denom.I * (xMat.T * yMat)    return wsdef ridgeTest(xArr, yArr):    xMat = mat(xArr);    yMat = mat(yArr).T    yMean = mean(yMat, 0)    yMat = yMat - yMean  # to eliminate X0 take mean off of Y    # regularize X's    xMeans = mean(xMat, 0)  # calc mean then subtract it off    xVar = var(xMat, 0)  # calc variance of Xi then divide by it    xMat = (xMat - xMeans) / xVar    numTestPts = 30    wMat = zeros((numTestPts, shape(xMat)[1]))    for i in range(numTestPts):        ws = ridgeRegres(xMat, yMat, exp(i - 10))        wMat[i, :] = ws.T    return wMat# 直到这里我才理解回归的精髓,即这里面并不是求解一个w值,而是求出一个序列的w序列,# 然后根据这个序列预测后一个序列的值!# 前向逐步线性回归(这里面重点是将x,y归一化;其中x是标准化处理,y进行归一化处理,都汇集到0处,# 这样,x-y系数就为1,近似单位一的正相关)# 即求解y=x上下浮动近似# 正则化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# 这里我弄不清了:为什么x需要除以一个数,而y不需要?def stageWise(xArr,yArr,eps=0.01,numIt=100):    xMat = mat(xArr);yMat = mat(yArr).T    yMean = mean(yMat)    yMat = yMat - yMean    xMat = regularize(xMat)    m,n = shape(xMat)    returnMat = zeros((numIt,n))    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 signal in [-1,1]:                wsTest = ws.copy()                wsTest[j] += eps * signal                yTest = xMat * wsTest                rssE = rssError(yTest.A,yMat.A)                if rssE < lowestError:                    lowestError = rssE                    wsMax = wsTest        ws = wsMax.copy()        returnMat[i,:] = ws.T    return returnMat
  1. 测试段:
""" @author: zoutai@file: test.py @time: 2017/11/24 @description: """from unit08.regression import *xArr,yArr = loadDataSet("ex0.txt")xMat = mat(xArr)yMat = mat(yArr)w = standRegres(xArr,yArr)yHat = mat(xArr) * wimport matplotlib.pyplot as pltfig = plt.figure()ax =fig.add_subplot(111)# 1、flatten()将数据都表示称一维数据,但是数据格式还是原来的维数# 2、A[0],A相当于原矩阵(?)ax.scatter(xMat[:,1].flatten().A[0],yMat.T[:,0].flatten().A[0])# 这里画图没有排序,下一个实验会发现有错误ax.plot(xMat[:,1].flatten().A[0],yHat)plt.show()# 评测预测准确度:相关系数cov:函数corrcoef()covMat = corrcoef(yMat,yHat.T)print(covMat)# the result is:# [[ 1.          0.98647356]#  [ 0.98647356  1.        ]]# 对角表示自己和自己的关联度,为1,;0.98为这两个的关联度,越接近1,表示越好

""" @author: zoutai@file: test.py @time: 2017/11/24 @description: """from unit08.regression import *xArr,yArr = loadDataSet("ex0.txt")xMat = mat(xArr)yMat = mat(yArr)#yHat = lwlrTest(xArr,xArr,yArr,0.003)yHat = lwlrTest(xArr,xArr,yArr,0.01)import matplotlib.pyplot as pltfig = plt.figure()ax =fig.add_subplot(111)# 1、flatten()将数据都表示称一维数据,但是数据格式还是原来的维数# 2、A[0],A相当于原矩阵(?)# 排序srtInd = xMat[:,1].argsort(0) # 排序后的序号xSort = xMat[srtInd][:,0,:]ax.scatter(xMat[:,1].flatten().A[0],yMat.T[:,0].flatten().A[0])ax.plot(xSort[:,1].flatten().A[0],yHat[srtInd],color='red',)ax.set_title("k = 0.01")plt.show()# 评测预测准确度:相关系数cov:函数corrcoef()covMat = corrcoef(yMat,yHat.T)print(covMat)# the result is:# [[ 1.          0.98647356]#  [ 0.98647356  1.        ]]# 对角表示自己和自己的关联度,为1,;0.98为这两个的关联度,越接近1,表示越好# 预测鲍鱼的年龄(前100个预测后100个)# 1加权回归法abX,abY = loadDataSet("abalone.txt")yHat = lwlrTest(abX[100:199],abX[0:99],abY[0:99],10)error1 = rssError(yHat.T,abY[100:199])print("the lwlr error is :",error1)ws = standRegres(abX[0:99],abY[0:99])yHat2 = abX[100:199] * wserror2 = rssError(yHat2.T.A,abY[100:199]) # .A运算应该是将mat矩阵转化为array数组print("stand error is :",error2)# the result is :# the lwlr error is : 517.571190538# stand error is : 518.636315325# test3、岭回归ridgeWeights = ridgeTest(abX,abY)

""" @author: zoutai@file: test.py @time: 2017/11/24 @description: """from unit08.regression import *xArr,yArr = loadDataSet("ex0.txt")xMat = mat(xArr)yMat = mat(yArr)import matplotlib.pyplot as pltfig = plt.figure()ax =fig.add_subplot(111)abX,abY = loadDataSet("abalone.txt")# test3、岭回归# 这个地方我没有仔细思考,直接摘录来了ridgeWeights = ridgeTest(abX,abY)ax.plot(ridgeWeights)plt.show()

""" @author: zoutai@file: test.py@time: 2017/11/24@description:"""from unit08.regression import *xArr,yArr = loadDataSet("ex0.txt")xMat = mat(xArr)yMat = mat(yArr)import matplotlib.pyplot as pltfig = plt.figure()ax =fig.add_subplot(111)abX,abY = loadDataSet("abalone.txt")# test3、岭回归# 这个地方我没有仔细思考,直接摘录来了ridgeWeights = stageWise(abX,abY,0.001,5000)ax.plot(ridgeWeights)plt.show()

书上原版链接

阅读全文
0 0
原创粉丝点击