改善深层神经网络:超参数调试、正则化以及优化

  这周的视频主要讲了超参数搜索方法、Batch Norm归一化处理、SoftMax回归以及TensorFlow计算框架的使用。

搜索超参数

  在之前的课程中出现了很多超参数,如学习率$a$、神经网络层数$l$,在求解过程中需要对超参数的取值进行调整。超参数的调整可以遵循以下几个规则

  1. 随机搜索优于网格搜索,在进行网格搜索时,同一个纬度取的值较少,如下图,同样是取25个值,在进行网格搜索时超参数1只使用了5个值,而进行随机搜索时参数1和参数2都使用了25个值。


  1. 由粗略搜索到精细搜索,即先在大范围内寻找效果好的区域范围,再在该范围内进行精细搜索
  2. 第1条中说的随机搜索并不是在有效范围内均匀随机取值,而是需要选择合适的坐标系。对于隐藏层数来说,可以在规定范围内进行均匀随机取值,如范围时2到4层,取值时选取2、3、4三个值。但是对于学习率α,其范围在0.0001到1之间,如果α有很大可能在0.0001到0.1之间,若随机均匀取值,那么在0.1到1之间将用去90%的资源,这是不合理的。这时候要是取对数坐标,就能在0.0001到0.1之间取得更多的值。

  为了优化模型效果,通常有两种方式进行训练。第一种是选择一个模型进行训练,观察其代价函数,在其变化的过程中,不断调节超参数,使曲线不上升,这种方法适用于数据量大、时间充足的情况;第二种是同时建立多个模型,观察所有模型的代价函数,选择表现较好的模型,这种方法适用于计算能力较强的情况。

Batch Norm归一化处理

  在视频中Ng把输入层归一化推广到隐含层归一化,并且从前向传播角度说明了Batch Norm的好处。其实可以从公式推导角度证明Batch Norm为什么可以加快训练速度。
  当使用sigmoid函数作为激活函数时,其导数在x=0时取得最大值,当x远离0时其导数基本为0。而对于正态分布而言,有95%的数据在[-2,2]的范围内,这样在进行反向传播时出现梯度消失的数据较少,使得整体上保持较快速度收敛。如果不进行Batch Norm处理,数据就会落在激活函数的饱和区,这样梯度越来越小,甚至出现梯度消失现象。




  下面说说Batch Norm的处理过程
$$\mu=\frac{1}{m}\sum_{i}^{}z^{(i)}$$
$$\sigma^2=\frac{1}{m}\sum_{i}^{} (z^{(i)}-\mu)^2$$
$$z^{(i)}_{norm}=\frac{z^{(i)-\mu}}{\sqrt{\sigma^2+\varepsilon}}$$
$${z^{(i)}_{norm}}^{‘} = \gamma z^{(i)}_{norm}+\beta$$
最后又加入了$\gamma$、$\beta$参数,同样可以通过梯度下降进行求解。

SoftMax回归

  当进行二分类时,最后一层的激活函数可以采用sigmoid函数,当涉及多分类时就要用到softmax函数。先给出softmax函数的形式

$$h_{\theta}(x^{(i)})=
\begin{bmatrix}
p(y^{(i)}=1|x^{(i)};\theta)\\
p(y^{(i)}=2|x^{(i)};\theta)\\
\vdots\\
p(y^{(i)}=3|x^{(i)};\theta)\\
\end{bmatrix}=
\frac{1}{\sum_{j=1}^{k}e^{\theta^{T}_{j}x^{(i)}}}
\begin{bmatrix}
e^{\theta^{T}_{1}x^{(i)}}\\
e^{\theta^{T}_{2}x^{(i)}}\\
\vdots\\
e^{\theta^{T}_{k}x^{(i)}}\\
\end{bmatrix}
$$
举个视频的例子就是




  softmax回归做了两件事情,第一步是将模型的每个输出加上了指数映射,将其取值范围定义在正实数,第二步是把经过转换的输出进行归一化,得到概率分布。在网上给出的推导版本中都是直接给出了softmax的指数形式,其实线性回归、logistic回归、softmax回归都是从广义线性模型推导出来的,当y的分布是正态分布时得到的就是线性模型,当y是两点分布时得到的是logistic回归模型,当y是多项式分布时得到的是softmax回归模型。

TensorFlow的使用

  在进行神经网络搭建事,个人觉得还是keras比较好用,接口抽象的比较友好,不过既然视频提到了TensorFlow,那也研究一下吧,贴上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#coding=utf-8
import tensorflow as tf
import numpy as np

#准备数据
train_X = np.linspace(-1,1,100)
train_Y = 2 * train_X + np.random.randn(*(train_X.shape))*0.33 + 10

#定义模型
X = tf.placeholder("float")
Y = tf.placeholder("float")
w = tf.Variable(0.0,name="weight")
b = tf.Variable(0.0,name="bias")
#定义均方误差损失函数
loss = tf.square(Y - tf.multiply(X,w) -b)
tran_op = tf.train.GradientDescentOptimizer(0.01).minimize(loss)

#模型训练
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
epoch =1
for i in range(10):
for (x,y) in zip(train_X,train_Y):
_,w_value,b_value = sess.run([tran_op,w,b],feed_dict={X:x,Y:y})
print "Epoch:{}, w:{}, b:{}".format(epoch,w_value,b_value)
epoch+=1

输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Epoch:1, w:-0.157984390855, b:0.157984390855

Epoch:2, w:-0.311834096909, b:0.315006256104

Epoch:3, w:-0.45063239336, b:0.459648668766

Epoch:4, w:-0.587551951408, b:0.605401754379

Epoch:5, w:-0.719821453094, b:0.749299347401

Epoch:6, w:-0.839450538158, b:0.882369875908

Epoch:7, w:-0.967249691486, b:1.02779650688

Epoch:8, w:-1.08310699463, b:1.16273617744

Epoch:9, w:-1.18981790543, b:1.29001784325
...
Epoch:990, w:1.9911210537, b:10.0346708298

Epoch:991, w:1.99132072926, b:10.0349149704

Epoch:992, w:1.9895298481, b:10.0327787399

Epoch:993, w:1.99043321609, b:10.0338306427

Epoch:994, w:1.99787294865, b:10.0422964096

Epoch:995, w:1.98872160912, b:10.03211689

Epoch:996, w:1.99850010872, b:10.042755127

Epoch:997, w:1.99492764473, b:10.0389518738

Epoch:998, w:1.99669957161, b:10.0407981873

Epoch:999, w:1.99851024151, b:10.0426464081

Epoch:1000, w:2.01060414314, b:10.0547399521
-------------本文结束感谢您的阅读-------------

本文标题:改善深层神经网络:超参数调试、正则化以及优化

文章作者:小建儿

发布时间:2017年11月24日 - 19:11

最后更新:2018年11月17日 - 18:11

原始链接:http://yajian.github.io/改善深层神经网络:超参数调试、正则化以及优化/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。