初学者的CNN搭建示例(torch,cifar10数据集)
来源:互联网 发布:s5700交换机ip mac绑定 编辑:程序博客网 时间:2024/05/22 10:47
前言:
- 之前一直眼高手低,哦是懒,也就是偶尔翻翻书,不怎么摸代码更不用说project了。
- 本硕都是电气,硕士快结束喜欢上AI这东西,半路出家就搞起了机器学习,原因呢很偶然。
- 三月份还没写过二分查找,五月面试的时候面试官夸我的python用的溜、数据结构算法底子不错、而后实现了cifar10数据集测试集75%(还没有对数据做一些白化、旋转、拉伸等处理,如果做的话准确率应该会更高),看来多动手管用。
- 后期可能去用TensorFlow多一些,在此,对之前torch中搭建CNN遇到的问题做一个总的回顾吧。
- 本文可能适合类似我的初学者,大神请跳过或者指教下,ok,开始。
- 前言
- torch的教程入门
- torch教程之后的继续
- 数据的来源
- trainset和testset的形成
- CNN网络的搭建
- 参数的选择和训练
- Gungun结语
torch的教程入门
- torch的语言lua就我目前用到的来看,我觉得还是蛮人性化和简单的。我的语言底子(基本没底子)也就会一丢丢python,看着网上的torch入门教程(请自行百度吧,很多)学的torch使用。
- 我记得有个系列教程的,http://blog.csdn.net/u010946556/article/details/51329208这个是第一个,在文章末尾会有整个系列链接,应该是一共7篇,感谢这位博主,我跟着从头看到尾码了一下,对torch搭建CNN有了一个大致的了解。如果跟我一样基本小白的,可以跟这个博主教程走一遍,也花不了多少时间。
torch教程之后的继续
跟着上面的博主教程走完,可以看到你的代码成功运行,测试集准确率大概不到50%,进一步需要自己做了。
1.数据的来源
那个博主训练集只有10000个样本,所以直接去官网下载cifar-10数据集吧,我下载的是matlab版本的数据,文件后缀是.mat,然后torch读取此类型文件应该是要装一个包,就是下面代码中的‘matio’,至于如何安装,链接在此https://github.com/soumith/matio-ffi.torch/blob/master/README.md,感谢这位的教程帮了我忙。下面代码是load数据部分,手段可能很蠢(没啥经验,请原谅),但运行没毛病,这一点放心。
require 'nn'require 'paths'require 'optim'--载入cifar 10,注意labels为0-9,而不是1-10,另外训练50000组,测试10000组local matio=require'matio'source1= matio.load('/Users/xuhy/Downloads/cifar-10-batches-mat/data_batch_1.mat')--训练部分1a1=source1.data:reshape(10000,3,32,32);b1=source1.labels;source2= matio.load('/Users/xuhy/Downloads/cifar-10-batches-mat/data_batch_2.mat')--训练部分2a2=source2.data:reshape(10000,3,32,32);b2=source2.labels;source3= matio.load('/Users/xuhy/Downloads/cifar-10-batches-mat/data_batch_3.mat')--训练部分3a3=source3.data:reshape(10000,3,32,32);b3=source3.labels;source4= matio.load('/Users/xuhy/Downloads/cifar-10-batches-mat/data_batch_4.mat')--训练部分4a4=source4.data:reshape(10000,3,32,32);b4=source4.labels;source5= matio.load('/Users/xuhy/Downloads/cifar-10-batches-mat/data_batch_5.mat')--训练部分5a5=source5.data:reshape(10000,3,32,32);b5=source5.labels;--测试部分source6=matio.load('/Users/xuhy/Downloads/cifar-10-batches-mat/test_batch.mat')--测试部分数据a6=source6.data:reshape(10000,3,32,32);b6=source6.labels;--再次注意labels为0-9,至此数据载入完成
这个地方自己可以输出原始data看看结构,没记错的话原始应该为10000*1024的tensor,这里reshape成了10000*3*32*32,就是RGB三通道。
然后需要将数据进行拼接,因为训练集被分成了5个部分,另外要注意,labels的数据是0~9而不是1~10,可以自己输出测试下,这关系到后面的loss function,所以特意给了自己标注。
2.trainset和testset的形成
自己可以手动输出几组看下数据类型,这过程会熟练对tensor的操作,在上面load和reshape之后,进行拼接,形成trainset和dataset。
train_data=torch.cat(a1,a2,1);train_data=torch.cat(train_data,a3,1);train_data=torch.cat(train_data,a4,1);train_data=torch.cat(train_data,a5,1);--得到train_data,Tensor(50000,3,32,32)train_labels=torch.cat(b1,b2,1);train_labels=torch.cat(train_labels,b3,1);train_labels=torch.cat(train_labels,b4,1);train_labels=torch.cat(train_labels,b5,1);--得到train_labels(50000,1),取值0~9test_data=a6;--test_data,Tensor(10000,3,32,32)test_labels=b6;--test_labels,(10000,1),取值0~9--构建trainset和testset,暂时没做validationset,后面如果做,训练集用40000个即可trainset={ size=50000, data=(train_data:double()):clone(),--没加深拷贝之前,老是在第一个epoch上就内存占满卡死, label=train_labels:clone()--同上,这个可能和lua的内存调用有关,传递的是引用不是数值,直接clone过来就OK了?}testset={ size=10000, data=(test_data:double()):clone(),--同上,蜜汁尴尬啊, label=test_labels:clone()--同上}
这里有两个值得注意的点:(1)使用cat进行拼接,参数取“1”、“2”应该是表示列方向拼接、行方向拼接,总之这里可以自己体会下,将两个10000*3*32*32的tensor拼接为20000*3*32*32的tensor应该怎么做;(2)另外就是这个深拷贝clone的现象,我也觉得很奇怪,因为时而出现内存炸了的情况有时候又没有,这里需要大神指点下了,就是去掉这个clone部分,在第一个epoch就死了,偶尔呢又没事,具体原因我也没摸清楚。至此训练集、测试集准备完成。
3.CNN网络的搭建
一开始使用的网络是最开始提及的教程系列的网络,后来在看到http://www.cnblogs.com/neopenx/p/4480701.html后对将网络简化为3个卷积层和3个池化层,最后展开softmax,去掉了全连接层,而且第一个采用maxpooling,第二个和第三个采用overlapped average pooling,效果可以好到75%准确率测试集。
但是有个问题,就是读者可以自己试下会看到结果对learning rate等参数初始化敏感,而且对输入数据做了标准化处理。
后续加上batch normalization结构后,去掉数据标准化过程(教程中有,自己走一遍教程的应该还记得),会发现结果对初始参数不怎么敏感,而且收敛速度变快了,很快就达到了测试集75%准确率,大概二三十个epoch?有点忘了。大家可以对比下有无BN层的情况。
关于BN层的理解和使用,链接我忘记了,自己百度去吧,如果没记错参数分别为(通道数、初始γ、初始β、true表示带缩放和偏置)?
-- 神经网络结构net=nn.Sequential()net:add(nn.SpatialConvolution(3,32,3,3))net:add(nn.SpatialBatchNormalization(32,1e-5,0.1,true))net:add(nn.ReLU())net:add(nn.SpatialMaxPooling(2,2,2,2))net:add(nn.SpatialConvolution(32,32,4,4))net:add(nn.SpatialBatchNormalization(32,1e-5,0.1,true))net:add(nn.ReLU())net:add(nn.SpatialAveragePooling(2,2,1,1))net:add(nn.SpatialConvolution(32,64,5,5))net:add(nn.SpatialBatchNormalization(64,1e-5,0.1,true))net:add(nn.ReLU())net:add(nn.SpatialAveragePooling(2,2,1,1))net:add(nn.View(64*6*6))net:add(nn.Linear(64*6*6,10))net:add(nn.LogSoftMax())criterion=nn.ClassNLLCriterion()
分类问题,这里用NLL作为loss function。
4.参数的选择和训练
本文开头的推荐教程系列使用了简单的sgd训练,熟悉深度学习的同学都知道,比较常用的是mini batch sgd,这个地方推荐一个链接http://blog.csdn.net/u012749168/article/details/52684794,本人就是在这之上调整了一下的,细心的同学可以发现其中的区别,我认为原来的代码是有一些问题的(?),比如求size这里原来的代码是-t,我这里是-(t-1),剩下的不同点,认真看了的都能发现。
另外这个链接给出了GPU也就是加上cuda的模式,直接跑会出现问题,因为链接中少了一个:cuda,没有对indices进行:cuda处理。
PS:我的和链接中的微微有点不同,但本质上是一致的,另外我这个版本在CPU跑了几次没有问题,之前没有加BN层时在GPU跑了几次,代码也应该没啥问题吧。
sgd_params={ learningRate=1.0, weightDecay=5e-4, momentum=0.5}x,dl_dx=net:getParameters()step=function(batch_size) local current_loss=0 local count=0 local shuffle=torch.randperm(trainset.size)--打乱生成1-50000的随机组数 batch_size=batch_size or 200 for t=1,trainset.size,batch_size do print(t) local size=math.min(t+batch_size-1,trainset.size)-(t-1) local inputs=torch.Tensor(size,3,32,32) local targets=torch.Tensor(size) for i=1,size do--生成batchsize样本 local input=trainset.data[shuffle[i+t-1]] local target=trainset.label[shuffle[i+t-1]] inputs[i]=input targets[i]=target+1---------------- end local feval=function(x_new) if x ~=x_new then x:copy(x_new) end dl_dx:zero()--梯度归零 local loss=criterion:forward(net:forward(inputs),targets)--求loss net:backward(inputs,criterion:backward(net.output,targets))--两次backward,一次求梯度,一次更新权值 return loss,dl_dx end _, fs=optim.sgd(feval,x,sgd_params)--fs是一个loss function数值的table count=count+1 current_loss=current_loss+fs[1] end return current_loss/countendeval=function(dataset,batch_size) local count=0 batch_size=batch_size or 200 for i=1,dataset.size,batch_size do local size=math.min(i+batch_size-1,dataset.size)-(i-1) local inputs=dataset.data[{{i,i+size-1}}] local targets=dataset.label[{{i,i+size-1}}]:long():add(1)------------------ local outputs=net:forward(inputs)--用计算好的模型计算输出 local _,indices=torch.max(outputs,2)--? local guessed_right=indices:eq(targets):sum() count=count+guessed_right end return count/dataset.sizeendmax_iters=66do for i=1,max_iters do local loss=step() print(string.format( 'Epoch:%d Current loss:%4f', i,loss)) local accuracy=eval(trainset) print(string.format( 'Accuracy on the trainset:%4f',accuracy)) endend--测试集数据标准化testset.data=testset.data:double()
这里解释一下几个函数:(1)step()这个函数,输入是batchsize,默认为200,我在GPU上跑的时候,选择的是128,也就是在下面的循环里是local loss=step(128),step()这个函数就是进行一次全样本也就是1个epoch训练,并返回loss值;(2)eval(dataset)这函数很直观了,评价一个dataset的accuracy。
PS:这里给个建议,代码最好不要复制过去使用,如果像我一样比较小白,一句话一句话自己敲进去,遇到不明白的函数或者表达,百度之然后翻阅下博客论文什么的,消除这个疑问,然后继续,当敲到最后一句代码且没什么疑问的时候,你会发现学到了不少东西,动手动脑思考,这也是给我自己的要求了。
Gungun结语
因为后续可能短时间没办法继续更新这部分了,本来后面的打算是有两个,一是对数据进行处理,包括拉伸旋转剪切等扩充数据集看下能把准确率提高多少,二是采用vgg、resnet等各种大佬结构练下。
有机会再说,先这样吧。
- 初学者的CNN搭建示例(torch,cifar10数据集)
- Keras入门课3 -- 使用CNN识别cifar10数据集
- cifar10数据集的读取Python/Tensorflow
- python实现cifar10数据集的可视化
- tensorflow cifar10数据集的测试
- python实现cifar10数据集的可视化
- 转换Cifar10数据集
- TensorFlow学习之CNN-Cifar10代码阅读与详解(一):cifar10数据批量读取
- TensorFlow入门-CIFAR10&CNN
- 制作自己的python版本的类CIFAR10数据集
- 制作python版本的类CIFAR10数据集.Tensorflow
- caffe基础-14cifar10数据集的训练
- cifar10数据集的训练测试及ResNet20模型测试
- 4用于cifar10的卷积神经网络-4.4/4.5cifar10数据集读取和数据增强扩充(上/下)
- TensorFlow-CIFAR10 CNN代码分析
- TensorFlow-CIFAR10 CNN代码分析
- python显示cifar10数据集中的图片
- caffe使用cifar10数据集问题记录
- JAVA知识点总结16-多线程
- 图解JAVA中Spring Aop作用
- Spark Q&A : Kryo serialization failed: Buffer overflow
- usbplayer demo
- Python进阶
- 初学者的CNN搭建示例(torch,cifar10数据集)
- 1012. 数字分类 (20)
- SpringMVC 文档学习笔记
- RxJava 从入门到爱上它
- QML让圆形物体按照圆形轨迹运动和color使用rgba值的Demo
- Linux下启动和停止apache服务
- hadoop涉及到分摊磁盘io负载的配置
- <Shader> 最终版本的水纹效果
- ubuntu12.04 挂载samba网盘命令