Bp神经网络的调参(未完,待续)

                                            Bp神经网络的调参(上)

    各位数据游侠,炼丹师,由于最近项目上的数据迟迟未到,闲的无聊,so 盘一盘神经网络。虽说之前各种大大小小的网络都使用过,然而对其网络的改进工作却迟迟没有落实,所以。。。不过经过几天时间的摸索,看了各大教程,大多数文章都是不管三七二十一,先甩出一大堆理论(比如:超参数,前前后后一共接近十几个)暂且不谈你能否调出一个好的神经网络模型,就这么参数的组合,估计也是够喝一壶的了。我这几天着重的对learing_rate(学习率)和batch_size(每批送入到网络训练的数据)这两个参数进行了调参的操作,后来再针对梯度下降的方法进行了优化,使用了优化器加快了梯度下降的步伐。大多数教程显示了很多理论,并没有具体的操作,下面是我最近几天调参的一些心得,当然还有待更新。

                                                               第一部分.数据集

    由于项目上的数据集数量比较少,在这里我一样采用的那个经典的数据集:Mnist数据集,在这儿附上下载链接:mnist手写数据集至于这数据集的格式啥的,我不过多的介绍,相信只要是搞过深度学习这个方向的都会知道这数据集的格式。至于刚入门并不了解的,可以自行百度?。
                                                          在这里插入图片描述
如果还不会,兄弟,我已经教不了你了*____*,请自行脑补?。

                                                               第二部分.bp神经网络的搭建

    首先,我提前说下,我的网络结构比较简单,只用了一层的隐藏层,至于后面复杂的,我得保留点神秘感,其实我都提前弄好了,后面遇到的调参问题可能会更加复杂,所以暂且在这里先设置下悬念。我先展示下我的代码样例:

import tensorflow as tf 
from tensorflow.examples.tutorials.mnist import input_data
import matplotlib.pyplot as plt
import numpy as np

#载入训练集
mnist=input_data.read_data_sets("MNIST_data",one_hot=True)

#每个批次的大小,相当于每次放入100张图片
batch_size=1000
#计算一共多少批次
n_batch=mnist.train._num_examples//batch_size

x=tf.placeholder(tf.float32,[None,784])
y=tf.placeholder(tf.float32,[None,10])

#创建一个简单的神经网络
W=tf.Variable(tf.zeros([784,10]))
b=tf.Variable(tf.zeros([10]))
prediction=tf.nn.softmax(tf.matmul(x,W)+b)

loss=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=prediction))

train_step=tf.train.GradientDescentOptimizer(0.01).minimize(loss)
#初始化变量
init=tf.global_variables_initializer()

correct_prediction=tf.equal(tf.argmax(y,1),tf.argmax(prediction,1))
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

fig_loss=np.zeros([100])
fig_train_acc=np.zeros([100])
fig_test_acc=np.zeros([100])
with tf.Session() as sess:
    sess.run(init)
    for epoch in range(100):
        for batch in range(n_batch):
            #next_batch自动获取下100到200个图片,然后200到300的图片,并保存batch_xs,batch_ys中
            batch_xs,batch_ys=mnist.train.next_batch(batch_size)
            sess.run(train_step,feed_dict={x:batch_xs,y:batch_ys})    

        train_acc=sess.run(accuracy,feed_dict={x:batch_xs,y:batch_ys})        
        test_acc=sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})
        Loss=sess.run(loss,feed_dict={x:batch_xs,y:batch_ys})
        
        fig_loss[epoch]=Loss
        fig_train_acc[epoch]=train_acc
        fig_test_acc[epoch]=test_acc        
        print("Iter"+str(epoch)+" , Training Accuracy:"+str(train_acc)+" , Testing Accuracy:"+str(test_acc)+" , Loss:"+str(Loss))
plt.subplot(2,1,1)
plt.plot(np.arange(100),fig_loss,label="loss",marker=">")
plt.xlabel("epoch")
plt.ylabel("Loss")
plt.title("Loss    lr=0.01")
plt.subplot(2,1,2)
plt.plot(np.arange(100),fig_train_acc,label="train_acc",marker="*")
plt.plot(np.arange(100),fig_test_acc,label="test_acc",marker="o")
plt.xlabel("epoch")
plt.ylabel("acc")
plt.title("train_acc  vs   test_acc   lr=0.01")
plt.legend()
plt.show()

    我大致的解释下我的代码:首先导包和导入训练集那些我就不说了,之后我把训练集划分成了500批次(n_batch),每批送入100张图片(batch_size),至于为什么这么做,后面的文章再说。然后定义了一层简单的神经网络,接着是loss,优化方法等等,然后把数据喂到(feed)网络中,最过可视化我们的loss,以及训练集和测试集的变化图(判断是否过拟合)。

                                                               第三部分.调参过程的可视化

