热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

torch7框架深度学习(1)

前面已经安装好了torch,下面就来看看如何在torch框架上搭建深度学习模型,我一直觉得源码结合原理是机器学习最好的学习途径。所以我们从分析一个简单的案例开始吧。参考Supervis

前面已经安装好了torch,下面就来看看如何在torch框架上搭建深度学习模型,我一直觉得源码结合原理是机器学习最好的学习途径。所以我们从分析一个简单的案例开始吧。

参考Supervised Learning

这个例子呢,主要是以有监督的方式构建一个深度学习模型实现对数据集SVHN的分类。

SVHN是 The Street View House Numbers Dataset, 数据集介绍见 SVHN数据集

代码主要分为五个部分

  1. 数据的预处理

  2. 网络模型的构建

  3. 损失函数的定义

  4. 训练网络

  5. 测试数据

数据的预处理

  1. require 'torch' -- torch 
  2. require 'image' -- to visualize the dataset 
  3. require 'nn' -- provides a normalization operator 

加载头文件

  1. if not opt then 
  2. print '==> processing options' 
  3. cmd = torch.CmdLine() 
  4. cmd:text() 
  5. cmd:text('SVHN Dataset Preprocessing') 
  6. cmd:text() 
  7. cmd:text('Options:') 
  8. cmd:option('-size', 'small', 'how many samples do we load: small | full | extra') 
  9. cmd:option('-visualize', true, 'visualize input data and weights during training') 
  10. cmd:text() 
  11. opt = cmd:parse(arg or {}) 
  12. end 

文件的命令行参数。主要有两个参数(文件大小和是否可视化选项),torch.CmdLine()函数参见torch.CmdLine()

  1. www = 'http://data.neuflow.org/data/housenumbers/' 
  2.  
  3. train_file = 'train_32x32.t7' 
  4. test_file = 'test_32x32.t7' 
  5. extra_file = 'extra_32x32.t7' 
  6.  
  7. if not paths.filep(train_file) then 
  8. os.execute('wget ' .. www .. train_file) 
  9. end 
  10. if not paths.filep(test_file) then 
  11. os.execute('wget ' .. www .. test_file) 
  12. end 
  13. if opt.size == 'extra' and not paths.filep(extra_file) then 
  14. os.execute('wget ' .. www .. extra_file)  
  15. end 

用于数据集的下载,数据集网址,但是这个网址好像被墙了,访问不了。所以我自己令下载的数据集SVHN,其中只下载了 train_32x32.mat和 test_32x32.mat文件,因为数据太大机子跑得太慢。

顺便说一句上边代码中 os.execute(string)是执行string指令,wget是下载指令,参见linux 应用之wget 命令详解

下载下来的数据是 mat格式的,要转换成 torch使用的t7格式,文档中说可以使用mattorch工具实现,但是我在虚拟机上没有装matlab,所以安装mattorch总是失败。 另外使用matio同样可以实现matlab和torch间数据转换。

下面是安装matio的指令matio-ffi

  1. sudo apt-get install libmatio2 
  2. sudo luarocks install matio 

