红色石头的我的网站:redstonewill.compython
上节课咱们主要介绍了逻辑回归,以输出几率的形式来处理二分类问题。咱们介绍了逻辑回归的Cost function表达式,并使用梯度降低算法来计算最小化Cost function时对应的参数w和b。经过计算图的方式来说述了神经网络的正向传播和反向传播两个过程。本节课咱们未来探讨Python和向量化的相关知识。web
1. Vectorization
深度学习算法中,数据量很大,在程序中应该尽可能减小使用loop循环语句,而可使用向量运算来提升程序运行速度。算法
向量化(Vectorization)就是利用矩阵运算的思想,大大提升运算速度。例以下面所示在Python中使用向量化要比使用循环计算速度快得多。编程
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("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")
输出结果相似于:数组
250286.989866
Vectorized version:1.5027523040771484ms
250286.989866
For loop:474.29513931274414ms
从程序运行结果上来看,该例子使用for循环运行时间是使用向量运算运行时间的约300倍。所以,深度学习算法中,使用向量化矩阵运算的效率要高得多。网络
为了加快深度学习神经网络运算速度,可使用比CPU运算能力更强大的GPU。事实上,GPU和CPU都有并行指令(parallelization instructions),称为Single Instruction Multiple Data(SIMD)。SIMD是单指令多数据流,可以复制多个操做数,并把它们打包在大型寄存器的一组指令集。SIMD可以大大提升程序运行速度,例如python的numpy库中的内建函数(built-in function)就是使用了SIMD指令。相比而言,GPU的SIMD要比CPU更强大一些。dom
2. More Vectorization Examples
上一部分咱们讲了应该尽可能避免使用for循环而使用向量化矩阵运算。在python的numpy库中,咱们一般使用np.dot()函数来进行矩阵运算。机器学习
咱们将向量化的思想使用在逻辑回归算法上,尽量减小for循环,而只使用矩阵运算。值得注意的是,算法最顶层的迭代训练的for循环是不能替换的。而每次迭代过程对J,dw,b的计算是能够直接使用矩阵运算。编程语言
3. Vectorizing Logistic Regression
在《神经网络与深度学习》课程笔记(2)中咱们介绍过,整个训练样本构成的输入矩阵X的维度是(nxn
x,m),权重矩阵w的维度是(nxn
x,1),b是一个常数值,而整个训练样本构成的输出矩阵Y的维度为(1,m)。利用向量化的思想,全部m个样本的线性输出Z能够用矩阵表示:svg
Z=wTX+bZ
=
w
T
X
+
b
在python的numpy库中能够表示为:
Z = np.dot(w.T,X) + b
A = sigmoid(Z)
其中,w.T表示w的转置。
这样,咱们就可以使用向量化矩阵运算代替for循环,对全部m个样本同时运算,大大提升了运算速度。
4. Vectorizing Logistic Regression’s Gradient Output
再来看逻辑回归中的梯度降低算法如何转化为向量化的矩阵形式。对于全部m个样本,dZ的维度是(1,m),可表示为:
dZ=A−Yd
Z
=
A
−
Y
db可表示为:
db=1m∑i=1mdz(i)d
b
=
1
m
∑
i
=
1
m
d
z
(
i
)
对应的程序为:
db = 1/m*np.sum(dZ)
dw可表示为:
dw=1mX⋅dZTd
w
=
1
m
X
⋅
d
Z
T
对应的程序为:
dw = 1/m*np.dot(X,dZ.T)
这样,咱们把整个逻辑回归中的for循环尽量用矩阵运算代替,对于单次迭代,梯度降低算法流程以下所示:
Z = np.dot(w.T,X) + b
A = sigmoid(Z)
dZ = A-Y
dw = 1/m*np.dot(X,dZ.T)
db = 1/m*np.sum(dZ)
w = w - alpha*dw
b = b - alpha*db
其中,alpha是学习因子,决定w和b的更新速度。上述代码只是对单次训练更新而言的,外层还须要一个for循环,表示迭代次数。
5. Broadcasting in Python
下面介绍使用python的另外一种技巧:广播(Broadcasting)。python中的广播机制可由下面四条表示:
让全部输入数组都向其中shape最长的数组看齐,shape中不足的部分都经过在前面加1补齐
输出数组的shape是输入数组shape的各个轴上的最大值
若是输入数组的某个轴和输出数组的对应轴的长度相同或者其长度为1时,这个数组可以用来计算,不然出错
当输入数组的某个轴的长度为1时,沿着此轴运算时都用此轴上的第一组值
简而言之,就是python中能够对不一样维度的矩阵进行四则混合运算,但至少保证有一个维度是相同的。下面给出几个广播的例子,具体细节可参阅python的相关手册,这里就不赘述了。
值得一提的是,在python程序中为了保证矩阵运算正确,可使用reshape()函数来对矩阵设定所需的维度。这是一个很好且有用的习惯。
6. A note on python/numpy vectors
接下来咱们将总结一些python的小技巧,避免没必要要的code bug。
python中,若是咱们用下列语句来定义一个向量:
a = np.random.randn(5)
这条语句生成的a的维度是(5,)。它既不是行向量也不是列向量,咱们把a叫作rank 1 array。这种定义会带来一些问题。例如咱们对a进行转置,仍是会获得a自己。因此,若是咱们要定义(5,1)的列向量或者(1,5)的行向量,最好使用下来标准语句,避免使用rank 1 array。
a = np.random.randn(5,1)
b = np.random.randn(1,5)
除此以外,咱们还可使用assert语句对向量或数组的维度进行判断,例如:
assert(a.shape == (5,1))
assert会对内嵌语句进行判断,即判断a的维度是否是(5,1)的。若是不是,则程序在此处中止。使用assert语句也是一种很好的习惯,可以帮助咱们及时检查、发现语句是否正确。
另外,还可使用reshape函数对数组设定所需的维度:
a.reshape((5,1))
7. Quick tour of Jupyter/iPython Notebooks
Jupyter notebook(又称IPython notebook)是一个交互式的笔记本,支持运行超过40种编程语言。本课程全部的编程练习题都将在Jupyter notebook上进行,使用的语言是python。
关于Jupyter notebook的简介和使用方法能够看个人另外两篇博客:
8. Explanation of logistic regression cost function(optional)
在上一节课的笔记中,咱们介绍过逻辑回归的Cost function。接下来咱们将简要解释这个Cost function是怎么来的。
首先,预测输出y^y
^的表达式能够写成:
y^=σ(wTx+b)y
^
=
σ
(
w
T
x
+
b
)
其中,σ(z)=11+exp(−z)σ
(
z
)
=
1
1
+
e
x
p
(
−
z
)。y^y
^能够当作是预测输出为正类(+1)的几率:
y^=P(y=1|x)y
^
=
P
(
y
=
1
|
x
)
那么,当y=1时:
p(y|x)=y^p
(
y
|
x
)
=
y
^
当y=0时:
p(y|x)=1−y^p
(
y
|
x
)
=
1
−
y
^
咱们把上面两个式子整合到一个式子中,获得:
P(y|x)=y^y(1−y^)(1−y)P
(
y
|
x
)
=
y
^
y
(
1
−
y
^
)
(
1
−
y
)
因为log函数的单调性,能够对上式P(y|x)进行log处理:
logP(y|x)=logy^y(1−y^)(1−y)=ylogy^+(1−y)log(1−y^)l
o
g
P
(
y
|
x
)
=
l
o
g
y
^
y
(
1
−
y
^
)
(
1
−
y
)
=
y
l
o
g
y
^
+
(
1
−
y
)
l
o
g
(
1
−
y
^
)
咱们但愿上述几率P(y|x)越大越好,对上式加上负号,则转化成了单个样本的Loss function,越小越好,也就获得了咱们以前介绍的逻辑回归的Loss function形式。
L=−(ylogy^+(1−y)log(1−y^))L
=
−
(
y
l
o
g
y
^
+
(
1
−
y
)
l
o
g
(
1
−
y
^
)
)
若是对于全部m个训练样本,假设样本之间是独立同分布的(iid),咱们但愿总的几率越大越好:
max∏i=1mP(y(i)|x(i))m
a
x
∏
i
=
1
m
P
(
y
(
i
)
|
x
(
i
)
)
一样引入log函数,加上负号,将上式转化为Cost function:
J(w,b)=−1m∑i=1mL(y^(i),y(i))=−1m∑i=1my(i)logy^(i)+(1−y(i))log(1−y^(i))J
(
w
,
b
)
=
−
1
m
∑
i
=
1
m
L
(
y
^
(
i
)
,
y
(
i
)
)
=
−
1
m
∑
i
=
1
m
y
(
i
)
l
o
g
y
^
(
i
)
+
(
1
−
y
(
i
)
)
l
o
g
(
1
−
y
^
(
i
)
)
上式中,1m1
m表示对全部m个样本的Cost function求平均,是缩放因子。
9. Summary
本节课咱们主要介绍了神经网络基础——python和向量化。在深度学习程序中,使用向量化和矩阵运算的方法可以大大提升运行速度,节省时间。以逻辑回归为例,咱们将其算法流程包括梯度降低转换为向量化的形式。同时,咱们也介绍了python的相关编程方法和技巧。
更多AI资源请关注公众号:红色石头的机器学习之路(ID:redstonewill)