交通运输网站建设的方案,wordpress jquery报错,社区论坛自助建站网,做拍卖网站有哪些cifar10数据集上进行图片分类#xff0c;基于tensorflow框架#xff0c;
旨在探究不同的改进策略对分类准确率的影响#xff0c;如何一步步得提高准确率 一、问题描述
当我们在处理图像识别或者图像分类或者其他机器学习任务的时候#xff0c;我们总是迷茫于做出哪些改进…cifar10数据集上进行图片分类基于tensorflow框架
旨在探究不同的改进策略对分类准确率的影响如何一步步得提高准确率 一、问题描述
当我们在处理图像识别或者图像分类或者其他机器学习任务的时候我们总是迷茫于做出哪些改进能够提升模型的性能识别率、分类准确率。。。或者说我们在漫长而苦恼的调参过程中到底调的是哪些参数。。。所以我花了一部分时间在公开数据集CIFAR-10 [1] 上进行探索来总结出一套方法能够快速高效并且有目的性地进行网络训练和参数调整。
CIFAR-10数据集有60000张图片每张图片均为分辨率为32*32的彩色图片分为RGB3个信道。CIFAR-10的分类任务是将每张图片分成青蛙、卡车、飞机等10个类别中的一个类别。本文主要使用基于卷积神经网络的方法CNN来设计模型完成分类任务。
首先为了能够在训练网络的同时能够检测网络的性能我对数据集进行了训练集/验证集/测试集的划分。训练集主要用户进行模型训练验证集主要进行参数调整测试集主要进行模型性能的评估。因此我将60000个样本的数据集分成了45000个样本作为训练集5000个样本作为验证集10000个样本作为测试集。接下来我们一步步来分析如果进行模型设计和改进。 二、搭建最简单版本的CNN
对于任何的机器学习问题我们一上来肯定是采用最简单的模型一方面能够快速地run一个模型以了解这个任务的难度另一方面能够有一个baseline版本的模型利于进行对比实验。所以我按照以往经验和网友的推荐设计了以下的模型。 模型的输入数据是网络的输入是一个4维tensor尺寸为(128, 32, 32, 3)分别表示一批图片的个数128、图片的宽的像素点个数32、高的像素点个数32和信道个数3。首先使用多个卷积神经网络层进行图像的特征提取卷积神经网络层的计算过程如下步骤
卷积层1卷积核大小3*3卷积核移动步长1卷积核个数64池化大小2*2池化步长2池化类型为最大池化激活函数ReLU。卷积层2卷积核大小3*3卷积核移动步长1卷积核个数128池化大小2*2池化步长2池化类型为最大池化激活函数ReLU。卷积层3卷积核大小3*3卷积核移动步长1卷积核个数256池化大小2*2池化步长2池化类型为最大池化激活函数ReLU。全连接层隐藏层单元数1024激活函数ReLU。分类层隐藏层单元数10激活函数softmax。
参数初始化所有权重矩阵使用random_normal(0.0, 0.001)所有偏置向量使用constant(0.0)。使用cross entropy作为目标函数使用Adam梯度下降法进行参数更新学习率设为固定值0.001。 该网络是一个有三层卷积层的神经网络能够快速地完成图像地特征提取。全连接层用于将图像特征整合成分类特征分类层用于分类。cross entropy也是最常用的目标函数之一分类任务使用cross entropy作为目标函数非常适合。Adam梯度下降法也是现在非常流行的梯度下降法的改进方法之一学习率过大会导致模型难以找到较优解设置过小则会降低模型训练效率因此选择适中的0.001。这样我们最基础版本的CNN模型就已经搭建好了接下来进行训练和测试以观察结果。
训练5000轮观察到loss变化曲线、训练集准确率变化曲线和验证集准确率变化曲线如下图。测试集准确率为69.36%。 结果分析首先我们观察训练loss目标函数值变化刚开始loss从200不断减小到接近0但是在100轮左右开始出现震荡并且随着训练幅度越来越大说明模型不稳定。然后观察训练集和验证集的准确率发现训练集准确率接近于1验证集准确率稳定在70%左右说明模型的泛化能力不强并且出现了过拟合情况。最后评估测试集发现准确率为69.36%也没有达到很满意的程度说明我们对模型需要进行很大的改进接下来进行漫长的调参之旅吧 三、数据增强有很大的作用
使用数据增强技术data augmentation主要是在训练数据上增加微小的扰动或者变化一方面可以增加训练数据从而提升模型的泛化能力另一方面可以增加噪声数据从而增强模型的鲁棒性。主要的数据增强方法有翻转变换 flip、随机修剪random crop、色彩抖动color jittering、平移变换shift、尺度变换scale、对比度变换contrast、噪声扰动noise、旋转变换/反射变换 rotation/reflection等可以参考Keras的官方文档 [2] 。获取一个batch的训练数据进行数据增强步骤之后再送入网络进行训练。 我主要做的数据增强操作有如下方面
图像切割生成比图像尺寸小一些的矩形框对图像进行随机的切割最终以矩形框内的图像作为训练数据。图像翻转对图像进行左右翻转。图像白化对图像进行白化操作即将图像本身归一化成Gaussian(0,1)分布。为了进行对比实验观测不同数据增强方法的性能实验1只进行图像切割实验2只进行图像翻转实验3只进行图像白化实验4同时进行这三种数据增强方法同样训练5000轮观察到loss变化曲线、训练集准确率变化曲线和验证集准确率变化曲线对比如下图。 结果分析我们观察训练曲线和验证曲线很明显地发现图像白化的效果好其次是图像切割再次是图像翻转而如果同时使用这三种数据增强技术不仅能使训练过程的loss更稳定而且能使验证集的准确率提升至82%左右提升效果十分明显。而对于测试集准确率也提升至80.42%。说明图像增强确实通过增加训练集数据量达到了提升模型泛化能力以及鲁棒性的效果从准确率上看也带来了将近10%左右的提升因此数据增强确实有很大的作用。但是对于80%左右的识别准确率我们还是不够满意接下来继续调参。 四、从模型入手使用一些改进方法
接下来的步骤是从模型角度进行一些改进这方面的改进是诞生论文的重要区域由于某一个特定问题对某一个模型的改进千变万化没有办法全部去尝试因此一般会实验一些general的方法比如批正则化batch normalization、权重衰减weight decay。我这里实验了4种改进方法接下来依次介绍。
权重衰减weight decay对于目标函数加入正则化项限制权重参数的个数这是一种防止过拟合的方法这个方法其实就是机器学习中的l2正则化方法只不过在神经网络中旧瓶装新酒改名为weight decay [3]。dropout在每次训练的时候让某些的特征检测器停过工作即让神经元以一定的概率不被激活这样可以防止过拟合提高泛化能力 [4]。批正则化batch normalizationbatch normalization对神经网络的每一层的输入数据都进行正则化处理这样有利于让数据的分布更加均匀不会出现所有数据都会导致神经元的激活或者所有数据都不会导致神经元的激活这是一种数据标准化方法能够提升模型的拟合能力 [5]。LRNLRN层模仿生物神经系统的侧抑制机制对局部神经元的活动创建竞争机制使得响应比较大的值相对更大提高模型泛化能力。
为了进行对比实验实验1只使用权重衰减实验2使用权重衰减dropout实验3使用权重衰减dropout批正则化实验4使用权重衰减dropout批正则化LRN同样都训练5000轮观察到loss变化曲线、训练集准确率变化曲线和验证集准确率变化曲线对比如下图。 结果分析我们观察训练曲线和验证曲线随着每一个模型提升的方法都会使训练集误差和验证集准确率有所提升其中批正则化技术和dropout技术带来的提升非常明显而如果同时使用这些模型提升技术会使验证集的准确率从82%左右提升至88%左右提升效果十分明显。而对于测试集准确率也提升至85.72%。我们再注意看左图使用batch normalization之后loss曲线不再像之前会出现先下降后上升的情况而是一直下降这说明batch normalization技术可以加强模型训练的稳定性并且能够很大程度地提升模型泛化能力。所以如果能提出一种模型改进技术并且从原理上解释同时也使其适用于各种模型那么就是非常好的创新点也是我想挑战的方向。现在测试集准确率提升至85%左右接下来我们从其他的角度进行调参。 五、变化的学习率进一步提升模型性能
在很多关于神经网络的论文中都采用了变化学习率的技术来提升模型性能大致的想法是这样的
首先使用较大的学习率进行训练观察目标函数值和验证集准确率的收敛曲线。如果目标函数值下降速度和验证集准确率上升速度出现减缓时减小学习率。循环步骤2直到减小学习率也不会影响目标函数下降或验证集准确率上升为止。
为了进行对比实验实验1只使用0.01的学习率训练实验2前10000个batch使用0.01的学习率10000个batch之后学习率降到0.001实验3前10000个batch使用0.01的学习率10000~20000个batch使用0.001的学习率20000个batch之后学习率降到0.0005。同样都训练5000轮观察到loss变化曲线、训练集准确率变化曲线和验证集准确率变化曲线对比如下图。 结果分析我们观察到当10000个batch时学习率从0.01降到0.001时目标函数值有明显的下降验证集准确率有明显的提升而当20000个batch时学习率从0.001降到0.0005时目标函数值没有明显的下降但是验证集准确率有一定的提升而对于测试集准确率也提升至86.24%。这说明学习率的变化确实能够提升模型的拟合能力从而提升准确率。学习率在什么时候进行衰减、率减多少也需要进行多次尝试。一般在模型基本成型之后使用这种变化的学习率的方法以获取一定的改进精益求精。 六、加深网络层数会发生什么事情
现在深度学习大热所以在计算资源足够的情况下想要获得模型性能的提升大家最常见打的想法就是增加网络的深度让深度神经网络来解决问题但是简单的网络堆叠不一定就能达到很好地效果抱着深度学习的想法我按照plain-cnn模型 [6]我做了接下来的实验。
卷积层1卷积核大小3*3卷积核移动步长1卷积核个数16激活函数ReLU使用batch_normal和weight_decay接下来的n层卷积核大小3*3卷积核移动步长1卷积核个数16激活函数ReLU使用batch_normal和weight_decay。卷积层2卷积核大小3*3卷积核移动步长2卷积核个数32激活函数ReLU使用batch_normal和weight_decay接下来的n层卷积核大小3*3卷积核移动步长1卷积核个数32激活函数ReLU使用batch_normal和weight_decay。卷积层3卷积核大小3*3卷积核移动步长2卷积核个数64激活函数ReLU使用batch_normal和weight_decay接下来的n层卷积核大小3*3卷积核移动步长1卷积核个数64激活函数ReLU使用batch_normal和weight_decay。池化层使用全局池化对64个隐藏单元分别进行全局池化。全连接层隐藏层单元数10激活函数softmax使用batch_normal和weight_decay。
为了进行对比实验进行4组实验每组的网络层数分别设置81420和32。同样都训练5000轮观察到loss变化曲线、训练集准确率变化曲线和验证集准确率变化曲线对比如下图。 结果分析我们惊讶的发现加深了网络层数之后性能反而下降了达不到原来的验证集准确率网络层数从8层增加到14层准确率有所上升但从14层增加到20层再增加到32层准确率不升反降这说明如果网络层数过大由于梯度衰减的原因导致网络性能下降因此需要使用其他方法解决梯度衰减问题使得深度神经网络能够正常work。 七、终极武器残差网络
2015年Microsoft用残差网络 [7] 拿下了当年的ImageNet这个残差网络就很好地解决了梯度衰减的问题使得深度神经网络能够正常work。由于网络层数加深误差反传的过程中会使梯度不断地衰减而通过跨层的直连边可以使误差在反传的过程中减少衰减使得深层次的网络可以成功训练具体的过程可以参见其论文[7]。
通过设置对比实验观察残差网络的性能进行4组实验每组的网络层数分别设置203244和56。观察到loss变化曲线和验证集准确率变化曲线对比如下图。
同的改进策略对分类准确率的影响如何一步步得提高准确率。 代码
import numpy as np
# 序列化和反序列化
import pickle
from sklearn.preprocessing import OneHotEncoder
import warnings
warnings.filterwarnings(ignore)
import tensorflow as tf#数据加载def unpickle(file):import picklewith open(file, rb) as fo:dict pickle.load(fo, encodingISO-8859-1)return dict
labels []
X_train []
for i in range(1,6):data unpickle(./cifar-10-batches-py/data_batch_%d%(i))labels.append(data[labels])X_train.append(data[data])
# 将list类型转换为ndarray
X_train np.array(X_train)X_train np.transpose(X_train.reshape(-1,3,32,32),[0,2,3,1]).reshape(-1,3072)y_train np.array(labels).reshape(-1)# reshape
X_train X_train.reshape(-1,3072)# 目标值概率
one_hot OneHotEncoder()
y_train one_hot.fit_transform(y_train.reshape(-1,1)).toarray()# 测试数据加载
test unpickle(./cifar-10-batches-py/test_batch)
X_test test[data]
X_test np.transpose(X_test.reshape(-1,3,32,32),[0,2,3,1]).reshape(-1,3072)
y_test one_hot.transform(np.array(test[labels]).reshape(-1,1)).toarray()# 从总数据中获取一批数据
index 0
def next_batch(X,y):global indexbatch_X X[index*128:(index1)*128]batch_y y[index*128:(index1)*128]index1if index 390:index 0return batch_X,batch_y# 构建神经网络X tf.placeholder(dtypetf.float32,shape [None,3072])
y tf.placeholder(dtypetf.float32,shape [None,10])
kp tf.placeholder(dtypetf.float32)### 变量
def gen_v(shape,std 5e-2):return tf.Variable(tf.truncated_normal(shape shape,stddevstd))def conv(input_,filter_,b):conv tf.nn.conv2d(input_,filter_,strides[1,1,1,1],paddingSAME) bconv tf.layers.batch_normalization(conv,trainingTrue)conv tf.nn.relu(conv)return tf.nn.max_pool(conv,[1,3,3,1],[1,2,2,1],SAME)def net_work(X,kp):
# 形状改变4维input_ tf.reshape(X,shape [-1,32,32,3])
# 第一层filter1 gen_v(shape [3,3,3,64])b1 gen_v(shape [64])pool1 conv(input_,filter1,b1)# 第二层filter2 gen_v([3,3,64,128])b2 gen_v(shape [128])pool2 conv(pool1,filter2,b2)# 第三层filter3 gen_v([3,3,128,256])b3 gen_v([256])pool3 conv(pool2,filter3,b3)# 第一层全连接层dense tf.reshape(pool3,shape [-1,4*4*256])fc1_w gen_v(shape [4*4*256,1024])fc1_b gen_v([1024])bn_fc_1 tf.layers.batch_normalization(tf.matmul(dense,fc1_w) fc1_b,trainingTrue)relu_fc_1 tf.nn.relu(bn_fc_1)
# fc1.shape [-1,1024]# dropoutdp tf.nn.dropout(relu_fc_1,keep_probkp)# fc2 输出层out_w gen_v(shape [1024,10])out_b gen_v(shape [10])out tf.matmul(dp,out_w) out_breturn out# 损失函数准确率最优化out net_work(X,kp)
loss tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labelsy,logitsout))
# 准确率
y_ tf.nn.softmax(out)
# equal 相当于
equal tf.equal(tf.argmax(y,axis -1),tf.argmax(y_,axis 1))
accuracy tf.reduce_mean(tf.cast(equal,tf.float32))opt tf.train.AdamOptimizer(0.01).minimize(loss)
opt# 开启训练saver tf.train.Saver()# config tf.ConfigProto(allow_soft_placementTrue)
# config.gpu_options.allocator_type BFC
# config.gpu_options.per_process_gpu_memory_fraction 0.80epoches 100
with tf.Session() as sess:sess.run(tf.global_variables_initializer())for i in range(epoches):batch_X,batch_y next_batch(X_train,y_train)opt_,loss_ ,score_train sess.run([opt,loss,accuracy],feed_dict {X:batch_X,y:batch_y,kp:0.5})print(iter count:%d。mini_batch loss:%0.4f。训练数据上的准确率%0.4f。测试数据上准确率...%(i1,loss_,score_train ))if score_train 0.6:saver.save(sess,./model/estimator,i1)saver.save(sess,./model/estimator,i1)for i in range(77):X_test1,y_test1 next_batch(X_test,y_test)score_test sess.run([accuracy],feed_dict {X:X_test1,y:y_test1,kp:1.0})print(测试数据上的准确率,score_test,y_[0],y[0])epoches 1100
with tf.Session() as sess:saver.restore(sess,./model/estimator-100)for i in range(100,epoches):batch_X,batch_y next_batch(X_train,y_train)opt_,loss_ ,score_train sess.run([opt,loss,accuracy],feed_dict {X:batch_X,y:batch_y,kp:0.5})print(iter count:%d。mini_batch loss:%0.4f。训练数据上的准确率%0.4f。测试数据上准确率%0.4f%(i1,loss_,score_train,score_test))if score_train 0.6:saver.save(sess,./model/estimator,i1)saver.save(sess,./model/estimator,i1)if (i%100 0) and (i ! 100):score_test sess.run(accuracy,feed_dict {X:X_test,y:y_test,kp:1.0})print(----------------测试数据上的准确率---------------,score_test)