手写体数字识别二

转自:

http://www.aichengxu.com/view/2464034

本节代码地址:

https://github.com/vic-w/torch-practice/tree/master/mnist

根据个人理解,注释了一些原作者没有注释的代码

[plain]  view plain  copy
  1. luarocks install mnist  

[plain]  view plain  copy
  1. require 'torch'  
  2. require 'nn'  
  3. require 'optim'  
  4. --require 'cunn'  
  5. --require 'cutorch'  
  6. mnist = require 'mnist'  
  7. --mnist中包含我们需要的训练数据和测试数据  
  8. fullset = mnist.traindataset()  
  9. testset = mnist.testdataset()  
  10.   
  11. trainset = {  
  12.     size = 50000,  
  13.     data = fullset.data[{{1,50000}}]:double(),  
  14.     label = fullset.label[{{1,50000}}]  
  15. }  
  16.   
  17. validationset = {  
  18.     size = 10000,  
  19.     data = fullset.data[{{50001,60000}}]:double(),  
  20.     label = fullset.label[{{50001,60000}}]  
  21. }  
  22. --数据减去他们的均值  
  23. trainset.data = trainset.data - trainset.data:mean()  
  24. validationset.data = validationset.data - validationset.data:mean()  
  25. model = nn.Sequential()  
  26. model:add(nn.Reshape(1, 28, 28))  
  27. model:add(nn.MulConstant(1/256.0*3.2))  
  28. model:add(nn.SpatialConvolutionMM(1, 20, 5, 5, 1, 1, 0, 0))  
  29. model:add(nn.SpatialMaxPooling(2, 2 , 2, 2, 0, 0))  
  30. model:add(nn.SpatialConvolutionMM(20, 50, 5, 5, 1, 1, 0, 0))  
  31. model:add(nn.SpatialMaxPooling(2, 2 , 2, 2, 0, 0))  
  32. model:add(nn.Reshape(4*4*50))  
  33. model:add(nn.Linear(4*4*50, 500))  
  34. model:add(nn.ReLU())  
  35. model:add(nn.Linear(500, 10))  
  36. model:add(nn.LogSoftMax())  
  37.   
  38. model = require('weight-init')(model, 'xavier')  
  39.   
  40. criterion = nn.ClassNLLCriterion()  
  41.   
  42. --model = model:cuda()  
  43. --criterion = criterion:cuda()  
  44. --trainset.data = trainset.data:cuda()  
  45. --trainset.label = trainset.label:cuda()  
  46. --validationset.data = validationset.data:cuda()  
  47. --validationset.label = validationset.label:cuda()  
  48.   
  49. sgd_params = {  
  50.    learningRate = 1e-2,  
  51.    learningRateDecay = 1e-4,  
  52.    weightDecay = 1e-3,  
  53.    momentum = 1e-4  
  54. }  
  55. --获取模型的初始参数,x是权值,dl_dx是梯度  
  56. x, dl_dx = model:getParameters()  
  57.   
  58. step = function(batch_size)  
  59.     local current_loss = 0  
  60.     local count = 0  
  61.     local shuffle = torch.randperm(trainset.size)--随机下标,用来打乱训练数据  
  62.     batch_size = batch_size or 200--批处理数目为200  
  63.     for t = 1,trainset.size,batch_size do  
  64.         -- setup inputs and targets for this mini-batch  
  65.         local size = math.min(t + batch_size - 1, trainset.size) - t  
  66.         local inputs = torch.Tensor(size, 28, 28)--:cuda()  
  67.         local targets = torch.Tensor(size)--:cuda()  
  68.         for i = 1,size do  
  69.             local input = trainset.data[shuffle[i+t]]  
  70.             local target = trainset.label[shuffle[i+t]]  
  71.             -- if target == 0 then target = 10 end  
  72.             inputs[i] = input--将随机打乱位置的数据集加入到训练输入和输出集  
  73.             targets[i] = target  
  74.         end  
  75.         targets:add(1)  
  76.         local feval = function(x_new)--这个函数是个迭代训练函数  
  77.             -- reset data  
  78.             if x ~= x_new then x:copy(x_new) end  
  79.             dl_dx:zero()--梯度归零,类似这个函数zeroGradParameters()    
  80.   
  81.             -- perform mini-batch gradient descent  
  82.             local loss = criterion:forward(model:forward(inputs), targets)--两次前向计算,一次是带入模型计算输出,一次是用输出和目标输出求误差  
  83.             model:backward(inputs, criterion:backward(model.output, targets))--两次后向计算,一次是带入误差函数求梯度,一次是用梯度和输入数据更新权值  
  84.   
  85.             return loss, dl_dx--返回误差和梯度  
  86.         end  
  87.   
  88.         _, fs = optim.sgd(feval, x, sgd_params)--优化函数  
  89.   
  90.         -- fs is a table containing value of the loss function  
  91.         -- (just 1 value for the SGD optimization)  
  92.         count = count + 1  
  93.         current_loss = current_loss + fs[1]  
  94.     end  
  95.   
  96.     -- normalize loss  
  97.     return current_loss / count  
  98. end  
  99.   
  100. eval = function(dataset, batch_size)  
  101.     local count = 0  
  102.     batch_size = batch_size or 200  
  103.       
  104.     for i = 1,dataset.size,batch_size do  
  105.         local size = math.min(i + batch_size - 1, dataset.size) - i  
  106.         local inputs = dataset.data[{{i,i+size-1}}]--:cuda()  
  107.         local targets = dataset.label[{{i,i+size-1}}]:long()--:cuda()  
  108.         local outputs = model:forward(inputs)--用训练好的模型计算输出  
  109.         local _, indices = torch.max(outputs, 2)  
  110.         indices:add(-1)  
  111.         local guessed_right = indices:eq(targets):sum()--计算命中数目  
  112.         count = count + guessed_right  
  113.     end  
  114.   
  115.     return count / dataset.size  
  116. end  
  117.   
  118. max_iters = 30  
  119.   
  120. do  
  121.     local last_accuracy = 0  
  122.     local decreasing = 0  
  123.     local threshold = 1 -- how many deacreasing epochs we allow  
  124.     for i = 1,max_iters do  
  125.         local loss = step()  
  126.         print(string.format('Epoch: %d Current loss: %4f', i, loss))  
  127.         local accuracy = eval(validationset)  
  128.         print(string.format('Accuracy on the validation set: %4f', accuracy))  
  129.         if accuracy < last_accuracy then  
  130.             if decreasing > threshold then break end  
  131.             decreasing = decreasing + 1  
  132.         else  
  133.             decreasing = 0  
  134.         end  
  135.         last_accuracy = accuracy  
  136.     end  
  137. end  
  138.   
  139. testset.data = testset.data:double()  
  140. eval(testset)  

猜你喜欢

转载自blog.csdn.net/ccccccod/article/details/79055592