回顾 Logistic Regression
z=ωTx+b→a=σ(z)→L(a,y)
浅层神经网络(只有一层隐藏单元)
在本周的课程中,浅层神经网络的
W 均没有转置,也就是说,对于
m 个大小为
nx 的输入样本,
W 的大小为
m∗nx
神经网络的命名中,输入层的下一层作为神经网络的第一层,输出层作为神经网络的最后一层。图中每一个节点进行线性和非线性变换,即
z=ωTx+b 和
a=g(z),
g(x) 为激活函数。
要理解课程最重要的是分清每个符号的代表的意思
网络中每个符号的含义
以每个输入样本为照片拉成的向量为例,输入样本的大小为
nx∗m,
nx=w∗h∗channels
xi:单个输入向量的
i 位置上的值
a[j]: 第j层的输入值
ai[j]: 第
j 层的第
i个输入值
n[i]:第
i 层输入向量的维度,
n[0]=nx
x(i):第
i 个输入的样本
所以该浅层神经网络的第一层计算过程可以表示为
z1[1]=ω1[1]Tx(i)+b1[1],a1[1]=g(z1[1])
z2[1]=ω2[1]Tx(i)+b2[1],a2[1]=g(z2[1])
z3[1]=ω3[1]Tx(i)+b3[1],a3[1]=g(z3[1])
z4[1]=ω4[1]Tx(i)+b4[1],a4[1]=g(z4[1])
整个网络的计算过程可表示为
Z[1]=W[1]A[0]+b[1],A[0]∈(n0∗m),W∈(n1∗n0),b1∈(n1,1)
A[1]=g(Z[1])
Z[2]=W[2]A[1]+b[2],A[1]∈(n1∗m),W∈(n2∗n1),b1∈(n2,1)
A[2]=g(Z[2])
W[1] 的直观表示为
⎣⎢⎡——————ω1[1]Tω2[1]Tω3[1]T——————⎦⎥⎤
激活函数的选择
可选函数
Sigmoid:a=1+e−z1
Tanh:a=ez+e−zez−e−z
ReLU:a=max(0,z)
leakyReLU:a=max(0.01z,z)
激活函数的选择
sigmoid 函数在二分类具有很好的表现性能;除了该场景
tanh 函数几乎在其他所有场合比
sigmoid 函数有更好的表现性能;
sigmoid 和
tanh 通常只在输出层使用,其余层的激活函数通常选择
ReLU,因为
sigmoid 或
tanh 在
z 较大或者较小时的梯度较小,使用梯度下降法速率变化较慢,而
ReLU 在大多数
z 空间内的激活函数的导数比0大很多,从而使梯度下降很快,当
z<0 时,尽管梯度为0,但只要隐藏单元足够多就可以保证训练的速率;
leakyReLU 的表现性能略优于
ReLU,但没有很广泛的应用
使用非线性激活函数
如果使用线性激活函数,多个隐藏层的激活函数经线性变换后可以变为一个式子,多个隐藏层没有意义,因此只能使用非线性激活函数
神经网络的梯度下降
最后一层激活函数为
sigmoid 函数
dZ[2]=A[2]−Y
dW[2]=m1dZ[2]A[1]T
db[2]=m1np.sum(dZ[2],axis=1,keepdims=True)
dZ[1]=W[2]TdZ[2]∗g[1]′(Z[1])
dW[1]=m1dZ[1]XT
db[1]=m1np.sum(dZ[1],axis=1,keepdims=True)
注意
dZ[1] 的求解是两个矩阵对应位置相乘,使用
np.sum() 时注意
keepdims 保证矩阵加法不会使矩阵维度减少,避免不必要的错误
梯度下降详解
n[i] 为每一个层的节点个数
L(A[2],y)=m1i=1∑mJ(A[2],y),L∈(1∗1)
J(A[2],y)=−(ylogA[2]+(1−y)log(1−A[2])),J∈(1∗m)
dA[2]=−(A[2]y−1−A[2]1−y),dA[2]∈(1∗m)
dZ[2]=(A[2]∗(1−A[2])dA[2]=A[2]−Y,dZ[2]∈(1∗m)
dW[2]=m1dZ[2]A[1]T,dW[2]∈(1∗n[1])这里乘m1是因为通过m个样本的求和求得dW[2]
db[2]=m1np.sum(dZ[2],axis=1,keepdims=True),db[2]∈(1∗1)
dZ[1]=W[2]TdZ[2]∗g[1]′(Z[1]),dZ[1]∈(n[1]∗m),根据维度对比,这两个矩阵只能点乘
dW[1]=m1dZ[1]XT,dW[1]∈(n[1],n[0]
db[1]=m1np.sum(dZ[1],axis=1,keepdims=True),db∈(n[1],1)
对矩阵求导,最好是根据输出矩阵的维度确定矩阵转置和相乘的位置
初始化
对logistic来说,可以将
ω 初始化为0;但对于浅层神经网络而言,如果将
W 初始为0,那么两个节点完全对称,节点计算一样的函数,在迭代之后的计算仍然相同;也就是说无论如何迭代计算两个节点的权重都相同。
在实际应用时用
np.random.randn(())∗0.01 初始化 ,选择乘0.01是为了使
W 变小,那么激活函数就不会落在函数平缓的地方,加快迭代速率。当训练浅层网络时,0.01满足要求,对于深层网络则需要选择其他的数值。