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系統上跑還是蠻快的
    ===========================================================================================
    =

附件


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM