一,多层感知机简介
多层感知机也叫 深度前馈网络 或 前馈神经网络。
“多层”本质上指的是多层隐含层,神经网络的非线性也主要体现在隐含层非线性的激活函数上,理论上只要隐含节点足够多,只要有一层隐含层就可以拟合任意函数,但隐含层越多,就越容易拟合复杂函数,并且所需的隐含单元也越少。
但是,层数较深的神经网络会出现很多问题:
- 过拟合
- 参数难以调试
- 梯度消失
- 等等
解决方法有:
1,Dropout解决过拟合问题
- 过拟合:神经网络的参数一般都很多,经常会出现参数比数据还要多的情况,所以过拟合很容易出现。
- Dropout:主要思想是在训练时,将神经网络某些层的输出节点数据随机丢弃一部分,这种做法本质上等于创造了很多新的随机的样本,通过增大样本量、减少特征数量来防止过拟合。一般来说对越复杂越大的神经网络,dropout的效果越显著。
2,自适应学习率算法减轻调试参数的负担
- 参数难以调试:主要是因为SGD的受学习速率的设置影响很大;神经网络通常不是一个凸优化问题,处处充分局部最优;但有理论表明,神经网络可能有很多局部最优解都可以达到比较好的分类效果,而全局最优反而容易是过拟合的解。
- 自适应学习率算法:这种算法通常会随着训练轮数的增加而不断调整学习速率,从而使加速收敛并且最终稳定地落入到一个局部最优解中。常用的算法有Adagrad、Adam、Adadelta等等。
3,Relu激活函数解决梯度消失问题
- 梯度消失:当神经网络层数较多时,一些激活函数如sigmoid激活函数在误差反向传播中梯度值会逐渐减小,经过多层的传递后会呈指数级急剧减小,因此梯度值在传递到前面几层时会变得非常小,小到无法更新神经网络的参数,起不到训练的作用。
- Relu激活函数:
y=max(0,x)
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()
运行结果