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

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

简单的线性回归的实现

首先我们在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_

输出结果如下
【笔记】简单的线性回归的实现以及向量化的实现

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

上一篇:API解析------------在逻辑回归中predict()与score()的用法


下一篇:python实现BP神经网络