深度学习之course1————浅层神经网络
神经网络概述
- 从Logistic Regression过渡到Neural Network。某种意义上看,Logistic Regression可以看成一个只有一层的neural network, 即没有hidden layer。
- 每一层的计算,类似于Logistic Regression:先计算z,再计算a。然后本层的a再作为下一层的输入计算。
- 重要的记号:不同layer的变量,在neural network中用上标中括号表示,比如:(W^{[i]})表示第i层的权重。
神经网络的表示
- Neural Network的组成:一个input layer,多个hidden layer,一个output layer
- training set作为输入层,即第0层,因此有 (X = a^{[0]})
- 每一层输入,上标[i]表示layer的层数,下标j表示neuron的序号(每层有多个neuron)
- 一个惯例,input layer不计算在neuron Network的层数里,并且input layer的上标是0。因此一个例子中的是neural network是2层的。
- 注意每层的参数w和b的维度。w的行数是本层的neuron的个数,列数数是上一层neuron的个数。b是一个列向量,行数与w相同。
计算神经网络的输出
每个neuron的计算分为两步:z计算出线性组合,a计算**函数
每层的计算向量化(注意这里只是一个数据样本x的情况,后面会讲如何扩展为m个数据样本的情况)
整理后,向量化的表示:
Given input x(a single training set):
z[1]=W[1]a[0]+b[1] a[1]=σ(z[1]) z[2]=W[2]a[1]+b[2] a[2]=σ(z[2])
两点说明:
- 对中括号上标,本层的输出a,和参数w、b的上标是一样的,而输入的上标则是上一层的。有些文档里可能会把w、b的上标保持和上一层一样,这是不同的习惯吧。
- 上面计算时的(w^{[1]}_1)做了转置,最终向量化时W没有没有转置,这是因为前者是按照logistic regression的习惯定义的,即w是列向量。而后者是W的定义,每一行是该层对应neuron的参数,已经行向量了。
多样本向量化
前一节,已经强调了是针对一个training example的向量化,这一节要进一步对所有training example做向量化。
- 首先,是非向量化的实现,即对m个training example进行迭代如下:
即在上一节的公式上,对x、z、a添加小括号上标。z和a和x的维度是一样的,即和training example对应的,而参数w和b没有training example这一维度,或者说w和b是对所有m个training example计算结果做平均。
2.向量化 - 先弄清每个矩阵的维度X,Z以及A。三个变量的维度是一致的,在column方向都表示不同的training example;在row的方向表示不同的neuron:
- 基于上面对X,Z以及A的定义,有: Z[1]=W[1]A[0]+b[1] A[1]=σ(Z[1]) Z[2]=W[2]A[1]+b[2] A[2]=σ(Z[2])
向量化实现的解释
其实就一句话:一个矩阵A乘以B,且B是列向量,那么B扩展为矩阵是没有问题的,结果也从一个列向量变成矩阵。
**函数
- activation function是指将线性组合计算的 z,进一步映射的non-linear function。比如sigmoid function就是将线性组合计算的z从实数域映射到了开区间(0,1)。
- 常用的activation function有
sigmoid function a=σ(z)=11+e−z 映射到开区间(0,1)
tanh function: a shift verison a sigmoid function a=tanh(z)=ez−e−zez+e−z 映射到开区间(-1,1)
在hidden layer中用tanh代替sigmoid,基本上效果会更好,因为tanh会产生一个均值为0的结果,相当于自动做了中心化处理。 Andrew对选用sigmoid还是tanh的建议:hidden layer尽量用tanh而不是sigmoid,output layer根据输出需要可用sigmoid;另外每一层也可以选用不同的activation function。
ReLU function a=max(0,a)
sigmoid和tanh共同的不足是:当z很大或很小时,导数都趋近于0,这会导致梯度下降的速度比较慢。因此,又引入了ReLU function(Rectified Linear Unit),这个名字听起来挺牛逼,但实际表达式很简单,就是将线性函数小于0的部分做了修正(Rectifed),最简单的修正就是直接让其等于0。 而且Andrew极力推荐ReLU:if you’re not sure what to use for your hidden layer, I would just use the relu activation function that’s what you see most people using these days.
ReLU的一个好处是(我也不确定为什么是好处,Andrew只是说 in practice this works just fine):ReLU在小于0的时候,导数为0。 ReLU另一个版本叫做Leaky ReLU,即在小于0的部分,修正为一个斜率很小的直线(ReLU修正为了斜率为0的直线):
Leaky ReLUE通常比ReLU效果更好,但实践中去不常用(为毛好的东西不用?)。 相比sigmoid或tanh,ReLU或Leaky ReLU计算的更快 ,这也很显然,线性函数的导数就是一个常数。
3. Activation Function的建议
1.sigmoid:除非在output layer要做binary classification会用到,hidden layer几乎不会用。要用也是有限用tanh
2. 默认或最常用的是ReLU(或者也可以尝试Leaky ReLU)
3.面对具体情况,也可以尝试不同的算法,再选择最好的。
为什么需要非线性**函数
一句话解释:
the composition of two linear functions is itself a linear function.
因此无论你做多少层的network,其实与做一层没什么区别。
当然,在output layer是可以不用activation function,或者用linear activation function;这种情况一般是要求输出实数集结果(比如预测房价)。即便如此,在hidden layer还是要用non-linear activation function。
**函数的导数
三种activation function的导数:
- sigmoid function dz=a*(1-a)
- tanh function dz=1−tanh(z)2
- ReLU function 这个就很简单了,唯一要注意0的时候不可导,因此做个修正,直接定义0点的导数为0。
**神经网络的梯度下降 **
- gradient descent的关键是求cost function对参数的偏导数
- 求导过程使用的是Backpropagation
- 首先做forward propagation,求解出每一层的输出A
- 然后向后,逐层求解对每一层参数的偏导数
随机初始化
与logistic regression不同,初始化参数不可固定为0,而是每个参数都要随机初始化。
主要原因是:如果每个参数w和b都是0,则同一层的每个neuron计算结果完全一样(输入一样a,参数一样w,则z一样);接下来反向传播时的偏导数也一样,下一轮迭代同一层的每个neuron的w又是一样的。这样整个neural Network上每一层的neuron是同质的,自然不会有好的performance。
不过,对b参数,可以都初始化为0。
另外需要注意,虽然w是随机初始化,但最好使用较小的随机数。主要是避免让z的计算值过大,导致activation function对z的偏导数趋于0,导致Gradient descent下降较慢。 通常的做法是对random的值乘以一个比率,比如0.01(但具体怎么选这个比率,也要根据情况而定,这应该又是一个超参了): W[1]=np.random.randn((2,2))∗0.01
The general methodology to build a Neural Network is to:
- Define the neural network structure ( # of input units, # of hidden units, etc).
- Initialize the model’s parameters
- Loop:
Implement forward propagation
Compute loss
Implement backward propagation to get the gradients
Update parameters (gradient descent)
本文参考了毛帅的博客如若侵权请告知删除