zoukankan      html  css  js  c++  java
  • 机器学习:线性回归

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

    线性回归

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

    (small W) 求导
      
      (large frac{partial L}{partial W} = frac{partial (Y - XW)^{T}(Y - XW)}{partial W})
      
         (large = frac{partial (Y^{T} - W^{T}X^{T})(Y - XW)}{partial W})
      
         (large = frac{partial (Y^{T}Y - Y^{T}XW - W^{T}X^{T}Y + W^{T}X^{T}XW)}{partial W})
      
         (large = 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})
       
         (large = 0 - X^{T}Y - X^{T}Y + (X^{T}X + (X^{T}X)^{T})W)
       
         (large = - 2X^{T}Y + (2X^{T}X)W)
       
         (large = - 2X^{T}(Y - XW))
      
    另导数为 0 得到最优的 (small W)
      
      (large - 2X^{T}(Y - XW) = 0)
      (large X^{T}Y = X^{T}XW)
      (large (X^{T}X)^{-1}X^{T}Y = (X^{T}X)^{-1}X^{T}XW)
      
      (large 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 使用核函数来对附近的点赋予权重,核的类型可以自由选择,常用的是高斯核
      
      (large Weight(i,i) = exp(frac{|x_{i}-x|}{-2k^{2}}))
      
      只含对角元素的矩阵,x 是测试点,xi 与 x 越近权重越大,k 越大权重越大,权值必然小于 1
      k 越大越容易欠拟合,越小越容易过拟合
      
    算法如下
      
      (large 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 是单位矩阵
      回归系数
        
        (large 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 方法
      限制所有回归系数的绝对值的和必须小于某个值
        
        (large 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
    
    


  • 相关阅读:
    C#密封类和密封方法
    C#类和结构以及堆和栈大烩菜(本来就迷,那就让暴风来的更猛烈吧!)
    C#类、对象、方法、属性详解(摘)感谢博客园,感谢提供者。
    软件工程第十五周总结
    软件工程课堂十一(计算最长英语单词链)
    软件工程第十四周总结
    梦断代码阅读笔记03
    软件工程课堂十(找水王)
    软件工程课堂九(用户体验评价)
    软件工程第十三周总结
  • 原文地址:https://www.cnblogs.com/moonlight-lin/p/12445390.html
Copyright © 2011-2022 走看看