深度学习——第6章 浅层神经网络(NN)

第6章 浅层神经网络(NN)

目录

6.1 神经网络模型概述

6.2 神经网络正向传播

6.3 神经网络反向传播

6.4 W和b的初始化

6.5 总结

上一课主要介绍了一些神经网络必备的基础知识,包括Sigmoid激活函数、损失函数、梯度下降和计算图。这些知识对学习神经网络非常有用。本节将开始真正的神经网络学习,从一个浅层的神经网络出发,详细推导其正向传播和反向传播完整过程。

6.1 神经网络模型概述

首先,我们来看一个简单的神经网络模型:

在这里插入图片描述

最简单的神经网络模型由输入层(Input Layer)、隐藏层(Hidden Layer)、输出层(Output Layer)组成,我们称之为2层神经网络。隐藏层和输出层都由个数不一的神经元组成。如上图所示,输入层有3个输入:x1、x2、x3,分别代表不同的输入特征。例如一张图片所有的像素值(当然不止3个)。一般地,输入层不标注 ◯ \bigcirc ,表示没有神经元。该神经网络模型隐藏层包含了4个神经元,输出层只有1个神经元。

需要特别注意的是,在解决二分类或者预测问题时,输出层神经元个数为1。如果是多分类问题,输出层就需要多个神经元。这里先介绍最简单的神经网络模型,多分类问题之后再详细介绍。

第1章已经介绍过单个神经元的结构:

在这里插入图片描述
单个神经元包含参数 W W W b b b,分别称之为权重系数(参数)和常数项。 W W W的维度与输入 x x x的维度相同, b b b是单个元素的标量。神经元整个计算过程分成两部分:线性计算和非线性计算。

我们来看上面的神经网络模型,输入层矩阵 x x x的维度是(3,1)。通常我们习惯把 X X X记为 a [ 0 ] a^{[0]} a[0],上标[0]表示输入层。因为输入层没有神经元计算,所以用0标注。隐藏层有4个神经元,每个神经元均与 a [ 0 ] a^{[0]} a[0] 连接。因此,隐藏层的权重系数 W [ 1 ] W^{[1]} W[1]的维度是(4,3),注意这里的上标[1]表示隐藏层。隐藏层的常数项 b [ 1 ] b^{[1]} b[1]的维度是(4,1)。输出层只有1个神经元,与4个隐藏层神经元相连接。因此,输出层的权重
W [ 2 ] W^{[2]} W[2]的维度是(1,4),上标[2]表示输出层。同理,输出层常数项 b [ 2 ] b^{[2]} b[2]的维度是(1,1),即只有一个元素。

神经网络每次迭代训练由正向传播和反向传播两部分组成。正向传播就是训练样本数据通过输入层–>隐藏层–>输出层,经过各层神经元计算后得到预测值,预测值与真实样本标签误差产生损失函数。然后,再进行反向传播。为了让损失函数减小,利用梯度下降算法,更新权重系数 W W W和常数项 b b b。这样就完成了一次迭代训练。经过多次的迭代训练之后,通常能使损失函数逐渐减小,最终确定最优化时对应的 W W W b b b。这样,整个神经网络的训练过程就结束了。

6.2 神经网络正向传播

知道了输入 x x x,参数 W [ 1 ] W^{[1]} W[1] b [ 1 ] b^{[1]} b[1] W [ 2 ] W^{[2]} W[2] b [ 2 ] b^{[2]} b[2]的维度之后,接下来重点推导一下神经网络的正向传播过程。

6.2.1 网络输出

从输入层到隐藏层,h1、h2、h3、h4神经元计算分为线性部分和非线性部分,整个过程可以写成:

z 1 [ 1 ] = W 1 [ 1 ] x + b 1 [ 1 ] , a 1 [ 1 ] = g ( z 1 [ 1 ] ) z_1^{[1]}=W_1^{[1]}x+b_1^{[1]},\ \ a_1^{[1]}=g(z_1^{[1]}) z1[1]=W1[1]x+b1[1],  a1[1]=g(z1[1])

z 2 [ 1 ] = W 2 [ 1 ] x + b 2 [ 1 ] , a 2 [ 1 ] = g ( z 2 [ 1 ] ) z_2^{[1]}=W_2^{[1]}x+b_2^{[1]},\ \ a_2^{[1]}=g(z_2^{[1]}) z2[1]=W2[1]x+b2[1],  a2[1]=g(z2[1])

