美文网首页
机器学习:线性回归

机器学习:线性回归

作者: moon_light_ | 来源:发表于2020-03-08 20:11 被阅读0次

    优点:结果易于理解,计算上不复杂
    缺点:对非线性的数据拟合不好

    线性回归

    用于数值预测,回归方程为
      \small y = x_{1}w_{1} + x_{2}w_{2} + ... + x_{n}w_{n} + b
      
    写成矩阵形式
      \small y = XW + b
      
    为方便计算,添加 \small x_{0}=1, 取 \small w_{0} = b, 将式子改写为
      \small y = XW
      
    采用平方差做损失函数
      \small L = \sum_{i=1}^{n}(y_{i} -X_{i}W)^2
      
    用矩阵表示为
      \small L = (Y - XW)^{T}(Y - XW)
      
      其中 X 是 (m,n) 矩阵,W 是 (n,1) 矩阵,Y 是 (m,1) 矩阵

    \small W 求导
      
      \small \frac{\partial L}{\partial W} = \frac{\partial (Y - XW)^{T}(Y - XW)}{\partial W}
      
         \small = \frac{\partial (Y^{T} - W^{T}X^{T})(Y - XW)}{\partial W}
      
         \small = \frac{\partial (Y^{T}Y - Y^{T}XW - W^{T}X^{T}Y + W^{T}X^{T}XW)}{\partial W}
      
         \small = \frac{\partial Y^{T}Y}{\partial W} - \frac{\partial Y^{T}XW}{\partial W} - \frac{\partial W^{T}X^{T}Y}{\partial W} + \frac{\partial W^{T}X^{T}XW}{\partial W}
       
         \small = 0 - X^{T}Y - X^{T}Y + (X^{T}X + (X^{T}X)^{T})W
       
         \small = - 2X^{T}Y + (2X^{T}X)W
       
         \small = - 2X^{T}(Y - XW)
      
    另导数为 0 得到最优的 \small W
      
      \small - 2X^{T}(Y - XW) = 0
      \small X^{T}Y = X^{T}XW
      \small (X^{T}X)^{-1}X^{T}Y = (X^{T}X)^{-1}X^{T}XW
      
      \small W = (X^{T}X)^{-1}X^{T}Y
      
    代码

    def standRegres(xArr, yArr):
        """
        xArr - 样本特征,是 (m,n) 矩阵,每行的第一个值既 X0 固定为 1
        yArr - 样本标签,是 (1,m)
        """
        xMat = np.mat(xArr)
        yMat = np.mat(yArr).T
    
        xTx = xMat.T * xMat
        if np.linalg.det(xTx) == 0.0:
            # 如果行列式等于 0,意味着没有逆矩阵
            return None
    
        # 也可以用 ws = np.linalg.solve(xTx, xMat.T*yMat)
        w = xTx.I * xMat.T * yMat
    
        # ws 是 (n,1) 矩阵
        return w
    

    通过相关系统判断效果好坏

    # 结果越接近 1 效果越好
    np.corrcoef(yEstimate, yActual)
    
    局部加权线性回归 (Locally Weighted Linear Regression,LWLR)

    线性回归的一个问题是有可能出现欠拟合现象,就是偏离拟合曲线的点比较多
    与此对应的有过拟合问题,就是拟合曲线过于迎合数据点,这意味着曲线被噪点干扰比较大
      
    解决欠拟合问题的一个方法是局部加权线性回归
      给待预测点附近的每个点赋予权重,然后在这个子集上基于最小均方差进行普通的回归
      注意:与 kNN 一样,这种算法每次预测均需要事先选取出对应的数据子集
      
    LWLR 使用核函数来对附近的点赋予权重,核的类型可以自由选择,常用的是高斯核
      
      \small Weight(i,i) = exp(\frac{|x_{i}-x|}{-2k^{2}})
      
      只含对角元素的矩阵,x 是测试点,xi 与 x 越近权重越大,k 越大权重越大,权值必然小于 1
      k 越大越容易欠拟合,越小越容易过拟合
      
    算法如下
      \small W = (X^{T}Weight\ X)^{-1}X{^T}Weight\ Y
      
    代码

    def lwlr(testPoint, xArr, yArr, k=1.0):
        """
        testPoint - 待预测的点 (1,n)
        xArr - 样本特征 (m,n),每个样本的第一个值既 X0 固定为 1
        yArr - 样本标签 (1,m)
        """
        xMat = np.mat(xArr)
        yMat = np.mat(yArr).T
    
        m = np.shape(xMat)[0]
    
        # eye 是单位矩阵,对角线是 1,其余是 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 np.linalg.det(xTx) == 0.0:
            # 如果行列式等于 0,意味着没有逆矩阵
            return
    
        # 得出回归系数 (n,1)
        w = xTx.I * (xMat.T * (weights * yMat))
        return testPoint * w
    
    
    缩减法

    如果数据的特征比样本点还多,则不能再使用前面的方法,因为在计算逆矩阵时会出错
      
    岭回归
      岭回归最先用来处理特征数多于样本数的情况
      现在也用于在估计中加入偏差,从而得到更好的估计
      
      为 \small X^TX 加上 \small r \cdot I 使得矩阵可逆,其中 r 是用户定义的数值,I 是单位矩阵
      回归系数
        \small W = (X^{T}X + rI)^{-1}X^TY
        
      代码

    def ridgeRegres(xMat, yMat, lam=0.2):
        """
        xMat - 样本特征 (m,n),每个样本的第一个值既 X0 固定为 1
        yMat - 样本标签 (1,m)
        """
        xTx = xMat.T * xMat
    
        # 加上 r*I 使得矩阵可逆
        denom = xTx + np.eye(np.shape(xMat)[1]) * lam
        if np.linalg.det(denom) == 0.0:
            return
    
        w = denom.I * (xMat.T * yMat)
        return w
    
    
    def ridgeTest(xArr, yArr):
        """
        xArr - 样本特征 (m,n),每个样本的第一个值既 X0 固定为 1
        yArr - 样本标签 (1,m)
        """
        xMat = np.mat(xArr)
        yMat = np.mat(yArr).T
    
        # Y 数据标准化,减去均值
        yMean = np.mean(yMat, 0)
        yMat = yMat - yMean
    
        # X 数据标准化,减去均值,除以方差
        xMeans = np.mean(xMat, 0)
        xVar = np.var(xMat, 0)
        xMat = (xMat - xMeans) / xVar
    
        numTestPts = 30
        # 初始化回归系数矩阵,每行是一次迭代产生的回归系数
        wMat = np.zeros((numTestPts, np.shape(xMat)[1]))
        for i in range(numTestPts):
            # 迭代,尝试不同的 r 参数
            ws = ridgeRegres(xMat, yMat, np.exp(i - 10))
            wMat[i, :] = ws.T
    
        # 返回所有回归系数,为了定量地找到最佳参数值,还需要进行交叉验证
        # 一般讲,r 很小时就和普通回归系数一样,r 很大时回归系数趋向于 0
        return wMat
    
    


    lasso 方法
      限制所有回归系数的绝对值的和必须小于某个值
        \small \sum_{k=1}^{n}w_{k}^{2} \leqslant \lambda
      
    前向逐步回归
      属于一种贪心算法,每步尽可能减少误差
      一开始所有的权重都设为 1,然后每步所做的决策是对某个权重增加或减少一个很小的值
      
      前向逐步回归算法可以得到与 lasso 差不多的效果,但更加简单
      
      代码

    def stageWise(xArr, yArr, step=0.01, numIt=100):
        """
        xArr - 样本特征 (m,n),每个样本的第一个值既 X0 固定为 1
        yArr - 样本标签 (1,m)
        step - 步长
        numIt - 迭代次数
        """
        xMat = np.mat(xArr)
        yMat = np.mat(yArr).T
    
        # Y 数据标准化,减去均值
        yMean = np.mean(yMat, 0)
        yMat = yMat - yMean
    
        # X 数据标准化,减去均值,除以方差
        xMeans = np.mean(xMat, 0)
        xVar = np.var(xMat, 0)
        xMat = (xMat - xMeans) / xVar
    
        m, n = np.shape(xMat)
    
        # 初始化回归系数矩阵,每行是一次迭代产生的回归系数
        returnMat = np.zeros((numIt, n))
        ws = np.zeros((n, 1))
        wsMax = ws.copy()
    
        # 迭代
        for i in range(numIt):
            lowestError = np.inf
    
            # 每个系数
            for j in range(n):
                # 每个方向
                for sign in [-1, 1]:
                    wsTest = ws.copy()
    
                    # 在上一次迭代产生的系数向量的基础上,按指定的步长、指定的方向,调整指定的系数
                    wsTest[j] += step * sign
    
                    # 预测结果
                    yTest = xMat * wsTest
    
                    # 计算方差
                    rssE = ((yMat.A - yTest.A) ** 2).sum()
    
                    # 效果更好则保存该系数
                    if rssE < lowestError:
                        lowestError = rssE
                        wsMax = wsTest
    
            # 得到本次迭代的最佳系数
            ws = wsMax.copy()
    
            # 保存该最佳系数
            returnMat[i, :] = ws.T
    
        # 返回结果
        return returnMat
    
    

    相关文章

      网友评论

          本文标题:机器学习:线性回归

          本文链接:https://www.haomeiwen.com/subject/cwyldhtx.html