回顾 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满足要求,对于深层网络则需要选择其他的数值。