• 【笔记】简单的线性回归的实现以及向量化的实现


    简单的线性回归的实现以及向量化的实现

    简单的线性回归的实现

    首先我们在notebook上先加载上相应的库

      import numpy as np
      import matplotlib.pyplot as plt
    

    我们先使用自己设计的一个假的数据来实验

      x = np.array([1,2,3,4,5])
      y = np.array([1,3,2,3,5])
    

    在将x和y都设计出来以后,我们再用散点图的方式将这个数据集可视化出来

      plt.scatter(x,y)
      plt.axis([0,6,0,6])
    

    可视化以后的图片如下

    然后我们推导一下这个公式,看看是如何实现的

    我们首先是计算x和y相应的均值

      x_mean = np.mean(x)
      y_mean = np.mean(y)
    

    然后我们开始具体的计算a和b,重点是a的计算,从公式来看,a相当于由一个分子一个分母构成的,分子分母部分都是求和得出的,将分子设为num,分母为d,进行初始化,都初始化为0

      num = 0.0
      d = 0.0
    

    在循环中,我们每次都从x和y中取出一个值,我们设这个值为x_i和y_i,使用zip方式将这两个放在一起,每次都各取一个值,然后分子分母部分就按照公式计算

      for x_i,y_i in zip(x,y):
          num += (x_i - x_mean) * (y_i - y_mean)
          d += (x_i - x_mean) ** 2
    

    那么a就是分子除以分母

      a = num /d
    

    相应的,b就是用y的均值减去a乘上x的均值

      b = y_mean - a * x_mean
    

    a和b如下

    我们可以将这条直线可视化出来,我们可以设其为y_hat

      y_hat = a * x + b
    

    在绘制方面,首先我们使用散点图的方式将数据绘制出来,然后我们使用plot将直线再绘制出来,设其颜色为红色,坐标轴范围0-6

      plt.scatter(x,y)
      plt.plot(x,y_hat,color='r')
      plt.axis([0,6,0,6])
    

    图像如下图所示

    现在,如果来了一个新的x

      x_predict = 6
    

    那么y就等于ax+b

      y_predict = a * x_predict + b
    

    预测结果可得

      y_predict
    

    那么我们可以在python chame中写出属于自己的简单的线性回归算法,思想与上面无异
    代码如下

      import numpy as np
      from metrics import r2_score
    
    
            class SimpleLinearRegression1:
    
          def __init__(self):
              """初始化Simple linear Regression模型"""
              self.a_ = None
              self.b_ = None
    
          def fit(self, x_train, y_train):
              """根据训练数据集x_train,y_train训练Simple Linear Regression模型"""
              assert x_train.ndim == 1, 
                  "simple Linear Regression can only solve single"
              assert len(x_train) == len(y_train), 
                  "the size of x train must be equal to the size of y_train"
    
              x_mean = np.mean(x_train)
              y_mean = np.mean(y_train)
    
              num = 0.0
              d = 0.0
              for x_i, y_i in zip(x_train, y_train):
                  num += (x_i - x_mean) * (y_i - y_mean)
                  d += (x_i - x_mean) ** 2
    
              self.a_ = num / d
              self.b_ = y_mean - self.a_ * x_mean
    
              return self
    
          def predict(self, x_predict):
              """给定待预测数掘集x_predict,返同表示x_predict的结果向量"""
              assert x_predict.ndim == 1, 
                  "simple Linear Regression can only solve single feature training data."
              assert self.a_ is not None and self.b_ is not None, 
                  "must fit before predict! "
    
              return np.array([self._predict(x) for x in x_predict])
    
          def _predict(self, x_single):
             "给定单个待预测数据x_single,返同x_single的阿测结果值"""
              return self.a_ * x_single + self.b_
    
          def score(self, x_test, y_test):
              """根据给定的测试数据集确定当前的模型"""
    
              y_predict = self.predict(x_test)
              return r2_score(y_test, y_predict)
    
          def __repr__(self):
              return "SimpleLinearRegression1()"
    

    使用自己的算法
    首先我们在notebook中引用自己写好的

      from SimpleLinearRegression import SimpleLinearRegression1
    

    然后我们对其进行实例化

      reg1 = SimpleLinearRegression1()
    

    然后我们fit一下x和y就可以了

      reg1.fit(x,y)
    

    之后我们进行预测,因为要求是一个数组,因此使用np.array进行包装一下

      reg1.predict(np.array([x_predict]))
    

    然后我们可以看一下具体学到的a和b的参数

      reg1.a_
      reg1.b_
    

    然后我们再绘制一下这条直线,方法很简单,和上面操作没有什么差别,依然是设置直线,绘制散点图,再绘制出直线即可

      y_hat1 = reg1.predict(x)
      plt.scatter(x,y)
      plt.plot(x,y_hat1,color='r')
      plt.axis([0,6,0,6])
    

    图像如下

    我们如果想使其效率更高一些的话,可以使用向量化这个技巧

    向量化的实现

    上面我们使用循环的方式将a给求出来的,使用for循环的话,性能是不高的,如果可以将其改成向量的运算,那么性能将会有一定的提升的

    我们可以将上述的a变换成两个向量之间的计算

    对于这个式子,我们是可以不使用for循环一直计算的
    w可以表示成(w1,w2,…,wm)
    v可以表示成(v1,v2,…,vm)
    那么其就变成了w点乘v

    这样我们就可以直接使用numpy中向量的运算
    这样的性能是比for循环高很多的

    实现方面

    我们先将SimpleLinearRegression中的代码进行修改,增添一个类SimpleLinearRegression2,将其修改成向量的运算方式,我们只需要改变fit函数的逻辑就可以,将num分子改成点乘的方式,由于出来的是一个数,那么我们使用.dot的方法,对d也同理

    代码如下

      import numpy as np
      from metrics import r2_score
    
    
      class SimpleLinearRegression2:
    
          def __init__(self):
              """初始化Simple linear Regression模型"""
              self.a_ = None
              self.b_ = None
    
          def fit(self, x_train, y_train):
              """根据训练数据集x_train,y_train训练Simple Linear Regression模型"""
              assert x_train.ndim == 1, 
                  "simple Linear Regression can only solve single"
              assert len(x_train) == len(y_train), 
                  "the size of x train must be equal to the size of y_train"
    
              x_mean = np.mean(x_train)
              y_mean = np.mean(y_train)
      
              num = (x_train - x_mean).dot(y_train - y_mean)
              d = (x_train - x_mean).dot(x_train - x_mean)
    
              self.a_ = num / d
              self.b_ = y_mean - self.a_ * x_mean
    
              return self
    
          def predict(self, x_predict):
              """给定待预测数掘集x_predict,返同表示x_predict的结果向量"""
              assert x_predict.ndim == 1, 
                  "simple Linear Regression can only solve single feature training data."
              assert self.a_ is not None and self.b_ is not None, 
                  "must fit before predict! "
    
              return np.array([self._predict(x) for x in x_predict])
    
          def _predict(self, x_single):
              "给定单个待预测数据x_single,返同x_single的结果值"""
              return self.a_ * x_single + self.b_
    
          def score(self, x_test, y_test):
              """根据给定的测试数据集确定当前的模型"""
    
              y_predict = self.predict(x_test)
              return r2_score(y_test, y_predict)
    
          def __repr__(self):
              return "SimpleLinearRegression2()"
    

    那么我们在notebook中来实现一下

    首先还是引用新的类

      from SimpleLinearRegression import SimpleLinearRegression2
    

    然后实例化,然后操作同上

      reg2 = SimpleLinearRegression2()
      reg2.fit(x,y)
      reg2.a_
      reg2.b_
    

    同样绘制一个图片用来可视化

      y_hat2 = reg2.predict(x)
      plt.scatter(x,y)
      plt.plot(x,y_hat2,color='r')
      plt.axis([0,6,0,6])
    

    图像如下

    向量化实现的性能测试
    我们通过创建一个相对于更大的数据,进而再创建一个向量big_x,然后我们再创建一个big_y,使其与big_x产生一个线性关系,但是我们不能让其完全呈现出,在后面添加一个符合正态分布的一个噪音np.random.normal(size=m)

      m = 1000000
      big_x = np.random.random(size=m)
      big_y = big_x * 2.0 + 3.0 + np.random.normal(size=m)
    

    然后我们测试一下两个版本所对应的性能,通过对比就可以知道两者的性能差距是多少

      %timeit reg1.fit(big_x,big_y)
      %timeit reg2.fit(big_x,big_y)
    

    结果如下

    很明显,向量带来的性能提升是很巨大的,所以一般可以向量化就要向量化,不过要基于公式的基础上更深入才可以

    然后我们看一下训练出来的两种a和b的情况

      reg1.a_
      reg1.b_
      reg2.a_
      reg2.b_
    

    输出结果如下

    感谢观看,文笔有限,博客不出彩,还请多多见谅
  • 相关阅读:
    周杰伦理片,吴奇隆胸店,邓紫棋牌室,黄家驹留所,金秀贤鸭蛋,郭富城管员,苍井空调店,齐达内衣店,乔布斯袜店……能接下去么?
    华彬庄园_百度百科
    9月19号-9月21号丰宁坝上草原行
    寻找INTERIGHT衬衫男神! [复制链接]
    新公司,新挑战
    docker~通过vs2017的Dockerfile来生成镜像
    EF架构~codeFirst从初始化到数据库迁移
    干货~powershell与bash和docker在项目中怎么用
    docker~Dockerfile优化程序的部署
    代码混淆 GSON完满解决
  • 原文地址:https://www.cnblogs.com/jokingremarks/p/14282994.html
Copyright © 2020-2023  润新知