diff options
Diffstat (limited to 'nerv/nn/layer_repo.lua')
-rw-r--r-- | nerv/nn/layer_repo.lua | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/nerv/nn/layer_repo.lua b/nerv/nn/layer_repo.lua index 647aac9..35ac104 100644 --- a/nerv/nn/layer_repo.lua +++ b/nerv/nn/layer_repo.lua @@ -1,10 +1,136 @@ +--- Implements a concecpt that stores a collection of layers. + +--- The class for storing a collection of layers. +-- @type nerv.LayerRepo + local LayerRepo = nerv.class("nerv.LayerRepo") +--- The constructor. +-- @param layer_spec the *layer specification*, a declarative way of creating layers in the collection. The layer specification is structured as follow: +-- +-- { +-- [<layer_typename1>] = +-- { +-- <layer_id1> = <layer_conf1>, +-- <layer_id2> = <layer_conf2>, +-- <layer_id3> = <layer_conf3>, +-- ... +-- }, +-- [<layer_typename2>] = +-- { +-- ... +-- }, +-- ... +-- } +-- To be short, the specification is a table containing pairs of a layer type +-- name string (such as `"nerv.AffineLayer"`) and a table which maps layer +-- identifiers to `layer_conf`. For `layer_conf`, see `nerv.Layer.__init` and +-- the `__init` doc for an individual layer type. +-- +-- Here is an example: +-- +-- { +-- ["nerv.AffineLayer"] = +-- { +-- affine0 = {dim_in = {429}, dim_out = {2048}, +-- params = {ltp = "affine0_ltp", bp = "affine0_bp"}}, +-- affine1 = {dim_in = {2048}, dim_out = {2048}, +-- params = {ltp = "affine1_ltp", bp = "affine1_bp"}}, +-- affine2 = {dim_in = {2048}, dim_out = {2048}, +-- params = {ltp = "affine2_ltp", bp = "affine2_bp"}}, +-- affine3 = {dim_in = {2048}, dim_out = {2048}, +-- params = {ltp = "affine3_ltp", bp = "affine3_bp"}}, +-- affine4 = {dim_in = {2048}, dim_out = {2048}, +-- params = {ltp = "affine4_ltp", bp = "affine4_bp"}}, +-- affine5 = {dim_in = {2048}, dim_out = {2048}, +-- params = {ltp = "affine5_ltp", bp = "affine5_bp"}}, +-- affine6 = {dim_in = {2048}, dim_out = {2048}, +-- params = {ltp = "affine6_ltp", bp = "affine6_bp"}}, +-- affine7 = {dim_in = {2048}, dim_out = {3001}, +-- params = {ltp = "affine7_ltp", bp = "affine7_bp"}} +-- }, +-- ["nerv.SigmoidLayer"] = +-- { +-- sigmoid0 = {dim_in = {2048}, dim_out = {2048}}, +-- sigmoid1 = {dim_in = {2048}, dim_out = {2048}}, +-- sigmoid2 = {dim_in = {2048}, dim_out = {2048}}, +-- sigmoid3 = {dim_in = {2048}, dim_out = {2048}}, +-- sigmoid4 = {dim_in = {2048}, dim_out = {2048}}, +-- sigmoid5 = {dim_in = {2048}, dim_out = {2048}}, +-- sigmoid6 = {dim_in = {2048}, dim_out = {2048}} +-- }, +-- ["nerv.SoftmaxCELayer"] = -- softmax + ce criterion layer for finetune output +-- { +-- ce_crit = {dim_in = {3001, 1}, dim_out = {1}, compressed = true} +-- }, +-- ["nerv.SoftmaxLayer"] = -- softmax for decode output +-- { +-- softmax = {dim_in = {3001}, dim_out = {3001}} +-- } +-- } +-- @param param_repo the default parameter repo to be used for binding parameters, if one layer +-- does not specify `pr` in its layer config `layer_conf` +-- @param global_conf a table describing the computation state and providing +-- with some global settings + function LayerRepo:__init(layer_spec, param_repo, global_conf) self.layers = {} self:add_layers(layer_spec, param_repo, global_conf) end +--- Add more layers to the collection (repo). +-- @param layer_spec the *layer specification*, a declarative way of creating layers in the collection. +-- @param param_repo the default parameter repo to be used for binding parameters, if one layer +-- does not specify `pr` in its layer config `layer_conf` +-- @param global_conf a table describing the computation state and providing +-- with some global settings +-- +-- Here is an example for adding graph layers based on the previous example: +-- layer_repo:add_layers( +-- { +-- ["nerv.GraphLayer"] = +-- { +-- global_transf = { +-- dim_in = {429}, dim_out = {429}, +-- layer_repo = layer_repo, +-- connections = { +-- {"<input>[1]", "blayer1[1]", 0}, +-- {"blayer1[1]", "wlayer1[1]", 0}, +-- {"wlayer1[1]", "blayer2[1]", 0}, +-- {"blayer2[1]", "wlayer2[1]", 0}, +-- {"wlayer2[1]", "<output>[1]", 0} +-- } +-- }, +-- main = { +-- dim_in = {429}, dim_out = {3001}, +-- layer_repo = layer_repo, +-- connections = { +-- {"<input>[1]", "affine0[1]", 0}, +-- {"affine0[1]", "sigmoid0[1]", 0}, +-- {"sigmoid0[1]", "affine1[1]", 0}, +-- {"affine1[1]", "sigmoid1[1]", 0}, +-- {"sigmoid1[1]", "affine2[1]", 0}, +-- {"affine2[1]", "sigmoid2[1]", 0}, +-- {"sigmoid2[1]", "affine3[1]", 0}, +-- {"affine3[1]", "sigmoid3[1]", 0}, +-- {"sigmoid3[1]", "affine4[1]", 0}, +-- {"affine4[1]", "sigmoid4[1]", 0}, +-- {"sigmoid4[1]", "affine5[1]", 0}, +-- {"affine5[1]", "sigmoid5[1]", 0}, +-- {"sigmoid5[1]", "affine6[1]", 0}, +-- {"affine6[1]", "sigmoid6[1]", 0}, +-- {"sigmoid6[1]", "affine7[1]", 0}, +-- {"affine7[1]", "<output>[1]", 0} +-- } +-- } +-- } +-- }, param_repo, gconf) +-- +-- To fully understand the example, please check the doc for `nerv.GraphLayer`, +-- and notice that `layer_repo` itself is passed to the graph layer config because +-- primitive layers such as `"affine0"` have been created by the layer +-- specification during the construction (see the example in `__init`). + function LayerRepo:add_layers(layer_spec, param_repo, global_conf) local layers = self.layers for ltype, llist in pairs(layer_spec) do @@ -28,6 +154,9 @@ function LayerRepo:add_layers(layer_spec, param_repo, global_conf) end end +--- Rebind the parameters. +-- @param param_repo the new parameter repo used for parameter rebinding + function LayerRepo:rebind(param_repo) if self.__rebinding then return @@ -46,6 +175,8 @@ function LayerRepo:rebind(param_repo) self.__rebinding = false end +--- Get a layer from the collection (repo) by its identifier. +-- @param lid the layer id function LayerRepo:get_layer(lid) local layer = self.layers[lid] if layer == nil then |