z 3 [ 1 ] = W 3 [ 1 ] x + b 3 [ 1 ] , a 3 [ 1 ] = g ( z 3 [ 1 ] ) z_3^{[1]}=W_3^{[1]}x+b_3^{[1]},\ \ a_3^{[1]}=g(z_3^{[1]}) z3[1]=W3[1]x+b3[1],  a3[1]=g(z3[1])

z 4 [ 1 ] = W 4 [ 1 ] x + b 4 [ 1 ] , a 4 [ 1 ] = g ( z 4 [ 1 ] ) z_4^{[1]}=W_4^{[1]}x+b_4^{[1]},\ \ a_4^{[1]}=g(z_4^{[1]}) z4[1]=W4[1]x+b4[1],  a4[1]=g(z4[1])

其中,下标表示第几个神经元。例如 z j [ l ] z_j^{[l]} zj[l]就表示第 l l l层的第 j j j个神经元。注意, j j j从1开始, l l l从0开始。 z j [ l ] z_j^{[l]} zj[l]是线性输出, a j [ l ] a_j^{[l]} aj[l]是非线性输出, g ( ⋅ ) g(\cdot) g()表示激活函数。关于激活函数,稍后详细介绍。

从隐藏层到输出层,只有一个out神经元。注意此时神经元的输入不是 x x x,而是隐藏层的输出 a [ 1 ] a^{[1]} a[1]。整个过程为:

z 1 [ 2 ] = W 1 [ 2 ] a [ 1 ] + b 1 [ 2 ] , a 1 [ 2 ] = g ( z 1 [ 2 ] ) z_1^{[2]}=W_1^{[2]}a^{[1]}+b_1^{[2]},\ \ a_1^{[2]}=g(z_1^{[2]}) z1[2]=W1[2]a[1]+b1[2],  a1[2]=g(z1[2])

为了提高程序运算速度,我们利用之前介绍的向量化思想,将上述表达式转换成矩阵运算的形式:

z [ 1 ] = W [ 1 ] x + b [ 1 ] z^{[1]}=W^{[1]}x+b^{[1]} z[1]=W[1]x+b[1]

a [ 1 ] = g ( z [ 1 ] ) a^{[1]}=g(z^{[1]}) a[1]=g(z[1])

z [ 2 ] = W [ 2 ] a [ 1 ] + b [ 2 ] z^{[2]}=W^{[2]}a^{[1]}+b^{[2]} z[2]=W[2]a[1]+b[2]

a [ 2 ] = g ( z [ 2 ] ) a^{[2]}=g(z^{[2]}) a[2]=g(z[2])

以上介绍的是单个样本的正向传输过程,如果有m个样本,则输入X的维度为(3,m)。最简单的可以使用for循环来计算其正向输出。这里,我们用上标(i)表示第i个样本。过程如下:

for i=1 to m:

Z [ 1 ] ( i ) = W [ 1 ] X ( i ) + b [ 1 ] Z^{[1](i)}=W^{[1]}X^{(i)}+b^{[1]} Z[1](i)=W[1]X(i)+b[1]

A [ 1 ] ( i ) = g ( Z [ 1 ] ( i ) ) A^{[1](i)}=g(Z^{[1](i)}) A[1](i)=g(Z[1](i))

Z [ 2 ] ( i ) = W [ 2 ] A [ 1 ] ( i ) + b [ 2 ] Z^{[2](i)}=W^{[2]}A^{[1](i)}+b^{[2]} Z[2](i)=W[2]A[1](i)+b[2]

A [ 2 ] ( i ) = g ( Z [ 2 ] ( i ) ) A^{[2](i)}=g(Z^{[2](i)}) A[2](i)=g(Z[2](i))

这里,X、Z、A都采用大写的形式,表示矩阵。 Z [ 1 ] Z^{[1]} Z[1] A [ 1 ] A^{[1]} A[1]的维度为(4,m), Z [ 2 ] Z^{[2]} Z[2] A [ 2 ] A^{[2]} A[2]的维度为(1,m)。对这四个矩阵均可以这样理解:行表示第几个神经元,列表示样本数目m。

不使用for循环,直接采用矩阵运算的形式,可得:

Z [ 1 ] = W [ 1 ] X + b [ 1 ] Z^{[1]}=W^{[1]}X+b^{[1]} Z[1]=W[1]X+b[1]

