神经网络基础篇:向量化(Vectorization)
向量化
向量化是非常基础的去除代码中for循环的艺术,在深度学习安全领域、深度学习实践中,会经常发现自己训练大数据集,因为深度学习算法处理大数据集效果很棒,所以的代码运行速度非常重要,否则如果在大数据集上,代码可能花费很长时间去运行,将要等待非常长的时间去得到结果。所以在深度学习领域,运行向量化是一个关键的技巧,让举个栗子说明什么是向量化。
在逻辑回归中需要去计算\(z={{w}^{T}}x+b\),\(w\)、\(x\)都是列向量。如果有很多的特征那么就会有一个非常大的向量,所以\(w\in {{\mathbb{R}}^{{{n}_{x}}}}\) , \(x\in{{\mathbb{R}}^{{{n}_{x}}}}\),所以如果想使用非向量化方法去计算\({{w}^{T}}x\),需要用如下方式(python)
z=0
for i in range(n_x):
z += w[i]*x[i]
z += b
这是一个非向量化的实现,会发现这真的很慢,作为一个对比,向量化实现将会非常直接计算\({{w}^{T}}x\),代码如下:
z=np.dot(w,x)+b
这是向量化计算\({{w}^{T}}x\)的方法,将会发现这个非常快

让用一个小例子说明一下,在的将会写一些代码(以下是在Jupyter notebook上写的Python代码,)
import numpy as np #导入numpy库
a = np.array([1,2,3,4]) #创建一个数据a
print(a)
# [1 2 3 4]
import time #导入时间库
a = np.random.rand(1000000)
b = np.random.rand(1000000) #通过round随机得到两个一百万维度的数组
tic = time.time() #现在测量一下当前时间
#向量化的版本
c = np.dot(a,b)
toc = time.time()
print("Vectorized version:" + str(1000*(toc-tic)) +"ms") #打印一下向量化的版本的时间
#继续增加非向量化的版本
c = 0
tic = time.time()
for i in range(1000000):
c += a[i]*b[i]
toc = time.time()
print(c)
print("For loop:" + str(1000*(toc-tic)) + "ms")#打印for循环的版本的时间
返回值见图。
在两个方法中,向量化和非向量化计算了相同的值,如所见,向量化版本花费了1.5毫秒,非向量化版本的for循环花费了大约几乎500毫秒,非向量化版本多花费了300倍时间。所以在这个例子中,仅仅是向量化的代码,就会运行300倍快。这意味着如果向量化方法需要花费一分钟去运行的数据,for循环将会花费5个小时去运行。
一句话总结,以上都是再说和for循环相比,向量化可以快速得到结果。
可能听过很多类似如下的话,“大规模的深度学习使用了GPU或者图像处理单元实现”,但是做的所有的案例都是在jupyter notebook上面实现,这里只有CPU,CPU和GPU都有并行化的指令,他们有时候会叫做SIMD指令,这个代表了一个单独指令多维数据,这个的基础意义是,如果使用了built-in函数,像np.function或者并不要求实现循环的函数,它可以让python的充分利用并行化计算,这是事实在GPU和CPU上面计算,GPU更加擅长SIMD计算,但是CPU事实上也不是太差,可能没有GPU那么擅长吧。接下来,将看到向量化怎么能够加速的代码,经验法则是,无论什么时候,避免使用明确的for循环。
以下代码及运行结果截图:



向量化的更多例子(More Examples of Vectorization)
从上面例子中,知道了怎样通过numpy内置函数和避开显式的循环(loop)的方式进行向量化,从而有效提高代码速度。
经验提醒,当在写神经网络程序时,或者在写逻辑(logistic)回归,或者其他神经网络模型时,应该避免写循环(loop)语句。虽然有时写循环(loop)是不可避免的,但是可以使用比如numpy的内置函数或者其他办法去计算。当这样使用后,程序效率总是快于循环(loop)。
让看另外一个例子。如果想计算向量\(u=Av\),这时矩阵乘法定义为,矩阵乘法的定义就是:\(u_{i} =\sum_{j}^{}{A_{\text{ij}}v_{i}}\),这取决于怎么定义\(u_{i}\)值。同样使用非向量化实现,\(u=np.zeros(n,1)\), 并且通过两层循环\(for(i):for(j):\),得到\(u[i]=u[i]+A[i][j]*v[j]\) 。现在就有了\(i\) 和 \(j\) 的两层循环,这就是非向量化。向量化方式就可以用\(u=np.dot(A,v)\),右边这种向量化实现方式,消除了两层循环使得代码运行速度更快。

