aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules7
-rw-r--r--Makefile47
m---------Penlight0
-rw-r--r--README.md55
-rw-r--r--README.rst64
-rw-r--r--lua/config.lua67
-rw-r--r--lua/main.lua45
-rw-r--r--lua/network.lua113
-rw-r--r--lua/reader.lua113
-rw-r--r--lua/select_linear.lua62
-rw-r--r--lua/timer.lua33
-rw-r--r--lua/tnn.lua136
-rw-r--r--nerv/Makefile22
-rw-r--r--nerv/doc/nerv.md6
-rw-r--r--nerv/doc/nerv_class.md8
-rw-r--r--nerv/doc/nerv_io.md13
-rw-r--r--nerv/doc/nerv_layer.md13
-rw-r--r--nerv/doc/nerv_matrix.md20
-rw-r--r--nerv/doc/nerv_nn.md43
-rw-r--r--nerv/doc/nerv_param.md10
-rw-r--r--nerv/examples/asr_trainer.lua256
-rw-r--r--nerv/examples/swb_baseline.lua84
-rw-r--r--nerv/examples/swb_baseline2.lua203
-rw-r--r--nerv/examples/swb_baseline_basic.lua162
-rw-r--r--nerv/examples/timit_baseline2.lua212
-rw-r--r--nerv/init.lua229
-rw-r--r--nerv/io/sgd_buffer.lua7
-rw-r--r--nerv/layer/affine.lua43
-rw-r--r--nerv/layer/bias.lua15
-rw-r--r--nerv/layer/combiner.lua16
-rw-r--r--nerv/layer/dropout.lua16
-rw-r--r--nerv/layer/duplicate.lua7
-rw-r--r--nerv/layer/elem_mul.lua11
-rw-r--r--nerv/layer/graph.lua7
-rw-r--r--nerv/layer/gru.lua20
-rw-r--r--nerv/layer/identity.lua7
-rw-r--r--nerv/layer/init.lua60
-rw-r--r--nerv/layer/lstm.lua20
-rw-r--r--nerv/layer/lstm_gate.lua17
-rw-r--r--nerv/layer/mse.lua16
-rw-r--r--nerv/layer/rnn.lua7
-rw-r--r--nerv/layer/sigmoid.lua11
-rw-r--r--nerv/layer/softmax.lua11
-rw-r--r--nerv/layer/softmax_ce.lua16
-rw-r--r--nerv/layer/tanh.lua11
-rw-r--r--nerv/layer/window.lua15
-rw-r--r--nerv/lib/cblas.h596
-rw-r--r--nerv/lib/matrix/cumatrix.c52
-rw-r--r--nerv/lib/matrix/cumatrix.h3
-rw-r--r--nerv/lib/matrix/generic/mmatrix.c2
-rw-r--r--nerv/matrix/cumatrix.c5
-rw-r--r--nerv/matrix/generic/mmatrix.c2
-rw-r--r--nerv/matrix/init.lua21
-rw-r--r--nerv/nerv46
-rw-r--r--nerv/nerv-scm-1.rockspec3
-rw-r--r--nerv/nn/layer_dag.lua16
-rw-r--r--nerv/nn/layer_repo.lua28
-rw-r--r--nerv/nn/param_repo.lua59
-rw-r--r--nerv/test/parse_args.lua15
59 files changed, 2008 insertions, 1196 deletions
diff --git a/.gitmodules b/.gitmodules
index 9f556c5..2b346c4 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,9 @@
[submodule "luajit-2.0"]
path = luajit-2.0
- url = http://luajit.org/git/luajit-2.0.git
+ url = https://speechlab.sjtu.edu.cn/gitlab/nerv-dev/luajit.git
[submodule "luarocks"]
path = luarocks
- url = https://github.com/keplerproject/luarocks.git
+ url = https://speechlab.sjtu.edu.cn/gitlab/nerv-dev/luarocks.git
+[submodule "Penlight"]
+ path = Penlight
+ url = https://speechlab.sjtu.edu.cn/gitlab/nerv-dev/Penlight.git
diff --git a/Makefile b/Makefile
index 0982295..28012da 100644
--- a/Makefile
+++ b/Makefile
@@ -1,19 +1,42 @@
.PHONY: all clean install luajit luarocks speech
+############## EDIT THESE LINES #####################
SHELL := /bin/bash
PREFIX := $(CURDIR)/install/
-all: luajit luarocks install
+#CUDA_BASE := /usr/local/cuda-7.0
+CUDA_BASE := /usr/local/cuda
+BLAS_BASE := /usr/lib/
+BLAS_LDFLAGS := -L$(BLAS_BASE) -Wl,-rpath=$(BLAS_BASE)
+BLAS_TYPE := atlas
+KALDI_BASE := /speechlab/tools/KALDI/kaldi-master/
+#######################################################
+MKL_LDFLAGS := -lmkl_rt
+ATLAS_LDFLAGS := -lcblas -llapack_atlas
+ifeq ($(BLAS_TYPE), mkl)
+BLAS_LDFLAGS += $(MKL_LDFLAGS)
+else ifeq ($(BLAS_TYPE), atlas)
+BLAS_LDFLAGS += $(ATLAS_LDFLAGS)
+else
+$(error Invalid blas type)
+endif
+export CUDA_BASE
+export KALDI_BASE
+export BLAS_LDFLAGS
+
+.PHONY: nerv speech/speech_utils speech/htk_io speech/kaldi_io speech/kaldi_decode \
+ nerv-clean speech/speech_utils-clean speech/htk_io-clean speech/kaldi_io-clean speech/kaldi_decode-clean \
+ Penlight
+
+all: luajit luarocks Penlight nerv
luajit:
PREFIX=$(PREFIX) ./tools/build_luajit.sh
luarocks:
PREFIX=$(PREFIX) ./tools/build_luarocks.sh
-install:
- cd nerv; $(PREFIX)/bin/luarocks make CFLAGS=$(CFLAGS)
-speech:
- cd speech/speech_utils; $(PREFIX)/bin/luarocks make
- cd speech/htk_io; $(PREFIX)/bin/luarocks make
- cd speech/kaldi_io; $(PREFIX)/bin/luarocks make
-clean:
- cd nerv && make clean
- cd speech/speech_utils && make clean
- cd speech/htk_io && make clean
- cd speech/kaldi_io && make clean
+
+speech: speech/speech_utils speech/htk_io speech/kaldi_io speech/kaldi_decode
+speech-clean: speech/speech_utils-clean speech/htk_io-clean speech/kaldi_io-clean speech/kaldi_decode-clean
+clean: nerv-clean speech-clean
+
+nerv Penlight speech/speech_utils speech/htk_io speech/kaldi_io speech/kaldi_decode:
+ cd $@; $(PREFIX)/bin/luarocks make
+nerv-clean speech/speech_utils-clean speech/htk_io-clean speech/kaldi_io-clean speech/kaldi_decode-clean:
+ cd $(subst -clean,,$@); make clean LUA_BINDIR=$(PREFIX)/bin/
diff --git a/Penlight b/Penlight
new file mode 160000
+Subproject 16d149338af9efc910528641c5240c5641aeb8d
diff --git a/README.md b/README.md
deleted file mode 100644
index fe9dfc1..0000000
--- a/README.md
+++ /dev/null
@@ -1,55 +0,0 @@
-#The Nerv Toolkit User Manual#
-NOTE: This readme is obsolete and will be rearranged, for further information, please check http://nerv-sjtu.github.io/nerv/
-
-This user manual will information about how to use __Nerv__ and __Nerv__'s interface.
-
-##How to make and start using##
-First make sure you have __lua__ and __CUDA__ installed on your computer.
-__Nerv__ is currently developed via github.You can download and make __Nerv__ by doing the following:
-```
-cd ~
-git clone https://github.com/Nerv-SJTU/nerv.git
-cd nerv
-git submodule init && git submodule update
-make
-#To include some new CUDA feature(e.x. atomicCAS), use "make CFLAGS=-D__NERV_FUTURE_CUDA_7"
-
-#further, if you want the speech modules
-git clone https://github.com/Nerv-SJTU/nerv-speech.git speech
-make speech
-```
-The `git submodule` command is for the __luajit__ repository inside __Nerv__.
-Now, you can try to run some example scripts.
-```
-./install/bin/nerv examples/cumatrix_example.lua
-```
-To get an example of DNN(for ASR) training, run(this requires the speech modules)
-You need to be at or (copy files from) `/slfs1`(SJTU speechlab cluster) to get this running.
-```
-./install/bin/nerv nerv/examples/asr_trainer.lua nerv/examples/swb_baseline.lua
-```
-
-##How to contribute##
-Fork the original repository, then use the __pull&merge__ function in github to contribute.
-The pull&merge request can be found on your dashboard in github. See this [sync-help] to sync with the original repository.
-
-##Nerv Packages##
-* __luaT__
-Nerv uses [luaT]\(a [Torch] library\) to define lua class in C.
-* __[The Nerv OOP](nerv/doc/nerv_class.md)__
-Enables object-oriented programming in Nerv.
-* __[The Nerv utility functions](nerv/doc/nerv.md)__
-Inlcudes some utility functions from luaT to implement __Nerv.Class__.
-* __[The Nerv Matrix Package](nerv/doc/nerv_matrix.md)__
-The matrix package is a basic package in __Nerv__ that is used to store and manipulate matrices.
-* __[The Nerv IO Package](nerv/doc/nerv_io.md)__
-The IO package is used to read and write parameters to file.
-* __[The Nerv Parameter Package](nerv/doc/nerv_param.md)__
-The parameter package is used to store, read model parameters from file.
-* __[The Nerv Layer Package](nerv/doc/nerv_layer.md)__
-The layer package is used to define propagation and backpropagation of different type of layers.
-* __[The Nerv NN Package](nerv/doc/nerv_nn.md)__
-The nn package is for organizing a neural network, it contains __nerv.LayerRepo__, __nerv.ParamRepo__, and __nerv.DAGLayer__.
-[luaT]:https://github.com/torch/torch7/tree/master/lib/luaT
-[Torch]:https://github.com/torch
-[sync-help]:https://help.github.com/articles/syncing-a-fork/
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..c00743c
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,64 @@
+NERV Toolkit
+============
+
+NOTE: This readme is in-progress.
+
+Installation
+------------
+First, make sure you have at least one implementation of BLAS and CUDA installed
+on your computer.
+
+- Checkout NERV:
+
+ ::
+
+ bash
+ git clone https://speechlab.sjtu.edu.cn/gitlab/nerv-dev/nerv.git
+
+- Checkout submodules (luajit, luarocks, Penlight, etc.):
+
+ ::
+
+ cd nerv
+ git submodule init && git submodule update
+
+- Build NERV: you can specify either ``mkl`` or ``atlas`` to ``BLAS_TYPE``.
+ ``BLAS_BASE`` is the directory containing BLAS ``.so`` files. By default,
+ ``atlas`` is used for ``BLAS_TYPE``, ``/usr/lib/`` is used for ``BLAS_BASE``,
+ and ``/usr/local/cuda`` is used for ``CUDA_BASE``.
+
+ ::
+
+ # an example for compiling on SJTU Speechlab major cluster
+ make BLAS_TYPE=mkl BLAS_BASE=/home/intel/mkl/lib/intel64/ CUDA_BASE=/usr/local/cuda
+
+- To include some new features (e.g. ``atomicCAS`` in CUDA), add corresponding flags to
+ ``NERV_FEAT`` (e.g. ``NERV_FEAT=-D__NERV_FUTURE_CUDA_7``) while making:
+
+ ::
+
+ make NERV_FEAT=-D__NERV_FUTURE_CUDA_7 BLAS_TYPE=mkl BLAS_BASE=/home/intel/mkl/lib/intel64/ CUDA_BASE=/usr/local/cuda
+
+- For speech tasks, you need to install related lua rocks (Lua packages):
+
+ ::
+
+ # checkout speech repository to local directory nerv/speech (suppose you're
+ # still at the root directory of NERV repo)
+ git clone https://speechlab.sjtu.edu.cn/gitlab/nerv-dev/nerv-speech.git speech
+ # build and install HTK I/O support, Kaldi I/O support, Kaldi decoding support, etc.
+ make speech BLAS_TYPE=mkl BLAS_BASE=/home/intel/mkl/lib/intel64/
+
+Example & Tutorial
+------------------
+For speech tasks, please refer to ``tutorial/`` in ``nerv-speech`` repository.
+
+Contribution
+------------
+The basic rule is simple: just fork the original repository, then create a pull
+request (merge request) to the administrator of the project. If you want to fix
+any bugs in existing code, don't hesitate to create a pull (merge) request to
+the repository with clear and detailed analysis of the problem. If you want to
+add additional task-specific functionalities (modules) for speech to NERV,
+please create a luarocks-compliant package and also a pull (merge) request to
+the ``nerv-speech`` repository instead of ``nerv``.
diff --git a/lua/config.lua b/lua/config.lua
deleted file mode 100644
index 1ec1198..0000000
--- a/lua/config.lua
+++ /dev/null
@@ -1,67 +0,0 @@
-function get_global_conf()
- local global_conf = {
- lrate = 0.15,
- wcost = 1e-5,
- momentum = 0,
- clip = 5,
- cumat_type = nerv.CuMatrixFloat,
- mmat_type = nerv.MMatrixFloat,
- vocab_size = 10000,
- nn_act_default = 0,
- hidden_size = 300,
- layer_num = 1,
- chunk_size = 15,
- batch_size = 20,
- max_iter = 3,
- param_random = function() return (math.random() / 5 - 0.1) end,
- dropout = 0.5,
- timer = nerv.Timer(),
- pr = nerv.ParamRepo(),
- }
- return global_conf
-end
-
-function get_layers(global_conf)
- local pr = global_conf.pr
- local layers = {
- ['nerv.LSTMLayer'] = {},
- ['nerv.DropoutLayer'] = {},
- ['nerv.SelectLinearLayer'] = {
- ['select'] = {dim_in = {1}, dim_out = {global_conf.hidden_size}, vocab = global_conf.vocab_size, pr = pr},
- },
- ['nerv.CombinerLayer'] = {},
- ['nerv.AffineLayer'] = {
- output = {dim_in = {global_conf.hidden_size}, dim_out = {global_conf.vocab_size}, pr = pr}
- },
- ['nerv.SoftmaxCELayer'] = {
- softmax = {dim_in = {global_conf.vocab_size, global_conf.vocab_size}, dim_out = {1}, compressed = true},
- },
- }
- for i = 1, global_conf.layer_num do
- layers['nerv.LSTMLayer']['lstm' .. i] = {dim_in = {global_conf.hidden_size, global_conf.hidden_size, global_conf.hidden_size}, dim_out = {global_conf.hidden_size, global_conf.hidden_size}, pr = pr}
- layers['nerv.DropoutLayer']['dropout' .. i] = {dim_in = {global_conf.hidden_size}, dim_out = {global_conf.hidden_size}}
- layers['nerv.CombinerLayer']['dup' .. i] = {dim_in = {global_conf.hidden_size}, dim_out = {global_conf.hidden_size, global_conf.hidden_size}, lambda = {1}}
- end
- return layers
-end
-
-function get_connections(global_conf)
- local connections = {
- {'<input>[1]', 'select[1]', 0},
- {'select[1]', 'lstm1[1]', 0},
- {'dropout' .. global_conf.layer_num .. '[1]', 'output[1]', 0},
- {'output[1]', 'softmax[1]', 0},
- {'<input>[2]', 'softmax[2]', 0},
- {'softmax[1]', '<output>[1]', 0},
- }
- for i = 1, global_conf.layer_num do
- table.insert(connections, {'lstm' .. i .. '[1]', 'dup' .. i .. '[1]', 0})
- table.insert(connections, {'lstm' .. i .. '[2]', 'lstm' .. i .. '[3]', 1})
- table.insert(connections, {'dup' .. i .. '[1]', 'lstm' .. i .. '[2]', 1})
- table.insert(connections, {'dup' .. i .. '[2]', 'dropout' .. i .. '[1]', 0})
- if i > 1 then
- table.insert(connections, {'dropout' .. (i - 1) .. '[1]', 'lstm' .. i .. '[1]', 0})
- end
- end
- return connections
-end
diff --git a/lua/main.lua b/lua/main.lua
deleted file mode 100644
index ce0270a..0000000
--- a/lua/main.lua
+++ /dev/null
@@ -1,45 +0,0 @@
-nerv.include('reader.lua')
-nerv.include('timer.lua')
-nerv.include('config.lua')
-nerv.include(arg[1])
-
-local global_conf = get_global_conf()
-local timer = global_conf.timer
-
-timer:tic('IO')
-
-local data_path = 'nerv/nerv/examples/lmptb/PTBdata/'
-local train_reader = nerv.Reader(data_path .. 'vocab', data_path .. 'ptb.valid.txt.adds')
-local val_reader = nerv.Reader(data_path .. 'vocab', data_path .. 'ptb.valid.txt.adds')
-
-local train_data = train_reader:get_all_batch(global_conf)
-local val_data = val_reader:get_all_batch(global_conf)
-
-local layers = get_layers(global_conf)
-local connections = get_connections(global_conf)
-
-local NN = nerv.NN(global_conf, train_data, val_data, layers, connections)
-
-timer:toc('IO')
-timer:check('IO')
-io.flush()
-
-timer:tic('global')
-local best_cv = 1e10
-for i = 1, global_conf.max_iter do
- timer:tic('Epoch' .. i)
- local train_ppl, val_ppl = NN:epoch()
- if val_ppl < best_cv then
- best_cv = val_ppl
- else
- global_conf.lrate = global_conf.lrate / 2.0
- end
- nerv.printf('Epoch %d: %f %f %f\n', i, global_conf.lrate, train_ppl, val_ppl)
- timer:toc('Epoch' .. i)
- timer:check('Epoch' .. i)
- io.flush()
-end
-timer:toc('global')
-timer:check('global')
-timer:check('network')
-timer:check('gc')
diff --git a/lua/network.lua b/lua/network.lua
deleted file mode 100644
index 0c11321..0000000
--- a/lua/network.lua
+++ /dev/null
@@ -1,113 +0,0 @@
-nerv.include('select_linear.lua')
-
-local nn = nerv.class('nerv.NN')
-
-function nn:__init(global_conf, train_data, val_data, layers, connections)
- self.gconf = global_conf
- self.network = self:get_network(layers, connections)
- self.train_data = self:get_data(train_data)
- self.val_data = self:get_data(val_data)
-end
-
-function nn:get_network(layers, connections)
- self.gconf.dropout_rate = 0
- local layer_repo = nerv.LayerRepo(layers, self.gconf.pr, self.gconf)
- local graph = nerv.GraphLayer('graph', self.gconf,
- {dim_in = {1, self.gconf.vocab_size}, dim_out = {1},
- layer_repo = layer_repo, connections = connections})
- local network = nerv.Network('network', self.gconf,
- {network = graph, clip = self.gconf.clip})
- network:init(self.gconf.batch_size, self.gconf.chunk_size)
- return network
-end
-
-function nn:get_data(data)
- local err_output = {}
- local softmax_output = {}
- local output = {}
- for i = 1, self.gconf.chunk_size do
- err_output[i] = self.gconf.cumat_type(self.gconf.batch_size, 1)
- softmax_output[i] = self.gconf.cumat_type(self.gconf.batch_size, self.gconf.vocab_size)
- output[i] = self.gconf.cumat_type(self.gconf.batch_size, 1)
- end
- local ret = {}
- for i = 1, #data do
- ret[i] = {}
- ret[i].input = {}
- ret[i].output = {}
- ret[i].err_input = {}
- ret[i].err_output = {}
- for t = 1, self.gconf.chunk_size do
- ret[i].input[t] = {}
- ret[i].output[t] = {}
- ret[i].err_input[t] = {}
- ret[i].err_output[t] = {}
- ret[i].input[t][1] = data[i].input[t]
- ret[i].input[t][2] = data[i].output[t]
- ret[i].output[t][1] = output[t]
- local err_input = self.gconf.mmat_type(self.gconf.batch_size, 1)
- for j = 1, self.gconf.batch_size do
- if t <= data[i].seq_len[j] then
- err_input[j - 1][0] = 1
- else
- err_input[j - 1][0] = 0
- end
- end
- ret[i].err_input[t][1] = self.gconf.cumat_type.new_from_host(err_input)
- ret[i].err_output[t][1] = err_output[t]
- ret[i].err_output[t][2] = softmax_output[t]
- end
- ret[i].seq_length = data[i].seq_len
- ret[i].new_seq = {}
- for j = 1, self.gconf.batch_size do
- if data[i].seq_start[j] then
- table.insert(ret[i].new_seq, j)
- end
- end
- end
- return ret
-end
-
-function nn:process(data, do_train)
- local timer = self.gconf.timer
- local total_err = 0
- local total_frame = 0
- for id = 1, #data do
- if do_train then
- self.gconf.dropout_rate = self.gconf.dropout
- data[id].do_train = true
- else
- self.gconf.dropout_rate = 0
- data[id].do_train = false
- end
- timer:tic('network')
- self.network:mini_batch_init(data[id])
- self.network:propagate()
- timer:toc('network')
- for t = 1, self.gconf.chunk_size do
- local tmp = data[id].output[t][1]:new_to_host()
- for i = 1, self.gconf.batch_size do
- if t <= data[id].seq_length[i] then
- total_err = total_err + math.log10(math.exp(tmp[i - 1][0]))
- total_frame = total_frame + 1
- end
- end
- end
- if do_train then
- timer:tic('network')
- self.network:back_propagate()
- self.network:update()
- timer:toc('network')
- end
- timer:tic('gc')
- collectgarbage('collect')
- timer:toc('gc')
- end
- return math.pow(10, - total_err / total_frame)
-end
-
-function nn:epoch()
- local train_error = self:process(self.train_data, true)
- local val_error = self:process(self.val_data, false)
- return train_error, val_error
-end
diff --git a/lua/reader.lua b/lua/reader.lua
deleted file mode 100644
index 0c7bcb6..0000000
--- a/lua/reader.lua
+++ /dev/null
@@ -1,113 +0,0 @@
-local Reader = nerv.class('nerv.Reader')
-
-function Reader:__init(vocab_file, input_file)
- self:get_vocab(vocab_file)
- self:get_seq(input_file)
-end
-
-function Reader:get_vocab(vocab_file)
- local f = io.open(vocab_file, 'r')
- local id = 0
- self.vocab = {}
- while true do
- local word = f:read()
- if word == nil then
- break
- end
- self.vocab[word] = id
- id = id + 1
- end
- self.size = id
-end
-
-function Reader:split(s, t)
- local ret = {}
- for x in (s .. t):gmatch('(.-)' .. t) do
- table.insert(ret, x)
- end
- return ret
-end
-
-function Reader:get_seq(input_file)
- local f = io.open(input_file, 'r')
- self.seq = {}
- while true do
- local seq = f:read()
- if seq == nil then
- break
- end
- seq = self:split(seq, ' ')
- local tmp = {}
- for i = 1, #seq do
- if seq[i] ~= '' then
- table.insert(tmp, self.vocab[seq[i]])
- end
- end
- table.insert(self.seq, tmp)
- end
-end
-
-function Reader:get_in_out(id, pos)
- return self.seq[id][pos], self.seq[id][pos + 1], pos + 1 == #self.seq[id]
-end
-
-function Reader:get_all_batch(global_conf)
- local data = {}
- local pos = {}
- local offset = 1
- for i = 1, global_conf.batch_size do
- pos[i] = nil
- end
- --while true do
- for i = 1, 100 do
- local input = {}
- local output = {}
- for i = 1, global_conf.chunk_size do
- input[i] = global_conf.mmat_type(global_conf.batch_size, 1)
- input[i]:fill(global_conf.nn_act_default)
- output[i] = global_conf.mmat_type(global_conf.batch_size, 1)
- output[i]:fill(global_conf.nn_act_default)
- end
- local seq_start = {}
- local seq_end = {}
- local seq_len = {}
- for i = 1, global_conf.batch_size do
- seq_start[i] = false
- seq_end[i] = false
- seq_len[i] = 0
- end
- local has_new = false
- for i = 1, global_conf.batch_size do
- if pos[i] == nil then
- if offset < #self.seq then</