- 前馈神经网络、网络层数、输入层、隐藏层、输出层、隐藏单元、激活函数的概念。
- 感知机相关;利用tensorflow等工具定义简单的几层网络(激活函数sigmoid),递归使用链式法则来实现反向传播。
- 激活函数的种类以及各自的提出背景、优缺点。(和线性模型对比,线性模型的局限性,去线性化)
- 深度学习中的正则化(参数范数惩罚:L1正则化、L2正则化;数据集增强;噪声添加;early stop;Dropout层)、正则化的介绍。
- 深度模型中的优化:参数初始化策略;自适应学习率算法(梯度下降、AdaGrad、RMSProp、Adam;优化算法的选择);batch norm层(提出背景、解决什么问题、层在训练和测试阶段的计算公式);layer norm层。
一、前馈神经网络
概念:前馈神经网络、网络层数、输入层、隐藏层、输出层、隐藏单元、激活函数
前馈神经网络:前馈神经网络是一种最简单的神经网络,各神经元分层排列。每个神经元只与前一层的神经元相连。接收前一层的输出,并输出给下一层.各层间没有反馈。
网络层数:一般是指设置或者搭建的模型有多少层。以上图为例,网络层为3。注:一般不包括输入层。
输入层:一般指数据输入模型的一层,如图中 Layer L 1 L_1 L1 层。
输出层:一般指模型的最后一层,即Layer L 4 L_4 L4 层;
隐藏层:指除开输入层和输出层之外的中间层,如图Layer L 2 L_2 L2 层和 L 3 L_3 L3 层;
隐藏单元:一般指隐藏层中的单元结构。
激活函数:一般指加权之后的值到输出之间函数,通过激活函数将上一层的输出作为下一层输入之前进行非线性变化,使模型不再是单一的线性变换。
二、简单的神经网络(tensorflow)
前期准备
首先给网络提供
M
M
M 个训练对
(
X
,
Y
)
(X,Y)
(X,Y),
X
X
X 为输入,
Y
Y
Y 为期望的输出。输入通过激活函数
g
(
h
)
g(h)
g(h) 和隐藏层传播到输出层。输出
Y
^
\hat{Y}
Y^ 是网络的输出,得到
e
r
r
o
r
=
Y
−
Y
^
error=Y-\hat{Y}
error=Y−Y^。其损失函数
J
(
W
)
J(W)
J(W) 如下:
J
(
W
)
=
1
2
M
∑
i
=
1
N
(
Y
i
−
Y
^
i
)
2
J(W)=\frac{1}{2M}\sum_{i=1}^{N}(Y_i-\hat{Y}_i)^2
J(W)=2M1i=1∑N(Yi−Y^i)2
其中,
i
i
i 取遍所有输出层的神经元(1 到 N)。然后可以使用
J
(
W
)
J(W)
J(W) 的梯度并使用链式法则求导,来计算连接第
i
i
i 个输出层神经元到第
j
j
j 个隐藏层神经元的权重
W
i
j
W_{ij}
Wij 的变化:
Δ
W
i
j
=
−
η
∂
J
∂
W
i
j
=
η
1
M
∂
(
Y
i
−
Y
^
i
)
2
∂
Y
^
∂
Y
^
∂
h
i
∂
h
i
∂
W
i
j
=
η
1
M
(
Y
i
−
Y
^
i
)
g
′
(
h
i
)
O
j
\Delta W_{ij}=-\eta\frac{\partial{J}}{\partial W_{ij}}=\eta\frac{1}{M}\frac{\partial{(Y_i-\hat{Y}_i)^2}}{\partial{\hat{Y}}} \frac{\partial{\hat{Y}}}{\partial{h_i}} \frac{\partial{h_i}}{\partial{W_{ij}}}=\eta\frac{1}{M}(Y_i-\hat{Y}_i)g'(h_i)O_j
ΔWij=−η∂Wij∂J=ηM1∂Y^∂(Yi−Y^i)2∂hi∂Y^∂Wij∂hi=ηM1(Yi−Y^i)g′(hi)Oj
这里,
O
j
O_j
Oj 是隐藏层神经元的输出,
h
i
h_i
hi 表示输出层的输入值。这很容易理解,但现在怎么更新连接第
n
n
n 个隐藏层的神经元
k
k
k 到第
n
+
1
n+1
n+1 个隐藏层的神经元
j
j
j 的权值
W
j
k
W_{jk}
Wjk?过程是相同的:将使用损失函数的梯度和链式法则求导,但这次计算
W
j
k
W_{jk}
Wjk:
通过二层的全连接网络,实现 mnist
数据集分类任务。
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist_path = '/home/jie/Jie/codes/tf/datasets/MNIST_data/'
mnist = input_data.read_data_sets(mnist_path, one_hot=True)
# 定义超参数和其他常量
n_input = 784 # 28 * 28
n_classes = 10
max_epochs = 10000
learning_rate = 0.5
batch_size = 10
seed = 0
n_hidden = 30
## Sigmoid 函数的导数
def sigmaprime(x):
return tf.multiply(tf.sigmoid(x), tf.subtract(tf.constant(1.0), tf.sigmoid(x)))
# 为训练数据创建占位符
x_in = tf.placeholder(tf.float32, [None, n_input], name='x_in')
y = tf.placeholder(tf.float32, [None, n_classes], name='y')
# 创建模型
def multilayer_perceptron(x, weight, biases):
h_layer_1 = tf.add(tf.matmul(x, weights['h1']), biases['h1'])
out_layer_1 = tf.sigmoid(h_layer_1)
h_out = tf.add(tf.matmul(out_layer_1, weights['h2']), biases['h2'])
return tf.sigmoid(h_out), h_out, out_layer_1, h_layer_1
# 权重
weights = {
'h1':tf.Variable(tf.random_normal([n_input, n_hidden], seed=seed)),
'h2':tf.Variable(tf.random_normal([n_hidden, n_classes], seed=seed))}
# 偏置
biases = {
'h1':tf.Variable(tf.random_normal([1, n_hidden], seed=seed)),
'h2':tf.Variable(tf.random_normal([1, n_classes], seed=seed))}
# 正向传播
y_hat, h_2, o_1, h_1 = multilayer_perceptron(x_in, weights, biases)
# loss function
err = y - y_hat
loss = tf.reduce_mean(tf.square(err, name='loss'))
# 反向传播
delta_2 = tf.multiply(err, sigmaprime(h_2))
delta_w_2 = tf.matmul(tf.transpose(o_1), delta_2)
wtd_error = tf.matmul(delta_2, tf.transpose(weights['h2']))
delta_1 = tf.multiply(wtd_error, sigmaprime(h_1))
delta_w_1 = tf.matmul(tf.transpose(x_in), delta_1)
eta = tf.constant(learning_rate)
# 更新权重
train = [
tf.assign(weights['h1'], tf.add(weights['h1'], tf.multiply(eta, delta_w_1))),
tf.assign(biases['h1'], tf.add(biases['h1'], tf.multiply(eta, tf.reduce_mean(delta_1, axis=[0])))),
tf.assign(weights['h2'], tf.add(weights['h2'], tf.multiply(eta, delta_w_2))),
tf.assign(biases['h2'], tf.add(biases['h2'], tf.multiply(eta, tf.reduce_mean(delta_2, axis=[0]))))
]
# 定义精度
acc_mat = tf.equal(tf.argmax(y_hat, 1), tf.argmax(y, 1))
accuracy = tf.reduce_sum(tf.cast(acc_mat, tf.float32))
# train
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
for epoch in range(max_epochs):
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
_, loss1 = sess.run([train, loss], feed_dict={x_in: batch_xs, y: batch_ys})
if epoch % 1000 == 0:
print('Epoch: {0} loss: {1}'.format(epoch, loss1))
acc_test = sess.run(accuracy, feed_dict={x_in: mnist.test.images, y:mnist.test.labels})
acc_train = sess.run(accuracy, feed_dict={x_in: mnist.train.images, y:mnist.train.labels})
# 评估
print('Accuracy Train%: {1} Accuracy Test%: {2}'.format(epoch, acc_train / 600, (acc_test / 100)))
输出结果
Epoch: 0 loss: 0.3155866861343384
Epoch: 1000 loss: 0.023114416748285294
Epoch: 2000 loss: 0.017101742327213287
Epoch: 3000 loss: 0.01927866041660309
Epoch: 4000 loss: 0.019498592242598534
Epoch: 5000 loss: 0.017000144347548485
Epoch: 6000 loss: 0.006083908025175333
Epoch: 7000 loss: 0.018798980861902237
Epoch: 8000 loss: 0.04835653677582741
Epoch: 9000 loss: 0.0037784664891660213
Accuracy Train%: 84.58166666666666 Accuracy Test%: 92.65
三、激活函数
1、概述
主要作用:提供网络的非线性建模能力。
假设一个神经网络中仅包含线性卷积和全连接运算,那么该网络仅能够表达线性映射,即无论神经网络有多少层,输出都是输入的线性组合,与没有隐藏层效果相当。加入(非线性)激活函数之后,深度神经网络才具备了分层的非线性映射学习能力,几乎可以逼近任意函数。
激活函数的性质:
- 可微性: 当优化方法是基于梯度的时候,这个性质是必须的。
- 单调性: 当激活函数是单调的时候,单层网络能够保证是凸函数。
- 输出值的范围: 当激活函数输出值是 有限 的时候,基于梯度的优化方法会更加 稳定,因为特征的表示受有限权值的影响更显著;当激活函数的输出是 无限 的时候,模型的训练会更加高效,不过在这种情况小,一般需要更小的learning rate
常用的激活函数:
- sigmoid
- tanh
- ReLU
- Leaky ReLU
- Maxout
- ELU
2、sigmoid 激活函数
(1)定义
s
i
g
m
o
i
d
sigmoid
sigmoid 函数,即著名的
L
o
g
i
s
t
i
c
Logistic
Logistic 函数,是常用的非线性激活函数,可将变量映射到
(
0
,
1
)
(0,1)
(0,1) 之间,公式如下:
f
(
x
)
=
1
1
+
e
−
x
f(x)=\frac{1}{1+e^{-x}}
f(x)=1+e−x1
几何图像如下:
(2)特点
能将输入的连续实值映射到 ( 0 , 1 ) (0,1) (0,1) 之间。特别的,若非常小的负值,输出为 0;非常大的正值,输出为1。
(3)缺点
缺点1:梯度爆炸和梯度消失
在深度神经网络中梯度反向传播时可能会导致梯度爆炸和梯度消失,其中梯度爆炸发生的概率非常小,而梯度消失发生的概率比较大。
s
i
g
m
o
i
d
sigmoid
sigmoid 函数的导数为:
f
′
(
x
)
=
e
−
x
(
1
+
e
−
x
)
2
=
f
(
x
)
(
1
−
f
(
x
)
)
f'(x)=\frac{e^{-x}}{(1+e^{-x})^2}=f(x)(1-f(x))
f′(x)=(1+e−x)2e−x=f(x)(1−f(x))
当网络权值初始化为 ( 1 , + ∞ ) (1,+∞) (1,+∞)区间内的值,则会出现梯度爆炸情况。
sigmoid 的软饱和性。从上图可以看到,其两侧导数逐渐趋近于0,具有这种性质的称为软饱和激活函数。具体的,饱和又可分为左饱和与右饱和。
lim
n
→
∞
f
′
(
x
)
=
0
\lim_{n \to \infty} f'(x)=0 \quad
n→∞limf′(x)=0
与软饱和对应的是硬饱和,即
f
′
(
x
)
=
0
,
当
∣
x
∣
>
c
,
其
中
c
为
常
数
。
f'(x)=0,当|x|>c,其中 c 为常数。
f′(x)=0,当∣x∣>c,其中c为常数。
s i g m o i d sigmoid sigmoid 的软饱和性,使得深度神经网络在二三十年里一直难以有效的训练,是阻碍神经网络发展的重要原因。具体来说,由于在后向传递过程中, s i g m o i d sigmoid sigmoid 向下传导的梯度包含了一个 f ′ ( x ) f'(x) f′(x) 因子( s i g m o i d sigmoid sigmoid 关于输入的导数),因此一旦输入落入饱和区, f ′ ( x ) f'(x) f′(x) 就会变得接近于 0 0 0,导致了向底层传递的梯度也变得非常小。此时,网络参数很难得到有效训练。这种现象被称为梯度消失。一般来说, s i g m o i d sigmoid sigmoid 网络在 5 层之内就会产生梯度消失现象
缺点2:Sigmoid 的 output 不是0均值(即zero-centered)
其值域在[0,1]之间,函数输出不是0均值的,权重更新效率降低,因为这会导致后层的神经元的输入是非0均值的信号,这会对梯度产生影响:假设后层神经元的输入都为正(e.g.
x
>
0
x>0
x>0 elementwise in ),那么对w求局部梯度则都为正,这样在反向传播的过程中w要么都往正方向更新,要么都往负方向更新,导致有一种捆绑的效果,使得收敛缓慢。 当然了,若按batch去训练,那么每个batch可能得到不同的符号(正或负),那么相加一下这个问题还是可以缓解。因此,非0均值这个问题虽然会产生一些不好的影响,不过跟上面提到的梯度消失问题相比还是要好很多的。
缺点3:耗时
其解析式中含有幂运算,计算机求解时相对来讲比较耗时。对于规模比较大的深度网络,这会较大地增加训练时间。
缺点4:梯度弥散(死区)
受现有的梯度下降算法所限(严重依赖逐层的梯度计算值),Sigmoid函数对落入
(
−
∞
,
−
5
)
∪
(
5
,
+
∞
)
(-∞,-5) ∪ (5,+∞)
(−∞,−5)∪(5,+∞)的输入值,梯度计算为
0
0
0,发生 梯度弥散。因此该函数存在一正一负 两块“死区”[蓝框区域]:
3、tanh函数
tanh是双曲函数中的一种,又名 双曲正切:
t
a
n
h
(
x
)
=
e
x
−
e
−
x
e
x
+
e
−
x
=
2
s
i
g
m
o
i
d
(
2
x
)
−
1
tanh(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}}=2sigmoid(2x)-1
tanh(x)=ex+e−xex−e−x=2sigmoid(2x)−1
导数为:
t
a
n
h
′
(
x
)
=
4
e
−
2
x
(
e
−
2
x
+
1
)
2
=
2
t
a
n
h
(
x
)
(
1
−
t
a
n
h
(
x
)
)
tanh'(x)=\frac{4 e^{-2x}}{(e^{-2x}+1)^2}=2tanh(x)(1-tanh(x))
tanh′(x)=(e−2x+1)24e−2x=2tanh(x)(1−tanh(x))
优点:
- tanh解决了sigmoid的输出非“零为中心”的问题。
缺点:
- 依然有sigmoid函数梯度消失的问题。
- 依然指数运算。
4、ReLU函数
ReLU(Rectified Linear Unit,修正线性单元),是一种线性且不饱和的激活函数。公式如下:
f
(
x
)
=
m
a
x
(
0
,
x
)
f(x)=max(0,x)
f(x)=max(0,x)
导数如下:
f
′
(
x
)
=
{
1
,
if
x
>
0
0
,
if
x
≤
0
f'(x)=\begin{cases} 1, & \text{if $x>0$} \\ 0 , & \text{if $x\leq0$ } \end{cases}
f′(x)={1,0,if x>0if x≤0
优点
- ReLU解决了梯度消失的问题,至少 x x x 在正区间内,神经元不会饱和。
- 由于ReLU线性、非饱和的形式,在SGD中能够快速收敛。
- 计算速度要快很多。线性计算
缺点
- ReLU的输出不是“零为中心”(Notzero-centered output)。
- 随着训练的进行,可能会出现神经元死亡,权重无法更新的情况。(不可逆转的死亡)
- 解释:训练神经网络的时候,一旦学习率没有设置好,第一次更新权重的时候,输入是负值,那么这个含有ReLU的神经节点就会死亡,再也不会被激活。
- 因为:ReLU的导数在x>0的时候是1,在x<=0的时候是0。如果x<=0,那么ReLU的输出是0,那么反向传播中梯度也是0,权重就不会被更新,导致神经元不再学习。 也就是说,这个ReLU激活函数在训练中将不可逆转的死亡,导致了训练数据多样化的丢失。
- 在实际训练中,如果学习率设置的太高,可能会发现网络中40%的神经元都会死掉,且在整个训练集中这些神经元都不会被激活。所以,设置一个合适的较小的学习率,会降低这种情况的发生。为了解决神经元节点死亡的情况,有人提出了Leaky ReLU、P-ReLU、R-ReLU、ELU等激活函数。
5、Leaky ReLU
Leaky ReLU 是 ReLU 激活函数的改进版本,公式如下:
f
(
x
)
=
{
x
,
if
x
>
0
a
x
,
if
x
≤
0
f(x)=\begin{cases} x, & \text{if $x>0$} \\ ax , & \text{if $x\leq0$ } \end{cases}
f(x)={x,ax,if x>0if x≤0
导数如下:
f
(
x
)
=
{
1
,
if
x
>
0
a
,
if
x
≤
0
f(x)=\begin{cases} 1, & \text{if $x>0$} \\ a , & \text{if $x\leq0$ } \end{cases}
f(x)={1,a,if x>0if x≤0
优点
- 神经元不会出现死亡的情况。
- 对于所有的输入,不管是大于等于0还是小于0,神经元不会饱和。
- 由于Leaky ReLU线性、非饱和的形式,在SGD中能够快速收敛。
- 计算速度要快很多。只有线性关系。
缺点
- Leaky ReLU函数中的 α α α,需要通过先验知识人工赋值,通常 α = 0.01 \alpha=0.01 α=0.01。
6、Maxout
Maxout 是 ReLU 的推广,定义如下:
f
(
x
)
=
m
a
x
(
w
1
T
x
+
b
1
,
w
2
T
x
+
b
2
,
⋯
,
w
n
T
x
+
b
n
)
f(x)=max(w^T_1x+b_1,w^T_2x+b_2,⋯,w^T_nx+b_n)
f(x)=max(w1Tx+b1,w2Tx+b2,⋯,wnTx+bn)
Maxout 网络能够近似任意连续函数,且当 w 2 , b 2 , … , w n , b n w_2,b_2,…,w_n,b_n w2,b2,…,wn,bn为0时,退化为ReLU。
优点
- Maxout能够缓解梯度消失
- 规避了ReLU神经元死亡的缺点
缺点
- 增加了参数和计算量。
7、ELU
ELU(Exponential Linear Units,指数线性单元)。它试图将激活函数的输出平均值接近零,从而加快学习速度。同时,它还能通过正值的标识来避免梯度消失的问题。
公式如下:
f
(
x
)
=
{
x
,
if
x
>
0
a
(
e
x
−
1
)
,
otherwise
f(x)=\begin{cases} x, & \text{if $x>0$} \\ a(e^x-1) , & \text{otherwise } \end{cases}
f(x)={x,a(ex−1),if x>0otherwise
其中,超参数
α
\alpha
α 常被设定为 1
导数如下:
f
′
(
x
)
=
{
1
,
if
x
>
0
a
e
x
,
otherwise
f'(x)=\begin{cases} 1, & \text{if $x>0$} \\ ae^x , & \text{otherwise } \end{cases}
f′(x)={1,aex,if x>0otherwise
优点
- 完美解决了死区问题。
- ELU激活函数的输出均值是接近于零的
缺点
- 计算较复杂。
8、激活函数的选择
(1)深度学习需要大量时间处理大量数据,模型的收敛速度尤为重要。所以,总体来讲,训练深度神经网络尽量使用 zero-centered 数据(预处理实现) 和 zero-centered 输出。
==》尽量选择输出具有 zero-centered 特点的激活函数来加速模型的收敛速度。
(2)在使用 ReLU 时,小心设置 learning_rate,而且注意不要出现很多神经元死亡。若不好解决,可尝试 Leaky ReLU、Maxout 等。
(3)最好不使用 sigmoid、tanh
(4)conv -> bn -> relu
标配的 module。
四、正则化
正则化是选择模型的一种方法,具体来说,选择经验风险与模型复杂度同时较小的模型(防止过拟合),这样可以较少泛化误差而不是训练误差。
常用正则化方法
- 参数范数惩罚:L1正则化、L2正则化;
- 数据集增强;
- 噪声添加;
- early stop;
- Dropout层
1、参数范数惩罚
参数范数惩罚通过对目标函数 J J J 添加一个参数范数惩罚 Ω ( θ ) Ω(θ) Ω(θ),限制模型的学习能力。
将正则化欧的目标函数记为
J
~
\tilde{J}
J~:
J
~
(
θ
;
X
,
y
)
=
J
(
θ
;
X
,
y
)
+
α
Ω
(
θ
)
\tilde{J}(\theta;X,y)=J(\theta;X,y)+\alphaΩ(θ)
J~(θ;X,y)=J(θ;X,y)+αΩ(θ)
其中
α
≥
0
\alpha\geq0
α≥0 是权衡范数惩罚项
Ω
Ω
Ω 和标准目标函数
J
(
X
;
θ
)
J(X;θ)
J(X;θ) 相对贡献的超参数,通过调整
α
\alpha
α 的大小,可以获得不同的参数选择偏好。
注意:参数包括模型中每一层仿射变换的权重和偏置,我们通常只对权重做惩罚,而不对偏置做正则惩罚。因为精确拟合偏置所需的数据通常比权重少的多,正则化偏置参数可能会导致明显的欠拟合。
(1)相关定义
L0范数:权重向量
W
W
W 中非0的元素的个数,通常表示为
∣
∣
W
∣
∣
0
||W||_0
∣∣W∣∣0。
L1范数:权值向量
W
W
W 中各个元素的绝对值之和,通常表示为
∣
∣
W
∣
∣
1
||W||_1
∣∣W∣∣1。
L2范数:权值向量
W
W
W 中各个元素的平方的和的开方值,通常表示为
∣
∣
W
∣
∣
2
||W||_2
∣∣W∣∣2。
任何的规则化算子,如果它在 W i = 0 W_i=0 Wi=0 处不可微,并且可以分解为一个“求和”的形式,则该规则化算子就可以实现稀疏。
稀疏的好处
-
特征选择(Feature Selection):能实现特征的自动选择
稀疏规则化算子会学习地去掉这些对最终输出结果没有关系或者不提供任何信息的特征,也就是把这些特征对应的权重置为0。 -
可解释性(Interpretability)
非零权重的特征为输出结果提供的信息是巨大的、决策性的。
(2)L0正则化
从直观上看,利用非零参数的个数,可以很好的来选择特征,实现特征稀疏的效果,具体操作时选择参数非零的特征即可。
但因为L0正则化很难求解,是个NP难问题,因此一般采用L1正则化。L1正则化是L0正则化的最优凸近似,比L0容易求解,并且也可以实现稀疏的效果。
(3)L1正则化
L1范数也称叫“稀疏规则算子”(Lasso regularization),L1范数和 L0范数 可以实现稀疏,L1因具有比L0更好的优化求解特性而被广泛应用。
(4)L2正则化
L2范数,在回归中称为:“岭回归” (Ridge Regression) 或 “权值衰减weight decay”。
让L2范数的规则项 ∣ ∣ W ∣ ∣ 2 ||W||_2 ∣∣W∣∣2 最小,可以使得 W W W 的每个元素都很小,都接近于0(不会让它等于0)。而越小的参数说明模型越简单,越简单的模型则越不容易产生过拟合现象。
2、数据扩增(data agumentation)
较少过拟合的最简单方法:增加训练集样本,也称数据扩增(data agumentation)。但是由于标注数据昂贵,需要通过其他方式增加样本。
- 图像处理:旋转、翻转、放缩、平移等等。
- GAN(对抗式生成网络)
3、噪声添加
噪声添加:将其直接添加到学习到的权重上。这项技术主要被用于循环神经网络的情况下。
在某些假设下,施加于权重的噪声可以被解释为与更传统的正则化形式等同,鼓励要学习的函数保持稳定。
4、Dropout
Dropout:在用前向传播算法和反向传播算法训练模型时,随机的从全连接DNN网络中去掉一部分隐含层的神经元。
两种理解:
- 减少神经元之间复杂的共适应关系:在每次训练的时候使用dropout,每个神经元有一定的概率被移除,这样可以使得一个神经元的训练不依赖于另外一个神经元,同样也就使得特征之间的协同作用被减弱。 Hinton认为,过拟合可以通过阻止某些特征的协同作用来缓解。
- 多模型效果平均的方式。对于减少测试集中的错误,我们可以将多个不同神经网络的预测结果取平均,而因为dropout的随机性,在每次dropout后,网络模型可看成不同结构的神经网络,而要训练的参数数目却是不变的,这就解脱了训练多个独立的不同神经网络的时耗问题。在测试输出的时候,将输出权重乘以保留概率1-p%,从而达到类似平均的效果。
左边的图为一个完全的全连接层,右边为应用dropout后的全连接层。
做法
- 训练阶段:每次更新参数之前,每个神经元有一定的概率被丢弃,假设为p%,p可以设为50或者根据验证集的表现来选取,输入层的p比较小,保留概率接近于1
- 测试阶段不dropout,保留所有单元的权重,而且要乘以保留概率1-p%,为了保证输出期望一致。
dropout不只用于前馈神经网络,还可以用于图模型,比如玻尔兹曼机。
5、早期停止(early stopping)
早期停止是一种交叉验证策略,将一部分数据集作为验证集(validation set)。
当我们看到验证集上的性能越来越差时,就停止对模型的训练。
五、深度模型中的优化(待完善)
1、参数初始化策略
目的:在训练中学到有用的信息,需要参数更新时的梯度不为0。而一般来讲,参数更新的梯度和反向传播得到的状态梯度以及输入激活值有关。
==》初始化条件:
- 各层激活值不会出现饱和现象(eg: sigmoid、tanh)
- 各层激活值不为0。
(1)全零初始化??
全零初始化:模型无法更新,而且模型权重的相同,导致模型的高度对称性。
==》需要破坏对称性
(2)随机初始化 (Random Initialization)
将参数值(通过高斯分布或均匀分布)随机初始化为 接近0的 一个很小的随机数(有正有负),从而使对称失效。
(3)Xavier
基本思想:保持输入和输出的方差一致,这样就避免了所有输出值都趋向于0。
(4)MSRA
(5)bias初始化
通常初始化为0(若初始化为0.01等值,可能并不能得到好的提升,反而可能下降)
(6)小结
-
Gaussian
满足 m e a n = 0 mean=0 mean=0, s t d = 1 std=1 std=1的高斯分布 x ∼ N ( m e a n , s t d ) x∼N(mean,std) x∼N(mean,std) -
Xavier
定义参数所在层的输入维度为n,输出维度为m,那么参数将以均匀分布的方式在 [ − 6 m + n , 6 m + n ] [-\sqrt{\frac{6}{m+n}},\sqrt{\frac{6}{m+n}}] [−m+n6,m+n6]的范围内进行初始化。 -
MSRA
满足 x ∼ N ( 0 , σ 2 ) x∼N(0,σ2) x∼N(0,σ2) 的高斯分布,其中 σ = s q r t ( 2 / n ) σ = sqrt(2/n) σ=sqrt(2/n) -
Uniform
满足min=0,max=1的均匀分布。 x ∼ U ( m i n , m a x ) x∼U(min,max) x∼U(min,max)
2、自适应学习率算法
梯度下降、AdaGrad、RMSProp、Adam;优化算法的选择
3、batch norm层
提出背景、解决什么问题、层在训练和测试阶段的计算公式
4、layer norm层
参考链接: