In [127]:
require 'nn'
require 'optim'

In [128]:
local matio = require 'matio'
data = matio.load('ex3data1.mat')

In [129]:
dataset_inputs = data.X

In [130]:
dataset_outputs = data.y

In [131]:
numOutput = torch.max(dataset_outputs) - torch.min(dataset_outputs) + 1

In [132]:
model = nn.Sequential()
model:add(nn.Linear(400,10))
model:add(nn.Sigmoid())

In [134]:
criterion = nn.ClassNLLCriterion()

In [135]:
x, dl_dx = model:getParameters()

In [137]:
feval = function()
    _nidx_ = (_nidx_ or 0) + 1
    if _nidx_ > (#dataset_inputs)[1] then _nidx_ = 1 end
    
    local inputs = dataset_inputs[_nidx_]
    local target = dataset_outputs[_nidx_]
    
    dl_dx:zero()
    
    local loss_x = criterion:forward(model:forward(inputs), target)
    model:backward(inputs, criterion:backward(model.output, target))
        
    return loss_x, dl_dx
end

In [138]:
sgd_params = {
    learningRate = 1e-1,
    learningRateDecay = 1e-3,
    weightDecay = 1e-1,
    momentum = 0
}

In [139]:
epochs = 1e2

In [140]:
for i = 1, epochs do
    current_loss = 0
    for i = 1, (#dataset_inputs)[1] do
        _, fs = optim.sgd(feval, x, sgd_params)
        current_loss = current_loss + fs[1]
    end
    
    current_loss = current_loss / (#dataset_inputs)[1]
    if i%10 == 1 then
        print('epoch = ' .. i .. ' of ' .. epochs .. ' current loss = ' .. current_loss)
    end
end


Out[140]:
epoch = 1 of 100 current loss = -0.71985149611886	
Out[140]:
epoch = 11 of 100 current loss = -0.8848647051594	
Out[140]:
epoch = 21 of 100 current loss = -0.88601792609442	
Out[140]:
epoch = 31 of 100 current loss = -0.88622996466128	
Out[140]:

Out[140]:
epoch = 41 of 100 current loss = -0.88630140694852	
Out[140]:
epoch = 51 of 100 current loss = -0.88633344231457	
Out[140]:
epoch = 61 of 100 current loss = -0.88635045053024	
Out[140]:
epoch = 71 of 100 current loss = -0.88636055038898	
Out[140]:
epoch = 81 of 100 current loss = -0.8863670455896	
Out[140]:
epoch = 91 of 100 current loss = -0.88637147921257	

In [141]:
function maxIndex(a)
    local idx = 0
    local mx = -1e5
    for i = 1,(#a)[1] do
        if mx < a[i] then
            mx = a[i]
            idx = i
        end
    end
    return idx
end

In [142]:
acc = 0.0
for i = 1, (#dataset_inputs)[1] do
    if (maxIndex(model:forward(dataset_inputs[i])) == dataset_outputs[i][1]) then
        acc = acc + 1
    end
end
print('accuracy: ' .. acc/(#dataset_inputs)[1])


Out[142]:
accuracy: 0.8064