A [ 1 ] = g ( Z [ 1 ] ) A^{[1]}=g(Z^{[1]}) A[1]=g(Z[1])

Z [ 2 ] = W [ 2 ] A [ 1 ] + b [ 2 ] Z^{[2]}=W^{[2]}A^{[1]}+b^{[2]} Z[2]=W[2]A[1]+b[2]

A [ 2 ] = g ( Z [ 2 ] ) A^{[2]}=g(Z^{[2]}) A[2]=g(Z[2])

这样,我们就完整地计算了神经网络模型的正向传播过程。有时候,为了便于理解, X X X也可以用 A [ 0 ] A^{[0]} A[0]表示。

6.2.2 激活函数

神经网络每个神经元都需要激活函数(Activation Function)来进行非线性运算。在上一篇中介绍的逻辑回归模型使用的Sigmoid函数,也是一种激活函数。下面重点介绍几个神经网络常用的激活函数 g ( x ) g(x) g(x),并作简单比较。

(1)Sigmoid函数

在这里插入图片描述

函数表达式为:

a = 1 1 + e − z a=\frac{1}{1+e^{-z}} a=1+ez1

(2)tanh函数

在这里插入图片描述

函数表达式为:

a = e z − e − z e z + e − z a=\frac{e^z-e^{-z}}{e^z+e^{-z}} a=ez+ezezez

(3)ReLU函数

在这里插入图片描述

函数表达式为:

a = m a x ( 0 , z ) a = max(0,z) a=max(0,z)

(4)Leaky ReLU函数

在这里插入图片描述

函数表达式为:

