5、多层感知机(MLP)

有理论研究表明,神经网络隐含层,层数越多,所需要的隐含节点可以越少。

实际使用中,使用层数较深的神经网络会遇到许多困难,比如容易过拟合、参数难以调试,梯度弥散等等。

过拟合:有一种方法叫Dropout,在使用复杂的卷积神经网络训练图像数据时尤其有效,简单说,就是将神经网络某一层的输出节点数据随机丢弃一部分。实质上等于创造出了很多新的随机样本,通过增大样本量、减少特征数量来防止过拟合。

参数难调:拿SGD来举例,不同的学习速率可能会有不同的局部最优解。Adagrad等自适应的方法可以减轻调试参数的负担。

梯度弥散:在ReLu激活函数出现之前,大多用Sigmoid激活函数,但是Sigmoid函数在反向传播中梯度值会逐渐减小,经过多层的传递后会呈指数级急剧减小,这种情况下,根据训练数据的反馈来更新神经网络的参数会非常缓慢。


那么多层神经网络(MLP)有什么用呢?为什么要有隐含层呢?

早期的神经网络没有隐含层,无法解决XOR问题。因为没有隐含层的神经网络是线性的。


TensorFlow实现MLP:

#-*-coding:utf-8-*-
"""
Created on 17/3/17 下午7:24

base Info
"""
__author__ = 'sun'
__version__ = '1.0'

# load data and initial a session
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
mnist = input_data.read_data_sets("MNIST_data/",one_hot=True)
sess = tf.InteractiveSession()

# parameters initialization
in_units = 784 # 输入节点数
h1_units = 300 # 隐含层输出节点数
# 隐含层的权重,因为模型使用的激活函数是ReLU,所以需要使用正态分布给参数加一点噪声来打破完全对称并且避免0梯度。
W1 = tf.Variable(tf.truncated_normal([in_units,h1_units],stddev=0.01))
b1 = tf.Variable(tf.zeros([h1_units]))
# W2 b2 是输出层的权重及偏置项
W2 = tf.Variable(tf.zeros([h1_units,10]))
b2 = tf.Variable(tf.zeros([10]))

# Step1: 定义输入x的placeholder,定义隐含层、输出层公式
x = tf.placeholder(tf.float32,[None,in_units])
keep_prob = tf.placeholder(tf.float32) # Dropout的比率,一种防止过拟合的方法。

hidden1 = tf.nn.relu(tf.matmul(x,W1) + b1) # 隐含层
hidden1_drop = tf.nn.dropout(hidden1,keep_prob) # 随机将一部分节点置为0,keep_prob即为保留数据而不置为0的比例。
y = tf.nn.softmax(tf.matmul(hidden1_drop,W2) + b2)

# Step2: 定义损失函数和选择优化器
y_ = tf.placeholder(tf.float32,[None,10]) # 预测结果
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y),
                                              reduction_indices=[1]))
train_step = tf.train.AdagradOptimizer(0.3).minimize(cross_entropy)  #利用Adagrad缓解参数调优问题。

# Step3: 训练,一般来说,越复杂越大规模的神经网络,Dropout的效率越显著。
tf.global_variables_initializer().run()
for i in range(3000):
    batch_xs,batch_ys = mnist.train.next_batch(100) #一共30W样本
    train_step.run({x: batch_xs, y_: batch_ys, keep_prob: 0.75}) # 保留75%的节点,其余都置为0


# Step4: 评估
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(y_,1)) # 预测相等的样本数
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32)) # 准确率
print(accuracy.eval({x: mnist.test.images, y_: mnist.test.labels,
                     keep_prob: 1.0}))


总结:

相比之前的SoftMax,我们的准确率大幅提升,这里我们添加一个隐含层,并使用了 Dropout、Adagrad、ReLU方法。

不过,使用全连接神经网络也是有局限的,下一篇我们讲解卷积神经网络,可以再次提高准确率。


延伸阅读:

我们为什么要用激活函数、激活函数都有哪些?都长什么样?有哪些优缺点?怎么选激活函数?

http://blog.csdn.net/u013146742/article/details/51986575

ReLU对Sigmoid的主要变化包括三点:

1、单侧抑制 

2、相对宽阔的兴奋边界。

3、稀疏激活性

传统的S函数有接近一半的神经元被激活,不符合神经科学的研究。Softplus虽然有单侧抑制,但是却没有稀疏激活性,目前ReLu及其几种变形已经成为主流激活函数。输出层一般都还是S函数,因为最接近概率输出分布。


你可能感兴趣的:(TensorFlow)