此时下载的数据是 columns x rows x channels x num ,但image.display()要求的数据组织形式是: num x channels x columns x rows,所以需要进行重组织,由于我也是个刚开始使用torch没一周的人,所以就用较原始的办法重组织了,谁有好办法希望教教我!下面是数据转换的代码

  1. matio = require'matio' 
  2. loaded = matio.load('/SVHN_Data/train_32x32.mat') 
  3. tempData=loaded.X:permute(4,3,1,2) 
  4. trainData = { 
  5. data = tempData, 
  6. labels = loaded.y[{{},{1}}], -- loaded.y:size() --> 26032 x 1 
  7. size = function() return trsize end 

数据存放在'/SVHN_Data'文件夹内
------------------------------------------------------下面一段是用来看数据转换的对不对 --------------------------------
torch 结果
enter description here
matlab结果
enter description here
颜色不大一样,一个是在笔记本上跑的,一个是在台机上跑的,不知道是不是机器的原因还是什么原因

---------------------------------------------------------------------END---------------------------------------------------------

  1. if opt.size == 'extra' then 
  2. print '==> using extra training data' 
  3. trsize = 73257 + 531131 
  4. tesize = 26032 
  5. elseif opt.size == 'full' then 
  6. print '==> using regular, full training data' 
  7. trsize = 73257 
  8. tesize = 26032 
  9. elseif opt.size == 'small' then 
  10. print '==> using reduced training data, for fast experiments' 
  11. trsize = 10000 
  12. tesize = 2000 
  13. end 

上面这一段是设置训练集和测试集的大小。
================================================================= START ==================================================

  1. loaded = torch.load(train_file,'ascii') 
  2. trainData = { 
  3. data = loaded.X:transpose(3,4), 
  4. labels = loaded.y[1], 
  5. size = function() return trsize end 

上面这段代码很容易理解,就是分别将数据和标签起别名data和labels方便后续使用,size返回的是训练样本的个数。唯一需要注意的是transpose()函数的使用,这是因为在matlab中数据的表达一般是先列后行,而在torch中数据的表达一般是先行后列,所以这里对后两维进行了转置
这段代码被上面自己下载数据并处理取代
====================================================== END ======================================================

  1. if opt.size == 'extra' then 
  2. loaded = torch.load(extra_file,'ascii') 
  3. trdata = torch.Tensor(trsize,3,32,32) 
  4. trdata[{ {1,(#trainData.data)[1]} }] = trainData.data 
  5. trdata[{ {(#trainData.data)[1]+1,-1} }] = loaded.X:transpose(3,4) 
  6. trlabels = torch.Tensor(trsize) 
  7. trlabels[{ {1,(#trainData.labels)[1]} }] = trainData.labels 
  8. trlabels[{ {(#trainData.labels)[1]+1,-1} }] = loaded.y[1] 
  9. trainData = { 
  10. data = trdata, 
  11. labels = trlabels, 
  12. size = function() return trsize end 

  13. end 

当数据选择extra时,上面对训练集进行拼接。

同样加载测试集

  1. loaded = matio.load('/SVHN_Data/test_32x32.mat') 
  2. tempData = loaded.X:permute(4,3,1,2) 
  3. testData = {data = tempData, labels =loaded.y, size = function() return tesize end} 
  4. tempData = nil 

下面进行数据的预处理
数据的预处理包含三个trick
+ 图像从RGB空间映射到YUV空间
+ Y通道使用 contrastive normalization operator进行局部规范化
+ 对所有的数据在每个通道进行规范化到0,1之间

  1. -- RGB==>YUV 
  2. for i=1,trainData:size() do  
  3. trainData.data[i] = image.rgb2yuv(trainData.data[i]) -- 等价于 trainData.data[{{i},{},{},{}}] 
  4. end 
  5. for i=1,testData:size() do 
  6. testData.data[i] = image.rgb2yuv(testData.data[i]) 
  7. end 
  8.  
  9. -- Name Channels for convenience 
  10. channels = {'y','u','v'} 
  11.  
  12.  
  13. -- 单通道进行规范化 
  14. Mean={} 
  15. Std={} 
  16. for i=1, channel in ipairs(channels) do --此处和for i=1,3 do等价 
  17. Mean[i]= trainData.data[{{},{i},{},{}}]:mean() 
  18. Std[i] = trainData.data[{{},{i},{},{}}]:std() 
  19. trainData.data[{{},{i},{},{}}]=trainData.data[{{},{i},{},{}}]:csub(Mean[i]) 
  20. trainData.data[{{},{i},{},{}}]=trainData.data[{{},{i},{},{}}]:div(Std[i]) 
  21. end 
  22.  
  23. for i=1,3 do 
  24. testData.data[{{},{i},{},{}}]:add(-Mean[i]) -- add 和csub 
  25. -- 这个用法见Tensor的手册,改变后替代原来数据,所以和上面是一样的 
  26. testData.data[{{},{i},{},{}}]:div(Std[i]) 
  27. end 
  28. -- 至于为什么测试数据使用训练集的统计量归一化,参见机器学习相关理论 

Y通道局部的规范化需要使用nn包里的算子

  1. -- Define the normalization neighborhood: 
  2. neighborhood = image.gaussian1D(7) 
  3.  
  4. -- Define our local normalization operator (It is an actual nn module,  
  5. -- which could be inserted into a trainable model): 
  6. normalization = nn.SpatialContrastiveNormalization(1, neighborhood):float() 
  7.  
  8. -- Normalize all Y channels locally: 
  9. for i = 1,trainData:size() do 
  10. trainData.data[{ i,{1},{},{} }] = normalization:forward(trainData.data[{ i,{1},{},{} }]) --前向计算 
  11. end 
  12. for i = 1,testData:size() do 
  13. testData.data[{ i,{1},{},{} }] = normalization:forward(testData.data[{ i,{1},{},{} }]) 
  14. end 

关于函数 nn.SpatialContrastiveNormalization(1, neighborhood) 参见 torch/nn/SpatialContrastiveNormalization.lua

===================== It's always good practice to verify that data is properly normalized ========================

  1. for i,channel in ipairs(channels) do 
  2. trainMean = trainData.data[{ {},i }]:mean() 
  3. trainStd = trainData.data[{ {},i }]:std() 
  4.  
  5. testMean = testData.data[{ {},i }]:mean() 
  6. testStd = testData.data[{ {},i }]:std() 
  7.  
  8. print('training data, '..channel..'-channel, mean: ' .. trainMean) 
  9. print('training data, '..channel..'-channel, standard deviation: ' .. trainStd) 
  10.  
  11. print('test data, '..channel..'-channel, mean: ' .. testMean) 
  12. print('test data, '..channel..'-channel, standard deviation: ' .. testStd) 
  13. end 

================================================= END ======================================

最后是数据的可视化,显示了前256个数据Y,U,V通道上的效果

  1. if opt.visualize then 
  2. first256Samples_y = trainData.data[{ {1,256},1 }] 
  3. first256Samples_u = trainData.data[{ {1,256},2 }] 
  4. first256Samples_v = trainData.data[{ {1,256},3 }] 
  5. image.display{image=first256Samples_y, nrow=16, legend='Some training examples: Y channel'} 
  6. image.display{image=first256Samples_u, nrow=16, legend='Some training examples: U channel'} 
  7. image.display{image=first256Samples_v, nrow=16, legend='Some training examples: V channel'} 
  8. end 

具体的代码见附件

命令行执行: (1_data.lua)是文件名

  1. qlua 1_data.lua 

 

enter description here

result.png

结果见下图(Y通道)
enter description here
github上给的结果(Y通道)
enter description here

 

================================================== 结论 ===================================

  1. torch 挺好用的,和我胃口-

  2. 在笔记本上安装虚拟机跑深度学习的代码。。。真是蛮拼的。。。这速度感人啊,直接在ubuntu系统上跑还是蛮快的
    ===========================================================================================
    =

附件


推荐阅读
author-avatar
求道金林
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有