欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

神经网络与深度学习(6)

程序员文章站 2022-07-14 19:23:24
...

1. 向量化

1.1向量化是什么

我们这里首先就要详细介绍一下向量化。 我们要向量化的地方主要是logsitic回归中的z=WTX+b中的循环计算,因为我们知道W和X都是向量,如果一定要实现的话,可能是这样子(原谅吴大大的真迹):
神经网络与深度学习(6)
这样就需要很多循环嵌套,而如果使用向量化的话,那么算法就非常简单了:
神经网络与深度学习(6)
只需要这样一句话,其核心就是np.dot(w,x),这是python里的数组的点乘操作。

1.2 到底快多少

那么这样的转换到底有多快才是我们要关注的问题,如果是在同一个数量级上,那么优化也没有太多的意义呀。别急,我们编写代码来实现一下,然后对比看看所花费的时间就知道了。

比较代码如下:

import numpy as np
import time
a=np.random.rand(1000000)
b=np.random.rand(1000000)
tic=time.time();
c=np.dot(a,b)
toc=time.time();
print(c)
print("Vectorization:"+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:"+str(1000*(toc-tic))+"ms")

输出结果如下:

250096.917742
Vectorization:1.001596450805664ms
250096.917742
For:650.4576206207275ms

可以看到这两者速度的差距可以达到600倍左右的数量级。这基本上是相当于你1分钟出结果的代码,如果使用循环的话,可能需要10个小时才能出来。这差距就很大了。如果是1天能出结果的,用循环的话,可能需要600天。这就不能够接受了。

1.3原理

这背后的原理如同吴恩达所说,是使用了SIMD(Single Instruction Multiple Data,单指令多数据流)指令集,这个指令集在CPU和GPU上面都有,可以在C语言或者Java语言编写过程中获得代码优化,只不过GPU上面更胜一筹,具体的可以参见《SIMD指令集》。

事实上,python的numpy的操作,只有在对array类型的对象时,才会表现出非凡的速度,否则的话,它可能还不如python内置函数(毕竟内置函数也是经过精心优化过的),具体比较参见《Python内置函数与numPy运算速度对比》。

2. 向量化的应用

2.1 在更多范围上应用

上面只是举了一个例子,其实使用向量化计算可以有很多更方便的操作。
例如对向量中的每一个取指数,取对数,取绝对值,取最大值等等。都可以使用numpy的函数。

import numpy as np
u=np.array(X)#u是一个数组
u=np.exp(v)#取指数
u=np.log(v)#取对数
u=np.abs(v)#取绝对值

那么它怎么应用到加速我们的logistic回归上呢。

2.2 向量化去掉一个循环

首先我们还记得之前我们的代码中有两个循环,如下图所示:
神经网络与深度学习(6)
我们所要做的就是让这两个循环消失,首先我们先消失第二个循环,只需要这样做就可以了。

dw=np.zeros((n,1))#初始化dw为一个n*1的向量
......
dw+=x[i]dz[i]#替换第二个循环方框中的代码
......
dw/=m#再最后平均其值

但是现在我们只消失了一个循环,如何把第一个循环也去掉呢?

2.3 去掉另一个循环

我们回顾一下我们所要做的事情。
神经网络与深度学习(6)

我们第一个循环无怪乎是在做这样的重复的事情。如果我们把W看做是一个1*n的向量的话,就似乎容易了很多,最终就可以转换为:

Z=[z1,z2,z3,...zm]=[w1,w2,...,wn][x1,x2,...,xm]+[b,b,...,b]
的形式,其中xi为列向量。

可能我这样解释,不够形象,还是搬出吴大大的手绘吧:
神经网络与深度学习(6)

这样可能更有助于大家的理解。那么这么一个复杂的公式的话,该怎么实现呢?只需要一行代码就可以实现了。

Z=np.dot(W,X)+b

最神奇的地方还在于你这样写,pyhon会自动把b转换为一个向量。吴大大说,这叫做“广播”(我读书少,我记得广播在C#、Java里不是这意思)。那么什么是广播呢,在后面的讲解中我们会进一步介绍。

大家有没有发现,直到现在,我们已经把2个循环都去掉了。但是实际上我们还是有一点没有做,那就是我们只是做了正向传播,反向传播的过程我们还没有向量化。这个,我们留到下一节再讲。