下面看下实测效果:
在这里插入图片描述

效果看起来还可以嘛!!为了保证确认无误,我翻出了以下宝图:

在这里插入图片描述

左看右看,前看后看,好像很接近good learning rate?,因为这是我尝试了几次选出来的,当然肯定不是最好的。在这里知识介绍一下我的调参思路,准确说:我这边还是粗调参,你需要进行精调参。看到这里,你是不是很疑问,要是学习率调大点,或者调小一点会对结果有什么影响呢?满足你们的好奇心,接下来我针对不同的学习率,画出其各种图。如下:

学习率:0.001      batch_size=100

在这里插入图片描述

由上图可以看到:loss曲线的下降的比较慢,前面一段时间经过了很久才下降到了1.7左右附近。loss曲线下降的慢的原因:学习率选低了(暂且我们先下个结论)。再看曲线是否过拟合呢?emmmm,轻微的过拟合了,看起来咋还不错,一看最后的准确率,才80%多,至于这个原因又是为啥?我也先下个结论:(epoch设置的太小了),究竟是不是这样,我们再往下看:

学习率:0.01      batch_size=100

在这里插入图片描述

学习率:0.1      batch_size=100


在这里插入图片描述

学习率:0.2      batch_size=100


在这里插入图片描述

发现什么了吗??随着学习率的增加,loss的震荡越来越剧烈。不过准确率却是在上升的。并且每次的训练集准确率的表现也是随着学习率的增加而变得越来越剧烈,这又是为啥?这里我选择了调整batch_size的大小,也就是每次送入图片的数量。如下:

学习率:0.001      batch_size=500

在这里插入图片描述

学习率:0.01      batch_size=500


在这里插入图片描述

学习率:0.1      batch_size=500

在这里插入图片描述

学习率:0.2      batch_size=500


在这里插入图片描述

再看看,和上面依次对比下(保证学习率一样,增大batch),是不是感觉看上去舒服了很多,起码不是那种人生大起大落的感觉了吧,总结一下:当loss曲线表现为震荡的时候,我们需要考虑的是降低学习率,或者增加batch_size. 但是这边有个问题:降低学习率,带来的稳定性提升了,但是收敛速度却下降了(上图0.001的时候,是因为准确率只有80%多吗?其实并不是,你给他足够多的epoch,他也可以提升到我们的90多准确率,不过付出的代价就是更多的epoch),低的学习率还会带来一个问题就是local min(局部最优),这个得需要你自己多次的实验。同样batch_size也不是越多越好的,如果在二者产生平衡需要你自己去发现。
在这里,针对下降速度/收敛速度比较慢的问题,我才用的是优化器的方法,怎么使用呢?很简单,如下:

#用优化器代替梯度下降
train_step=tf.train.AdamOptimizer(0.01).minimize(loss)

就这么简单??确实就这么简单,使用完优化器的代码是不是真的缩短了很多时间呢??是否加快了收敛速度呢?答案:是的,并且达到90多最多只需要2步,比之前梯度下降提升了接近10倍,惊不惊喜,意不意外?。

    我们再来看下使用优化器后我们的结果如何(这里我就只选择学习率为0.01的时候举列了):

学习率:0.01      batch_size=100


在这里插入图片描述

学习率:0.01      batch_size=500

在这里插入图片描述

学习率:0.01      batch_size=1000


在这里插入图片描述

可以看到,batch_size并非越大越好,batch_size从100到500确实能够提升曲线的平滑度,但是再往后并非提升很多。但是从图中可以看到,准确率确实提升了一点,重点是收敛的速度,从第一步开始基本就已经90多左右了。但是这个曲线有个小问题:过拟合。怎么解决,留着我下次写吧,有哪里说错或者说的不好的,还请多多指正。

                                                               第四部分.总结

loss震荡的原因:1.学习率太低,解决方法:增加学习率/epoch       2.batch_size设置的有点低,解决方法:增加batch_size.       3.网络结构太简单。有哪里说错或者说的不好的,还请多多指正。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值