local DropoutLayer = nerv.class("nerv.DropoutLayer", "nerv.Layer") function DropoutLayer:__init(id, global_conf, layer_conf) nerv.Layer.__init(self, id, global_conf, layer_conf) if self.gconf.dropout_rate == nil then nerv.warning("[DropoutLayer:propagate] dropout rate is not set") end self:check_dim_len(1, 1) -- two inputs: nn output and label end function DropoutLayer:bind_params() -- do nothing end function DropoutLayer:init(batch_size, chunk_size) if self.dim_in[1] ~= self.dim_out[1] then nerv.error("mismatching dimensions of input and output") end if chunk_size == nil then chunk_size = 1 end self.mask = {} for t = 1, chunk_size do self.mask[t] = self.mat_type(batch_size, self.dim_in[1]) end end function DropoutLayer:batch_resize(batch_size, chunk_size) if chunk_size == nil then chunk_size = 1 end for t = 1, chunk_size do if self.mask[t] == nil or self.mask[t]:nrow() ~= batch_size then self.mask[t] = self.mat_type(batch_size, self.dim_in[1]) end end end function DropoutLayer:propagate(input, output, t) if t == nil then t = 1 end if self.gconf.dropout_rate then self.mask[t]:rand_uniform() -- since we will lose a portion of the actvations, we multiply the -- activations by 1 / (1 - rate) to compensate self.mask[t]:thres_mask(self.mask[t], self.gconf.dropout_rate, 0, 1 / (1.0 - self.gconf.dropout_rate)) output[1]:mul_elem(input[1], self.mask[t]) else output[1]:copy_fromd(input[1]) end end function DropoutLayer:update(bp_err, input, output, t) -- no params, therefore do nothing end function DropoutLayer:back_propagate(bp_err, next_bp_err, input, output, t) if t == nil then t = 1 end if self.gconf.dropout_rate then next_bp_err[1]:mul_elem(bp_err[1], self.mask[t]) else next_bp_err[1]:copy_fromd(bp_err[1]) end end function DropoutLayer:get_params() return nerv.ParamRepo({}, self.loc_type) end