a = { λ z , z ⩽ 0 z , z > 0 a=\left\{\begin{array}{cc} \lambda z, & z\leqslant0\\ z, & z> 0 \end{array}\right. a={λz,z,z0z>0

其中, λ \lambda λ为可变参数,一般 λ ∈ ( 0 , 1 ) \lambda\in(0,1) λ(0,1),例如 λ = 0.01 \lambda=0.01 λ=0.01

介绍完了这些常用的激活函数之后,考虑如何选择合适的激活函数呢?首先我们来比较Sigmoid函数和tanh函数。对于隐藏层的激活函数,一般来说,tanh函数要比Sigmoid函数表现更好一些。因为tanh函数的取值范围在(-1,+1),即隐藏层的输出被限定在(-1,+1)之间,可以看成是在0值附近分布,均值为0。这样从隐藏层到输出层,数据起到了归一化(均值为0)的效果。因此,隐藏层的激活函数,tanh比Sigmoid更好一些。而对于输出层的激活函数,因为二分类问题的输出取值为[0, 1]之间,所以一般会选择Sigmoid作为激活函数。

观察Sigmoid函数和tanh函数,我们发现有这样一个问题,就是当 ∣ z ∣ |z| z很大的时候,激活函数的斜率(梯度)很小。因此,在这个区域内,梯度下降算法会运行得比较慢。在实际应用中,应尽量避免使z落在这个区域,使 ∣ z ∣ |z| z尽可能限定在零值附近,从而提高梯度下降算法运算速度。

为了弥补Sigmoid函数和tanh函数的这个缺陷,就出现了ReLU激活函数。ReLU激活函数在 z z z大于零时梯度始终为1;在 z z z小于零时梯度始终为0; z z z等于零时的梯度可以当成1也可以当成0,实际应用中并不影响。对于隐藏层,选择ReLU作为激活函数能够保证 z z z大于零时梯度始终为1,从而提高神经网络梯度下降算法运算速度。但当 z z z小于零时,存在梯度为0的缺点。实际应用中,这个缺点影响不是很大,但为了弥补这个缺点,出现了Leaky ReLU激活函数,能够保证 z z z小于零时梯度不为0。

值得注意的是,如果是二分类问题,输出层可以使用Sigmoid激活函数。如果是预测问题,输出层则可以不需要使用激活函数,因为预测值一般在整个实数范围之间。又或者,如果输出值总是正数,例如房价预测问题,则可以使用ReLU激活函数。

因此,是否使用激活函数,使用哪个激活函数,并不是固定不变的,需要根据问题本身进行考量和判断,做到活学活用,真正理解。本文为了简化内容,仅仅以二分类为例,介绍神经网络的基本模型。更复杂的情况,后面的章节将会详细介绍。

有的人可能会有疑问:为什么每个神经元需要非线性单元,需要激活函数?以上面这个神经网络模型为例,我们来看如果没有激活函数,模型最后的输出是什么。

假设没有激活函数,则有 A = Z A = Z A=Z。那么,神经网络的各层输出为:

Z [ 1 ] = W [ 1 ] X + b [ 1 ] Z^{[1]}=W^{[1]}X+b^{[1]} Z[1]=W[1]X+b[1]

A [ 1 ] = Z [ 1 ] A^{[1]}=Z^{[1]} A[1]=Z[1]

Z [ 2 ] = W [ 2 ] A [ 1 ] + b [ 2 ] Z^{[2]}=W^{[2]}A^{[1]}+b^{[2]} Z[2]=W[2]A[1]+b[2]

A [ 2 ] = Z [ 2 ] A^{[2]}=Z^{[2]} A[2]=Z[2]

直接对 A [ 2 ] A^{[2]} A[2]表达式展开:

A [ 2 ] = W [ 2 ] A [ 1 ] + b [ 2 ] = W [ 2 ] ( W [ 1 ] X + b [ 1 ] ) + b [ 2 ] = ( W [ 2 ] W [ 1 ] X ) + ( W [ 2 ] b [ 1 ] + b [ 2 ] ) = W ′ X + b ′ A^{[2]}=W^{[2]}A^{[1]}+b^{[2]}=W^{[2]}(W^{[1]}X+b^{[1]})+b^{[2]}\\=(W^{[2]}W^{[1]}X)+(W^{[2]}b^{[1]}+b^{[2]})=W'X+b' A[2]=W[2]A[1]+b[2]=W[2](W[1]X+b[1])+b[2]=(W[2]W[1]X)+(W[2]b[1]+b[2])=WX+b

经过推导,发现 A [ 2 ] A^{[2]} A[2]仍是输入变量 X X X的线性组合。这表明,使用神经网络与直接使用线性模型的效果并没有什么两样。即便是包含多层隐藏层的神经网络,如果不使用非线性激活函数,最终的输出仍然是输入 X X X的线性模型。这样的话神经网络就没有任何作用了。另外,如果只有输出层使用非线性激活函数,那么整个神经网络的结构就类似于一个简单的逻辑回归模型,而失去了神经网络模型本身的优势和价值。因此,隐藏层一般必须使用非线性激活函数。

6.3 神经网络反向传播

神经网络正向传播最终得到的输出 Y ^ = A [ 2 ] \hat Y=A^{[2]} Y^=A[2]。因为是二分类问题,其损失函数与逻辑回归模型一样,在上一篇已经推导过逻辑回归模型的损失函数:

L = − [ y l o g y ^ + ( 1 − y ) l o g ( 1 − y ^ ) ] L=-[ylog\hat y+(1-y)log(1-\hat y)] L=[ylogy^+(1y)log(1y^)]

对于 m m m个样本的损失函数为:

J = − 1 m ∑ i = 1 m y ( i ) l o g y ^ ( i ) + ( 1 − y ( i ) ) l o g ( 1 − y ^ ( i ) ) J=-\frac{1}{m}\sum_{i=1}^my^{(i)}log\hat y^{(i)}+(1-y^{(i)})log(1-\hat y^{(i)}) J=m1i=1my(i)logy^(i)+(1y(i))log(1y^(i))

接下来,我们来计算损失函数 J J J对各个变量 A [ 2 ] A^{[2]} A[2] Z [ 2 ] Z^{[2]} Z[2] W [ 2 ] W^{[2]} W[2] b [ 2 ] b^{[2]} b[2] A [ 1 ] A^{[1]} A[1] Z [ 1 ] Z^{[1]} Z[1] W [ 1 ] W^{[1]} W[1] b [ 1 ] b^{[1]} b[1]的偏导数。

J J J A [ 2 ] A^{[2]} A[2]求偏导数:

d A [ 2 ] = ∂ J ∂ A [ 2 ] = A [ 2 ] − Y A [ 2 ] ( 1 − A [ 2 ] ) dA^{[2]}=\frac{\partial J}{\partial A^{[2]}}=\frac{A^{[2]}-Y}{A^{[2]}(1-A^{[2]})} dA[2]=A[2]J=A[2](1A[2])A[2]Y

J J J Z [ 2 ] Z^{[2]} Z[2]求偏导数:

d Z [ 2 ] = d A [ 2 ] ⋅ ∂ A [ 2 ] ∂ Z [ 2 ] dZ^{[2]}=dA^{[2]}\cdot\frac{\partial A^{[2]}}{\partial Z^{[2]}} dZ[2]=dA[2]Z[2]A[2]

这里,若使用Sigmoid激活函数,它的导数为:

g ( z ) ′ = a ( 1 − a ) g(z)'=a(1-a) g(z)=a(1a)

则有:

∂ A [ 2 ] ∂ Z [ 2 ] = A [ 2 ] ( 1 − A [ 2 ] ) \frac{\partial A^{[2]}}{\partial Z^{[2]}}=A^{[2]}(1-A^{[2]}) Z[2]A[2]=A[2](1A[2])

将其带入 d Z [ 2 ] dZ^{[2]} dZ[2]中,得:

d Z [ 2 ] = A [ 2 ] − Y A [ 2 ] ( 1 − A [ 2 ] ) ⋅ A [ 2 ] ( 1 − A [ 2 ] ) = A [ 2 ] − Y dZ^{[2]}=\frac{A^{[2]}-Y}{A^{[2]}(1-A^{[2]})}\cdot A^{[2]}(1-A^{[2]})=A^{[2]}-Y dZ[2]=A[2](1A[2])A[2]YA[2](1A[2])=A[2]Y

发现 d Z [ 2 ] dZ^{[2]} dZ[2]的表达式是不是很简单呢?

J 对 W [ 2 ] J对W^{[2]} JW[2]求偏导数:

d W [ 2 ] = 1 m d Z [ 2 ] ⋅ ∂ Z [ 2 ] ∂ W [ 2 ] = 1 m d Z [ 2 ] ⋅ A [ 1 ] T dW^{[2]}=\frac1m dZ^{[2]}\cdot\frac{\partial Z^{[2]}}{\partial W^{[2]}}=\frac1m dZ^{[2]}\cdot A^{[1]T} dW[2]=m1dZ[2]W[2]Z[2]=m1dZ[2]A[1]T

其中, A [ 1 ] T A^{[1]T} A[1]T表示 A [ 1 ] A^{[1]} A[1]的转置。

J 对 b [ 2 ] J对b^{[2]} Jb[2] 求偏导数:

d b [ 2 ] = 1 m n p . s u m ( d Z [ 2 ] , a x i s = 1 ) db^{[2]}=\frac1mnp.sum(dZ^{[2]},\ \ axis=1) db[2]=m1np.sum(dZ[2],  axis=1)

这里的np.sum()是Python Numpy中的求和函数,参数axis = 0表示矩阵行相加,axis = 1表示矩阵列相加。

J J J A [ 1 ] A^{[1]} A[1]求偏导数:

d A [ 1 ] = d Z [ 2 ] ⋅ ∂ Z [ 2 ] ∂ A [ 1 ] = W [ 2 ] T ⋅ d Z [ 2 ] dA^{[1]}=dZ^{[2]}\cdot\frac{\partial Z^{[2]}}{\partial A^{[1]}}=W^{[2]T}\cdot dZ^{[2]} dA[1]=dZ[2]A[1]Z[2]=W[2]TdZ[2]

J 对 Z [ 1 ] J对Z^{[1]} JZ[1]求偏导数:

d Z [ 1 ] = d A [ 1 ] ⋅ ∂ A [ 1 ] ∂ Z [ 1 ] = d A [ 1 ] ∗ g [ 1 ] ′ ( Z [ 1 ] ) = W [ 2 ] T ⋅ d Z [ 2 ] ∗ g [ 1 ] ′ ( Z [ 1 ] ) dZ^{[1]}=dA^{[1]}\cdot\frac{\partial A^{[1]}}{\partial Z^{[1]}}=dA^{[1]}*g^{[1]'}(Z^{[1]})=W^{[2]T}\cdot dZ^{[2]}*g^{[1]'}(Z^{[1]}) dZ[1]=dA[1]Z[1]A[1]=dA[1]g[1](Z[1])=W[2]TdZ[2]g[1](Z[1])

其中, g [ 1 ] ′ ( Z [ 1 ] ) g^{[1]'}(Z^{[1]}) g[1](Z[1])表示 A [ 1 ] A^{[1]} A[1] Z [ 1 ] Z^{[1]} Z[1]的导数。上式中的*号表示两个矩阵对应元素相乘, ⋅ \cdot 表示矩阵相乘。

J J J W [ 1 ] W^{[1]} W[1]求偏导数:

d W [ 1 ] = d Z [ 1 ] ⋅ ∂ Z [ 1 ] ∂ W [ 1 ] = 1 m d Z [ 1 ] ⋅ A [ 0 ] T dW^{[1]}=dZ^{[1]}\cdot\frac{\partial Z^{[1]}}{\partial W^{[1]}}=\frac1mdZ^{[1]}\cdot A^{[0]T} dW[1]=dZ[1]W[1]Z[1]=m1dZ[1]A[0]T

J J J b [ 1 ] b^{[1]} b[1]求偏导数:

d b [ 1 ] = 1 m n p . s u m ( d Z [ 1 ] , a x i s = 1 ) db^{[1]}=\frac1mnp.sum(dZ^{[1]},\ \ axis=1) db[1]=m1np.sum(dZ[1],  axis=1)

好了,我们已经完整地推导了神经网络反向传播过程。

我把正向传播和反向传播涉及的公式全都整理出来,以供查阅:

在这里插入图片描述
计算完 W W W b b b的导数之后,利用上一篇介绍过的梯度下降算法,更新 W W W b b b

W [ 1 ] = W [ 1 ] − η ⋅ d W [ 1 ] W^{[1]}=W^{[1]}-\eta\cdot dW^{[1]} W[1]=W[1]ηdW[1]

b [ 1 ] = b [ 1 ] − η ⋅ d b [ 1 ] b^{[1]}=b^{[1]}-\eta\cdot db^{[1]} b[1]=b[1]ηdb[1]

W [ 2 ] = W [ 2 ] − η ⋅ d W [ 2 ] W^{[2]}=W^{[2]}-\eta\cdot dW^{[2]} W[2]=W[2]ηdW[2]

b [ 2 ] = b [ 2 ] − η ⋅ d b [ 2 ] b^{[2]}=b^{[2]}-\eta\cdot db^{[2]} b[2]=b[2]ηdb[2]

其中, η \eta η是学习因子。

6.4 W和b的初始化

神经网络模型在开始训练时需要对各层权重系数 W W W和常数项 b b b进行初始化赋值。初始化赋值时, b b b一般全部初始化为0即可,但是 W W W不能全部初始化为0。接下来我们来分析一下原因。

还是上面的神经网络模型,如果 W [ 1 ] W^{[1]} W[1] W [ 2 ] W^{[2]} W[2]全部初始化为0,即:

W [ 1 ] = [ 0 0 0 0 0 0 0 0 0 0 0 0 ] W^{[1]}= \left[ \begin{matrix} 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 \end{matrix} \right] W[1]= 000000000000

W [ 2 ] = [ 0 0 0 0 ] W^{[2]}= \left[ \begin{matrix} 0 & 0 & 0 & 0 \end{matrix} \right] W[2]=[0000]

这样使得隐藏层四个神经元的输出都相同,即:

A 1 [ 1 ] = A 2 [ 1 ] = A 3 [ 1 ] = A 4 [ 1 ] A_1^{[1]}=A_2^{[1]}=A_3^{[1]}=A_4^{[1]} A1[1]=A2[1]=A3[1]=A4[1]

经过推导得到:

d Z 1 [ 1 ] = d Z 2 [ 1 ] = d Z 3 [ 1 ] = d Z 4 [ 1 ] dZ_1^{[1]}=dZ_2^{[1]}=dZ_3^{[1]}=dZ_4^{[1]} dZ1[1]=dZ2[1]=dZ3[1]=dZ4[1]

以及:

d W 1 [ 1 ] = d W 2 [ 1 ] = d W 3 [ 1 ] = d W 4 [ 1 ] dW_1^{[1]}=dW_2^{[1]}=dW_3^{[1]}=dW_4^{[1]} dW1[1]=dW2[1]=dW3[1]=dW4[1]

因此,隐藏层四个神经元对应的权重行向量 W 1 [ 1 ] W_1^{[1]} W1[1] W 2 [ 1 ] W_2^{[1]} W2[1] W 3 [ 1 ] W_3^{[1]} W3[1] W 4 [ 1 ] W_4^{[1]} W4[1]每次迭代更新都会得到完全相同的结果。也就是说,始终有:

W 1 [ 1 ] = W 2 [ 1 ] = W 3 [ 1 ] = W 4 [ 1 ] W_1^{[1]}=W_2^{[1]}=W_3^{[1]}=W_4^{[1]} W1[1]=W2[1]=W3[1]=W4[1]

这样隐藏层设置多个神经元就没有任何意义了。

所以,一般对 W W W进行随机初始化。相应的Python语句为:

W1 = np.random.randn((4,3))*0.01
b1 = np.zero((4,1))
W2 = np.random.randn((1,4))*0.01
b2 = 0    

值得注意的是,W1和W2都习惯性地乘以0.01。究其原因,是因为如果使用Sigmoid或者tanh作为激活函数的话, W W W比较小,得到的 ∣ Z ∣ |Z| Z也比较小(零点附近),而零点附近区域的梯度比较大,这样能大大提高梯度下降算法的更新速度,尽快找到全局最优解。如果 W W W较大,得到的 ∣ Z ∣ |Z| Z也比较大,接近曲线平缓区域,梯度很小,更新速度慢,训练过程也会慢很多。当然,如果使用ReLU或者Leaky ReLU,则可以不乘以0.01。

6.5 总结

本文主要介绍了最简单的2层神经网络模型,详细推导其正向传播过程和反向传播过程,得到了各权重系数W和常数项b的导数表达式。我们也列举了常见的四种激活函数,分析各自的优缺点。最后,简单解释了参数初始化的方法和注意事项。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/218825.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MX6ULL学习笔记(十二)Linux 自带的 LED 灯

前言 前面我们都是自己编写 LED 灯驱动,其实像 LED 灯这样非常基础的设备驱动,Linux 内 核已经集成了。Linux 内核的 LED 灯驱动采用 platform 框架,因此我们只需要按照要求在设备 树文件中添加相应的 LED 节点即可,本章我们就来学…

windows10 php8连接sql server

一、环境安装 文章目录 一、环境安装1.安装php拓展2.在 Windows 上安装PHP驱动程序3.在 Windows 上安装ODBC驱动 二、php连接sqlserver三、注意事项数据库相关设置相关语法sqlsrv_fetch_array 的示例:sqlsrv_fetch 的示例:echo 和 print_r 的不同 所用资…

【卡塔尔世界杯数据可视化与新闻展示】

卡塔尔世界杯数据可视化与新闻展示 前言数据获取与处理可视化页面搭建功能实现新闻信息显示详情查看登录注册评论信息管理 创新点结语 前言 随着卡塔尔世界杯的临近,对于足球爱好者来说,对比赛的数据分析和新闻报道将成为关注的焦点。本文将介绍如何使用…

论文阅读:PointCLIP V2: Prompting CLIP and GPT for Powerful3D Open-world Learning

https://arxiv.org/abs/2211.11682 0 Abstract 大规模的预训练模型在视觉和语言任务的开放世界中都表现出了良好的表现。然而,它们在三维点云上的传输能力仍然有限,仅局限于分类任务。在本文中,我们首先协作CLIP和GPT成为一个统一的3D开放世…

C++ 运算符重载

目录 前言 算术运算符重载 加号运算符 位运算符重载 左移运算符 自增自减运算符重载 前置自增运算符 后置自增运算符 赋值运算符重载 等号赋值运算符重 关系运算符重载 相等 不等 函数调用运算符重载 总结 前言 在C中,运算符重载是一种强大的特性…

jmeter,csv文件参数化+断言 实现一个接口的case

1、case 及其 测试数据 注意保存文件的编码格式 id,name,limit,status,address,start_time,assert_status,assert_message 100,小米100,1000,1,某某会展中心101,2023-8-20 14:20,200,add event success ,,,,,,10021,parameter error 100,小米102,1002,1,某某会展中心103,2023-…

Centos7部署SVN

文章目录 (1)SVN概述(2)SVN与Samba共享(3)安装SVN(4)SVN搭建实例(5)pc连接svn服务器(6)svn图标所代表含义 (1)…

ArrayList与LinkLIst

ArrayList 在Java中,ArrayList是java.util包中的一个类,它实现了List接口,是一个动态数组,可以根据需要自动增长或缩小。下面是ArrayList的一些基本特性以及其底层原理的简要讲解: ArrayList基本特性: 动…

听GPT 讲Rust源代码--src/tools(13)

File: rust/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incoherent_impl.rs 在Rust源代码中,路径为rust/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incoherent_impl.rs的文件是为了处理Rust代码中的不一致实现问题而存在的。…

生成小程序URLlink链接遇到的坑

这里写自定义目录标题 前端生成小程序URL link背景用户打开小程序的常用方法短链接短链接优缺点优点缺点 生成短链接步骤 可能会遇到的问题:其他 注意📢 前端生成小程序URL link ![h5打开小程序](https://img-blog.csdnimg.cn/direct/a4cfe3ef6d184c6d9…

MQTT的奇妙之旅:探索RabbitMQ Web MQTT插件的威力【RabbitMQ 十一】

欢迎来到我的博客,代码的世界里,每一行都是一个故事 MQTT的奇妙之旅:探索RabbitMQ Web MQTT插件的威力 前言第一:揭秘RabbitMQ Web MQTT插件背景和目的:MQTT 协议简介:WebSockets 和 MQTT 的融合&#xff1…

让高清媒体无限畅享——Movist Pro for Mac推广文章

随着科技的迅猛发展,高清媒体已经成为我们日常生活中不可或缺的一部分。无论是观看电影、追剧、还是欣赏高清音乐视频,我们都希望能够获得最佳的视听体验。为了满足这一需求,我们向大家推荐一款强大的高清媒体播放器——Movist Pro for Mac。…

Selenium安装WebDriver:ChromeDriver与谷歌浏览器版本快速匹配_最新版120

最近在使用通过selenium操作Chrome浏览器时,安装中遇到了Chrome版本与浏览器驱动不匹配的的问题,在此记录安装下过程,如何快速找到与谷歌浏览器相匹配的ChromeDriver驱动版本。 1. 确定Chrome版本 我们首先确定自己的Chrome版本 Chrome设置…

【后端卷前端3】

侦听器 监听的数据是 data()中的动态数据~响应式数据 <template><div><p>{{showHello}}</p><button click"updateHello">修改数据</button></div> </template><script>export default {name: "goodsTe…

关于枚举的简单理解

1. 枚举的简单认识 1.1 枚举的引入 枚举是在JDK1.5以后引入的。主要用途是&#xff1a;将一组常量组织起来&#xff0c;在这之前表示一组常量通常使用定义常量的方式如下面的代码所示&#xff1a; public static final int RED 1; public static final int GREEN 2; public…

selenium 与 chromedriver安装

本文章向大家介绍selenium 安装与 chromedriver安装&#xff0c;主要包括selenium 安装与 chromedriver安装使用实例、应用技巧、基本知识点总结和需要注意事项供大家参考。 一、安装selenium 1、Selenium简介 Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开…

HNU-计算机网络-实验4-网络层与链路层协议分析(PacketTracer)

计算机网络 课程基础实验四网络层与链路层协议分析&#xff08;PacketTracer&#xff09; 计科210X 甘晴void 202108010XXX 文章目录 计算机网络 课程基础实验四<br>网络层与链路层协议分析&#xff08;PacketTracer&#xff09;一、实验目的二、实验内容4.1 路由器交换…

工业性能CCD图像处理+

目录 硬件部分 ​编辑 软件部分 CCD新相机的调试处理&#xff08;更换相机处理&#xff0c;都要点执行检测来查看图像变化&#xff09; 问题:新相机拍摄出现黑屏&#xff0c;图像拍摄不清晰&#xff0c;&#xff08;可以点击图像&#xff0c;向下转动鼠标的滚轮&#xff08…

NVIDIA A100 PCIE 40GB k8s-device-plugin install in kubernetes

文章目录 1. 目标2. 简介2.1 英伟达 A100 技术规格2.2 架构优势2.3 显卡跑分对比2.4 英伟达 A100 与 kubernetes 3. 安装 NVIDIA A100 GPU 40G 硬件4. NVIDIA R450 datacenter driver5. NVIDIA Container Toolkit6. 创建 runtimeclass5. MIG Strategies6. 配置仓库7. 下载镜像8…

【Java系列】详解多线程(三)—— 线程安全(上篇)

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Java系列专栏】【JaveEE学习专栏】 本专栏旨在分享学习Java的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 一…