下面通过另一个例子继续了解向量化。如果已经有一个向量\(v\),并且想要对向量\(v\)的每个元素做指数操作,得到向量\(u\)等于\(e\)的\(v_1\),\(e\)的\(v_2\),一直到\(e\)的\(v_n\)次方。这里是非向量化的实现方式,首先初始化了向量\(u=np.zeros(n,1)\),并且通过循环依次计算每个元素。但事实证明可以通过python的numpy内置函数,帮助计算这样的单个函数。所以会引入import numpy as np,执行 \(u=np.exp(v)\) 命令。注意到,在之前有循环的代码中,这里仅用了一行代码,向量\(v\)作为输入,\(u\)作为输出。已经知道为什么需要循环,并且通过右边代码实现,效率会明显的快于循环方式。
事实上,numpy库有很多向量函数。比如 u=np.log是计算对数函数(\(log\))、 np.abs() 计算数据的绝对值、np.maximum(v, 0) 按元素计算\(v\)中每个元素和和0相比的最大值,v**2 代表获得元素 \(v\) 每个值的平方、 1/v 获取 \(v\) 中每个元素的倒数等等。所以当想写循环时候,检查numpy是否存在类似的内置函数,从而避免使用循环(loop)方式。

那么,将刚才所学到的内容,运用在逻辑回归的梯度下降上,看看是否能简化两个计算过程中的某一步。这是逻辑回归的求导代码,有两层循环。在这例子有\(n\)个特征值。如果有超过两个特征时,需要循环 \(dw_1\) 、\(dw_2\) 、\(dw_3\) 等等。所以 \(j\) 的实际值是1、2 和 \(n_x\),就是想要更新的值。所以想要消除第二循环,在这一行,这样就不用初始化 \(dw_1\) , \(dw_2\) 都等于0。去掉这些,而是定义 \(dw\) 为一个向量,设置 \(u=np.zeros(n(x),1)\)。定义了一个\(x\)行的一维向量,从而替代循环。仅仅使用了一个向量操作 \(dw=dw+x^{(i)}dz^{(i)}\) 。最后,得到 \(dw=dw/m\) 。现在通过将两层循环转成一层循环,仍然还有这个循环训练样本。


