462c287d0bfeb3486a0f79e4e463e48c64c659fc
[dagnn.git] / test-dagnn.lua
1 #!/usr/bin/env luajit
2
3 --[[
4
5    Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/
6    Written by Francois Fleuret <francois.fleuret@idiap.ch>
7
8    This file is free software: you can redistribute it and/or modify
9    it under the terms of the GNU General Public License version 3 as
10    published by the Free Software Foundation.
11
12    It is distributed in the hope that it will be useful, but WITHOUT
13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15    License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this file.  If not, see <http://www.gnu.org/licenses/>.
19
20 ]]--
21
22 require 'torch'
23 require 'nn'
24 require 'dagnn'
25
26 -- torch.setnumthreads(params.nbThreads)
27 torch.setdefaulttensortype('torch.DoubleTensor')
28 torch.manualSeed(2)
29
30 function checkGrad(model, criterion, input, target)
31    local params, gradParams = model:getParameters()
32
33    local epsilon = 1e-5
34
35    local output = model:forward(input)
36    local loss = criterion:forward(output, target)
37    local gradOutput = criterion:backward(output, target)
38    gradParams:zero()
39    model:backward(input, gradOutput)
40    local analyticalGradParam = gradParams:clone()
41
42    local err = 0
43
44    for i = 1, params:size(1) do
45       local x = params[i]
46
47       params[i] = x - epsilon
48       local output0 = model:forward(input)
49       local loss0 = criterion:forward(output0, target)
50
51       params[i] = x + epsilon
52       local output1 = model:forward(input)
53       local loss1 = criterion:forward(output1, target)
54
55       params[i] = x
56
57       local ana = analyticalGradParam[i]
58       local num = (loss1 - loss0) / (2 * epsilon)
59
60       if num ~= ana then
61          err = math.max(err, torch.abs(num - ana) / torch.abs(num))
62       end
63    end
64
65    return err
66 end
67
68 function printTensorTable(t)
69    if torch.type(t) == 'table' then
70       for i, t in pairs(t) do
71          print('-- ELEMENT [' .. i .. '] --')
72          printTensorTable(t)
73       end
74    else
75       print(tostring(t))
76    end
77 end
78
79 --               +-- Linear(10, 10) --> ReLU --> d --+
80 --              /                              /      \
81 --             /                              /        \
82 --  --> a --> b -----------> c --------------+          e -->
83 --                            \                        /
84 --                             \                      /
85 --                              +----- Mul(-1) ------+
86
87 model = nn.DAG()
88
89 a = nn.Linear(50, 10)
90 b = nn.ReLU()
91 c = nn.Linear(10, 15)
92 d = nn.CMulTable()
93 e = nn.CAddTable()
94
95 model:connect(a, b, c)
96 model:connect(b, nn.Linear(10, 15), nn.ReLU(), d)
97 model:connect(d, e)
98 model:connect(c, d)
99 model:connect(c, nn.Mul(-1), e)
100
101 model:setInput(a)
102 model:setOutput(e)
103
104 local input = torch.Tensor(30, 50):uniform()
105 local output = model:updateOutput(input):clone()
106
107 output:uniform()
108
109 print('Error = ' .. checkGrad(model, nn.MSECriterion(), input, output))
110
111 print('Writing /tmp/graph.dot')
112 model:saveDot('/tmp/graph.dot')