神经网络学习
深度学习→一类通过多层非线性变换对高复杂性数据建模算法的合集。隐藏层可以从输入特征中抽取更高维的组合特征,可以有效解决不易提取特征向量的问题,如图像识别、语音识别问题。
搭建神经网络的3个步骤
- 定义神经网络的结构和前向传播的输出结果,比如输入x、输入层/输出层权重系数w1/w2,前向传播的输出 y = ( x w 1 ) w 2 y=(xw_1)w_2 y=(xw1)w2
- 定义损失函数以及选择反向传播优化的算法,以交叉熵为损失函数,反向传播更新输入层/输出层系数
- 在训练数据上反复运行前向传播/反向传播优化算法,直到达到训练次数或损失函数最低。
重要的术语
激活函数
z
=
X
w
T
+
b
z = Xw^T+b
z=XwT+b
a
=
g
(
z
)
a = g(z)
a=g(z)
如果数据可以通过直线划分平面,就可以选择线性模型解决。而在线性模型基础上添加非线性激活函数g(),可以解决线性不可分的复杂问题。
常见的激活函数如下:
第一种:Relu函数,是默认的激活函数。
- 形如g(z) = max(z,0)
- 梯度为 d d z g = { 1 , z ⩾ 0 0 , z < 0 \frac{d}{dz}g=\{^{0,z<0}_{1,z\geqslant0} dzdg={1,z⩾00,z<0
- 当z<0时,梯度为0;当z≥0时,梯度等于1,此时下降速度足够快,计算速度快。
第二种:Sigmoid函数,主要在二分类问题使用。
- 形如 g ( z ) = 1 1 + exp − z g(z)=\frac{1}{1+\exp^{-z}} g(z)=1+exp−z1
- 梯度为 d d z g = g ( z ) ∗ ( 1 − g ( z ) ) \frac{d}{dz}g=g(z)*(1-g(z)) dzdg=g(z)∗(1−g(z))
- 仅在0左右有较大梯度结果,下降速度快,但当|z|稍微偏离0时,梯度为0,此时下降速度很慢。
第三种:tanh函数,是第二常用的激活函数。
- 形如 g ( z ) = 1 − exp − 2 x 1 + exp − 2 x g(z)=\frac{1-\exp^{-2x}}{1+\exp^{-2x}} g(z)=1+exp−2x1−exp−2x
- 梯度为 d d z g = 1 − g 2 ( z ) \frac{d}{dz}g=1-g^2(z) dzdg=1−g2(z)
- 仅在0左右有较大梯度结果,下降速度快,但当|z|稍微偏离0时,梯度为0,此时下降速度很慢。
损失函数
评估模型性能,例如分类问题中选择交叉熵判断输出向量与期望向量的接近程度,因为交叉熵刻画了两个概率分布之间的距离。
H
(
p
,
q
)
=
−
∑
(
p
(
x
)
l
o
g
q
(
x
)
)
H(p,q)=-\sum(p(x)logq(x))
H(p,q)=−∑(p(x)logq(x))
利用Softmax回归将前向传播得到的结果变成概率分布。
回归问题最常用的损失函数是均方误差。
优化算法
优化算法是根据定义好的损失函数优化神经网络中参数的取值,从而使得神经网络模型再训练数据集上的损失函数达到一个较小值。梯度下降算法主要用于优化单个参数的取值,而反向传播算法在所有参数上使用梯度下降算法。
对于N层神经网络,反向传播或者梯度下降算法是通过前向传播算出最后一层的激活函数结果
a
[
n
]
=
g
[
n
]
(
z
[
n
]
)
a^{[n]}=g^{[n]}(z^{[n]})
a[n]=g[n](z[n])。
如果是回归问题,以均方误差为损失函数,
E
k
=
1
2
∑
(
a
[
n
]
−
Y
)
2
E_k=\frac{1}{2}\sum(a^{[n]}-Y)^2
Ek=21∑(a[n]−Y)2;如果是分类问题,以交叉熵为损失函数,
E
k
=
−
∑
(
p
(
x
)
log
q
(
x
)
)
E_k=-\sum(p(x)\log{q(x)})
Ek=−∑(p(x)logq(x))
反推出
d
d
z
[
n
]
E
k
\frac{d}{dz^{[n]}}E_k
dz[n]dEk,然后根据链式规则、激活函数
g
[
n
]
g^{[n]}
g[n]的导数来求
d
d
w
[
n
]
E
k
、
d
d
b
[
n
]
E
k
、
d
d
z
[
n
−
1
]
E
k
、
d
d
w
[
n
−
1
]
E
k
、
d
d
b
[
n
−
1
]
E
k
\frac{d}{dw^{[n]}}E_k、\frac{d}{db^{[n]}}E_k、\frac{d}{dz^{[n-1]}}E_k、\frac{d}{dw^{[n-1]}}E_k、\frac{d}{db^{[n-1]}}E_k
dw[n]dEk、db[n]dEk、dz[n−1]dEk、dw[n−1]dEk、db[n−1]dEk。
然后以
v
←
v
+
Δ
v
=
v
+
η
∗
d
d
v
E
k
v\leftarrow v+\Delta v=v+\eta*\frac{d}{dv}E_k
v←v+Δv=v+η∗dvdEk更新参数v,找到损失函数最小时的v就是所求了。
在实践中,梯度下降算法迭代更新参数v,不断沿着梯度的反方向让参数朝着总损失最小的方向更新。梯度通过求偏导得出,定义学习率
η
\eta
η表示参数更新的幅度。
但是梯度下降法可能只得到局部最优解,只有当损失函数为凸函数时,梯度下降算法才能保证达到全局最优解。
另外由于每一轮迭代需要计算全部训练数据上的损失函数,计算时间过长。为此以随机梯度下降算法优化,即每一轮迭代只随机优化某一条训练数据,参数更新速度加快。存在的问题是可能无法达到最优,新办法是每次计算一小部分训练数据(batch)上的损失函数,通过矩阵运算,每次在一个batch上优化神经网络的参数既提高更新速度,也减少迭代次数。
from tensorflow as tf
from numpy.random import RandomState
batch_size = 8
x = tf.placeholder(tf.float32,shape=(None,2),name='x-input')
y_ = tf.placeholder(tf.float32,shape=(None,1),name='y-input')
w1 = tf.Variable(tf.random_normal([2,1],stddev=1,seed=1))
y = tf.matmul(x,w1)
loss_less = 10
loss_more = 1
loss = tf.reduce_sum(tf.where(tf.greater(y,y_),
(y-y_)*loss_more,(y_-y)*loss_less))
train_step = tf.train.AdamOptimizer(0.001).minimize(loss)
rdm = RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size,2)
Y = [[x1+x2+rdm.rand()/10.0-0.05] for (x1,x2) in X]
with tf.Session() as sess:
init_op = tf.initialize_all_variables()
sess.run(init_op)
STEPS = 5000
for i in range(STEPS):
start = (i*batch_size)%dataset_size
end = min(start+batch_size,dataset_size)
sess.run(train_step,feed_dict={x:X[start:end],y_:Y[start:end]})
学习率
learning rate的优化→指数衰减法
先使用较大的learning rate快速得到一个较优解,然后随着迭代逐渐减小learning rate,使得模型再后期更稳定。未完待续
参数的初始化
好的参数初始值有利于模型快速收敛。
如果所有参数(w,b)都为0,则无论多少层模型得到的结果不变;当所有参数都很小的时候(≈0),前面提到的激活函数都会有较大梯度,下降速度快,收敛快。经验上浅层神经网络
ω
←
0.01
,
b
←
0
\omega\leftarrow0.01,b\leftarrow0
ω←0.01,b←0,深层神经网络以较小值初始化。
正则化
通过正则化解决过拟合问题。未完待续
滑动平均模型
滑动平均模型让模型在未知数据上更加健壮。未完待续
参考资料
《机器学习》周志华
吴恩达《神经网络和深度学习》第二周神经网络基础
《Tensorflow 实战Google深度学习框架》