希望这个博客有给读者一点向量化感觉,减少一层循环使代码更快,但事实证明能做得更好。所以在下个博客,将进一步的讲解逻辑回归,将会看到更好的监督学习结果。在训练中不需要使用任何 for 循环,也可以写出代码去运行整个训练集。到此为止一切都好。
神经网络基础篇:向量化(Vectorization)的更多相关文章
- 【原创 深度学习与TensorFlow 动手实践系列 - 3】第三课:卷积神经网络 - 基础篇
[原创 深度学习与TensorFlow 动手实践系列 - 3]第三课:卷积神经网络 - 基础篇 提纲: 1. 链式反向梯度传到 2. 卷积神经网络 - 卷积层 3. 卷积神经网络 - 功能层 4. 实 ...
- 基础篇|一文搞懂RNN(循环神经网络)
基础篇|一文搞懂RNN(循环神经网络) https://mp.weixin.qq.com/s/va1gmavl2ZESgnM7biORQg 神经网络基础 神经网络可以当做是能够拟合任意函数的黑盒子,只 ...
- 《量化投资:以MATLAB为工具》连载(2)基础篇-N分钟学会MATLAB(中)
http://www.matlabsky.com/thread-43937-1-1.html <量化投资:以MATLAB为工具>连载(3)基础篇-N分钟学会MATLAB(下) ...
- 《量化投资:以MATLAB为工具》连载(1)基础篇-N分钟学会MATLAB(上)
http://blog.sina.com.cn/s/blog_4cf8aad30102uylf.html <量化投资:以MATLAB为工具>连载(1)基础篇-N分钟学会MATLAB(上) ...
- (转)深度学习word2vec笔记之基础篇
深度学习word2vec笔记之基础篇 声明: 1)该博文是多位博主以及多位文档资料的主人所无私奉献的论文资料整理的.具体引用的资料请看参考文献.具体的版本声明也参考原文献 2)本文仅供学术交流,非商用 ...
- 深度学习word2vec笔记之基础篇
作者为falao_beiliu. 作者:杨超链接:http://www.zhihu.com/question/21661274/answer/19331979来源:知乎著作权归作者所有.商业转载请联系 ...
- Andrew Ng - 深度学习工程师 - Part 1. 神经网络和深度学习(Week 2. 神经网络基础)
=================第2周 神经网络基础=============== ===2.1 二分分类=== ===2.2 logistic 回归=== It turns out, whe ...
- C#多线程之基础篇3
在上一篇C#多线程之基础篇2中,我们主要讲述了确定线程的状态.线程优先级.前台线程和后台线程以及向线程传递参数的知识,在这一篇中我们将讲述如何使用C#的lock关键字锁定线程.使用Monitor锁定线 ...
- 一步步学习javascript基础篇(0):开篇索引
索引: 一步步学习javascript基础篇(1):基本概念 一步步学习javascript基础篇(2):作用域和作用域链 一步步学习javascript基础篇(3):Object.Function等 ...
- 2000条你应知的WPF小姿势 基础篇<15-21>
在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师,对C#和WPF有着极深的热情.最为出色的是他维护了两个博客:2,000Things You Should Know ...
随机推荐
- MySQL数据库操作 Lab1
实验一 MySQL数据库操作 实验目的: 掌握MySQL安装.配置与登录方法,使用MySQL客户创建数据库及对数据库表完成各种操作 实验内容: 1. 安装MySQL数据库管理系统, ...
- 基于Java Swing和BouncyCastle的证书生成工具
"Almost no one will remember what he had just not interested." - Nobody "几乎没有人会记得他所丝毫 ...
- PHP-FFMpeg 操作音视频
目录 安装PHP-FFMpeg 视频中提取一张图片 视频中提取多张图片 调整视频大小 视频添加水印 生成音频波形 音频转换 给音频添加元数据 拼接多个音视频 截取音视频 提取 gif 动图 裁剪视频 ...
- NewStarCTF 2023 公开赛道 WEEK1|CRYPTO全解
一.brainfuck 附件信息 ++++++++[>>++>++++>++++++>++++++++>++++++++++>++++++++++++> ...
- 关于区间DP的一点点心得(虽然还是很菜)
自己今天对于区间 DP 的一个总结 区间 DP 的数组一般是二维,其状态一般表示区间 \((l,r)\). 区间 DP 在思考的时候是有一定套路的,思考时可以按照如下方式进行思考: 这段区间要维护的信 ...
- mysql 表级锁之一lock table
1.lock table t1 read: 1.1.当前线程: 读/写当前表/其他表: unlock tables; lock table t1 read; select * from t1; INS ...
- RLHF · PBRL | 发现部分 D4RL tasks 不适合做 offline reward learning 的 benchmark
论文题目:Benchmarks and Algorithms for Offline Preference-Based Reward Learning,TMLR 20230103 发表. open r ...
- Vue 项目部署到GitHub Pages并同步到Gitee Pages
前言:相信很多前端开发者都拥有自己的vue项目,若想把自己的项目做成网站分享给大家看,最常用的就是利用Github提供的GitHub Pages服务和Gitee提供的Gitee Pages服务.其中, ...
- 文心一言 VS 讯飞星火 VS chatgpt (135)-- 算法导论11.3 1题
一.用go语言,假设我们希望查找一个长度为 n 的链表,其中每一个元素都包含一个关键字k并具有散列值h(k).每一个关键字都是长字符串.那么在表中查找具有给定关键字的元素时,如何利用各元素的散列值呢? ...
- Codeforces Round #736 (Div. 2). D - Integers Have Friends
原题:D - Integers Have Friends 题意: 给定一个数组,求一个最长子数组满足\(a_i \,\, mod \,\, m \,\, = \,\, a_{i + 1} \,\, m ...