TensorFlow 神经网络优化

既然大家看到用TensorFlow 神经网络优化,想必对深层神经网络的数学理论有了一个大体的认识,所以本文不会对基础知识进行深入讲解,只是对基础知识进行整理和总结,起画龙点睛、增加理解深度的作用。

1、激活函数去线性化

首先大家看下面这两幅图,如果我们用线性模型实现对褐点和红点的分类,图一可以得到很好的结果,但是图二则无法得到很好的结果。因为当模型的输入只有一个的时候,会在形成一个二维坐标系上的一条直线。类似的,当模型有n个输入时,x和y形成了一个n+1维空间中的一个平面。线性模型最大的特点就是任意线性模型的组合仍然是线性模型。现实生活中,绝大多数问题都是无法线性分割的。我们一般会选择ReLU函数、sigmoid函数、tanh函数。以下代码展示了如何通过Tensorflow,以ReLU作为激活函数实现前向传播算法:

a = tf.nn.relu(tf.matmul(x, w1) + biases1)
y = tf.nn.relu(tf.matmul(a, w2) + biases2)

a是隐藏层,x是输入,w1是x的权重,biases1是输入中的偏置;

y是输出,w2是a(隐藏层)的权重,biases2是a中的偏置。

                     




2、损失函数定义

神经网络模型的效果以及优化的目标是通过损失函数来定义的。通俗点来说判断神经网络模型输出与期望之间的差距。损失函数包括两大类,一类是经典损失函数,另一类是自定义损失函数,经典损失函数又包括交叉熵损失函数和均方误差损失函数。下面我们一 一讲解下:

交叉熵损失函数:

交叉熵刻画了两个概率分部之间的距离,我们可以用它来计算输出概率和期望概率之间的距离,有的人就问了,神经网络输出的不是结果么,是的,神经网络最终输出层输出的是结果,所以在深层神经网络中的输出层之后会加入softmax层,通过softmax将神经网络输出变成一个概率分布。

下面看一下TensorFlow实现交叉熵的代码:

cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))
y_表示正确结果,y表示预测结果。tf.clip_by_value函数可以讲一个张量中的数值限制在一个范围之内,这样可以避免一些运算错误(比如log0 是无效的)。

因为交叉熵一般会与softmax回归一起使用,所以TensorFlow对这两个功能进行了系统的封装,并提供了tf.nn.softmax_cross_entorpy_with_logits函数,代码如下

cross_entry = tf.nn.softmax_cross_entorpy_with_logits(y, y_)

均方误差损失函数:

与分类问题不同,回归问题是对具体数值的预测,比如放假、销售预测等。对于回归问题,最常用的损失函数就是均方误差,其TensorFlow实现代码如下:

mse = tf.reduce_mean(tf.square(y_ - y))

自定义损失函数:

比如一件商品成本是1元,但是利润是10元,那么少预测一个就少挣10元,多预测一个才少挣1元,这时候为了利润最大化,所以定义一个当预测多于真实值和预测少于真实值有不同损失系数的损失函数,TensorFlow中代码如下:

loss = tf.reduce _sum(tf.select(tf.greater(v1, v2), (v1 - v2) * a, (v2 - v1) * b))
这里举一个例子,具体情况发挥自己的想象,来设计具体的损失函数。


3.学习率

学习率控制参数更新的速度,更形象具体点就是学习率决定了参数每次更新的幅度,如果幅度过大,可能导致参数在极优值的两侧来回移动;相反当学习率设置过小时,虽然能保证收敛性,但是大大降低优化速度。综上所述,学习率不能过大也不能过小,为了解决学习率的问题,TensorFlow提供了一种更加灵活的学习率设置方式——指数衰减法tf.train.exponential_decay函数实现了指数衰减学习率。通过这个函数,可以先使用较大的学习率来快速得到一个比较优的解,然后随着迭代的继续减小学习率,是的模型再训练后期更加稳定,TensorFlow实现代码如下:

decayed_learning_rate = learning_rate * decay_rate ^ (global_steps / decay_steps)
decayed_learning_rate为每一轮优化时实用的学习率,learning_rate为事先设定的初始学习率,decay_rate为衰减系数,decay_steps为衰减速度

4、过拟合

所谓过拟合就是当一个模型过于复杂之后,它可以很好的“记忆”每一个训练的数据,包括含有随机噪音的部分,这样就导致忘记去学习训练数据中通用的趋势。对这句话解释一下,就是有些训练数据本身有一定的错误性,包含着偶然性,如果我们的模型过于在乎这部分数据,就会导致模型过于复杂,而且导致整个模型的划分趋势不明显,这样就会导致模型的泛化能力不行。

为了避免过拟合问题,一个非常有用的方法就是正则化。正则化的思想是在损失函数中加入刻画模型复杂度的指标。模型复杂度只由权重w决定,常用刻画模型复杂度的函数R(w)有两种,一种是L1正则化,公式是:R(w)=||w||=E|wi| ; 另一种是L2正则化,计算公式是:R(w)=||w||^2 =E|wi^2|。无论是那种正则化方式,基本思想都是希望通过限制权重的大小,是的模型不能任意你和训练数据中的噪音。下面代码给出了两个函数的样例:

weights = tf.constant([[1.0, -2.0], [-3.0, 4.0]])
with tf.Session() as sess:
     print sess.run(tf.contrib.layers.l1_regularizer(.5)(weights))
     print sess.run(tf.contrib.layers.l2_regularizer(.5)(weights))

5、滑动平均模型
滑动平均模型可以使模型在测试数据上更健壮。在采用随机梯度下降算法训练神经网络时,使用滑动平均模型在很多应用中都可以在一定程度提高最终模型在测试数据上的表现。健壮性可能有些人不是很明白,健壮型的意思可以理解为泛化性,就是模型遇到考虑之外的情况也能处理。那么为什么使用随即梯度下降要使用滑动平均模型呢?请看下面介绍:

在TensorFlow中提供了tf.train.ExponentialMovingAverage 来实现滑动平均模型,初始化时需要提供一个衰减率,这个衰减率将用于控制模型更新的速度。尤其是随机梯度下降加入了随机因素,这样相应的会带来模型的不稳定性,这时候通过滑动平均模型定义一个衰减率控制模型更新速度就可以很好的避免随机性带来的弊端。这样随机性不会过大,也就是增强了模型的健壮性。

下面我们看一下滑动平均模型的公式:



好的,基础知识现在讲完了,具体代码可以看我的另一篇文章,通过TensorFlow实现MNIST手写数字识别:点击打开链接

猜你喜欢

转载自blog.csdn.net/u014182497/article/details/72317993
今日推荐