zoukankan      html  css  js  c++  java
  • 预测数值型数据:回归

    线性回归找到最佳拟合直线:寻找使得拟合误差最小的线性回归系数w

    采用平方误差。

    标准回归函数和数据载入函数:

    from numpy import  *
    def loadDataSet(filename):
        numFeatures=len(open(filename).readline().split('	'))-1  #tag键分隔文本的文件
        dataMat=[]
        labelMat=[]
        f=open(filename)
        for line in f.readlines():
            curLine=line.strip().split('	')
            lineArr=[]
            for i in range(numFeatures):
                lineArr.append(float(curLine[i]))
            dataMat.append(lineArr)
            labelMat.append(float(curLine[-1]))
        return dataMat,labelMat
    def standRegres(xArr,yArr):
        xMat=mat(xArr)
        yMat=mat(yArr).T
        xTx=xMat.T*xMat
        if linalg.det(xTx)==0.0:        #linalg.det()计算行列式,行列式等于0时矩阵不可逆
            print('此矩阵不可逆')
            return
        ws=xTx.I*(xMat.T*yMat)
        return ws
    

     返回值ws即为回归系数,因为训练数据集上只有两个特征,所以ws只有两个元素。

    预测值计算:

      yHat=ws[0]*x[0]+ws[1]*x[1]

    向量形式:yHat=WS*X

    绘制数据集散点图和拟合直线:

    def plotLine(xArr,yArr,ws):
        xMat=mat(xArr)
        yMat=mat(yArr)
        # yHat=xMat*ws
        import matplotlib.pyplot as plt
        fig=plt.figure()
        ax=fig.add_subplot(111)
        # print(yMat)
        # print(yMat.T)
        # print(yMat.T.flatten())
        # print(yMat.T[:,0].flatten().A[0])
        ax.scatter(xMat[:,1].flatten().A[0],yMat.T[:,0].flatten().A[0],s=5,c='y')
        xCopy=xMat.copy()
        xCopy.sort(0)
        yHat=xCopy*ws
        ax.plot(xCopy[:,1],yHat,c='r')        #plot划线,scatter画点
        plt.show()
    

     测试输出:

    if __name__=='__main__':
        xArr,yArr=loadDataSet('ex0.txt')
        ws = standRegres(xArr, yArr)
        print('回归系数为:', ws)
        plotLine(xArr, yArr, ws)
    

     输出结果为:

    回归系数为: [[3.00774324]
     [1.69532264]]
    

     

    衡量预测值yHat序列和真实值y序列的匹配程度:相关系数

    xMat = mat(xArr)
    yMat = mat(yArr)
    yHat=xMat*ws
    corr=corrcoef(yHat.T,yMat)
    print('相关系数为:',corr)
    

     输出:

    相关系数为: [[1.         0.98647356]
     [0.98647356 1.        ]]
    

    局部加权线性回归:上述方法明显欠拟合,因为它求的是具有最小均方误差的无偏估计,拟合函数不能获得很好的预测结果,局部加权线性回归允许在估计中引入一些偏差,从而降低预测的均方误差。

    原理:给待测点附近的数据点赋予一定的权重,然后再基于上述的最小均方误差进行普通的回归预测。距离预测点越近的数据点权重越大,对预测结果影响越大。类似于数值分析中的分段线性插值。

    回归系数时m阶单位矩阵,核函数选择高斯核。

    局部加权线性回归函数和预测函数:

    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('此矩阵不可逆!')
            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
    

    绘制数据集散点图和回归曲线:

    def plotLineAndPoint(xArr,yArr,yHat):
        import matplotlib.pyplot as plt
        xMat=mat(xArr)
        sortedIndex=xMat[:,1].argsort(0)
        xSorted=xMat[sortedIndex][:,0,:]      #三维矩阵的切片操作
        figure=plt.figure()
        ax=figure.add_subplot(111)
        ax.plot(xSorted[:,1],yHat[sortedIndex],c='r')
        ax.scatter(xMat[:,1].flatten().A[0],mat(yArr).T.flatten().A[0],s=5,c='y')
        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('此矩阵不可逆!')
            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
    

     测试:

    if __name__=='__main__':
        xArr,yArr=loadDataSet('ex0.txt')
        yHat = lwlrTest(xArr, xArr, yArr, 0.003)
        plotLineAndPoint(xArr, yArr, yHat)
    

     输出:

    上述回归曲线是在高斯核函数里取k=0.003时的结果,考虑了太多噪声,导致了过拟合,不同的k值对回归效果影响很大:

    k=0.5:

    k=0.1:

    k=0.01

    k=0.001

     

    此时部分样本计算过程发生了零溢出,矩阵不可逆,拟合曲线断续,而且过拟合。

    k=0.01时拟合效果很好。

    局部加权线性回归预测效果好,但是计算量大,因为对每个点的预测都需要使用整个数据集来更新权重矩阵进而求出回归系数。优化方法:距离预测点很远的数据点权重很小,接近零,可以忽略此种数据点,只计算距离预测点近的数据点。


    使用以上回归算法预测鲍鱼年龄时发现:(误差衡量标准为方差)

    k值越小的核函数得到的回归模型训练误差越小,这是因为使用较小的核造成了过拟合,其对新数据的预测效果较差。核大的回归模型训练误差大但是测试误差小。

    简单线性回归测试误差与局部加权回归类似。这表明必须在未知数据上比较效果才能选取到最佳回归模型。一般取多个数据集测试来比较预测效果。

    缩减系数来理解数据:岭回归

    如果数据的特征个数大于样本点,以上计算过程会出错,因为输入数据的矩阵xMat不满秩,不能求逆。

    岭回归:

    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('此矩阵不可逆!')
            return
        ws=denom.I*(xMat.T*yMat)    #n*1阶
        # print(ws)
        return ws
    def ridgeTest(xArr,yArr):
        xMat = mat(xArr)
        yMat = mat(yArr).T
        yMean=mean(yMat,0)
        yMat=yMat-yMean
        xMean=mean(xMat,0)
        # print(xMean)
        xVar=var(xMat,0)
        xMat=(xMat-xMean)/xVar
        numTest=30
        wMat=zeros((numTest,shape(xMat)[1]))     #30*n
        for i in range(numTest):
            ws=ridgeRegres(xMat,yMat,exp(i-10))
            wMat[i,:]=ws.T
        return wMat
    

    绘制回归系数随着lambda的变化曲线:

    def plotRidgeWeights(ridgeWeights):
        # print(ridgeWeights)
        import matplotlib.pyplot as plt
        fig=plt.figure()
        ax=fig.add_subplot(111)
        axisX = [(i - 10) for i in range(30)]  # log(λ)作为横坐标
        ax.plot(axisX,ridgeWeights)
        plt.show()
    

    测试:

    if __name__=='__main__':
        xArr,yArr=loadDataSet('abalone.txt')
        wMat=ridgeTest(xArr,yArr)
        plotRidgeWeights(wMat)
    

    输出:

    横坐标是log(lambda),八条曲线分别表示八个回归系数的变化。为了定量地找到最佳回归系数值,需要交叉验证。


    前向逐步回归:属于一种贪心算法,即每一步都尽可能减少误差。一开始,所有的权重都设置为0,然后每一步所做的决策是对某个权重增加或者减少一个很小的值。

    该算法简单,直接迭代产生系数矩阵,类似于牛顿下山法,由初始值开始迭代,产生符合精度要求的结果即可。

    def regularize(xMat):
        xMat2Regularize=xMat.copy()
        xMean=mean(xMat2Regularize,0)
        xVar=var(xMat2Regularize,0)
        xMat2Regularize=(xMat2Regularize-xMean)/xVar
        return xMat2Regularize
    def stageWise(xArr,yArr,step=0.01,numIter=100):
        xMat=mat(xArr)
        yMat=mat(yArr).T
        yMean=mean(yMat)
        yMat=yMat-yMean
        xMat=regularize(xMat)
        m,n=shape(xMat)
        returnMat=zeros((numIter,n))
        ws=zeros((n,1))
        wsTest=ws.copy()
        wsMax=ws.copy()
        for i in range(numIter):
            # print('权重矩阵为:',ws.T)
            lowestError=inf
            for j in range(n):
                for sign in [-1,1]:
                    wsTest=ws.copy()
                    wsTest[j]+=step*sign
                    yTest=xMat*wsTest
                    error=rssError(yMat.A,yTest.A)      #  .A 矩阵转化成数组
                    if error<lowestError:
                        lowestError=error
                        wsMax=wsTest
            ws=wsMax.copy()
            returnMat[i,:]=ws.T
        return  returnMat
    

     绘制回归系数与迭代次数之间的关系曲线:

    def plotFigure(weights):
        # print('最后十次迭代产生的权重向量为:
    ',weights[-10:-1,:])
        import matplotlib.pyplot as plt
        fig = plt.figure()
        ax = fig.add_subplot(111)
        ax.plot(weights)
        plt.show()
    

     测试算法:

    if __name__=='__main__':
        xArr,yArr=loadDataSet('abalone.txt')
        result=stageWise(xArr,yArr,0.001,5000)
        plotFigure(result)
    

     输出为:

    最后十次迭代产生的权重向量为:
     [[ 0.044 -0.011  0.12   0.022  2.023 -0.963 -0.105  0.187]
     [ 0.043 -0.011  0.12   0.022  2.023 -0.963 -0.105  0.187]
     [ 0.044 -0.011  0.12   0.022  2.023 -0.963 -0.105  0.187]
     [ 0.043 -0.011  0.12   0.022  2.023 -0.963 -0.105  0.187]
     [ 0.044 -0.011  0.12   0.022  2.023 -0.963 -0.105  0.187]
     [ 0.043 -0.011  0.12   0.022  2.023 -0.963 -0.105  0.187]
     [ 0.044 -0.011  0.12   0.022  2.023 -0.963 -0.105  0.187]
     [ 0.043 -0.011  0.12   0.022  2.023 -0.963 -0.105  0.187]
     [ 0.044 -0.011  0.12   0.022  2.023 -0.963 -0.105  0.187]]
    

     

    使用最小二乘法拟合直线得到的回归系数如下:

    [[ 0.0430442  -0.02274163  0.13214087  0.02075182  2.22403814 -0.99895312
      -0.11725427  0.16622915]]
    
  • 相关阅读:
    Freedur为什么会免费?
    Cocos2d-x中使用音频CocosDenshion引擎介绍与音频文件的预处理
    AssetManager asset的使用
    Android AsyncHttpClient
    UI标签库专题十三:JEECG智能开发平台 ckfinder(ckfinder插件标签)
    UBUNTU 下如何升级 gcc, g++
    java 泛型深入之Set有用工具 各种集合泛型深入使用演示样例,匿名内部类、内部类应用于泛型探讨
    最新Connectify注冊码(序列号) Connectify3.7序列号 破解版
    简单单元測试思想
    Dijkstra算法
  • 原文地址:https://www.cnblogs.com/zhhy236400/p/9931915.html
Copyright © 2011-2022 走看看