深度学习笔记(四)——神经网络和深度学习(浅层神经网络)

1.神经网络概览

神经网络的结构与逻辑回归类似,只是神经网络的层数比逻辑回归多一层,多出来的中间那层称为隐藏层或中间层。从计算上来说,神经网络的正向传播和反向传播过程只是比逻辑回归多了一次重复的计算。正向传播过程分成两层,第一层是输入层到隐藏层,用上标[1]来表示;第二层是隐藏层到输出层,用上标[2]来表示。方括号上标[i]表示当前所处的层数;圆括号上标(i)表示第i个样本。

同样,反向传播过程也分成两层。第一层是输出层到隐藏层,第二层是隐藏层到输入层。

2.神经网络表示

单隐藏层神经网络就是典型的浅层(shallow)神经网络。

结构上,从左到右,可以分成三层:输入层(Input layer),隐藏层(Hidden layer)和输出层(Output layer)。隐藏层的真正数值我们是不知道的,在训练集看不到他们的数值。隐藏层是抽象的非线性的中间层。

我们把输入矩阵记做a^{[0]},把隐藏层输出记为a^{[1]},上标从0开始。下标表示神经元个数,所以有四个神经元的的隐藏层就可以写为:

a^{[1]} = \begin{bmatrix} a_{1}^{[1]}\\ a_{2}^{[1]}\\ a_{3}^{[1]}\\ a_{4}^{[1]} \end{bmatrix}

最后,输出层记做a^{[2]},即\hat{y}。这种单隐藏层神经网络也被称为两层神经网络(2 layer NN)。之所以叫两层神经网络是因为,通常我们只会计算隐藏层输出和输出层的输出,输入层是不用计算的。这也是我们把输入层层数上标记为0的原因。

关于隐藏层对应的权重w^{[1]}和常数项b^{[1]}w^{[1]}的维度是(4,3)。这里的4对应着隐藏层神经元个数,3对应着输入层x特征向量包含元素个数。常数项b^{[1]}的维度是(4,1),这里的4同样对应着隐藏层神经元个数。关于输出层对应的权重w^{[2]}和常数项b^{[2]}w^{[2]}的维度是(1,4),这里的1对应着输出层神经元个数,4对应着隐藏层神经元个数。常数项b^{[2]}的维度是(1,1),因为输出只有一个神经元。总结一下,第i层的权重w^{[i]}维度的行等于i层神经元的个数,列等于i-1层神经元的个数;第i层常数项b^{[i]}维度的行等于i层神经元的个数,列始终为1。

3.计算神经网络的输出 

对于两层神经网络,从输入层到隐藏层对应一次逻辑回归运算;从隐藏层到输出层对应一次逻辑回归运算。每层计算时,要注意对应的上标和下标,一般我们记上标方括号表示第几层,下标表示第几个神经元。下标从1开始,上标从0开始。

从输入层到输出层的计算公式:

从隐藏层到输出层的计算公式:

其中a^{[1]}为:

上述每个节点的计算都对应着一次逻辑运算的过程,分别由计算z和a两部分组成。可以运用向量化来简化:

4.多个例子中的向量化

对于m个训练样本,我们也可以使用矩阵相乘的形式来提高计算效率。

对于每个样本i,可以使用for循环来求解其正向输出:

利用矩阵(输入矩阵的维度为(n_{x},m)(n_{x},m)(n_{x},m)),我们可以把上面的式子化简成:

Z^{[1]}A^{[1]}的维度都为(4,m),4是隐藏层神经元个数。Z^{[2]}A^{[2]}的维度都为(1,m)。行表示神经元个数,列表示样本数目m。

5.激活函数

神经网络隐藏层和输出层都需要激活函数(activation function)。之前我们使用的是Sigmoid函数作为激活函数,下面是几个不同的激活函数:

  • sigmoid函数

  • tanh函数

  • ReLU函数

  • Leaky ReLU函数

关于选择合适的激活函数:对隐藏层来说,选择tanh函数比选择sigmoid函数合适。因为tanh函数的取值范围在[-1,+1]之间,隐藏层的输出被限定在[-1,+1]之间,可以看成是在0值附近分布,均值为0。这样从隐藏层到输出层,数据起到了归一化(均值为0)的效果。对输出层来说,选择sigmoid函数更合适,因为二分类问题的输出取值为{0,+1}。

sigmoid和tanh函数在|z|很大的时候,激活函数的斜率(梯度)很小。所以在这个区域内梯度下降算法会运行得比较慢。应尽量避免使z落在这个区域,使|z|尽可能限定在零值附近,从而提高梯度下降算法运算速度。

ReLU激活函数可以弥补sigmoid函数和tanh函数的缺点。ReLU函数在z大于零时梯度始终为1;在z小于零时梯度始终为0;z等于零时的梯度可以当成1也可以当成0。对于隐藏层,选择ReLU作为激活函数能够保证z大于零时梯度始终为1,从而提高神经网络梯度下降算法运算速度。但当z小于零时,存在梯度为0的缺点。Leaky ReLU激活函数能弥补这个缺点,保证z小于零时梯度不为0。

总之,输出层的激活函数一般会选择sigmoid函数,隐藏层选择tanh函数更好些,实际应用中,通常会会选择使用ReLU或者Leaky ReLU函数,保证梯度下降速度不会太小。但还是具体情况具体分析。

6.为什么需要非线性激活函数?

如果使用线性激活函数,最终得到的结果仍然是输入变量x的线性组合,即使用神经网络与直接使用线性模型的效果并没有什么两样。即便是包含多层隐藏层的神经网络,如果使用线性函数作为激活函数,最终的输出仍然是输入x的线性模型。这样的话神经网络就没有任何作用了。因此,隐藏层的激活函数必须要是非线性的。

如果所有的隐藏层全部使用线性激活函数,只有输出层使用非线性激活函数,那么整个神经网络的结构就类似于一个简单的逻辑回归模型,失去了神经网络模型本身的优势和价值。

但如果是预测问题而不是分类问题,输出y是连续的情况下,输出层的激活函数可以使用线性函数。如果输出y恒为正值,也可以使用ReLU激活函数,这里需要具体问题具体分析。

7.激活函数的导数

 sigmoid函数的导数:

 tanh函数的导数:

ReLU函数的导数:

 Leaky ReLU函数的导数:

8.神经网络的梯度下降法

 神经网络正向传播过程为:

其中,g(⋅)表示激活函数。

反向传播是计算导数(梯度)的过程,下面是Cost function对各个参数的梯度:

9.直观理解反向传播(选修)

浅层神经网络(包含一个隐藏层),m个训练样本的正向传播过程和反向传播过程分别包含了6个表达式,其向量化矩阵形式如下图所示:

10.随机初始化

神经网络模型中的参数权重W是不能全部初始化为零的,会导致隐藏层设置的多个神经元没有意义。但参数b可以初始化为0,并不会影响神经网络训练效果。

所以我们需要对权重W进行随机初始化,通过运用下面的python代码:

W_1 = np.random.randn((2,2))*0.01
b_1 = np.zero((2,1))
W_2 = np.random.randn((1,2))*0.01
b_2 = 0

乘以0.01的目的是希望初始化得到的W值尽量小,使用sigmoid函数或者tanh函数时能使z也比较小,提高梯度下降算法的运算速度。如果激活函数是ReLU或者Leaky ReLU函数,不需要考虑这个问题。但是,如果输出层是sigmoid函数,则对应的权重W最好初始化到比较小的值。

猜你喜欢

转载自blog.csdn.net/zhao2018/article/details/83038969