-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathMyReshape.lua
94 lines (79 loc) · 2.66 KB
/
MyReshape.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
local MyReshape, parent = torch.class('nn.MyReshape', 'nn.Module')
function MyReshape:__init(...)
parent.__init(self)
local arg = {...}
self.size = torch.LongStorage()
self.batchsize = torch.LongStorage()
self.flexibleDimensions = {}
local n = #arg
self.size:resize(n) --note that this includes the minibatch dimension
for i=1,n do
self.size[i] = arg[i]
end
self.batchsize:resize(#self.size)
-- only used for non-contiguous input or gradOutput
self._input = torch.Tensor()
self._gradOutput = torch.Tensor()
end
function MyReshape:updateOutput(input)
assert(input:isContiguous())
if not input:isContiguous() then
self._input:resizeAs(input)
self._input:copy(input)
input = self._input
end
local curIdx = 1
self.batchsize:resize(#self.size)
for i = 1,#self.size do
if(self.size[i] == -1) then --if -1, then keep this coordinate with the same size as the input
self.batchsize[curIdx] = input:size(i)
curIdx = curIdx + 1
elseif(self.size[i] == 0) then --if 0, then kill this coordinate, by folding into previous coordinate
self.batchsize:resize(self.batchsize:size() - 1)
self.batchsize[curIdx-1] = self.batchsize[curIdx-1] * input:size(i)
elseif(self.size[i] == -2) then --choose this dimension so that everything else works
assert(i == #self.size)
local num = input:nElement()
prodSoFar = 1
for ii = 1,(i-1) do
prodSoFar = prodSoFar*self.batchsize[ii]
end
assert(num % prodSoFar == 0)
self.batchsize[curIdx] = num/prodSoFar
curIdx = curIdx + 1
else
self.batchsize[curIdx] = self.size[i]
curIdx = curIdx + 1
end
end
--now make sure that we're viewing the correct size
local prod = 1
for i = 1,self.batchsize:size() do
prod = prod*self.batchsize[i]
end
local db = 1
for i = 1,input:size():size() do
db = db*input:size(i)
end
--print('input')
--print(input:size())
--print('batch')
--print(self.batchsize)
assert(db == prod,db.." vs. "..prod)
assert(db == prod,'inconsistent sizes: '..db.." v.s. "..prod)
self.output:view(input, self.batchsize)
return self.output
end
function MyReshape:updateGradInput(input, gradOutput)
if not gradOutput:isContiguous() then
self._gradOutput:resizeAs(gradOutput)
self._gradOutput:copy(gradOutput)
gradOutput = self._gradOutput
end
self.gradInput:viewAs(gradOutput, input)
return self.gradInput
end
function MyReshape:__tostring__()
return torch.type(self) .. '(' ..
table.concat(self.size:totable(), 'x') .. ')'
end