在线手机动画网站模板,搜索大全引擎,网站开启微信支付功能,网销是什么该怎么做向量化使得简单线性回归性能提升 一、摘要二、向量化运算概述三、向量化运算在简单线性回归中的应用四、性能测试与结果分析 一、摘要
本文主要讲述了向量化运算在简单线性回归算法中的应用。通过回顾传统for循环方式实现的简单线性回归算法#xff0c;介绍了如何通过最小二乘… 向量化使得简单线性回归性能提升 一、摘要二、向量化运算概述三、向量化运算在简单线性回归中的应用四、性能测试与结果分析 一、摘要
本文主要讲述了向量化运算在简单线性回归算法中的应用。通过回顾传统for循环方式实现的简单线性回归算法介绍了如何通过最小二乘法计算a的值。然而这种方式在计算性能上存在效率较低的问题。为了提高性能视频引入了向量化运算的概念即将计算过程从循环方式转变为向量之间的计算。通过向量化运算可以快速地计算出结果相比传统的for循环方式在性能上具有显著的优势。视频还强调了向量化运算需要基于推导的结果进行对于入门级别的同学来说可以先实现更清晰的程序版本再基于这个版本进行向量化以更好地理解算法的原理。
二、向量化运算概述
向量化概述
向量化运算是一种重要的概念可以提高计算性能。通过将计算转换为向量之间的运算可以大大提升性能。
向量化运算性能高的原因 在计算机学科中向量化运算通常比for循环等具有更好的计算性能主要原因如下
硬件层面
利用SIMD指令集现代计算机的CPU通常支持单指令多数据SIMD指令集如Intel的SSE、AVX等。向量化运算能够直接利用这些指令集在一条指令中同时对多个数据元素进行相同的操作例如可以同时对4个或8个单精度浮点数进行加法运算。而for循环每次只能处理一个数据元素需要多条指令来完成相同数量数据的操作这使得向量化运算在数据处理效率上有天然的优势。提高缓存命中率向量化运算通常会连续访问内存中的数据这有利于提高CPU缓存的命中率。因为数据在内存中是连续存储的当加载一个数据元素时相邻的数据元素也很可能被加载到缓存中后续对这些数据的访问就可以直接从缓存中获取大大加快了访问速度。相比之下for循环可能会以非连续的方式访问数据导致缓存失效的情况更频繁需要从内存中多次读取数据增加了访问时间。
软件层面
减少指令开销for循环需要在每次迭代时执行循环控制指令如比较、跳转等这些指令会增加额外的开销。而向量化运算将多个数据的处理合并为一个操作减少了指令的数量和执行时间从而提高了整体性能。编译器优化编译器对向量化运算的优化能力更强。编译器可以识别向量化的代码模式并对其进行更高级的优化如自动展开循环、调整指令顺序等以充分利用硬件的特性。对于for循环虽然编译器也能进行一些优化但由于其灵活性较高编译器很难像对向量化运算那样进行深度优化。并行执行能力向量化运算更适合并行计算。在多核处理器或GPU等并行计算环境中向量化运算可以很容易地将数据划分到不同的核心或线程中进行并行处理从而进一步提高计算速度。for循环虽然也可以通过一些方式实现并行化但需要更多的代码调整和同步操作实现起来相对复杂且可能存在数据竞争等问题影响性能。
三、向量化运算在简单线性回归中的应用
在简单线性回归中a斜率的计算方式可以通过向量化运算来优化。通过将计算转换为向量点乘可以避免使用for循环提高效率。向量化运算的实现 基于上一篇博文中的SimpleLinearRegressionModel类所在工程中文件改名成为SimplyLearnRegressionDemo.py然后在其中新建一个SimpleLinearRegressionVectorModel类使得fit函数通过向量化运算来计算a和b。通过使用numpy的dot方法实现了向量点乘提高了计算速度。具体SimpleLinearRegressionVectorModel代码如下import numpy as npclass SimpleLinearRegressionModel:def __init__(self):# 初始化线性回归模型的参数a和b为Noneself.a_ Noneself.b_ Nonedef fit(self, x_train, y_train):根据训练数据集x_train,y_train训练Simple Linear Regression模型# 断言x_train的维度为1确保是单特征训练数据assert x_train.ndim 1, \Simple Linear Regressor can only solve single feature training data.# 断言x_train和y_train的长度相等确保数据匹配assert len(x_train) len(y_train), \the size of x_train must be equal to the size of y_train# 先分别求出x和y的均值x_mean np.mean(x_train)y_mean np.mean(y_train)# 先求a的分子部分numerator 0.0 # 分子denominator 0.0 # 分母# 遍历训练数据计算分子和分母for x_i, y_i in zip(x_train, y_train):numerator (x_i - x_mean) * (y_i - y_mean)denominator (x_i - x_mean) ** 2# 然后计算a的值self.a_ numerator / denominator# 最后计算b的值self.b_ y_mean - self.a_ * x_meanreturn selfdef predict(self, x_predict):给定待预测数据集x_predict返回表示x_predict的结果向量# 断言x_predict的维度为1确保是单特征数据assert x_predict.ndim 1, \Simple Linear Regressor can only solve single feature training data.# 断言模型已经训练过a_和b_不为Noneassert self.a_ is not None and self.b_ is not None, \must fit before predict!# 对每个待预测数据调用_predict方法生成预测结果数组return np.array([self._predict(x) for x in x_predict])def _predict(self, x_single):给定单个待预测数据x_single返回x_single的预测结果值# 根据训练得到的参数a_和b_进行预测计算return self.a_ * x_single self.b_def __repr__(self):# 返回模型的字符串表示形式return SimpleLinearRegressionModel()向量化的方式实现简单线性回归的算法class SimpleLinearRegressionVectorModel:def __init__(self):# 初始化线性回归模型的参数a和b为Noneself.a_ Noneself.b_ Nonedef fit(self, x_train, y_train):根据训练数据集x_train,y_train训练Simple Linear Regression模型# 断言x_train的维度为1确保是单特征训练数据assert x_train.ndim 1, \Simple Linear Regressor can only solve single feature training data.# 断言x_train和y_train的长度相等确保数据匹配assert len(x_train) len(y_train), \the size of x_train must be equal to the size of y_train# 先分别求出x和y的均值x_mean np.mean(x_train)y_mean np.mean(y_train)# 先求a的分子部分# 向量化的方式实现numerator (x_train - x_mean).dot(y_train - y_mean)denominator (x_train - x_mean).dot(x_train - x_mean)# 然后计算a的值self.a_ numerator / denominator# 最后计算b的值self.b_ y_mean - self.a_ * x_meanreturn selfdef predict(self, x_predict):给定待预测数据集x_predict返回表示x_predict的结果向量# 断言x_predict的维度为1确保是单特征数据assert x_predict.ndim 1, \Simple Linear Regressor can only solve single feature training data.# 断言模型已经训练过a_和b_不为Noneassert self.a_ is not None and self.b_ is not None, \must fit before predict!# 对每个待预测数据调用_predict方法生成预测结果数组return np.array([self._predict(x) for x in x_predict])def _predict(self, x_single):给定单个待预测数据x_single返回x_single的预测结果值# 根据训练得到的参数a_和b_进行预测计算return self.a_ * x_single self.b_def __repr__(self):# 返回模型的字符串表示形式return SimpleLinearRegressionVectorModel()四、性能测试与结果分析 在jupyter中进行性能测试 # 导入在PyCharm中封装好的工程项目
import sys
project_path D:/PycharmProjects/pythonProject/
if project_path not in sys.path:sys.path.append(project_path)from SimpleLinearRegressionDemo import SimpleLinearRegressionModel
from SimpleLinearRegressionDemo import SimpleLinearRegressionVectorModel# for循环实现的
sreg SimpleLinearRegressionModel()
# 向量化实现的
vreg SimpleLinearRegressionVectorModel()# 定义一个随机的测试数据
num 100000
# 自定义线性方程中的x,随机给定
big_x np.random.random(sizenum)
# 定义线性方程中的y其中np.random.normal(sizenum)是给定了一个噪声
big_y big_x * 2.0 3.0 np.random.normal(sizenum)# 使用魔法命令%timeit计算程序执行所花时间
%timeit sreg.fit(big_x,big_y)
%timeit vreg.fit(big_x,big_y)执行结果如下 51.9 ms ± 546 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
760 µs ± 11.9 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)下面为你详细解释其含义 第一行51.9 ms ± 546 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) 51.9 ms这是每次循环的平均执行时间单位是毫秒ms也就是说该代码每次循环平均花费 51.9 毫秒来执行。± 546 µs这表示测量结果的标准差单位是微秒µs。标准差反映了多次测量结果的离散程度这里说明每次循环执行时间在平均时间 51.9 毫秒左右波动波动范围大约是正负 546 微秒。mean ± std. dev. of 7 runs, 10 loops each这描述了测量的具体方式。7 runs 表示进行了 7 次独立的测试运行10 loops each 表示每次运行中代码循环执行了 10 次。最终的平均时间和标准差是基于这 7 次运行每次 10 个循环的所有测量结果计算得出的。 第二行760 µs ± 11.9 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each) 760 µs每次循环的平均执行时间单位是微秒µs即该代码每次循环平均花费 760 微秒来执行。± 11.9 µs测量结果的标准差单位是微秒。说明每次循环执行时间在平均时间 760 微秒左右波动波动范围大约是正负 11.9 微秒。mean ± std. dev. of 7 runs, 1,000 loops each同样描述了测量方式。进行了 7 次独立的测试运行每次运行中代码循环执行了 1000 次平均时间和标准差是基于这些测量结果计算的。 对比分析 从这两组数据可以看出第二组代码的执行效率明显高于第一组。第二组每次循环平均耗时 760 微秒而第一组每次循环平均耗时 51.9 毫秒即 51900 微秒。你可以根据这些性能数据来优化代码或者选择更高效的实现方式。 在jupyter中执行过程 结果显示向量化运算实现的SimpleLinearRegressionVectorModel性能大幅提升达到了68倍的速度提升。