3

tensorflow入门学习,深度学习神经网络为什么要使用激活函数,激活函数的作用是什么(...

 3 years ago
source link: https://blog.popkx.com/tensorflow-study-why-deep-learning-needs-activation-funciton-and-what-is-its-use-1/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

tensorflow入门学习,深度学习神经网络为什么要使用激活函数,激活函数的作用是什么(八)

发表于 2018-06-27 22:06:48   |   已被 访问: 642 次   |   分类于:   tensorflow   |   暂无评论

稍微留点心就会发现,一般的学习网络都有激活函数(也有激励函数等其他名称)。例如在第二节 识别手写数字实战项目中,我们使用了 softmax 函数作为激活函数。为什么要使用激活函数呢?它有什么用呢?本节将讨论这两点。

神经网络的基本数学公式


对于需要参考值的有监督类型的神经网络来说,有一个非常经典的公式(或者称网络):

 y = wx + b

很简单,却很有效。设系数矩阵为 w,偏置为 b,输入样本 x,即可计算出一组估计值 y,假设参考值为 y_,那么只要不断调整 wb,使得 yy_ 接近到满意的程度即可。常用损失函数来估计yy_的接近程度,常用梯度下降法调整wb。然而,上面的经典公式解决线性问题有不俗的表现,但是对非线性问题却无能为力,这是显然的。

人工神经网络的发展,迄今经历过数次大起大落,在发展早期,有人证明线性神经网络甚至不能解决简单的异或问题,使得神经网络进入寒冬。

线性可分和线性不可分


这里直接放两张图,左图是线性可分问题,用一条直线,就可以把两中类型完美的分开。右图是线性不可分问题,不可能使用直线将两中类型完美的分开。

对于左图的分类问题,使用线性神经网络可以完美解决。而线性神经网络不可能解决右图所示的分类问题。但是,y = wx + b 模型经过这么多年的发展,有着非常丰富的理论和经验,仅仅因为要解决的问题是非线性的缘故,就无法使用,太可惜了。所幸,人们发现了在线性的网络模型中引入非线性元素,就可以让整个网络解决非线性问题。怎么引入非线性元素呢?答案是,让线性的结果,经过非线性函数的处理即可。这个非线性函数就称为激活函数

激活函数的要求


  • 首先,激活函数必须是非线性的,这点上面已经分析。
  • 激活函数必须是可微分的。这是因为,调整 wb常常需要网络的梯度信息。
  • 激活函数不能消灭梯度,也不能引起梯度爆炸。对于深度学习而言,网络的层数往往非常多,梯度在传递的过程中,既不能衰减直至消失,也不能无限放大到夸张的程度。

当然,以上是激活函数的必要条件。并不是满足以上几点的函数,就能成为非常棒的激活函数。深度学习网络有时候像中医,经验非常重要,以下是经过实践检验的几个比较常用的激活函数。

1. Sigmoid 函数

函数原型:

函数图像:

1.单调连续,输出范围有限,可以用作输出层。
2.求导容易。

1.由于其软饱和性,容易产生梯度消失,导致训练出现问题。
2.输出不是以0为中心。

2. tanh 函数

函数原型:

函数图像:

1.比Sigmoid函数收敛速度更快。
2.相比Sigmoid函数,其输出以0为中心。

没有改变Sigmoid函数的最大问题——由于饱和性产生的梯度消失。

3. ReLU 函数

函数原型:

函数图像:

1.相比起Sigmoid和tanh,ReLU在SGD中能够快速收敛。据称,这是因为它线性、非饱和的形式。
2.Sigmoid和tanh涉及了很多很expensive的操作(比如指数),ReLU可以更加简单的实现。
3.有效缓解了梯度消失的问题。
4.在没有无监督预训练的时候也能有较好的表现。
5.提供了神经网络的稀疏表达能力。这点在 第四节 提到过。

随着训练的进行,可能会出现神经元死亡,权重无法更新的情况。如果发生这种情况,那么流经神经元的梯度从这一点开始将永远是0。也就是说,ReLU神经元在训练中不可逆地死亡了。

4. softmax 函数

函数原型:

sigmoid将一个real value映射到(0,1)的区间(当然也可以是(-1,1)),这样可以用来做二分类。而softmax把一个k维的real value向量(a1,a2,a3,a4….)映射成一个(b1,b2,b3,b4….)其中bi是一个0-1的常数,然后可以根据bi的大小来进行多分类的任务,如取权重最大的一维。 所以 softmax 函数特别适合解决分类问题。


这里以第二节中的实验为例,手写数字图片的分类,显然不是一个简单的线性问题。

#encoding=utf8
import input_data

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
import tensorflow as tf
x = tf.placeholder("float", [None, 784])
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
#y = tf.nn.softmax(tf.matmul(x,W) + b)         # 使用 softmax 激活函数
y = tf.matmul(x,W) + b                          # 不使用激活函数
y_ = tf.placeholder("float", [None,10])
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
for i in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})

这里的代码没有改变什么,只是把激活函数去掉了,但是最终识别的正确率却下降到非常低的程度,几乎为零。

$ python t.py
0.098

提高训练次数:

for i in range(10000):          # 训练次数为原来 10 倍
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

发现,即使增大训练量,识别正确率依然非常低。

$ python t.py
0.098
这就是非线性激活函数的用处了。

阅读更多:   tensorflow


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK