aboutsummaryrefslogtreecommitdiff
path: root/nerv/layer/init.lua
diff options
context:
space:
mode:
Diffstat (limited to 'nerv/layer/init.lua')
-rw-r--r--nerv/layer/init.lua156
1 files changed, 141 insertions, 15 deletions
diff --git a/nerv/layer/init.lua b/nerv/layer/init.lua
index c893df3..7521b7a 100644
--- a/nerv/layer/init.lua
+++ b/nerv/layer/init.lua
@@ -1,38 +1,96 @@
--- The following methods must be implemented to let a layer work properly
+--- Implements the concept of groups of parameters (`nerv.Param`) and
+-- computation nodes (`nerv.Layer`).
+
+--- The class describing a group of parameters (an internal state) that can be
+-- bound to layers. This class also implements the *chunk* interface (see
+-- `nerv.ChunkFile`) , which means instances of `nerv.Param` can be exported to
+-- chunk files as chunks.
+-- @type nerv.Param
local Param = nerv.class('nerv.Param')
+--- The constructor.
+-- @param id the identifier for the group of parameters
+-- @param global_conf a table describing the computation state and providing
+-- with some global settings
+
function Param:__init(id, global_conf)
self.id = id
self.gconf = global_conf
end
+--- Retrieve the metadata of the parameter group. This function implements the
+-- *chunk* interface.
+-- @return a table containing all metadata
+
function Param:get_info()
return self.info
end
+--- Set the metadata of the parameter group. This function implements the
+-- *chunk* interface.
+-- @param info a table containing all metadata
+
function Param:set_info(info)
self.info = info
end
+--- Read from the given file handle. This function implements the
+-- *chunk* interface.
+-- @param handle the file handle
+
function Param:read(handle)
nerv.error_method_not_implemented()
end
+--- Write to the given file handle. This function implements the
+-- *chunk* interface.
+-- @param handle the file handle
+
function Param:write(handle)
nerv.error_method_not_implemented()
end
-function Param:update(gradient)
- nerv.error_method_not_implemented()
-end
+--- Generate zero.
+-- @return zero
-function Param:gen_zero()
+function Param.gen_zero()
return 0
end
+--- The class describing a single computation node which calculates from the
+-- input ports to the output ports which could be the input of others.
+-- @type nerv.Layer
+
local Layer = nerv.class('nerv.Layer')
+--- The constructor. All inheriting classes should call this base constructor to
+-- initialize some predefined fields (of `self`):
+--
+-- * `id`: the identifier of the layer
+-- * `gconf`: a table describing the computation state and providing
+-- with some global settings
+-- * `lconf`: a table providing with settings dedicated for the layer. There
+-- are some fields considered to be "standard" and shared by all
+-- layers:
+-- * `dim_in`: an array of each input port dimension (width) with order
+-- * `dim_out`: an array of each output port dimension (width) with order
+-- * `params`: optional, a table containing pairs of the manually bound
+-- parameter name used by the layer and parameter id used to find the
+-- parameter in the parameter repo
+-- * `pr`: optional, the parameter repo (see `nerv.ParamRepo`) to find
+-- parameters while binding, used by `nerv.Layer.find_param`
+-- * `mat_type`: the type of matrix should be used when storing intermediate
+-- results
+-- * `loc_type`: a value from `nerv.ParamRepo.LOC_TYPES` indicating whether the
+-- storage of `nerv.Param` instances is on host or device RAM
+-- * `dim_in`: an array of each input port dimension (width) with order
+-- * `dim_out`: an array of each output port dimension (width) with order
+--
+-- @param id the identifier
+-- @param global_conf see `self.gconf`
+-- @param layer_conf see `self.lconf`
+
function Layer:__init(id, global_conf, layer_conf)
self.id = id
self.gconf = global_conf
@@ -48,22 +106,57 @@ function Layer:__init(id, global_conf, layer_conf)
self.dim_out = layer_conf.dim_out
end
+--- Initialize the layer, called for each epoch.
+
function Layer:init(batch_size)
nerv.error_method_not_implemented()
end
-function Layer:update(bp_err, input, output)
+--- Update (change the state of) the bound (tied) parameter according to the
+-- calculation.
+-- @param bp_err an array of row-major matrices storing the error
+-- back-propagated from the output ports
+-- @param input an array of row-major matrices storing the input before the
+-- forward propagation
+-- @param ouput an array of row-major matrices storing the output after the
+-- forward propagation
+-- @param t BPTT time `t`
+
+function Layer:update(bp_err, input, output, t)
nerv.error_method_not_implemented()
end
-function Layer:propagate(input, output)
+--- Calculate the values in output ports according to the input.
+-- @param input an array of row-major matrices storing the input before the
+-- forward propagation
+-- @param ouput an array of row-major matrices storing the output after the
+-- forward propagation
+-- @param t BPTT time `t`
+
+function Layer:propagate(input, output, t)
nerv.error_method_not_implemented()
end
-function Layer:back_propagate(bp_err, next_bp_err, input, output)
+--- Calculate the next error value (`next_bp_err`) by back-propagation.
+-- @param bp_err an array of row-major matrices storing the error
+-- back-propagated from the output ports
+-- @param next_bp_err an array of row-major matrices storing the next error
+-- back-propagated to the input ports
+-- @param input an array of row-major matrices storing the input before the
+-- forward propagation
+-- @param ouput an array of row-major matrices storing the output after the
+-- forward propagation
+-- @param t BPTT time `t`
+
+function Layer:back_propagate(bp_err, next_bp_err, input, output, t)
nerv.error_method_not_implemented()
end
+--- Check the length of the dimention array. This function is recommended for
+-- invocation when checking the ports in your layer implementation.
+-- @param len_in the expected number of input ports (-1 if variable)
+-- @param len_out the expected number of output ports (-1 if variable)
+
function Layer:check_dim_len(len_in, len_out)
local expected_in = #self.dim_in
local expected_out = #self.dim_out
@@ -77,27 +170,60 @@ function Layer:check_dim_len(len_in, len_out)
end
end
+--- Get all the parameters used by (bound to) the layer.
+-- @return a `nerv.ParamRepo` instance storing all the involved parameters
+
function Layer:get_params()
nerv.error_method_not_implemented()
end
+--- Lookup and bind the parameters in the repo specified in layer settings.
+-- This function will lead to the invocation of `find_param` if the layer is
+-- implemented appropriately.
+
function Layer:bind_params()
nerv.error_method_not_implemented()
end
+--- Get two arrays describing the dimension of input and ouput.
+-- @return two arrays: `<dim_in>, <dim_out>`
+
function Layer:get_dim()
return self.dim_in, self.dim_out
end
+--- Set an attribute to the layer.
+-- @param name the name of the attribute
+-- @param value the value of the attribute
+
function Layer:set_attr(name, value)
self[name] = value
end
+--- Get the contained (nested) layer inside the layer (useful for complex
+-- layers like `nerv.GraphLayer`).
+-- @param id the identifier of the nested layer to be find
+
function Layer:get_sublayer(id)
nerv.error('primitive layer does not have sublayers')
end
-function Layer:find_param(plist, lconf, gconf, p_type, p_dim, p_gen)
+--- Find the parameter according to the layer settings. This function should be
+-- used as the only way to locate a parameter in the implementation of
+-- `bind_params` (see `nerv.AffineLayer.bind_params`).
+-- @param plist the potential names for the parameter in the order of lookup priority
+-- @param lconf a table providing with settings dedicated for the layer
+-- @param gconf a table describing the computation state and providing with
+-- some global settings
+-- @param ptype the type for constructing the parameter instance when
+-- auto-generation is triggered
+-- @param pdim an array specifying each dimension of the parameter when
+-- auto-generation is triggered
+-- @param pgen the function used to generate values when auto-generation is
+-- triggered, `gconf.param_gen` will be used if `nil`
+
+function Layer:find_param(plist, lconf, gconf, ptype, pdim, pgen)
+
if type(plist) == "string" then
plist = {plist}
end
@@ -123,14 +249,14 @@ function Layer:find_param(plist, lconf, gconf, p_type, p_dim, p_gen)
pid = self.id .. '_' .. plist[1]
nerv.info("param id for [%s] of layer [%s] is not found in the specified param repo, " ..
"switch to auto-generate", plist_str, self.id)
- local p = p_type(pid, gconf)
- p.trans = self.mat_type(unpack(p_dim))
- p_gen = p_gen or gconf.param_gen
- or gconf.param_random -- obsolete name
- if type(p_gen) ~= "function" then
+ local p = ptype(pid, gconf)
+ p.trans = self.mat_type(unpack(pdim))
+ pgen = pgen or gconf.param_gen
+ or gconf.param_random -- obsolete name
+ if type(pgen) ~= "function" then
nerv.error("a param generate function is needed")
end
- p.trans:generate(p_gen)
+ p.trans:generate(pgen)
return p
end