TensorFlow实战(五)- 使用TensorFlow实现多层感知机

一,多层感知机简介

多层感知机也叫 深度前馈网络 或 前馈神经网络。

“多层”本质上指的是多层隐含层,神经网络的非线性也主要体现在隐含层非线性的激活函数上,理论上只要隐含节点足够多,只要有一层隐含层就可以拟合任意函数,但隐含层越多,就越容易拟合复杂函数,并且所需的隐含单元也越少。

但是,层数较深的神经网络会出现很多问题:

  • 过拟合
  • 参数难以调试
  • 梯度消失
  • 等等

解决方法有:

1,Dropout解决过拟合问题

  • 过拟合:神经网络的参数一般都很多,经常会出现参数比数据还要多的情况,所以过拟合很容易出现。
  • Dropout:主要思想是在训练时,将神经网络某些层的输出节点数据随机丢弃一部分,这种做法本质上等于创造了很多新的随机的样本,通过增大样本量、减少特征数量来防止过拟合。一般来说对越复杂越大的神经网络,dropout的效果越显著。

2,自适应学习率算法减轻调试参数的负担

  • 参数难以调试:主要是因为SGD的受学习速率的设置影响很大;神经网络通常不是一个凸优化问题,处处充分局部最优;但有理论表明,神经网络可能有很多局部最优解都可以达到比较好的分类效果,而全局最优反而容易是过拟合的解。
  • 自适应学习率算法:这种算法通常会随着训练轮数的增加而不断调整学习速率,从而使加速收敛并且最终稳定地落入到一个局部最优解中。常用的算法有Adagrad、Adam、Adadelta等等。

3,Relu激活函数解决梯度消失问题

  • 梯度消失:当神经网络层数较多时,一些激活函数如sigmoid激活函数在误差反向传播中梯度值会逐渐减小,经过多层的传递后会呈指数级急剧减小,因此梯度值在传递到前面几层时会变得非常小,小到无法更新神经网络的参数,起不到训练的作用。
  • Relu激活函数: y = m a x ( 0 , x ) ,类似人脑的阈值响应机制,由于右侧是线性的,梯度值不会变,所以不会出现梯度消失的问题。
    特点有三:
    ①单侧抑制。
    ②相对宽阔的兴奋边界。
    ③稀疏激活性。
    神经元编码的工作方式具有稀疏性,即大脑同时被激活的神经元只有1%~4%,而sigmoid激活函数会激活几乎一般的神经元吗,不符合神经科学的研究。
    Softplus虽然单侧抑制,但是不具有稀疏激活性,因而Relu及其变体(EIU、PRelu、RRelu、maxout等)成了最符合实际神经元也最流行的激活函数,它们可以带来训练速度和模型准确率的提升,但是输出层一般还是使用sigmoid或softmax激活函数,因为它们最接近概率输出分布。

二,用TensorFlow实现MLP

实现中用到了

  • Dropout
  • 自适应学习率算法Adagrad
  • Relu激活函数

一些基础

  • tf.nn.dropout(h1,keep_prob)
  • tf.truncated_normal(shape,stddev)
  • tf.train.AdagradOptimizer()
  • 之所以将W1初始化为截断的正态分布,是因为隐含层使用了Relu激活函数,所以需要正态分布给参数加一点噪声,来打破完全对称并且避免0梯度。在其他一些模型中,有时还需要给偏置赋上一些小的非零值来避免死亡神经元。而W2和b2直接赋值为0,是因为softmax激活函数在0附近最敏感、梯度最大。

tensorflow的实现

# 多层感知机的实现
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

# 0,导入数据
mnist = input_data.read_data_sets("MNIST_data/",one_hot=True)
print(mnist.train.images.shape,mnist.train.labels.shape)

# 1,定义模型计算公式
sess = tf.InteractiveSession()
in_units = 784
h1_units = 300
W1 = tf.Variable(tf.truncated_normal([in_units,h1_units],stddev=0.1))
b1 = tf.Variable(tf.zeros([h1_units]))
W2 = tf.Variable(tf.zeros([h1_units,10]))
b2 = tf.Variable(tf.zeros([10]))

X = tf.placeholder(tf.float32,[None,in_units])
keep_prob = tf.placeholder(tf.float32,)
h1 = tf.nn.relu(tf.matmul(X,W1)+b1)
h1_drop = tf.nn.dropout(h1,keep_prob)
y_pred = tf.nn.softmax(tf.matmul(h1_drop,W2)+b2)


# 2,定义loss,选定优化器
y = tf.placeholder(tf.float32,[None,10])
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y*tf.log(y_pred),reduction_indices=[1]))
train_step = tf.train.AdagradOptimizer(learning_rate=0.3).minimize(cross_entropy)

# 3,定义精确度计算公式
correct_prediction = tf.equal(tf.argmax(y_pred,1),tf.argmax(y,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

# 4,初始化参数
tf.global_variables_initializer().run()

# 4,迭代训练
epoch_num = 1
for epoch in range(epoch_num):
    avg_accuracy = 0.0
    avg_cost = 0.0
    for i in range(3000):
        batch_xs,batch_ys = mnist.train.next_batch(100)
        cost,acc,_ = sess.run([cross_entropy,accuracy,train_step],feed_dict={X:batch_xs,y:batch_ys,keep_prob:0.75})
        avg_cost += cost
        avg_accuracy += acc/3000
    print('Epoch %d: cost is %.7f,accuracy is %.7f.'%(epoch+1,avg_cost,avg_accuracy))
print('Train Finished!')
print('Test accuracy is %.4f.'%accuracy.eval({X:mnist.test.images,y:mnist.test.labels,keep_prob:1.0}))

# 5,Get one and predict
import matplotlib.pyplot as plt
import random
r = random.randint(0, mnist.test.num_examples - 1)
print("Label:", sess.run(tf.argmax(mnist.test.labels[r:r+1], 1)))
print("Prediction:", sess.run(tf.argmax(y_pred, 1),feed_dict={X: mnist.test.images[r:r + 1],keep_prob:1.0}))
plt.imshow(mnist.test.images[r:r + 1].reshape(28, 28), cmap='Greys', interpolation='nearest')
plt.show()

sess.close()

运行结果

1

猜你喜欢

转载自blog.csdn.net/h2026966427/article/details/79647479