13-向量化运算

向量化运算


  在上一篇博客中我们实现了一个属于我们自己的简单的线性回归算法。不过,我们的实现相对来说性能是比较低的。那么在这篇博客中,我将介绍一个非常重要的概念,叫做向量化运算

  我们首先回顾一下,之前实现的简单的线性回归算法。是优化下图中这样一个损失函数,使得这个损失函数达到最小值,那么我们通过最小二乘法的方法计算出了 a 和 b 相应的计算方式。
在这里插入图片描述
  对于 b 的计算方式非常简单,关键是对于 a 的计算方式。对于 a 的计算方式,我们之前使用了一个循环的方式来依次计算出了分子和分母这 m 个项然后将它们相加在一起。回忆一下,之前在学习 numpy 数组的时候说过,我们使用 for 循环的方式相对来讲性能效率是比较低的,不过有办法将这个计算变成向量之间计算的话,那么性能就会大大的提升,这就是向量化运算的意思。

  下面我们再来看看 a 的这个表达式:
在这里插入图片描述
  我们观察 a 的分子和分母,我们会发现它们都属于下图这样一种形式:
在这里插入图片描述
  就是对于 w 和 v 两个向量,将这两个向量中每个向量的对应项相乘最终再相加,所以我们就可以仔细研究一下上图这个式子,是不是对于这个式子,只能使用 for 循环的方式来进行计算呢?

  显然不是的。我们通过观察发现,我们可以让:
在这里插入图片描述
在这里插入图片描述
  然后,我们就可以将原式等价于:
在这里插入图片描述
  回想一下,在向量之间进行点乘就是对于这两个向量来说,对应的项相乘再相加。这样一来我们就可以使用 numpy 中向量的运算法则,非常快速的求出该式子,我们只需要将 w 和 v 两个向量进行点乘就可以了。那么,相信你已经明白了,为什么最后需要将 a 整理成下图所示的式子:
在这里插入图片描述
  原因就在于我们可以将它做向量化运算。下面,我们就具体实现一下。

  在之前的 SimpleLinearRegression.py 文件中添加一个类:SimpleLinearRegression2

import numpy as np

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训练模型"""
        assert x_train.ndim == 1, \
            "Simple Linear Regression can only solve single feature training data"
        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, y in zip(x_train, y_train):
            num += (x - x_mean) * (y - y_mean)
            d += (x - 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, 返回表示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, 返回x_single的预测结果值"""
        return self.a_ * x_single + self.b_
    def __repr__(self):
        return "SimpleLinearRegression1()"

# 使用向量化运算
# 只需要改变 fit 函数
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训练模型"""
        assert x_train.ndim == 1, \
            "Simple Linear Regression can only solve single feature training data"
        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, 返回表示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, 返回x_single的预测结果值"""
        return self.a_ * x_single + self.b_
    def __repr__(self):
        return "SimpleLinearRegression2()"

  然后,我们首先对 SimpleLinearRegression2 进行测试:

在这里插入图片描述
在这里插入图片描述
  我们从得到的图像可以看出,得到的图像是一致的。说明我们使用向量化实现的SimpleLinearRegression 没有问题。


  接下来,我们对两种方式进行性能的测试与比较:

  我们依然是接着上一篇博客中的 Jupyter Notebook 继续写。

在这里插入图片描述


  那么到这里,就介绍完了一个机器学习过程中一个非常重要的概念,向量化运算。在下一篇博客中,将会回到解决回归问题的问题中来。我们现在已经实现出了一个版本的线性回归算法,虽然是简单的线性回归,但是和我们之前实现 kNN 一样,我们实现出这个算法并不是我们整个应用机器学习算法的一个结束,关键是我们要评价一下衡量一下我们的这个算法到底好不好,我们在分类问题中可以比较容易的使用分类的准确度(accuracy)来进行评价,那么我们在回归问题中,应该如何评价我们这个线性回归问题的好坏呢?请听下回分解~~


具体代码见 12-简单线性回归的实现

猜你喜欢

转载自blog.csdn.net/qq_41033011/article/details/109007618