Regression算法

文章目录

  • 用线性回归找到最佳拟合直线
    • 标准回归函数
    • 局部加权线性回归函数

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

      from google.colab import drive
      drive.mount("/content/drive")
      
      Mounted at /content/drive
      
      from numpy import *
      
      def loadDataSet(fileName):
        numFeat = len(open(fileName).readline().split('\t')) - 1
        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
      

      这段代码定义了一个名为loadDataSet的函数,用于加载数据集并将其分为特征矩阵和标签向量。以下是对该函数的代码分析:

      def loadDataSet(fileName):
          numFeat = len(open(fileName).readline().split('\t')) - 1
          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. numFeat = len(open(fileName).readline().split('\t')) - 1

        • 通过打开文件并读取第一行,计算特征的数量。这里假设数据集是用 tab 分隔的文本文件,每一行的最后一个元素是标签。
        • 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]))

                      • 将当前行的特征值转换为浮点数并添加到 lineArr 中。
                      • dataMat.append(lineArr) 和 labelMat.append(float(curLine[-1]))

                        • 将特征数据添加到 dataMat 列表中,将标签值添加到 labelMat 列表中。
                        • return dataMat, labelMat

                          • 返回特征矩阵和标签向量作为元组。

      该函数的作用是从文件中读取数据集,并将其分为特征矩阵和标签向量。

      标准回归函数

      def standRegres(xArr, yArr):
        xMat = mat(xArr)
        yMat = mat(yArr).T
        xTx = xMat.T * xMat
        if linalg.det(xTx) == 0:
          print("This matrix is singular, cannot do inverse")
          return
        ws = xTx.I * (xMat.T * yMat)
        return ws
      

      这段代码是用于实现普通最小二乘线性回归(OLS)的 Python 函数。下面是对函数的代码分析:

      1. def standRegres(xArr, yArr):

        • 函数的定义,它接受两个参数:xArr是一个列表或数组,包含输入特征的数据集;yArr是一个列表或数组,包含对应的目标变量值。
        • xMat = mat(xArr)

          • 将输入特征数据集转换为一个 NumPy 矩阵。
          • yMat = mat(yArr).T

            • 将目标变量数据集转换为一个 NumPy 矩阵,并且将其转置,以确保其为列向量。
            • xTx = xMat.T * xMat

              • 计算特征数据矩阵的转置与其自身的乘积。这是用来计算线性回归系数的一个步骤。
              • if linalg.det(xTx) == 0:

                • 使用线性代数库(linalg)中的det()函数计算矩阵xTx的行列式(Determinant)。如果行列式为0,则说明矩阵不可逆(singular),这种情况下无法求解线性回归,因此打印错误消息并返回。
                • ws = xTx.I * (xMat.T * yMat)

                  • 如果矩阵可逆,那么使用矩阵的逆(I)乘以特征矩阵转置与目标变量矩阵的乘积来计算回归系数(weights)。
                  • return ws

                    • 返回计算得到的回归系数。

      该函数实现了基本的线性回归,通过计算输入特征与目标变量之间的关系,得出一个线性模型,用于预测目标变量的值。

      xArr, yArr = loadDataSet('/content/drive/MyDrive/Colab Notebooks/MachineLearning/《机器学习实战》/06丨预测数值型数据:回归/用线性回归找到最佳拟合直线/ex0.txt')
      
      xArr[:2]
      
      [[1.0, 0.067732], [1.0, 0.42781]]
      
      ws = standRegres(xArr, yArr)
      
      ws
      
      matrix([[3.00774324],
              [1.69532264]])
      
      xMat = mat(xArr)
      yMat = mat(yArr)
      yHat = xMat * ws
      
      import matplotlib.pyplot as plt
      fig = plt.figure()
      ax = fig.add_subplot(111)
      ax.scatter(xMat[:,1].flatten().A[0], yMat.T[:,0].flatten().A[0])
      xCopy = xMat.copy()
      xCopy.sort(0)
      yHat = xCopy*ws
      ax.plot(xCopy[:,1], yHat)
      plt.show()
      
      yHat = xMat*ws
      
      yHat.shape
      
      (200, 1)
      
      yMat.shape
      
      (1, 200)
      
      corrcoef(yHat.T, yMat)
      
      array([[1.        , 0.98647356],
             [0.98647356, 1.        ]])
      

      局部加权线性回归函数

      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("This matrix is singular, cannot do inverse")
          return
        ws = xTx.I * (xMat.T * (weights * yMat))
        return testPoint * ws
      

      这段代码实现了局部加权线性回归(Locally Weighted Linear Regression,LWLR)的函数。以下是对该函数的代码分析:

      1. def lwlr(testPoint, xArr, yArr, k=1.0):

        • 函数的定义,它接受四个参数:testPoint是待预测的数据点;xArr是一个列表或数组,包含输入特征的数据集;yArr是一个列表或数组,包含对应的目标变量值;k是一个可选参数,控制权重的带宽,默认为1.0。
        • xMat = mat(xArr)

          • 将输入特征数据集转换为一个 NumPy 矩阵。
          • yMat = mat(yArr).T

            • 将目标变量数据集转换为一个 NumPy 矩阵,并且将其转置,以确保其为列向量。
            • m = shape(xMat)[0]

              • 获取输入特征矩阵的行数,即数据集中样本的数量。
              • weights = mat(eye(m))

                • 创建一个单位矩阵作为权重矩阵,其大小为 m × m m \times m m×m,其中 m m m为数据集中样本的数量。
                • for j in range(m):

                  • 遍历数据集中的每个样本。
                  • diffMat = testPoint - xMat[j, :]

                    • 计算测试点与当前样本之间的差值。
                    • weights[j, j] = exp(diffMat*diffMat.T/(-2.0*k**2))

                      • 计算当前样本的权重,利用高斯核函数,其中 e x p exp exp 是指数函数, k k k 是带宽参数。
                      • xTx = xMat.T * (weights * xMat)

                        • 计算加权的特征矩阵的转置与自身的乘积。
                        • if linalg.det(xTx) == 0.0:

                          • 检查加权特征矩阵的行列式是否为0,如果是则无法求逆,打印错误消息并返回。
                          • ws = xTx.I * (xMat.T * (weights * yMat))

                            • 如果加权特征矩阵可逆,那么使用矩阵的逆(I)乘以加权特征矩阵转置与目标变量矩阵的乘积来计算回归系数。
                            • 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
      
      xArr, yArr = loadDataSet('/content/drive/MyDrive/Colab Notebooks/MachineLearning/《机器学习实战》/06丨预测数值型数据:回归/用线性回归找到最佳拟合直线/ex0.txt')
      
      yArr[0]
      
      3.176513
      
      lwlr(xArr[0], xArr, yArr, 1.0)
      
      :8: DeprecationWarning: Conversion of an array with ndim > 0 to a scalar is deprecated, and will error in future. Ensure you extract a single element from your array before performing this operation. (Deprecated NumPy 1.25.)
        weights[j, j] = exp(diffMat*diffMat.T/(-2.0*k**2))
      matrix([[3.12204471]])
      
      lwlr(xArr[0], xArr, yArr, 0.001)
      
      :8: DeprecationWarning: Conversion of an array with ndim > 0 to a scalar is deprecated, and will error in future. Ensure you extract a single element from your array before performing this operation. (Deprecated NumPy 1.25.)
        weights[j, j] = exp(diffMat*diffMat.T/(-2.0*k**2))
      matrix([[3.20175729]])
      
      yHat = lwlrTest(xArr, xArr, yArr, 0.01)
      
      :8: DeprecationWarning: Conversion of an array with ndim > 0 to a scalar is deprecated, and will error in future. Ensure you extract a single element from your array before performing this operation. (Deprecated NumPy 1.25.)
        weights[j, j] = exp(diffMat*diffMat.T/(-2.0*k**2))
      :5: DeprecationWarning: Conversion of an array with ndim > 0 to a scalar is deprecated, and will error in future. Ensure you extract a single element from your array before performing this operation. (Deprecated NumPy 1.25.)
        yHat[i] = lwlr(testArr[i], xArr, yArr, k)
      
      xMat = mat(xArr)
      srtInd = xMat[:,1].argsort(0)
      xSort = xMat[srtInd][:,0,:]
      
      import matplotlib.pyplot as plt
      fig = plt.figure()
      ax = fig.add_subplot(111)
      ax.plot(xSort[:,1], yHat[srtInd])
      ax.scatter(xMat[:,1].flatten().A[0], mat(yArr).T.flatten().A[0], s=2, c='red')
      plt.show()