机器学习实战笔记:回归

    回归的目的是预测数值型的目标值。即找到一个回归方程,通过求解其中的回归系数(该过程就称为回归),给定输入来得到预测值这里我们之谈论线性回归。

用线性回归找最佳拟合直线

     回归的一般方法:

  1. 收集数据;
  2. 准备数据;
  3. 分析数据:可以绘出数据的可视化二维图将有助于对数据做出理解和分析,在采用缩减法求得新回归系数之后,可以将新拟合线绘在图上作为对比
  4. 训练算法:找到回归系数
  5. 测试算法:使用R^2或者预测值和数据的拟合度,来分析模型的效果
  6. 使用算法;
from numpy import*

"""数据导入函数"""
def loadDataSet(fileName):
    numFeat=len(open(fileName).readline().split('\t'))-1   #特征数包括了x0
    dataMat=[]      #数据矩阵(其实是包括了x0的X矩阵)
    labelMat=[]     #标签矩阵
    fr=open(fileName)
    for line in fr.readlines():
        lineArr=[]
        curLine=line.strip().split('\t')   #每一行是一个样本的数据x0,x1,y.注意x0恒为1,实际上是人为加在b前面的,用于方便矩阵运算
        for i in range(numFeat):
            lineArr.append(float(curLine[i]))
        dataMat.append(lineArr)              #每一个样本的x0~xn加入矩阵X
        labelMat.append(float(curLine[-1]))  #每个样本的标签加入向量Y
    return dataMat,labelMat   #返回X,Y


"""标准线性回归函数"""
def standRegres(xArr,yArr):
    xMat=mat(xArr)
    yMat=mat(yArr).T
    xTx=xMat.T*xMat   #计算 X^T*X
    if (linalg.det(xTx)==0.0):    #linalg模块包含线性代数的函数 det用于计算矩阵的行列式
        print("该矩阵是奇异的,没有逆矩阵")
        return
    ws=xTx.I*(xMat.T*yMat)   #计算w=(X^T*X)^-1*X^Ty
    return ws
局部加权线性回归

    线性回归的一个问题是有可能出现欠拟合现象,因为它求的是具有最小均方差的无偏估计。所有有些方法允许在估计中引入一些偏差,从而降低预测的均方误差。局部加权线性回归就是其中的一个方法。该算法中,我们给待预测点附近的每个点赋予一定的权重,然后在这个子集上基于最小均方差来进行普通的回归。这种算法每次预测均需要事先选取出对应的数据子集。

    该算法解出的回归系数w形式如下:

                                    w=(X^T*W*X)^-1*X^TWy

     其中W是矩阵,用来给每个数据点赋予权重。

     局部加权线性回归使用“核”来对附近的点赋予更高的权重,一般的是使用高斯核。高斯核对应的权重如下:

                                    w(i,i)=exp(|x(i)-x|/-2k^2)

    这样就构建了一个只含对角元素的权重矩阵W,并且点x与x(i)越近,w(i,i)将会越大。k由用户指定,它决定了对附近的点赋予多大的权重。

def lwlr(testPoint,xArr,yArr,k=1.0):   #testPoint为待预测点
    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))   #随着样本点与待预测点距离的递增,权重将以指数级衰减,k用于控制衰减速度
    xTx=xMat.T*(weights*xMat)
    if linalg.det(xTx)==0.0:
        print("该矩阵是奇异矩阵,没有逆矩阵")
        return
    ws=xTx.I*(xMat.T*(weights*yMat))    #计算系数
    return testPoint*ws                #返回预测值

缩减系数来“理解”数据

    如果数据的特征比样本点还多(n>m),也就是说输入数据的矩阵X不是满秩矩阵,那么X是不能求逆矩阵的。为了解决这个问题,引入领回归和向前逐步回归。

    岭回归

    简单的说岭回归就是在矩阵X^T*X上加一个λE,使得矩阵可逆。E是m*m的单位阵。这种情况下,回归系数的计算公式变成:

                                            w=(X^T*X+λE)^-1*X^T*y

    岭回归最先用于处理特征数多余样本数的情况,现在也用于在估计中加入偏差,从而得到更好的估计。这里通过引入λ来限制了所有w之和,通过引入该惩罚项,能够减少不重要的参数,统计上称为缩减。

"""岭回归"""
def ridgeRegres(xMat,yMat,lam=0.2):
    xTx=xMat.T*xMat
    denom=xTx+eye(shape(xMat)[1])*lam    #X^T*X+λE
    if linalg.det(denom)==0.0:        
        print("该矩阵是奇异矩阵,没有逆矩阵")
        return
    ws=denom.I*(xMat.T*yMat)
    return ws                     #返回w

    前向逐步回归

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

     伪代码如下:

数据标准化,使其分布满足0均值和单位方差
在每轮迭代过程中:
    设置当前最小误差lowestError为正无穷
    对每个特征:
        增大或者缩小:
            改变一个系数得到一个新的W
            计算新W下的误差
            如果误差Error小于当前最小误差lowestError:
                设置Wbest等于当前的W
        将W设置为新的Wbest
"""前向逐步线性回归"""
def stageWise(xArr,yArr,eps=0.01,numIt=100):    #eps表示每次迭代需要调整的步长,numIt表示迭代次数
    xMat=mat(xArr)
    yMat=mat(yArr).T
    yMean=mean(yMat,0)    #mean()求取均值:0压缩行,对各列求均值,返回 1* n 矩阵;1缩列,对各行求均值,返回 m *1 矩阵
    yMat=yMat-yMean       #0均值,即每个数据减去均值
    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 sign in [-1,1]:
                wsTest=ws.copy()
                wsTest[j]+=eps*sign
                yTest=xMat*wsTest
                rssE=rssError(yMat.A,yTest.A)
                if rssE<lowestError:
                    lowestError=rssE
        wsMax=wsTest
        ws=wsMax.copy()
    returnMat[i,:]=ws.T


猜你喜欢

转载自blog.csdn.net/qq_29599907/article/details/80589999