zoukankan      html  css  js  c++  java
  • torch7框架 深度学习(1)

    前面已经安装好了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系统上跑还是蛮快的
      ===========================================================================================
      =

    附件

  • 相关阅读:
    RPC笔记之初探RPC:DIY简单RPC框架
    zookeeper笔记之基于zk实现分布式锁
    scala笔记之惰性赋值(lazy)
    Hive笔记之宏(macro)
    Zookeeper笔记之使用zk实现集群选主
    Zookeeper笔记之基于zk的分布式配置中心
    Zookeeper笔记之四字命令
    Zookeeper笔记之命令行操作
    复盘2018,展望2019
    爬虫笔记之w3cschool注册页面滑块验证码破解(巨简单滑块位置识别,非鼠标模拟轨迹)
  • 原文地址:https://www.cnblogs.com/YiXiaoZhou/p/6294150.html
Copyright © 2011-2022 走看看