向量化可以使计算的速度更快。
那么什么是向量化呢?
例如对于, 其中, , 即都是维的列向量
那么,非向量化 的实现如下:
z = 0
for i in range(n_x)
z += w[i] * x[i]
z +=b
向量化实现:
z = np.dot(w,x) + b
实际用python实现对比发现,向量化实现的运行时间比非向量化快很多。 以下以实际python实现进行对比。
import time
import numpy as np
a = np.random.rand(1000000)
b = np.random.rand(1000000)
# 向量化实现
tic = time.time()
c = np.dot(a, b)
toc = time.time()
print(c)
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")
运行结果:
249860.941919
Vectorized version:1.9125938415527344ms
249860.941919
For loop: 359.036922454834ms
从结果可以看出,向量化实现运行时间快将近300倍。因此在后续的机器学习算法实现中,尽量使用向量化方式实现。
不管是GPU还是CPU,,都有SIMD(Single Instruction Multiple Data)指令, 当使用np的内置函数像np
.dot(),都是针对运行进行了并行化计算的处理,因此运行更快。
因此,在任何时候,都要避免使用for运行进行计算。
向量化例子
尽量使用np中内置的函数,例如,对于向量
对向量中每个数进行指数运算,则调用np.exp(v)
log运算,调用np.log(v)
绝对值运算,调用abs(v)
获取最大值运算,调用np.maximum(v, 0)
平方运算,调用v**2
倒数运算,调用1/v
如下是一个逻辑回归中非向量化实现转换为向量化实现的例子
逻辑回归向量化实现
前向传播向量化
对于训练集中有m个训练样本时,对于每一个样本都要进行如下计算
第一个样本:
第二个样本:
…
第m个样本:
…
若用for循环实现,那么要循环m次。
以下介绍如何使用向量化实现
前面介绍过使用 X 来表示m个训练样本
该矩阵是一个大小的矩阵
那么可以通过如下一步完成计算
以上计算,在Python中通过一句代码即可实现,如下:
z = np.dot(w.T, X) + b
然后使用计算得到A的值。
梯度下降向量化
通过前面学习我们知道
向量化后为:
同时由前面的反向传播求导可知
,
,
=>
从而dw的计算如下:
db的计算如下:
因此,向量化表示如下
从而得到的dw向量
完整的梯度下降迭代计算向量化如下图所示
python广播机制
先通过一个例子解释下广播机制
对如下矩阵
进行如下计算,分别对矩阵的四列求和,并将矩阵的每个元素都除以对应列的和,
最简单的方法是通过for循环进行计算。但是在python中通过进行矩阵操作和广播机制即可实现,python代码如下
代码解析:
axis = 0表示对列进行求和,axis = 1表示对行进行求和
其中
percentage = 100 * A / cal.reshape(1, 4)
使用到了python的广播机制, 用一个3x4的矩阵A除以一个1x4的矩阵, 实际上3x4矩阵的每一行都会对应的处理1x4的矩阵,这就是广播机制
其他的广播机制的机制
例子1 - 对于如下
在python中使用的广播机制,实际上对应的计算为:
例子2 - 对于如下矩阵
利用python的广播机制,实际对应的计算为:
例子3 —— 对于如下计算
利用python的广播机制,实际对应的计算为
关于Python中广播机制的一般规则:矩阵 与 或矩阵进行加减乘除运算时,或矩阵都转换为矩阵进行运算。
对于矩阵与实数进行加减乘除时,都转换为维矩阵进行运算。