├── .gitignore ├── .gitmodules ├── DATA_FORMAT.md ├── LICENSE ├── MODEL_CONFIG.md ├── Makefile ├── Makefile.config.example ├── README.md ├── python ├── AnaDocLenPlot.py ├── client.py ├── draw_net.py ├── gen_word_embed_ind.sh ├── get_cross.py ├── get_fc2.py ├── get_kernel.py ├── get_kernel_next.py ├── grid_search.py ├── log2graph.py ├── log2graph_png.py └── measure_list.py ├── script ├── aaai_match_arci_qa.py ├── aaai_match_arci_qa_rank.py ├── aaai_match_arcii_qa.py ├── aaai_match_arcii_qa_rank.py ├── aaai_match_bilstm_mlp_qa_rank.py ├── aaai_match_bilstm_sim_dpool_msrp.py ├── aaai_match_bilstm_sim_dpool_qa_rank.py ├── aaai_match_bilstm_tensor_dpool_msrp.py ├── aaai_match_bilstm_tensor_dpool_qa_rank.py ├── aaai_match_ctnn_qa_rank.py ├── aaai_match_multigran_cnn_tensor_dpool_qa.py ├── aaai_match_multigran_cnn_tensor_dpool_qa_rank.py ├── analyse.py ├── bilstm.gate.py ├── bilstm.py ├── bilstm.test_crossentropy.py ├── cnn.py ├── cnn_lstm.py ├── conv_bilstm.py ├── conv_bilstm_share.py ├── conv_birnn.py ├── dataset_cfg.py ├── dnn_for_test.py ├── gate_cnn.py ├── gate_multi_window_cnn.py ├── gate_originword_cnn.py ├── gen_conf_file.py ├── gen_cv_file.py ├── ijcai_lcs_toy.py ├── ijcai_match_lstmd2_bilstm_tensor_dpool_paper.py ├── ijcai_match_lstmd2_bilstm_tensor_dpool_qa.py ├── ijcai_match_lstmd2_sim_dpool_msrp.py ├── ijcai_match_lstmd2_tensor_dpool_paper.py ├── ijcai_match_lstmd2_tensor_dpool_qa_rank.py ├── ijcai_match_lstmd2_tensor_gatedpool_qa.py ├── ijcai_match_lstmd2_tensor_lastpool_qa_rank.py ├── lm_bilstm_neg.py ├── lm_lstm_autoencoder.py ├── lstm.gate.py ├── lstm.py ├── match_bilstm_bilinear.py ├── match_bilstm_mlp.py ├── match_bilstm_sim.py ├── match_bilstm_sim_dpool.py ├── match_birnn_mlp.py ├── match_conv_bilstm.py ├── match_lstm_mlp.py ├── match_sim_agg.py ├── match_xor_mlp.py ├── max_rnn.py ├── multi_window_cnn.py ├── nb.py ├── nbp_lstm.py ├── parse_log.py ├── rnn.py ├── run_job.py ├── test_save_model.py └── visualize.py ├── simple.png ├── src ├── checker │ ├── checker.h │ ├── checker_impl-inl.hpp │ ├── checker_impl.cpp │ └── checker_impl.cu ├── global.h ├── grad_check.cpp ├── initializer │ ├── constant_init-inl.hpp │ ├── file_init-inl.hpp │ ├── gaussian_init-inl.hpp │ ├── initializer.h │ ├── initializer_impl-inl.hpp │ ├── initializer_impl.cpp │ ├── initializer_impl.cu │ ├── row_gaussian_init-inl.hpp │ ├── uniform_init-inl.hpp │ ├── uniform_range_init-inl.hpp │ ├── unitball_init-inl.hpp │ └── var_init-inl.hpp ├── io │ ├── json │ │ ├── json-forwards.h │ │ └── json.h │ └── jsoncpp.cpp ├── layer │ ├── common │ │ ├── activation_layer-inl.hpp │ │ ├── append_feature_layer-inl.hpp │ │ ├── augmentation_layer-inl.hpp │ │ ├── axis_split_layer-inl.hpp │ │ ├── batch_combine_layer-inl.hpp │ │ ├── batch_concat_layer-inl.hpp │ │ ├── batch_duplicate_layer-inl.hpp │ │ ├── batch_max_layer-inl.hpp │ │ ├── batch_norm_layer-inl.hpp │ │ ├── batch_select_layer-inl.hpp │ │ ├── batch_split_layer-inl.hpp │ │ ├── bgru_d2_layer-inl.hpp │ │ ├── blstm_layer-inl.hpp │ │ ├── channel_duplicate_layer-inl.hpp │ │ ├── concat_layer-inl.hpp │ │ ├── conv_lstm_split_layer-inl.hpp │ │ ├── conv_result_transform_layer-inl.hpp │ │ ├── convolution_layer-inl.hpp │ │ ├── convolution_param_layer-inl.hpp │ │ ├── convolution_var_layer-inl.hpp │ │ ├── convolutional_lstm_layer-inl.hpp │ │ ├── cross_layer-inl.hpp │ │ ├── diag_recurrent_layer-inl.hpp │ │ ├── dropout_layer-inl.hpp │ │ ├── duplicate4lstm_layer-inl.hpp │ │ ├── dynamic_k_max_pooling_layer-inl.hpp │ │ ├── dynamic_pooling_layer-inl.hpp │ │ ├── element_op_layer-inl.hpp │ │ ├── elu_layer-inl.hpp │ │ ├── embedding_layer-inl.hpp │ │ ├── feature_layer-inl.hpp │ │ ├── fill_curve_d2xy_layer-inl.hpp │ │ ├── fill_curve_xy2d_layer-inl.hpp │ │ ├── flatten_layer-inl.hpp │ │ ├── fullc_layer-inl.hpp │ │ ├── gate_alldim_layer-inl.hpp │ │ ├── gate_dynamic_pooling_d2_layer-inl.hpp │ │ ├── gate_layer-inl.hpp │ │ ├── gate_whole_pooling_d2_layer-inl.hpp │ │ ├── gate_whole_pooling_layer-inl.hpp │ │ ├── gating_layer-inl.hpp │ │ ├── gaussian_mask_layer-inl.hpp │ │ ├── gen_kernel_layer-inl.hpp │ │ ├── gru_d2_layer-inl.hpp │ │ ├── gru_d2_one_gate_layer-inl.hpp │ │ ├── gru_layer-inl.hpp │ │ ├── key_snip_layer-inl.hpp │ │ ├── length_fill_layer-inl.hpp │ │ ├── length_trans_layer-inl.hpp │ │ ├── letter_trigram_layer-inl.hpp │ │ ├── local_factor_layer-inl.hpp │ │ ├── local_layer-inl.hpp │ │ ├── lr2softmax_layer-inl.hpp │ │ ├── lstm_autoencoder_layer-inl.hpp │ │ ├── lstm_d2_layer-inl.hpp │ │ ├── lstm_d2_one_gate_optimize_layer-inl.hpp │ │ ├── lstm_d2_optimize_layer-inl.hpp │ │ ├── lstm_layer-inl.hpp │ │ ├── lstm_layer-inl.hpp.bak │ │ ├── lstm_peephole_layer-inl.hpp │ │ ├── lstm_skipconnect_layer-inl.hpp │ │ ├── match_combine_layer-inl.hpp │ │ ├── match_histogram_layer-inl.hpp │ │ ├── match_layer-inl.hpp │ │ ├── match_multi_layer-inl.hpp │ │ ├── match_tensor_fact_layer-inl.hpp │ │ ├── match_tensor_layer-inl.hpp │ │ ├── match_tensor_layer-inl.hpp.bak │ │ ├── match_topk_pooling_layer-inl.hpp │ │ ├── match_weighted_dot_layer-inl.hpp │ │ ├── match_weighted_radial_layer-inl.hpp │ │ ├── max_recurrent_layer-inl.hpp │ │ ├── memory_attention_in_layer-inl.hpp │ │ ├── memory_attention_out_layer-inl.hpp │ │ ├── merge_window_layer-inl.hpp │ │ ├── nbp_gen_lstm_input_layer-inl.hpp │ │ ├── one_hot_layer-inl.hpp │ │ ├── pad_layer-inl.hpp │ │ ├── parameter_layer-inl.hpp │ │ ├── phrase_ave_rep_layer-inl.hpp │ │ ├── pooling_layer-inl.hpp │ │ ├── pooling_var_layer-inl.hpp │ │ ├── pos_pred_rep_layer-inl.hpp │ │ ├── product_layer-inl.hpp │ │ ├── read_feature_layer-inl.hpp │ │ ├── recurrent_layer-inl.hpp │ │ ├── reshape_layer-inl.hpp │ │ ├── select_sub_rep_by_token_layer-inl.hpp │ │ ├── sequcence_dim_reduction_layer-inl.hpp │ │ ├── softmax_func_layer-inl.hpp │ │ ├── softmax_func_var_len_layer-inl.hpp │ │ ├── sort_axis_layer-inl.hpp │ │ ├── sort_axis_layer-inl.hpp.bak │ │ ├── split_layer-inl.hpp │ │ ├── sum_layer-inl.hpp │ │ ├── swap_axis_layer-inl.hpp │ │ ├── tensor_fullc_layer-inl.hpp │ │ ├── topk_pooling_layer-inl.hpp │ │ ├── whole_pooling_2d_layer-inl.hpp │ │ ├── whole_pooling_layer-inl.hpp │ │ └── xelu_layer-inl.hpp │ ├── input │ │ ├── image_layer-inl.hpp │ │ ├── label_feat_value_layer-inl.hpp │ │ ├── lcs_toy_data_layer-inl.hpp │ │ ├── list_textdata_layer-inl.hpp │ │ ├── lm_input_layer-inl.hpp │ │ ├── lstm_autoencoder_input_layer-inl.hpp │ │ ├── map_2_textdata_layer-inl.hpp │ │ ├── map_2_window_textdata_layer-inl.hpp │ │ ├── map_3_textdata_layer-inl.hpp │ │ ├── map_textdata_layer-inl.hpp │ │ ├── match_phrase_rep_layer-inl.hpp │ │ ├── memory_global_layer-inl.hpp │ │ ├── negative_sample_layer-inl.hpp │ │ ├── next_basket_data_layer-inl.hpp │ │ ├── pair_textdata_layer-inl.hpp │ │ ├── qa_textdata_layer-inl.hpp │ │ ├── sequence_classification_data_layer-inl.hpp │ │ ├── textdata_layer-inl.hpp │ │ └── word_rep_input_layer-inl.hpp │ ├── layer.h │ ├── layer_impl-inl.hpp │ ├── layer_impl.cpp │ ├── layer_impl.cu │ ├── loss │ │ ├── accuracy_layer-inl.hpp │ │ ├── activation_norm_loss_layer-inl.hpp │ │ ├── char_lstm_w2v_loss_layer-inl.hpp │ │ ├── cross_entropy_loss_layer-inl.hpp │ │ ├── euclid_distance_loss_layer-inl.hpp │ │ ├── hingeloss_layer-inl.hpp │ │ ├── listhingeloss_layer-inl.hpp │ │ ├── listwise_measure_layer-inl.hpp │ │ ├── lm_softmax_loss_layer-inl.hpp │ │ ├── logistic_layer-inl.hpp │ │ ├── negative_sample_loss_layer-inl.hpp │ │ ├── pair_weighted_hinge_loss_layer-inl.hpp │ │ ├── pairhingeloss_layer-inl.hpp │ │ ├── softmax_layer-inl.hpp │ │ └── word_class_softmax_loss_layer-inl.hpp │ ├── node.h │ └── op.h ├── net │ ├── multi_train_valid_test_net-inl.hpp │ ├── net.h │ ├── net_impl-inl.hpp │ ├── net_impl.cpp │ ├── net_impl.cu │ ├── test_net-inl.hpp │ ├── train_valid_net-inl.hpp │ └── train_valid_test_net-inl.hpp ├── statistic │ ├── statistic.h │ ├── statistic_impl-inl.hpp │ ├── statistic_impl.cpp │ └── statistic_impl.cu ├── textnet_main.cpp ├── textnet_matching.cpp ├── textnet_multi.cpp ├── textnet_nextbasket.cpp ├── textnet_senti.cpp ├── textnet_test.cpp ├── textnet_testonly.cpp ├── updater │ ├── adadelta_updater-inl.hpp │ ├── adagrad_updater-inl.hpp │ ├── adam_updater-inl.hpp │ ├── sgd_updater-inl.hpp │ ├── sgdstep_updater-inl.hpp │ ├── updater.h │ ├── updater_impl-inl.hpp │ ├── updater_impl.cpp │ └── updater_impl.cu └── utils │ ├── config.h │ ├── decoder.h │ ├── io.h │ ├── metric.h │ ├── random.h │ ├── settingv.cpp │ ├── settingv.h │ ├── thread.h │ ├── thread_buffer.h │ ├── timer.h │ └── utils.h └── test_data ├── data1.wid ├── data2.wid ├── feature.dat ├── feature1.dat ├── rel.dat └── word_trigram.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.pyc 3 | Makefile.config 4 | Makefile 5 | bin/ 6 | data/ 7 | model/ 8 | result/ 9 | analyse/ 10 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "mshadow"] 2 | path = mshadow 3 | url = https://github.com/pl8787/mshadow.git 4 | -------------------------------------------------------------------------------- /DATA_FORMAT.md: -------------------------------------------------------------------------------- 1 | ### Dataset Format 2 | 3 | #### **Word Dictionary File** 4 | 5 | > *(eg. word_dict.txt)* 6 | 7 | We map each word to a uniqe number, called `wid`, and save this mapping in the word dictionary file. 8 | 9 | For example, 10 | 11 | ``` 12 | word wid 13 | machine 1232 14 | learning 1156 15 | ``` 16 | 17 | #### **Corpus File** 18 | 19 | > *(eg. qid_query.txt and docid_doc.txt)* 20 | 21 | We use a value of string identifier (`qid`/`docid`) to represent a sentence, such as a `query` or a `document`. The second number denotes the length of the sentence. The following numbers are the `wid`s of the sentence. 22 | 23 | For example, 24 | 25 | ``` 26 | docid sentence_length sentence_wid_sequence 27 | GX000-00-0000000 42 2744 1043 377 2744 1043 377 187 117961 ... 28 | ``` 29 | 30 | #### **Relation File** 31 | 32 | > *(eg. relation.train.fold1.txt, relation.test.fold1.txt ...)* 33 | 34 | The relation files are used to store the relation between two sentences, such as the relevance relation between `query` and `document`. 35 | 36 | For example, 37 | 38 | ``` 39 | relevance qid docid 40 | 1 3571 GX245-00-1220850 41 | 0 3571 GX004-51-0504917 42 | 0 3571 GX006-36-4612449 43 | ``` 44 | 45 | #### **Embedding File** 46 | 47 | > *(eg. embed_wiki-pdc_d50_norm)* 48 | 49 | We store the word embedding into the embedding file. 50 | 51 | For example, 52 | 53 | ``` 54 | wid embedding 55 | 13275 -0.050766 0.081548 -0.031107 0.131772 0.172194 ... 0.165506 0.002235 56 | ``` 57 | -------------------------------------------------------------------------------- /Makefile.config.example: -------------------------------------------------------------------------------- 1 | # To compile release version or debug version 2 | COMPILE_VERSION = release # debug 3 | 4 | # If set to 1, then use cpu only 5 | CPU_ONLY := 1 6 | 7 | # If set to 1, then compile realtime analyse server 8 | REALTIME_SERVER := 1 9 | 10 | # To customize your choice of compiler, uncomment and set the following. 11 | # N.B. the default for Linux is g++ and the default for OSX is clang++ 12 | CUSTOM_CXX := /home/pangliang/local/gcc-4.8.3/bin/g++ 13 | 14 | # CUDA directory contains bin/ and lib/ directories that we need. 15 | CUDA_DIR := /usr/local/cuda 16 | # On Ubuntu 14.04, if cuda tools are installed via 17 | # "sudo apt-get install nvidia-cuda-toolkit" then use this instead: 18 | # CUDA_DIR := /usr 19 | 20 | # CUDA architecture setting: going with all of them (up to CUDA 5.5 compatible). 21 | # For the latest architecture, you need to install CUDA >= 6.0 and uncomment 22 | # the *_50 lines below. 23 | CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \ 24 | -gencode arch=compute_20,code=sm_21 \ 25 | -gencode arch=compute_30,code=sm_30 \ 26 | -gencode arch=compute_35,code=sm_35 \ 27 | #-gencode arch=compute_50,code=sm_50 \ 28 | #-gencode arch=compute_50,code=compute_50 29 | 30 | # BLAS choice: 31 | # cblas for CBLAS (default) 32 | # mkl for MKL 33 | BLAS := mkl 34 | BLAS_INCLUDE := /home/pangliang/intel/mkl/include 35 | BLAS_LIB := /home/pangliang/intel/mkl/lib/intel64 /home/pangliang/intel/lib/intel64 36 | 37 | # ZeroMQ 38 | ZMQ_INCLUDE := /home/pangliang/dependence/zeromq/include 39 | ZMQ_LIB := /home/pangliang/dependence/zeromq/lib 40 | 41 | # This is required only if you will compile the matlab interface. 42 | # MATLAB directory should contain the mex binary in /bin. 43 | # MATLAB_DIR := /usr/local 44 | # MATLAB_DIR := /Applications/MATLAB_R2012b.app 45 | 46 | # NOTE: this is required only if you will compile the python interface. 47 | # We need to be able to find Python.h and numpy/arrayobject.h. 48 | # PYTHON_INCLUDE := /usr/include/python2.7 \ 49 | /usr/lib/python2.7/dist-packages/numpy/core/include 50 | # Anaconda Python distribution is quite popular. Include path: 51 | # PYTHON_INCLUDE := $(HOME)/anaconda/include \ 52 | # $(HOME)/anaconda/include/python2.7 \ 53 | # $(HOME)/anaconda/lib/python2.7/site-packages/numpy/core/include 54 | 55 | # We need to be able to find libpythonX.X.so or .dylib. 56 | # PYTHON_LIB := /usr/lib 57 | # PYTHON_LIB := $(HOME)/anaconda/lib 58 | 59 | # OpenCV Config 60 | # OPENCV_INCLUDE := /home/pangliang/dependence/opencv/include 61 | # OPENCV_LIB := /home/pangliang/dependence/opencv/lib 62 | 63 | # BOOST CONFIG 64 | # BOOST_INCLUDE := /home/pangliang/dependence/boost/include 65 | # BOOST_LIB := /home/pangliang/dependence/boost/lib 66 | 67 | # level db 68 | # LEVELDB_INCLUDE := /home/pangliang/dependence/leveldb/include 69 | # LEVELDB_LIB := /home/pangliang/dependence/leveldb 70 | 71 | # Whatever else you find you need goes here. 72 | INCLUDE_DIRS := $(BLAS_INCLUDE) $(ZMQ_INCLUDE) /usr/local/include 73 | LIBRARY_DIRS := $(BLAS_LIB) $(ZMQ_LIB) /usr/local/lib /usr/lib 74 | 75 | 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TextNet 2 | ====== 3 | 4 | TextNet is a deep neural netwrok framework for text matching tasks. 5 | 6 | * [Contributors](https://github.com/pl8787/textnet-release/graphs/contributors) 7 | 8 | Quick Start 9 | ===== 10 | 1. Make a copy of `Makefile.config.example`. 11 | 12 | ``` bash 13 | cp Makefile.config.example Makefile.config 14 | ``` 15 | 16 | 2. Setting the environment path in `Makefile.config`. 17 | 18 | 3. Compile it! 19 | 20 | ``` 21 | mkdir bin 22 | make all -j 16 23 | ``` 24 | 25 | 4. Wirte you own network config file in `json`. 26 | You can find examples in [Textnet Model](https://github.com/pl8787/textnet-model). 27 | 28 | 5. Run! 29 | ``` 30 | ./bin/textnet [model_file] 31 | ``` 32 | 33 | Features 34 | ===== 35 | 36 | * Construct Models: [MODEL_CONFIG](MODEL_CONFIG.md) 37 | * Data Format: [DATA_FORMAT](DATA_FORMAT.md) 38 | 39 | Dependences 40 | ===== 41 | * mshadow: [Matrix Shadow](https://github.com/dmlc/mshadow) 42 | * jsoncpp: [Json on CPP](https://github.com/open-source-parsers/jsoncpp) 43 | * ZeroMQ: [Zero Message Queue](http://zeromq.org/) [src](https://github.com/zeromq/libzmq) 44 | * d3: [Data-Driven Documents](http://d3js.org/) [For future features] 45 | 46 | Version 47 | ====== 48 | v1.0 49 | 50 | Related Projects 51 | ===== 52 | * cxxnet: [CXXNET](https://github.com/dmlc/cxxnet) 53 | * Caffe: [Caffe](https://github.com/BVLC/caffe) 54 | 55 | Acknowledgements 56 | ===== 57 | The following people contributed to the development of the TextNet project: 58 | 59 | - **Liang Pang** 60 | - Institute of Computing Technolgy, Chinese Academy of Sciences 61 | - [Google Scholar](https://scholar.google.com/citations?user=1dgQHBkAAAAJ&hl=en) 62 | - [HomePage](http://www.bigdatalab.ac.cn/~pangliang/) 63 | - **Shengxian Wan** 64 | - Institute of Computing Technolgy, Chinese Academy of Sciences 65 | - [Google Scholar](https://scholar.google.com/citations?user=ue3ca0AAAAAJ&hl=en) 66 | - **Yixing Fan** 67 | - Institute of Computing Technolgy, Chinese Academy of Sciences 68 | - [Google Scholar](https://scholar.google.com/citations?user=w5kGcUsAAAAJ&hl=en) 69 | - **Yanyan Lan** 70 | - Institute of Computing Technolgy, Chinese Academy of Sciences 71 | - [HomePage](http://www.bigdatalab.ac.cn/~lanyanyan/) 72 | - **Jiafeng Guo** 73 | - Institute of Computing Technolgy, Chinese Academy of Sciences 74 | - [HomePage](http://www.bigdatalab.ac.cn/~gjf/) 75 | - **Jun Xu** 76 | - Institute of Computing Technolgy, Chinese Academy of Sciences 77 | - [HomePage](http://www.bigdatalab.ac.cn/~junxu/) 78 | - **Xueqi Cheng** 79 | - Institute of Computing Technolgy, Chinese Academy of Sciences 80 | - [HomePage](http://www.bigdatalab.ac.cn/~cxq/) 81 | -------------------------------------------------------------------------------- /python/AnaDocLenPlot.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding = utf-8 -*- 3 | import os 4 | import sys 5 | import numpy as np 6 | import matplotlib 7 | matplotlib.use('Agg') 8 | import matplotlib.pyplot as plt 9 | 10 | def PlotTwoScatter(x1,x2,savefile): 11 | fig = plt.figure(figsize=(8,8),dpi=100) 12 | fig.text(0.85,0.85,"rel-doc",size=16,ha="center",va="center",color="#000000",weight="bold") 13 | fig.text(0.85,0.42,"ret-doc",size=16,ha="center",va="center",color="#000000",weight="bold") 14 | ax1 = plt.subplot(2,1,1) 15 | ax2 = plt.subplot(2,1,2) 16 | xk = x1.keys() 17 | xk.extend(x2.keys()) 18 | xmax = np.max(xk) 19 | print xmax 20 | ax1.set_xlim(1,xmax) 21 | ax2.set_xlim(1,xmax) 22 | ax1.set_xlabel('') 23 | ax2.set_xlabel('') 24 | sum1 = np.sum(x1.values()) 25 | sum2 = np.sum(x2.values()) 26 | ax1.scatter(x1.keys(),x1.values(),color='#ff7700',edgecolor='#333333',s=40,marker='D',label='rel-doc') 27 | ax2.scatter(x2.keys(),x2.values(),color='#00ff77',edgecolor='#333333',s=40,marker='D',label='ret-doc') 28 | plt.savefig(savefile,dpi=100) 29 | 30 | 31 | if __name__ == '__main__': 32 | ranklistfile = sys.argv[3] 33 | relfile = sys.argv[2] 34 | docinfofile = sys.argv[1] 35 | savefile = sys.argv[4] 36 | print 'doc-len file:',docinfofile 37 | print 'rel file:',relfile 38 | print 'ranklist file:',ranklistfile 39 | ret = {} # query: [doc] (top-20 docs id) 40 | with open(ranklistfile,'r') as f: 41 | for line in f: 42 | r = line.split() 43 | qid = r[0] 44 | did = r[2] 45 | rank = int(r[3]) 46 | if qid in ret and rank > 20: 47 | continue 48 | if qid not in ret: 49 | ret[qid] = [] 50 | ret[qid].append(did) 51 | rel = {} # query: [doc] (relevance doc id) 52 | with open(relfile,'r') as f: 53 | for line in f: 54 | r = line.split() 55 | qid = r[0] 56 | did = r[2] 57 | label = int(r[3]) 58 | if qid not in rel: 59 | rel[qid] = [] 60 | if label > 0: 61 | rel[qid].append(did) 62 | doclen = {} # doc-id : length 63 | with open(docinfofile,'r') as f: 64 | for line in f: 65 | r = line.split() 66 | did = r[0] 67 | len = int(r[1]) 68 | doclen[did] = len 69 | ret_len = [] 70 | rel_len = [] 71 | for qid,ds in ret.items(): 72 | for d in ds: 73 | ret_len.append(doclen[d]) 74 | for d in rel[qid]: 75 | if d in doclen: 76 | rel_len.append(doclen[d]) 77 | #print ret_len 78 | #print rel_len 79 | rel_len_map = {} 80 | ret_len_map = {} 81 | for d in rel_len: 82 | idx = int(d / 100) 83 | if(idx > 200): 84 | continue 85 | if idx not in rel_len_map: 86 | rel_len_map[idx] = 1 87 | else: 88 | rel_len_map[idx] += 1 89 | #print idx,',', 90 | #print '\n' 91 | for d in ret_len: 92 | idx = int(d / 100) 93 | if(idx > 200): 94 | continue 95 | if idx not in ret_len_map: 96 | ret_len_map[idx] = 1 97 | else: 98 | ret_len_map[idx] += 1 99 | #print idx,',', 100 | #print '\n' 101 | PlotTwoScatter(rel_len_map,ret_len_map,savefile) 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /python/client.py: -------------------------------------------------------------------------------- 1 | import zmq 2 | import json 3 | import time 4 | import sys 5 | 6 | def get_nodes(model): 7 | node_set = set() 8 | node_list = [] 9 | for layer in model['layers']: 10 | if layer['bottom_nodes']: 11 | for node in layer['bottom_nodes']: 12 | if node not in node_set: 13 | node_set.add(node) 14 | node_list.append(node) 15 | if layer['top_nodes']: 16 | for node in layer['top_nodes']: 17 | if node not in node_set: 18 | node_set.add(node) 19 | node_list.append(node) 20 | print node_list 21 | return node_list 22 | 23 | context = zmq.Context() 24 | 25 | # Socket to talk to server 26 | print("Connecting to hello world server...") 27 | socket = context.socket(zmq.REQ) 28 | socket.connect("tcp://127.0.0.1:5000") 29 | 30 | node_list = get_nodes(json.loads(open(sys.argv[1]).read())) 31 | 32 | data_file = open("sample.data","w") 33 | 34 | # Do 10 requests, waiting each time for a response 35 | for request in range(1000): 36 | print("Sending request %s ..." % request) 37 | for node in node_list: 38 | socket.send_string(b'{"msg_type":2, "node_name": "%s", "static_node": ["diff"], "static_value": ["mean"]}' % node) 39 | 40 | # Get the reply. 41 | message = socket.recv() 42 | print >> data_file, message 43 | message = json.loads(message) 44 | print("Received reply %s [ %s ]" % (request, message)) 45 | 46 | time.sleep(1) 47 | 48 | data_file.close() 49 | -------------------------------------------------------------------------------- /python/gen_word_embed_ind.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | echo "Generate unupdate word embeddings." 3 | cat $1 | awk '{print $1" 0"}' > $1.ind 4 | -------------------------------------------------------------------------------- /python/get_cross.py: -------------------------------------------------------------------------------- 1 | import json 2 | import sys 3 | import cv2 4 | import numpy as np 5 | from sklearn import preprocessing 6 | 7 | json_file = sys.argv[1] 8 | node_name = sys.argv[2] 9 | output_dir = sys.argv[3] 10 | 11 | def draw_map(X, shape, file_name, relu = True): 12 | print 'Writting picture %s.' % file_name 13 | if relu: 14 | X = X * (X>0) 15 | min_max_scaler = preprocessing.MinMaxScaler() 16 | X = min_max_scaler.fit_transform(X.reshape(shape[0]*shape[1])) 17 | X = np.reshape(X, (shape[0], shape[1])) 18 | # X = cv2.resize(X, (100, 100), interpolation=cv2.INTER_NEAREST) 19 | cv2.imwrite(file_name, X*255, [int(cv2.IMWRITE_JPEG_QUALITY), 100]) 20 | 21 | def get_energy(X, shape, use_abs = False): 22 | if use_abs: 23 | sum = np.sum(np.abs(X)) 24 | else: 25 | sum = np.sum(X) 26 | return 1.0 * sum / (shape[0] * shape[1]) 27 | 28 | def get_node(json_obj, node_name): 29 | node_data = json_obj[0][node_name]['data'] 30 | node_shape = node_data["shape"] 31 | node_value = np.array(node_data["value"]) 32 | node_value = np.reshape(node_value, node_shape) 33 | return node_value 34 | 35 | json_obj = json.loads(open(json_file).read()) 36 | label_node = get_node(json_obj, "label") 37 | fc2_node = get_node(json_obj, "fc2") 38 | featmap_node = get_node(json_obj, node_name) 39 | 40 | for i in range(featmap_node.shape[0]): 41 | label = label_node[i][0][0][0] 42 | pred = 0 if fc2_node[i][0][0][0] > fc2_node[i][1][0][0] else 1 43 | for j in range(featmap_node.shape[1]): 44 | print 'processing %s %s' % (i, j) 45 | X = featmap_node[i][j] 46 | e = get_energy(X, (X.shape[0], X.shape[1])) 47 | file_name = '/'.join( [output_dir, \ 48 | '%s_%s_%s_%s_%s_%s.jpg'%(node_name, i, j, e, label, pred)] ) 49 | draw_map(X, (X.shape[0], X.shape[1]), file_name) 50 | 51 | print 'done' 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /python/get_fc2.py: -------------------------------------------------------------------------------- 1 | import json 2 | import sys 3 | import cv2 4 | import numpy as np 5 | from sklearn import preprocessing 6 | 7 | pred_file = open('pred.txt', 'w') 8 | label_file = open('label.txt', 'w') 9 | 10 | file_list = [(int(f.split('.')[-1]), f) for f in sys.argv[1:]] 11 | file_list = sorted(file_list, key = lambda x : x[0]) 12 | 13 | for i_part, f_name in file_list: 14 | print i_part 15 | json_file = f_name 16 | 17 | json_str = open(json_file).read() 18 | json_obj = json.loads(json_str)[0] 19 | 20 | node_data = json_obj["fc2"]["data"] 21 | label_data = json_obj["label"]["data"]["value"] 22 | 23 | node_shape = node_data["shape"] 24 | node_value = np.array(node_data["value"]) 25 | 26 | node_value = np.reshape(node_value, node_shape) 27 | 28 | for i in range(node_shape[0]): 29 | print 'processing %s' % i 30 | 31 | X = node_value[i] 32 | if X[0]>X[1]: 33 | print >>pred_file, 0 34 | else: 35 | print >>pred_file, 1 36 | 37 | print >>label_file, int(label_data[i]) 38 | pred_file.close() 39 | label_file.close() 40 | -------------------------------------------------------------------------------- /python/get_kernel.py: -------------------------------------------------------------------------------- 1 | import json 2 | import sys 3 | import cv2 4 | import numpy as np 5 | from sklearn import preprocessing 6 | 7 | json_file = sys.argv[1] 8 | node_idx = int(sys.argv[2]) 9 | output_dir = sys.argv[3] 10 | 11 | def draw_map(X, shape, file_name, relu = False): 12 | print 'Writting picture %s.' % file_name 13 | if relu: 14 | X = X * (X>0) 15 | min_max_scaler = preprocessing.MinMaxScaler() 16 | X = min_max_scaler.fit_transform(X.reshape(shape[0]*shape[1])) 17 | X = np.reshape(X, (shape[0], shape[1])) 18 | # X = cv2.resize(X, (100, 100), interpolation=cv2.INTER_NEAREST) 19 | cv2.imwrite(file_name, X*255, [int(cv2.IMWRITE_JPEG_QUALITY), 100]) 20 | 21 | def get_energy(X, shape, use_abs = False): 22 | if use_abs: 23 | sum = np.sum(np.abs(X)) 24 | else: 25 | sum = np.sum(X) 26 | return 1.0 * sum / (shape[0]*shape[1]) 27 | 28 | def get_node(json_obj): 29 | node_data = json_obj[0]['data'] 30 | node_shape = node_data["shape"] 31 | print 'get node shape: ', node_shape 32 | node_value = np.array(node_data["value"]) 33 | node_value = np.reshape(node_value, node_shape) 34 | return node_value 35 | 36 | json_obj = json.loads(open(json_file).read()) 37 | 38 | # list all layer names 39 | while node_idx == -1: 40 | for idx, layer in enumerate(json_obj['config']['layers']): 41 | print idx,'\t',layer['layer_name'] 42 | node_idx = input('node_idx:') 43 | 44 | featmap_node = get_node(json_obj['layers_params'][node_idx]) 45 | 46 | for i in range(featmap_node.shape[0]): 47 | print 'processing %s' % (i) 48 | X = featmap_node[i] 49 | kernel_size = int(X.shape[0]**0.5) 50 | X = np.reshape(X, (kernel_size, kernel_size)) 51 | e = get_energy(X, (X.shape[0], X.shape[1])) 52 | file_name = '/'.join( [output_dir, \ 53 | '%s_%s_%s.jpg'%(node_idx, i, e)] ) 54 | draw_map(X, (kernel_size, kernel_size), file_name) 55 | 56 | print 'done' 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /python/get_kernel_next.py: -------------------------------------------------------------------------------- 1 | import json 2 | import sys 3 | import cv2 4 | import numpy as np 5 | from sklearn import preprocessing 6 | 7 | json_file = sys.argv[1] 8 | node_idx = int(sys.argv[2]) 9 | channel = int(sys.argv[3]) 10 | output_dir = sys.argv[4] 11 | 12 | def draw_map(X, shape, file_name, relu = False): 13 | print 'Writting picture %s.' % file_name 14 | if relu: 15 | X = X * (X>0) 16 | min_max_scaler = preprocessing.MinMaxScaler() 17 | X = min_max_scaler.fit_transform(X.reshape(shape[0]*shape[1])) 18 | X = np.reshape(X, (shape[0], shape[1])) 19 | # X = cv2.resize(X, (100, 100), interpolation=cv2.INTER_NEAREST) 20 | cv2.imwrite(file_name, X*255, [int(cv2.IMWRITE_JPEG_QUALITY), 100]) 21 | 22 | def get_energy(X, shape, use_abs = False): 23 | if use_abs: 24 | sum = np.sum(np.abs(X)) 25 | else: 26 | sum = np.sum(X) 27 | return 1.0 * sum / (shape[0]*shape[1]) 28 | 29 | def get_node(json_obj): 30 | node_data = json_obj[0]['data'] 31 | node_shape = node_data["shape"] 32 | print 'get node shape: ', node_shape 33 | node_value = np.array(node_data["value"]) 34 | node_value = np.reshape(node_value, node_shape) 35 | return node_value 36 | 37 | json_obj = json.loads(open(json_file).read()) 38 | 39 | # list all layer names 40 | while node_idx == -1: 41 | for idx, layer in enumerate(json_obj['config']['layers']): 42 | print idx,'\t',layer['layer_name'] 43 | node_idx = input('node_idx:') 44 | 45 | featmap_node = get_node(json_obj['layers_params'][node_idx]) 46 | 47 | for i in range(featmap_node.shape[0]): 48 | print 'processing %s' % (i) 49 | X = featmap_node[i] 50 | kernel_size = int((X.shape[0]/channel)**0.5) 51 | X = np.reshape(X, (channel, kernel_size, kernel_size)) 52 | for j in range(channel): 53 | e = get_energy(X[j], (kernel_size, kernel_size)) 54 | file_name = '/'.join( [output_dir, \ 55 | '%s_%s_%s_%s.jpg'%(node_idx, i, j, e)] ) 56 | draw_map(X[j], (kernel_size, kernel_size), file_name) 57 | 58 | print 'done' 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /python/grid_search.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import json 4 | import copy 5 | import multiprocessing 6 | 7 | if len(sys.argv) < 5: 8 | print "Usage: python grid_search.py [model_template_file] [parameters_config] [process_number] [run_dir]" 9 | 10 | model_tpl_file = sys.argv[1] 11 | param_conf_file = sys.argv[2] 12 | proc_num = int(sys.argv[3]) 13 | run_dir = sys.argv[4] 14 | 15 | if not os.path.isdir(run_dir): 16 | os.mkdir(run_dir) 17 | print 'Create Run Directory' 18 | 19 | model_template = open(model_tpl_file).read() 20 | param_config = {} 21 | for line in open(sys.argv[2]): 22 | line = line.strip().split() 23 | param_config[line[0]] = line[1:] 24 | print 'Read Template & Config over.' 25 | 26 | def render_template(template, params): 27 | for k, v in params.items(): 28 | template = template.replace('{{%s}}' % k, v) 29 | return template 30 | 31 | _p = [ [0, k, 0, len(v)] for k, v in param_config.items() ] 32 | def get_one_config(p, d): 33 | rtn = [] 34 | if d == len(p): 35 | return [{k:param_config[k][idx] for idx, k, _, __ in p}] 36 | for i in range(p[d][3]): 37 | rtn += get_one_config(copy.deepcopy(p), d+1) 38 | p[d][0] += 1 39 | return rtn 40 | 41 | models_list = [] 42 | config_out_file = open(run_dir + '/run.conf', 'w') 43 | for idx, config in enumerate(get_one_config(_p, 0)): 44 | model = render_template(model_template, config) 45 | try: 46 | obj = json.loads(model) 47 | except Exception as e: 48 | print e 49 | exit() 50 | model_file = run_dir + '/' + model_tpl_file.split('/')[-1] + '.run%d' % idx 51 | log_file = run_dir + '/' + model_tpl_file.split('/')[-1] + '.log%d' % idx 52 | print model_file 53 | print >>config_out_file, model_file, config 54 | open(model_file, 'w').write(model) 55 | models_list.append((model_file, log_file)) 56 | config_out_file.close() 57 | 58 | def run_one_model(model_path, log_path): 59 | BIN = '/home/pangliang/matching/textnet_statistic/bin/textnet' 60 | command = '%s %s >%s 2>&1' % (BIN, model_path, log_path) 61 | print command 62 | os.system(command) 63 | 64 | # Schedule 65 | pool = multiprocessing.Pool(processes = proc_num) 66 | for model_path, log_path in models_list: 67 | pool.apply_async(run_one_model, (model_path, log_path)) 68 | pool.close() 69 | pool.join() 70 | 71 | 72 | -------------------------------------------------------------------------------- /python/log2graph.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import re 3 | 4 | reduce_interval = { 5 | "Train" : 1000, 6 | "Valid" : 1000, 7 | "Test" : 1000 8 | } 9 | 10 | seperator = ',' # '\t' 11 | 12 | 13 | def reduce_result(x, interval): 14 | y = {} 15 | count = {} 16 | for iter, value in x: 17 | idx = iter / interval 18 | if idx not in y: 19 | y[idx] = 0.0 20 | count[idx] = 0 21 | y[idx] += value 22 | count[idx] += 1 23 | for idx in y: 24 | y[idx] /= count[idx] 25 | 26 | # convert dict to list 27 | idx = 0 28 | rtn = [] 29 | while True: 30 | if idx in y: 31 | rtn.append(y[idx]) 32 | idx += 1 33 | elif idx == 0: 34 | rtn.append(0) 35 | idx += 1 36 | else: 37 | break 38 | return rtn 39 | 40 | pattern_raw = r"\[.+?\] \[(.+?)\:(.+?)\]\tIter\t(.+?)\:\tOut\[(.+?)\].*?=\t(.+)" 41 | 42 | log_lines = {} 43 | 44 | for line in open(sys.argv[1]): 45 | m = re.match(pattern_raw, line) 46 | if m: 47 | tag = m.group(1) 48 | phase = m.group(2) 49 | iter = int(m.group(3)) 50 | node = m.group(4) 51 | value = float(m.group(5)) 52 | if tag not in log_lines: 53 | log_lines[tag] = {} 54 | if node not in log_lines[tag]: 55 | log_lines[tag][node] = [] 56 | log_lines[tag][node].append([iter, value]) 57 | 58 | for tag in log_lines: 59 | for node in log_lines[tag]: 60 | log_lines[tag][node] = reduce_result(log_lines[tag][node], reduce_interval[tag]) 61 | print len(log_lines[tag][node]) 62 | 63 | _out = open(sys.argv[1]+".csv", 'w') 64 | # Write header 65 | _out.write("iter%s" % seperator) 66 | for tag in log_lines: 67 | for node in log_lines[tag]: 68 | _out.write("%s:%s%s"%(tag, node, seperator)) 69 | _out.write("\n") 70 | 71 | idx = 0 72 | while True: 73 | have_data = False 74 | _out.write("%d%s"%(idx, seperator)) 75 | for tag in log_lines: 76 | for node in log_lines[tag]: 77 | if idx < len(log_lines[tag][node]): 78 | _out.write("%f%s"%(log_lines[tag][node][idx], seperator)) 79 | have_data = True 80 | else: 81 | _out.write(seperator) 82 | _out.write("\n") 83 | if not have_data: 84 | break 85 | idx += 1 86 | 87 | _out.close() 88 | 89 | 90 | -------------------------------------------------------------------------------- /python/log2graph_png.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import re 3 | import numpy as np 4 | import matplotlib 5 | matplotlib.use('Agg') 6 | import matplotlib.pyplot as plt 7 | 8 | reduce_interval = { 9 | "Train" : 1000, 10 | "Valid" : 1000, 11 | "Test" : 1000 12 | } 13 | 14 | seperator = ',' # '\t' 15 | 16 | def reduce_result(x, interval): 17 | y = {} 18 | count = {} 19 | for iter, value in x: 20 | idx = iter / interval 21 | if idx not in y: 22 | y[idx] = 0.0 23 | count[idx] = 0 24 | y[idx] += value 25 | count[idx] += 1 26 | for idx in y: 27 | y[idx] /= count[idx] 28 | 29 | # convert dict to list 30 | idx = 0 31 | rtn = [] 32 | while True: 33 | if idx in y: 34 | rtn.append(y[idx]) 35 | idx += 1 36 | elif idx == 0: 37 | rtn.append(0) 38 | idx += 1 39 | else: 40 | break 41 | return rtn 42 | 43 | # test = '[Train:kTrain]\tIter\t3321:\tOut[loss] =\t0.228255' 44 | pattern_raw = r"\[.+?\] \[(.+?)\:(.+?)\]\tIter\t(.+?)\:\tOut\[(.+?)\].*?=\t(.+)" 45 | 46 | if __name__=='__main__': 47 | log_lines = {} 48 | 49 | for line in open(sys.argv[1]): 50 | m = re.match(pattern_raw, line) 51 | if m: 52 | tag = m.group(1) 53 | phase = m.group(2) 54 | iter = int(m.group(3)) 55 | node = m.group(4) 56 | value = float(m.group(5)) 57 | if tag not in log_lines: 58 | log_lines[tag] = {} 59 | if node not in log_lines[tag]: 60 | log_lines[tag][node] = [] 61 | log_lines[tag][node].append([iter, value]) 62 | #print log_lines['Train'] 63 | outpufile = sys.argv[1] + '.png' 64 | 65 | loss_x = [] 66 | loss_y = [] 67 | for idx,k in enumerate(log_lines['Train']['loss']): 68 | if idx % 10 == 0: 69 | loss_x.append(k[0]) 70 | loss_y.append(k[1]) 71 | train_map_x = [] 72 | train_map_y = [] 73 | test_map_x = [] 74 | test_map_y = [] 75 | 76 | for k in log_lines['Valid']['MAP']: 77 | train_map_x.append(k[0]) 78 | train_map_y.append(k[1]) 79 | for k in log_lines['Test']['MAP']: 80 | test_map_x.append(k[0]) 81 | test_map_y.append(k[1]) 82 | 83 | fig = plt.figure(figsize = (8,8),dpi = 120) 84 | ax1 = plt.subplot(211) 85 | ax2 = plt.subplot(212) 86 | 87 | p1 = ax1.plot(loss_x,loss_y,'-o',color="#ff0000",linewidth=2,markersize=2,label='train loss') 88 | 89 | x = np.linspace(0,len(test_map_x),len(test_map_x)) 90 | xticks = [] 91 | max_test_map = np.max(test_map_y) 92 | max_test_map_x = 0 93 | for idx,k in enumerate(test_map_y): 94 | if k == max_test_map: 95 | max_test_map_x = idx 96 | break 97 | 98 | ax2.set_xticks(x) 99 | ax2.set_xticklabels(train_map_x,rotation=70) 100 | p2 = ax2.plot(x,train_map_y,'-o',color="#78ff45",linewidth=2,markersize=2,label='train map') 101 | p3 = ax2.plot(x,test_map_y,'-o',color="#7845ff",linewidth=2,markersize=2,label='test map') 102 | ax2.annotate('%f'%(max_test_map),xy=(max_test_map_x,max_test_map),xytext=(max_test_map_x,max_test_map+0.0001)) 103 | plt.legend(loc=2) 104 | plt.savefig(outpufile,dpi=120) 105 | 106 | 107 | -------------------------------------------------------------------------------- /python/measure_list.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | def Measure(pred_list, label_list): 4 | TP = 0. 5 | FP = 0. 6 | TN = 0. 7 | FN = 0. 8 | if len(pred_list)!=len(label_list): 9 | exit() 10 | for i in range(len(pred_list)): 11 | if pred_list[i] == 1 and label_list[i] == 1: 12 | TP += 1 13 | elif pred_list[i] == 1 and label_list[i] == 0: 14 | FP += 1 15 | elif pred_list[i] == 0 and label_list[i] == 1: 16 | FN += 1 17 | elif pred_list[i] == 0 and label_list[i] == 0: 18 | TN += 1 19 | else: 20 | exit() 21 | Total = TP + FP + TN + FN 22 | Acc = (TP+TN)/Total 23 | if TP!=0: 24 | P = TP/(TP+FP) 25 | R = TP/(TP+FN) 26 | F1 = 2*P*R/(P+R) 27 | else: 28 | P = R = F1 =0 29 | 30 | return {"Acc" : Acc, 31 | "P" : P, 32 | "R" : R, 33 | "F1" : F1, 34 | "TP" : TP, 35 | "FP" : FP, 36 | "FN" : FN, 37 | "TN" : TN} 38 | 39 | def MakePredList(score_list, theta): 40 | pred_list = [1 if s >=theta else 0 for s in score_list ] 41 | return pred_list 42 | 43 | pred_list_file = open(sys.argv[1]) 44 | label_list_file = open(sys.argv[2]) 45 | cut_size = int(sys.argv[3]) 46 | 47 | pred_list = [] 48 | label_list = [] 49 | 50 | for line in pred_list_file: 51 | pred_list.append(float(line)) 52 | 53 | for line in label_list_file: 54 | label_list.append(int(line)) 55 | 56 | pred_list = pred_list[:cut_size] 57 | label_list = label_list[:cut_size] 58 | 59 | print Measure(pred_list, label_list) 60 | 61 | -------------------------------------------------------------------------------- /script/analyse.py: -------------------------------------------------------------------------------- 1 | #-*-coding:utf8-*- 2 | import json 3 | import numpy as np 4 | 5 | def load_tensor(json_root): 6 | shape = json_root['data']['shape'] 7 | len = shape[0]*shape[1]*shape[2]*shape[3] 8 | t = np.zeros(len) 9 | for i in range(len): 10 | t[i] = json_root['data']['value'][i] 11 | t = t.reshape(shape) 12 | return t 13 | 14 | def concat_tensors(tensors): 15 | return np.concatenate(tensors, axis=0) 16 | 17 | data_dir = '/home/wsx/exp/negneg/model/' 18 | def getAllPoolRet(): 19 | inFile = data_dir + 'test.cnn.ave.w2.d2.dp0.29900' 20 | outFile = inFile + '.pool_rep' 21 | batchs = json.loads(open(inFile).read()) 22 | # print batchs 23 | pool_reps = concat_tensors([load_tensor(batch['pool_rep']) for batch in batchs]) 24 | ys = concat_tensors([load_tensor(batch['y']) for batch in batchs]) 25 | fo = open(outFile, 'w') 26 | print 'ys.shape:', ys.shape 27 | print 'pool_rep.shape:' ,pool_reps.shape 28 | n_example = ys.shape[0] 29 | for i in range(n_example): 30 | fo.write(str(int(ys[i][0][0][0]))) 31 | for j in range(pool_reps.shape[3]): 32 | fo.write(' ' + str(pool_reps[i][0][0][j])) 33 | fo.write('\n') 34 | fo.close() 35 | 36 | 37 | getAllPoolRet() 38 | -------------------------------------------------------------------------------- /script/gen_conf_file.py: -------------------------------------------------------------------------------- 1 | #-*-coding:utf8-*- 2 | import json 3 | 4 | def gen_gaussion_filler_setting(mu, sigma): 5 | return {'init_type':3, 'mu':mu, 'sigma':sigma} 6 | 7 | def gen_zero_filler_setting(): 8 | return {'init_type':0, 'value':0} 9 | def gen_constant_filler_setting(val): 10 | return {'init_type':1, 'value':val} 11 | def gen_uniform_filler_setting(interval): 12 | return {'init_type':2, 'range':interval} 13 | 14 | def gen_sgd_setting(lr, l2 = None, batch_size = 1): 15 | # assert not l2 or l2 == 0 16 | setting = {} 17 | setting['updater_type'] = 0 18 | setting['lr'] = lr 19 | setting['batch_size'] = batch_size 20 | if l2: 21 | setting['l2'] = l2 22 | return setting 23 | 24 | def gen_adadelta_setting(l2 = None, batch_size = 1, eps = None, rho = None, norm2=0.): 25 | setting = {} 26 | setting['updater_type'] = 4 27 | setting['batch_size'] = batch_size 28 | if l2: 29 | setting['l2'] = l2 30 | if eps: 31 | setting['eps'] = eps 32 | if rho: 33 | setting['rho'] = rho 34 | if norm2 > 0: 35 | setting['norm2'] = norm2 36 | return setting 37 | 38 | def gen_adagrad_setting(lr, l2 = None, max_iter = -1, batch_size = 1, eps = None): 39 | setting = {} 40 | setting['updater_type'] = 1 41 | setting['lr'] = lr 42 | setting['batch_size'] = batch_size 43 | if l2: 44 | setting['l2'] = l2 45 | if eps: 46 | setting['eps'] = eps 47 | if max_iter > 0: 48 | setting['max_iter'] = max_iter 49 | return setting 50 | 51 | def gen_conf_file(net_setting, out_file): 52 | fo = open(out_file, 'w') 53 | fo.write(json.dumps(net_setting, sort_keys=True, indent=2)) 54 | fo.close() 55 | return 56 | 57 | 58 | # gen_conf_file(None, "tmp") 59 | # obj = [[1,2,3],123,123.123,'abc',{'key1':(1,2,3),'key2':(4,5,6)}] 60 | # encodedjson = json.dumps(obj) 61 | # print repr(obj) 62 | # print encodedjson 63 | # 64 | -------------------------------------------------------------------------------- /script/gen_cv_file.py: -------------------------------------------------------------------------------- 1 | #-*-coding:utf8-*- 2 | import random 3 | 4 | 5 | def gen_cv_tvts(all, n_fold): 6 | def get_one(all, n_fold, fold_idx): 7 | fold_size = int(len(all) / n_fold) 8 | test_fold = fold_idx 9 | if test_fold == n_fold-1: 10 | test = all[test_fold*fold_size :] 11 | else: 12 | test = all[test_fold*fold_size : (test_fold+1)*fold_size] 13 | valid_fold = (fold_idx+1) % n_fold 14 | if valid_fold == n_fold-1: 15 | valid = all[valid_fold*fold_size :] 16 | else: 17 | valid = all[valid_fold*fold_size : (valid_fold+1)*fold_size] 18 | train = [] 19 | for i in range(n_fold): 20 | if i == test_fold or i == valid_fold: 21 | continue 22 | if i == n_fold-1: 23 | train += all[i*fold_size :] 24 | else: 25 | train += all[i*fold_size : (i+1)*fold_size] 26 | assert len(train) + len(valid) + len(test) == len(all) 27 | return (train, valid, test) 28 | 29 | random.shuffle(all) 30 | tvts = [] 31 | for i in range(n_fold): 32 | tvts.append(get_one(all, n_fold, i)) 33 | return tvts 34 | 35 | def output(data, file): 36 | fo = open(file, 'w') 37 | for line in data: 38 | fo.write(line) 39 | fo.close() 40 | 41 | # one line is a example 42 | def main(allFile, n_fold, trainFile, validFile, testFile): 43 | all = open(allFile).readlines() 44 | tvts = gen_cv_tvts(all, n_fold) 45 | for i,tvt in enumerate(tvts): 46 | output(tvt[0], trainFile+'.'+str(i)) 47 | output(tvt[1], validFile+'.'+str(i)) 48 | output(tvt[2], testFile +'.'+str(i)) 49 | return 50 | 51 | if __name__ == '__main__': 52 | dir = '/home/wsx/dl.shengxian/data/mr/' 53 | all = dir + 'lstm.all.nopad' 54 | train = dir + 'lstm.train.nopad' 55 | valid = dir + 'lstm.valid.nopad' 56 | test = dir + 'lstm.test.nopad' 57 | main(all, 10, train, valid, test) 58 | -------------------------------------------------------------------------------- /script/visualize.py: -------------------------------------------------------------------------------- 1 | #-*-coding:utf8-*- 2 | import json 3 | import Image 4 | import numpy as np 5 | 6 | def load_tensor(json_root): 7 | shape = json_root['data']['shape'] 8 | len = shape[0]*shape[1]*shape[2]*shape[3] 9 | t = np.zeros(len) 10 | for i in range(len): 11 | t[i] = json_root['data']['value'][i] 12 | t = t.reshape(shape) 13 | return t 14 | 15 | def draw_image(pixels, ofile): 16 | img = Image.new( 'RGB', (len(pixels),len(pixels[0])), "black") # create a new black image 17 | ps = img.load() # create the pixel map 18 | 19 | for i in range(len(pixels)): # for every pixel: 20 | for j in range(len(pixels[i])): 21 | ps[i,j] = (pixels[i][j], pixels[i][j], pixels[i][j]) # set the colour accordingly 22 | 23 | print ofile 24 | img.save(ofile) 25 | 26 | def draw_01_image(pixels, ofile): 27 | for i in range(len(pixels)): 28 | for j in range(len(pixels[i])): 29 | pixels[i][j] *= 255 30 | draw_image(pixels, ofile) 31 | 32 | # -1到1的real值的图 33 | def draw_neg11_real_image(pixels, ofile): 34 | for i in range(len(pixels)): 35 | for j in range(len(pixels[i])): 36 | pixels[i][j] += 1 37 | pixels[i][j] *= 254/2 38 | draw_image(pixels, ofile) 39 | 40 | def output_matrix(mat, ofile): 41 | fo = open(ofile, 'w') 42 | for l in mat: 43 | for i in l: 44 | fo.write(str(i) + ' ') 45 | fo.write('\n') 46 | fo.close() 47 | 48 | def visualize(): 49 | test_iter = 10000 50 | test_file = './test.' + str(test_iter) 51 | batch = json.loads(open(test_file).read())[0] 52 | 53 | xor_sim = np.swapaxes(load_tensor(batch['xor_similarity_swap']), 1, 3) 54 | print 'xor_sim_shape:', xor_sim.shape 55 | 56 | rnn_sim = np.swapaxes(load_tensor(batch['sim_recurrent']),1, 3) 57 | print 'rnn_sim.shape:', xor_sim.shape 58 | 59 | 60 | output_matrix(rnn_sim[42][0].tolist(), './tmp') 61 | exit(0) 62 | img_prefix = './img.{0}/'.format(str(test_iter)) 63 | for i in range(rnn_sim.shape[0]): 64 | draw_01_image(xor_sim[i][0].tolist(), img_prefix + str(i)+'.png') 65 | for i in range(rnn_sim.shape[0]): 66 | for j in range(rnn_sim.shape[1]): 67 | draw_neg11_real_image(rnn_sim[i][j].tolist(), img_prefix + str(i)+'_'+str(j)+'_rnn.png') 68 | 69 | visualize() 70 | -------------------------------------------------------------------------------- /simple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pl8787/textnet-release/c85a4162c55b4cfe22eab6f8f0c8b615854f9b8f/simple.png -------------------------------------------------------------------------------- /src/checker/checker_impl-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_CHECKER_IMPL_INL_HPP_ 2 | #define TEXTNET_CHECKER_IMPL_INL_HPP_ 3 | 4 | #include "./checker.h" 5 | 6 | namespace textnet { 7 | namespace checker { 8 | 9 | template 10 | Checker* CreateChecker_() { 11 | return new Checker(); 12 | } 13 | 14 | } // namespace checker 15 | } // namespace textnet 16 | #endif 17 | -------------------------------------------------------------------------------- /src/checker/checker_impl.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #define _CRT_SECURE_NO_DEPRECATE 3 | // include the layer, this is where the actual implementations are 4 | 5 | #include "checker_impl-inl.hpp" 6 | // specialize the cpu implementation here 7 | namespace textnet { 8 | namespace checker { 9 | template<> 10 | Checker* CreateChecker() { 11 | return CreateChecker_(); 12 | } 13 | 14 | } // namespace checker 15 | } // namespace textnet 16 | -------------------------------------------------------------------------------- /src/checker/checker_impl.cu: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #define _CRT_SECURE_NO_DEPRECATE 3 | // include the layer, this is where the actual implementations are 4 | 5 | #include "checker_impl-inl.hpp" 6 | // specialize the gpu implementation here 7 | namespace textnet { 8 | namespace checker { 9 | template<> 10 | Checker* CreateChecker() { 11 | return CreateChecker_(); 12 | } 13 | 14 | } // namespace checker 15 | } // namespace textnet 16 | -------------------------------------------------------------------------------- /src/global.h: -------------------------------------------------------------------------------- 1 | #ifndef CXXNET_GLOBAL_H_ 2 | 3 | /*! \brief namespace of cxxnet */ 4 | namespace textnet { 5 | typedef mshadow::cpu cpu; 6 | typedef mshadow::gpu gpu; 7 | typedef mshadow::index_t index_t; 8 | typedef mshadow::default_real_t real_t; 9 | } // namespace textnet 10 | 11 | #define DEBUG 0 12 | #define LENGTH_DEBUG 0 13 | #define TIME_DEBUG 0 14 | 15 | #endif // CXXNET_GLOBAL_H_ 16 | -------------------------------------------------------------------------------- /src/initializer/constant_init-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_CONSTANT_INIT_INL_HPP_ 2 | #define TEXTNET_CONSTANT_INIT_INL_HPP_ 3 | 4 | #include 5 | #include "./initializer.h" 6 | 7 | namespace textnet { 8 | namespace initializer { 9 | 10 | template 11 | class ConstantInitializer : public Initializer{ 12 | public: 13 | ConstantInitializer(std::map &setting, 14 | mshadow::Random* prnd) { 15 | this->prnd_ = prnd; 16 | SetupInitializer(setting); 17 | } 18 | virtual ~ConstantInitializer(void) {} 19 | 20 | virtual void Require(std::map &setting) { 21 | // default value, just set the value you want 22 | this->defaults["value"] = SettingV(0.0f); 23 | 24 | // require value, set to SettingV(), 25 | // it will force custom to set in config 26 | 27 | Initializer::Require(setting); 28 | } 29 | 30 | virtual void SetupInitializer(std::map &setting) { 31 | Initializer::SetupInitializer(setting); 32 | 33 | this->init_type = setting["init_type"].iVal(); 34 | if (this->init_type == kZero) { 35 | this->value = 0.0f; 36 | } else if (this->init_type == kConstant) { 37 | this->value = setting["value"].fVal(); 38 | } 39 | } 40 | 41 | virtual void DoInitialize(mshadow::Tensor data) { 42 | data = this->value; 43 | } 44 | 45 | float value; 46 | }; 47 | } // namespace initializer 48 | } // namespace textnet 49 | #endif // TEXTNET_CONSTANT_INIT_INL_HPP_ 50 | 51 | -------------------------------------------------------------------------------- /src/initializer/file_init-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_FILE_INIT_INL_HPP_ 2 | #define TEXTNET_FILE_INIT_INL_HPP_ 3 | 4 | #include 5 | #include "./initializer.h" 6 | #include 7 | 8 | namespace textnet { 9 | namespace initializer { 10 | 11 | template 12 | class FileInitializer : public Initializer{ 13 | public: 14 | FileInitializer(std::map &setting, 15 | mshadow::Random* prnd) { 16 | this->prnd_ = prnd; 17 | SetupInitializer(setting); 18 | } 19 | virtual ~FileInitializer(void) {} 20 | 21 | virtual void Require(std::map &setting) { 22 | // default value, just set the value you want 23 | 24 | // require value, set to SettingV(), 25 | // it will force custom to set in config 26 | this->defaults["file_path"] = SettingV(); 27 | 28 | Initializer::Require(setting); 29 | } 30 | 31 | virtual void SetupInitializer(std::map &setting) { 32 | Initializer::SetupInitializer(setting); 33 | 34 | this->init_type = setting["init_type"].iVal(); 35 | file_path = setting["file_path"].sVal(); 36 | } 37 | 38 | virtual void DoInitialize(mshadow::Tensor data) { 39 | std::ifstream ifs(file_path.c_str()); 40 | vector vals; 41 | float s = 0; 42 | while (ifs >> s) { 43 | vals.push_back(s); 44 | } 45 | ifs.close(); 46 | utils::Check(vals.size() == data.shape_.Size(), "FileInitializer: parameter file error. %d params in file, but we need %d params.", vals.size(), data.shape_.Size()); 47 | 48 | mshadow::Tensor mat = data.FlatTo2D(); 49 | index_t idx = 0; 50 | for (index_t i = 0; i < mat.size(0); ++i) { 51 | for (index_t j = 0; j < mat.size(1); ++j) { 52 | mat[i][j] = vals[idx]; 53 | idx += 1; 54 | } 55 | } 56 | } 57 | 58 | string file_path; 59 | }; 60 | } // namespace initializer 61 | } // namespace textnet 62 | #endif // TEXTNET_CONSTANT_INIT_INL_HPP_ 63 | 64 | -------------------------------------------------------------------------------- /src/initializer/gaussian_init-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_GAUSSIAN_INIT_INL_HPP_ 2 | #define TEXTNET_GAUSSIAN_INIT_INL_HPP_ 3 | 4 | #include 5 | #include "./initializer.h" 6 | 7 | namespace textnet { 8 | namespace initializer { 9 | 10 | template 11 | class GaussianInitializer : public Initializer{ 12 | public: 13 | GaussianInitializer(std::map &setting, 14 | mshadow::Random* prnd) { 15 | this->prnd_ = prnd; 16 | SetupInitializer(setting); 17 | } 18 | virtual ~GaussianInitializer(void) {} 19 | 20 | virtual void Require(std::map &setting) { 21 | // default value, just set the value you want 22 | this->defaults["mu"] = SettingV(0.0f); 23 | this->defaults["sigma"] = SettingV(1.0f); 24 | 25 | // require value, set to SettingV(), 26 | // it will force custom to set in config 27 | 28 | Initializer::Require(setting); 29 | } 30 | 31 | virtual void SetupInitializer(std::map &setting) { 32 | Initializer::SetupInitializer(setting); 33 | 34 | this->init_type = setting["init_type"].iVal(); 35 | if (this->init_type == kGaussian) { 36 | this->mu = setting["mu"].fVal(); 37 | this->sigma = setting["sigma"].fVal(); 38 | } else if (this->init_type == kKaiming) { 39 | this->mu = 0.0; 40 | this->sigma = 1.0; 41 | } 42 | } 43 | 44 | virtual void DoInitialize(mshadow::Tensor data) { 45 | if (this->init_type == kKaiming) { 46 | float node_size = 1.0; 47 | for (int i = 1; i < dim; ++i) 48 | node_size *= data.shape_[i]; 49 | this->sigma = sqrt(2.0 / node_size); 50 | cout << "MSRA INITIAL: " << this->sigma << endl; 51 | } 52 | this->prnd_->SampleGaussian(&data, mu, sigma); 53 | } 54 | 55 | float mu; 56 | float sigma; 57 | }; 58 | } // namespace initializer 59 | } // namespace textnet 60 | #endif // TEXTNET_GAUSSIAN_INIT_INL_HPP_ 61 | 62 | -------------------------------------------------------------------------------- /src/initializer/initializer.h: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_INITIALIZER_INITIALIZER_H_ 2 | #define TEXTNET_INITIALIZER_INITIALIZER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "../global.h" 9 | #include "../utils/utils.h" 10 | #include "../utils/io.h" 11 | #include "../utils/settingv.h" 12 | 13 | /*! \brief namespace of textnet */ 14 | namespace textnet { 15 | /*! \brief namespace of layer defintiion */ 16 | namespace initializer { 17 | 18 | /*! \brief use integer to encode layer types */ 19 | typedef int InitType; 20 | 21 | /*! \brief these are enumeration */ 22 | const int kZero = 0; 23 | const int kConstant = 1; 24 | const int kUniform = 2; 25 | const int kGaussian = 3; 26 | const int kXavier = 4; 27 | const int kKaiming = 5; 28 | const int kUnitball = 6; 29 | const int kUniformRange = 7; 30 | const int kFileInit = 8; 31 | const int kVar = 9; 32 | const int kRowGaussian = 10; 33 | 34 | template 35 | class Initializer { 36 | public: 37 | Initializer(void) {} 38 | virtual ~Initializer(void) {} 39 | 40 | // To implement this function you need call base function in the end 41 | virtual void Require(std::map &setting) { 42 | defaults["init_type"] = SettingV(kZero); 43 | for (std::map::iterator it = defaults.begin(); 44 | it != defaults.end(); ++it) { 45 | std::string name = it->first; 46 | if (defaults[name].value_type == SET_NONE) { 47 | utils::Check(setting.count(name), 48 | "\tSetting [%s] needed for this layer.\n", name.c_str()); 49 | } else { 50 | if (!setting.count(name)) { 51 | setting[name] = defaults[name]; 52 | utils::Printf("\tSetting [%s] set to default value.\n", name.c_str()); 53 | } 54 | } 55 | } 56 | } 57 | 58 | virtual void SetupInitializer(std::map &setting) { 59 | init_type = 0; 60 | this->Require(setting); 61 | } 62 | 63 | virtual void DoInitialize(mshadow::Tensor data) {} 64 | 65 | virtual InitType GetInitType() { return init_type; } 66 | 67 | protected: 68 | InitType init_type; 69 | mshadow::Random* prnd_; 70 | // required setting 71 | std::map defaults; 72 | 73 | }; 74 | 75 | template 76 | Initializer* CreateInitializer(InitType type, 77 | std::map &setting, 78 | mshadow::Random* prnd); 79 | 80 | } // namespace initializer 81 | } // namespace textnet 82 | #endif // TEXTNET_INITIALIZER_INITIALIZER_H_ 83 | 84 | -------------------------------------------------------------------------------- /src/initializer/initializer_impl-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_INITIALIZER_IMPL_INL_HPP_ 2 | #define TEXTNET_INITIALIZER_IMPL_INL_HPP_ 3 | 4 | #include "./initializer.h" 5 | #include "./constant_init-inl.hpp" 6 | #include "./uniform_init-inl.hpp" 7 | #include "./uniform_range_init-inl.hpp" 8 | #include "./gaussian_init-inl.hpp" 9 | #include "./unitball_init-inl.hpp" 10 | #include "./file_init-inl.hpp" 11 | #include "./var_init-inl.hpp" 12 | #include "./row_gaussian_init-inl.hpp" 13 | 14 | namespace textnet { 15 | namespace initializer { 16 | template 17 | Initializer* CreateInitializer_( 18 | InitType type, 19 | std::map &setting, 20 | mshadow::Random* prnd) { 21 | switch(type) { 22 | case kZero: return new ConstantInitializer(setting, prnd); 23 | case kConstant: return new ConstantInitializer(setting, prnd); 24 | case kUniform: return new UniformInitializer(setting, prnd); 25 | case kUniformRange: return new UniformRangeInitializer(setting, prnd); 26 | case kFileInit: return new FileInitializer(setting, prnd); 27 | case kGaussian: return new GaussianInitializer(setting, prnd); 28 | case kXavier: return new UniformInitializer(setting, prnd); 29 | case kKaiming: return new GaussianInitializer(setting, prnd); 30 | case kUnitball: return new UnitballInitializer(setting, prnd); 31 | case kVar: return new VarInitializer(setting, prnd); 32 | case kRowGaussian: return new RowGaussianInitializer(setting, prnd); 33 | default: utils::Error("unknown initializer type id : \"%d\"", type); return NULL; 34 | } 35 | } 36 | 37 | } // namespace layer 38 | } // namespace textnet 39 | #endif 40 | -------------------------------------------------------------------------------- /src/initializer/initializer_impl.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #define _CRT_SECURE_NO_DEPRECATE 3 | // include the layer, this is where the actual implementations are 4 | 5 | #include "initializer_impl-inl.hpp" 6 | // specialize the cpu implementation here 7 | namespace textnet { 8 | namespace initializer { 9 | template<> 10 | Initializer* CreateInitializer( 11 | InitType type, 12 | std::map &setting, 13 | mshadow::Random* prnd) { 14 | return CreateInitializer_(type, setting, prnd); 15 | } 16 | template<> 17 | Initializer* CreateInitializer( 18 | InitType type, 19 | std::map &setting, 20 | mshadow::Random* prnd) { 21 | return CreateInitializer_(type, setting, prnd); 22 | } 23 | template<> 24 | Initializer* CreateInitializer( 25 | InitType type, 26 | std::map &setting, 27 | mshadow::Random* prnd) { 28 | return CreateInitializer_(type, setting, prnd); 29 | } 30 | template<> 31 | Initializer* CreateInitializer( 32 | InitType type, 33 | std::map &setting, 34 | mshadow::Random* prnd) { 35 | return CreateInitializer_(type, setting, prnd); 36 | } 37 | } // namespace initializer 38 | } // namespace textnet 39 | -------------------------------------------------------------------------------- /src/initializer/initializer_impl.cu: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #define _CRT_SECURE_NO_DEPRECATE 3 | // include the layer, this is where the actual implementations are 4 | 5 | #include "initializer_impl-inl.hpp" 6 | // specialize the cpu implementation here 7 | namespace textnet { 8 | namespace initializer { 9 | template<> 10 | Initializer* CreateInitializer( 11 | InitType type, 12 | std::map &setting, 13 | mshadow::Random* prnd) { 14 | return CreateInitializer_(type, setting, prnd); 15 | } 16 | template<> 17 | Initializer* CreateInitializer( 18 | InitType type, 19 | std::map &setting, 20 | mshadow::Random* prnd) { 21 | return CreateInitializer_(type, setting, prnd); 22 | } 23 | template<> 24 | Initializer* CreateInitializer( 25 | InitType type, 26 | std::map &setting, 27 | mshadow::Random* prnd) { 28 | return CreateInitializer_(type, setting, prnd); 29 | } 30 | template<> 31 | Initializer* CreateInitializer( 32 | InitType type, 33 | std::map &setting, 34 | mshadow::Random* prnd) { 35 | return CreateInitializer_(type, setting, prnd); 36 | } 37 | } // namespace initializer 38 | } // namespace textnet 39 | -------------------------------------------------------------------------------- /src/initializer/row_gaussian_init-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_ROW_GAUSSIAN_INIT_INL_HPP_ 2 | #define TEXTNET_ROW_GAUSSIAN_INIT_INL_HPP_ 3 | 4 | #include 5 | #include "./initializer.h" 6 | 7 | namespace textnet { 8 | namespace initializer { 9 | 10 | template 11 | class RowGaussianInitializer : public Initializer{ 12 | public: 13 | RowGaussianInitializer(std::map &setting, 14 | mshadow::Random* prnd) { 15 | this->prnd_ = prnd; 16 | SetupInitializer(setting); 17 | } 18 | virtual ~RowGaussianInitializer(void) {} 19 | 20 | virtual void Require(std::map &setting) { 21 | // default value, just set the value you want 22 | this->defaults["mu"] = SettingV(0.0f); 23 | this->defaults["sigma"] = SettingV(1.0f); 24 | 25 | // require value, set to SettingV(), 26 | // it will force custom to set in config 27 | 28 | Initializer::Require(setting); 29 | } 30 | 31 | virtual void SetupInitializer(std::map &setting) { 32 | Initializer::SetupInitializer(setting); 33 | 34 | this->init_type = setting["init_type"].iVal(); 35 | this->mu = setting["mu"].fVal(); 36 | this->sigma = setting["sigma"].fVal(); 37 | this->count = setting["count"].iVal(); 38 | } 39 | 40 | virtual void DoInitialize(mshadow::Tensor data) { 41 | using namespace mshadow::expr; 42 | using namespace mshadow; 43 | TensorContainer row; 44 | row.Resize(mshadow::Shape1(count)); 45 | this->prnd_->SampleGaussian(&row, mu, sigma); 46 | for (int i = 0; i < data.shape_.Size(); i += count) { 47 | for (int j = 0; j < count; ++j) { 48 | data.dptr_[i+j] = row[j]; 49 | } 50 | } 51 | } 52 | 53 | float mu; 54 | float sigma; 55 | int count; 56 | }; 57 | } // namespace initializer 58 | } // namespace textnet 59 | #endif // TEXTNET_ROW_GAUSSIAN_INIT_INL_HPP_ 60 | 61 | -------------------------------------------------------------------------------- /src/initializer/uniform_init-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_UNIFORM_INIT_INL_HPP_ 2 | #define TEXTNET_UNIFORM_INIT_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include "./initializer.h" 7 | 8 | namespace textnet { 9 | namespace initializer { 10 | 11 | template 12 | class UniformInitializer : public Initializer{ 13 | public: 14 | UniformInitializer(std::map &setting, 15 | mshadow::Random* prnd) { 16 | this->prnd_ = prnd; 17 | SetupInitializer(setting); 18 | } 19 | virtual ~UniformInitializer(void) {} 20 | 21 | virtual void Require(std::map &setting) { 22 | // default value, just set the value you want 23 | this->defaults["range"] = SettingV(0.0f); 24 | 25 | // require value, set to SettingV(), 26 | // it will force custom to set in config 27 | 28 | Initializer::Require(setting); 29 | } 30 | 31 | virtual void SetupInitializer(std::map &setting) { 32 | Initializer::SetupInitializer(setting); 33 | 34 | this->init_type = setting["init_type"].iVal(); 35 | if (this->init_type == kUniform) { 36 | this->range = setting["range"].fVal(); 37 | } else if (this->init_type == kXavier) { 38 | // Todo 39 | } 40 | } 41 | 42 | virtual void DoInitialize(mshadow::Tensor data) { 43 | this->prnd_->SampleUniform(&data, -range, range); 44 | } 45 | 46 | float range; 47 | }; 48 | } // namespace initializer 49 | } // namespace textnet 50 | #endif // TEXTNET_UNIFORM_INIT_INL_HPP_ 51 | 52 | -------------------------------------------------------------------------------- /src/initializer/uniform_range_init-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_UNIFORM_RANGE_INIT_INL_HPP_ 2 | #define TEXTNET_UNIFORM_RANGE_INIT_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include "./initializer.h" 7 | 8 | namespace textnet { 9 | namespace initializer { 10 | 11 | template 12 | class UniformRangeInitializer : public Initializer{ 13 | public: 14 | UniformRangeInitializer(std::map &setting, 15 | mshadow::Random* prnd) { 16 | this->prnd_ = prnd; 17 | SetupInitializer(setting); 18 | } 19 | virtual ~UniformRangeInitializer(void) {} 20 | 21 | virtual void Require(std::map &setting) { 22 | // default value, just set the value you want 23 | 24 | // require value, set to SettingV(), 25 | // it will force custom to set in config 26 | this->defaults["upper"] = SettingV(); 27 | this->defaults["lower"] = SettingV(); 28 | 29 | Initializer::Require(setting); 30 | } 31 | 32 | virtual void SetupInitializer(std::map &setting) { 33 | Initializer::SetupInitializer(setting); 34 | 35 | this->init_type = setting["init_type"].iVal(); 36 | if (this->init_type == kUniformRange) { 37 | this->lower = setting["lower"].fVal(); 38 | this->upper = setting["upper"].fVal(); 39 | utils::Check(lower < upper, "UniformRangeInitializer: range error."); 40 | } else if (this->init_type == kXavier) { 41 | // Todo 42 | } 43 | } 44 | 45 | virtual void DoInitialize(mshadow::Tensor data) { 46 | this->prnd_->SampleUniform(&data, lower, upper); 47 | } 48 | 49 | float lower, upper; 50 | }; 51 | } // namespace initializer 52 | } // namespace textnet 53 | #endif 54 | 55 | -------------------------------------------------------------------------------- /src/initializer/unitball_init-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_UNITBALL_INIT_INL_HPP_ 2 | #define TEXTNET_UNITBALL_INIT_INL_HPP_ 3 | 4 | #include 5 | #include "./initializer.h" 6 | 7 | namespace textnet { 8 | namespace initializer { 9 | 10 | template 11 | class UnitballInitializer : public Initializer{ 12 | public: 13 | UnitballInitializer(std::map &setting, 14 | mshadow::Random* prnd) { 15 | this->prnd_ = prnd; 16 | SetupInitializer(setting); 17 | } 18 | virtual ~UnitballInitializer(void) {} 19 | 20 | virtual void Require(std::map &setting) { 21 | // default value, just set the value you want 22 | this->defaults["mu"] = SettingV(0.0f); 23 | this->defaults["sigma"] = SettingV(1.0f); 24 | 25 | // require value, set to SettingV(), 26 | // it will force custom to set in config 27 | this->defaults["vec_len"] = SettingV(); 28 | 29 | Initializer::Require(setting); 30 | } 31 | 32 | virtual void SetupInitializer(std::map &setting) { 33 | Initializer::SetupInitializer(setting); 34 | 35 | this->init_type = setting["init_type"].iVal(); 36 | this->mu = setting["mu"].fVal(); 37 | this->sigma = setting["sigma"].fVal(); 38 | this->vec_len = setting["vec_len"].iVal(); 39 | } 40 | 41 | virtual void DoInitialize(mshadow::Tensor data) { 42 | this->prnd_->SampleGaussian(&data, mu, sigma); 43 | for (int i = 0; i < data.shape_.Size(); i += vec_len) { 44 | float norm = 0.0f; 45 | for (int j = 0; j < vec_len; ++j) { 46 | norm += data.dptr_[i+j] * data.dptr_[i+j]; 47 | } 48 | norm = sqrt(norm); 49 | for (int j = 0; j < vec_len; ++j) { 50 | data.dptr_[i+j] /= norm; 51 | } 52 | } 53 | } 54 | 55 | float mu; 56 | float sigma; 57 | int vec_len; 58 | }; 59 | } // namespace initializer 60 | } // namespace textnet 61 | #endif // TEXTNET_UNITBALL_INIT_INL_HPP_ 62 | 63 | -------------------------------------------------------------------------------- /src/initializer/var_init-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_VAR_INIT_INL_HPP_ 2 | #define TEXTNET_VAR_INIT_INL_HPP_ 3 | 4 | #include 5 | #include "./initializer.h" 6 | 7 | namespace textnet { 8 | namespace initializer { 9 | 10 | template 11 | class VarInitializer : public Initializer{ 12 | public: 13 | VarInitializer(std::map &setting, 14 | mshadow::Random* prnd) { 15 | this->prnd_ = prnd; 16 | SetupInitializer(setting); 17 | } 18 | virtual ~VarInitializer(void) {} 19 | 20 | virtual void Require(std::map &setting) { 21 | // default value, just set the value you want 22 | this->defaults["value"] = SettingV(0.0f); 23 | 24 | // require value, set to SettingV(), 25 | // it will force custom to set in config 26 | 27 | Initializer::Require(setting); 28 | } 29 | 30 | virtual void SetupInitializer(std::map &setting) { 31 | Initializer::SetupInitializer(setting); 32 | this->init_type = setting["init_type"].iVal(); 33 | value = setting["value"].fVal(); 34 | } 35 | 36 | virtual void DoInitialize(mshadow::Tensor data) { 37 | int init_size = data.shape_.Size(); 38 | utils::Check(init_size % 3 == 0, "In VarInit: init_size %% 3 != 0"); 39 | float * data_ptr = data.dptr_; 40 | for (int i = 0; i < init_size; i++) { 41 | if (i % 3 == 0) { 42 | data_ptr[i] = this->value; 43 | } else if (i % 3 == 1) { 44 | data_ptr[i] = 0.0f; 45 | } else { 46 | data_ptr[i] = -this->value; 47 | } 48 | } 49 | } 50 | 51 | float value; 52 | }; 53 | } // namespace initializer 54 | } // namespace textnet 55 | #endif // TEXTNET_VAR_INIT_INL_HPP_ 56 | 57 | -------------------------------------------------------------------------------- /src/layer/common/activation_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_ACTIVATION_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_ACTIVATION_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include "../layer.h" 6 | #include "../op.h" 7 | 8 | namespace textnet { 9 | namespace layer { 10 | 11 | template 12 | class ActivationLayer : public Layer{ 13 | public: 14 | ActivationLayer(LayerType type) { this->layer_type = type; } 15 | virtual ~ActivationLayer(void) {} 16 | 17 | virtual int BottomNodeNum() { return 1; } 18 | virtual int TopNodeNum() { return 1; } 19 | virtual int ParamNodeNum() { return 0; } 20 | 21 | virtual void Require() { 22 | // default value, just set the value you want 23 | 24 | // require value, set to SettingV(), 25 | // it will force custom to set in config 26 | 27 | Layer::Require(); 28 | } 29 | 30 | virtual void SetupLayer(std::map &setting, 31 | const std::vector*> &bottom, 32 | const std::vector*> &top, 33 | mshadow::Random *prnd) { 34 | Layer::SetupLayer(setting, bottom, top, prnd); 35 | } 36 | 37 | virtual void Reshape(const std::vector*> &bottom, 38 | const std::vector*> &top, 39 | bool show_info = false) { 40 | utils::Check(bottom.size() == BottomNodeNum(), 41 | "ActivationLayer:bottom size problem."); 42 | utils::Check(top.size() == TopNodeNum(), 43 | "ActivationLayer:top size problem."); 44 | top[0]->Resize(bottom[0]->data.shape_, bottom[0]->length.shape_); 45 | 46 | if (show_info) { 47 | bottom[0]->PrintShape("bottom0"); 48 | top[0]->PrintShape("top0"); 49 | } 50 | } 51 | 52 | virtual void CheckReshape(const std::vector*> &bottom, 53 | const std::vector*> &top) { 54 | // Check for reshape 55 | bool need_reshape = false; 56 | if (! (bottom[0]->data.shape_ == top[0]->data.shape_)) { 57 | need_reshape = true; 58 | } 59 | 60 | // Do reshape 61 | if (need_reshape) { 62 | this->Reshape(bottom, top); 63 | } 64 | } 65 | 66 | virtual void Forward(const std::vector*> &bottom, 67 | const std::vector*> &top) { 68 | using namespace mshadow::expr; 69 | top[0]->length = F(bottom[0]->length); 70 | top[0]->data = F(bottom[0]->data); 71 | } 72 | 73 | virtual void Backprop(const std::vector*> &bottom, 74 | const std::vector*> &top) { 75 | using namespace mshadow::expr; 76 | if (this->prop_error[0]) { 77 | bottom[0]->diff += F(top[0]->data) * top[0]->diff; 78 | } 79 | } 80 | }; 81 | } // namespace layer 82 | } // namespace textnet 83 | #endif // LAYER_ACTIVATION_LAYER_INL_HPP_ 84 | 85 | -------------------------------------------------------------------------------- /src/layer/common/batch_select_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_BATCH_SELECT_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_BATCH_SELECT_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "../layer.h" 11 | #include "../op.h" 12 | 13 | namespace textnet { 14 | namespace layer { 15 | 16 | template 17 | class BatchSelectLayer : public Layer{ 18 | public: 19 | BatchSelectLayer(LayerType type) { this->layer_type = type; } 20 | virtual ~BatchSelectLayer(void) {} 21 | 22 | virtual int BottomNodeNum() { return 1; } 23 | virtual int TopNodeNum() { return 1; } 24 | virtual int ParamNodeNum() { return 0; } 25 | 26 | virtual void Require() { 27 | // default value, just set the value you want 28 | 29 | // require value, set to SettingV(), 30 | // it will force custom to set in config 31 | this->defaults["step"] = SettingV(); 32 | 33 | Layer::Require(); 34 | } 35 | 36 | virtual void SetupLayer(std::map &setting, 37 | const std::vector*> &bottom, 38 | const std::vector*> &top, 39 | mshadow::Random *prnd) { 40 | Layer::SetupLayer(setting, bottom, top, prnd); 41 | 42 | step = setting["step"].iVal(); 43 | 44 | utils::Check(bottom.size() == BottomNodeNum(), 45 | "BatchSelectLayer:bottom size problem."); 46 | utils::Check(top.size() == TopNodeNum(), 47 | "BatchSelectLayer:top size problem."); 48 | 49 | } 50 | 51 | virtual void Reshape(const std::vector*> &bottom, 52 | const std::vector*> &top, 53 | bool show_info = false) { 54 | utils::Check(bottom.size() == BottomNodeNum(), 55 | "BatchSelectLayer:bottom size problem."); 56 | utils::Check(top.size() == TopNodeNum(), 57 | "BatchSelectLayer:top size problem."); 58 | 59 | nbatch = bottom[0]->data.size(0); 60 | utils::Check(nbatch % step == 0, 61 | "BatchSelectLayer: nbatch div step."); 62 | out_nbatch = nbatch / step; 63 | 64 | top[0]->Resize(out_nbatch, bottom[0]->data.size(1), bottom[0]->data.size(2), bottom[0]->data.size(3), out_nbatch, bottom[0]->length.size(1), true); 65 | 66 | if (show_info) { 67 | bottom[0]->PrintShape("bottom0"); 68 | top[0]->PrintShape("top0"); 69 | } 70 | } 71 | 72 | virtual void CheckReshape(const std::vector*> &bottom, 73 | const std::vector*> &top) { 74 | // Check for reshape 75 | bool need_reshape = false; 76 | if (nbatch != bottom[0]->data.size(0)) { 77 | need_reshape = true; 78 | } 79 | 80 | // Do reshape 81 | if (need_reshape) { 82 | this->Reshape(bottom, top); 83 | } 84 | } 85 | 86 | virtual void Forward(const std::vector*> &bottom, 87 | const std::vector*> &top) { 88 | using namespace mshadow::expr; 89 | mshadow::Tensor bottom_data2 = bottom[0]->data_d2(); 90 | mshadow::Tensor top_data2 = top[0]->data_d2(); 91 | mshadow::Tensor bottom_len = bottom[0]->length; 92 | mshadow::Tensor top_len = top[0]->length; 93 | 94 | for (int i = 0, j = 0; i < nbatch; i += step, j += 1) { 95 | top_data2[j] = F(bottom_data2[i]); 96 | top_len[j] = F(bottom_len[i]); 97 | } 98 | 99 | } 100 | 101 | virtual void Backprop(const std::vector*> &bottom, 102 | const std::vector*> &top) { 103 | using namespace mshadow::expr; 104 | mshadow::Tensor bottom_diff2 = bottom[0]->diff_d2(); 105 | mshadow::Tensor top_diff2 = top[0]->diff_d2(); 106 | 107 | for (int i = 0, j = 0; i < nbatch; i += step, j += 1) { 108 | bottom_diff2[i] += F(top_diff2[j]); 109 | } 110 | 111 | } 112 | 113 | protected: 114 | int nbatch; 115 | int out_nbatch; 116 | int step; 117 | 118 | }; 119 | } // namespace layer 120 | } // namespace textnet 121 | #endif // LAYER_BATCH_SELECT_LAYER_INL_HPP_ 122 | 123 | -------------------------------------------------------------------------------- /src/layer/common/conv_lstm_split_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_CONV_LSTM_SPLIT_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_CONV_LSTM_SPLIT_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "../layer.h" 11 | #include "../op.h" 12 | 13 | namespace textnet { 14 | namespace layer { 15 | 16 | template 17 | class ConvLstmSplitLayer : public Layer{ 18 | public: 19 | ConvLstmSplitLayer(LayerType type) { this->layer_type = type; } 20 | virtual ~ConvLstmSplitLayer(void) {} 21 | 22 | virtual int BottomNodeNum() { return 1; } 23 | virtual int TopNodeNum() { return 2; } 24 | virtual int ParamNodeNum() { return 0; } 25 | 26 | virtual void Require() { 27 | // default value, just set the value you want 28 | 29 | // require value, set to SettingV(), 30 | // it will force custom to set in config 31 | 32 | Layer::Require(); 33 | } 34 | 35 | virtual void SetupLayer(std::map &setting, 36 | const std::vector*> &bottom, 37 | const std::vector*> &top, 38 | mshadow::Random *prnd) { 39 | Layer::SetupLayer(setting, bottom, top, prnd); 40 | 41 | utils::Check(bottom.size() == BottomNodeNum(), "ConvLstmSplitLayer:bottom size problem."); 42 | utils::Check(top.size() == TopNodeNum(), "ConvLstmSplitLayer:top size problem."); 43 | 44 | } 45 | 46 | virtual void Reshape(const std::vector*> &bottom, 47 | const std::vector*> &top, 48 | bool show_info = false) { 49 | utils::Check(bottom.size() == BottomNodeNum(), "ConvLstmSplitLayer:bottom size problem."); 50 | utils::Check(top.size() == TopNodeNum(), "ConvLstmSplitLayer:top size problem."); 51 | 52 | batch_size= bottom[0]->data.size(0); 53 | doc_count = bottom[0]->data.size(1); 54 | doc_len = bottom[0]->data.size(2); 55 | feat_size = bottom[0]->data.size(3); 56 | 57 | utils::Assert(doc_count == 2, "ConvLstmSplitLayer:bottom size problem"); 58 | 59 | top[0]->Resize(batch_size, feat_size, doc_len, 1, true); 60 | top[1]->Resize(batch_size, feat_size, doc_len, 1, true); 61 | 62 | if (show_info) { 63 | bottom[0]->PrintShape("bottom0"); 64 | top[0]->PrintShape("top0"); 65 | top[1]->PrintShape("top1"); 66 | } 67 | } 68 | 69 | virtual void Forward(const std::vector*> &bottom, 70 | const std::vector*> &top) { 71 | using namespace mshadow::expr; 72 | mshadow::Tensor bottom_data = bottom[0]->data; 73 | mshadow::Tensor top0_data = top[0]->data; 74 | mshadow::Tensor top1_data = top[1]->data; 75 | 76 | for (index_t i = 0; i < batch_size; ++i) { 77 | // for (index_t j = 0; j < doc_count; ++j) { 78 | for (index_t m = 0; m < doc_len; ++m) { 79 | for (index_t n = 0; n < feat_size; ++n) { 80 | top0_data[i][n][m][0] = bottom_data[i][0][m][n]; 81 | top1_data[i][n][m][0] = bottom_data[i][1][m][n]; 82 | } 83 | } 84 | // } 85 | } 86 | } 87 | 88 | virtual void Backprop(const std::vector*> &bottom, 89 | const std::vector*> &top) { 90 | using namespace mshadow::expr; 91 | mshadow::Tensor bottom_diff = bottom[0]->diff; 92 | mshadow::Tensor top0_diff = top[0]->diff; 93 | mshadow::Tensor top1_diff = top[1]->diff; 94 | 95 | if (this->prop_error[0]) { 96 | for (index_t i = 0; i < batch_size; ++i) { 97 | // for (index_t j = 0; j < doc_count; ++j) { 98 | for (index_t m = 0; m < doc_len; ++m) { 99 | for (index_t n = 0; n < feat_size; ++n) { 100 | bottom_diff[i][0][m][n] += top0_diff[i][n][m][0]; 101 | bottom_diff[i][1][m][n] += top1_diff[i][n][m][0]; 102 | } 103 | } 104 | // } 105 | } 106 | } 107 | } 108 | 109 | protected: 110 | int batch_size; 111 | int doc_count; 112 | int doc_len; 113 | int feat_size; 114 | 115 | }; 116 | } // namespace layer 117 | } // namespace textnet 118 | #endif 119 | 120 | -------------------------------------------------------------------------------- /src/layer/common/conv_result_transform_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_CONV_RESULT_TRANSFORM_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_CONV_RESULT_TRANSFORM_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "../layer.h" 11 | #include "../op.h" 12 | 13 | namespace textnet { 14 | namespace layer { 15 | 16 | template 17 | class ConvResultTransformLayer : public Layer{ 18 | public: 19 | ConvResultTransformLayer(LayerType type) { this->layer_type = type; } 20 | virtual ~ConvResultTransformLayer(void) {} 21 | 22 | virtual int BottomNodeNum() { return 1; } 23 | virtual int TopNodeNum() { return 1; } 24 | virtual int ParamNodeNum() { return 0; } 25 | 26 | virtual void Require() { 27 | // default value, just set the value you want 28 | 29 | // require value, set to SettingV(), 30 | // it will force custom to set in config 31 | 32 | Layer::Require(); 33 | } 34 | 35 | virtual void SetupLayer(std::map &setting, 36 | const std::vector*> &bottom, 37 | const std::vector*> &top, 38 | mshadow::Random *prnd) { 39 | Layer::SetupLayer(setting, bottom, top, prnd); 40 | 41 | utils::Check(bottom.size() == BottomNodeNum(), "ConvResultTransformLayer:bottom size problem."); 42 | utils::Check(top.size() == TopNodeNum(), "ConvResultTransformLayer:top size problem."); 43 | } 44 | 45 | virtual void Reshape(const std::vector*> &bottom, 46 | const std::vector*> &top, 47 | bool show_info = false) { 48 | utils::Check(bottom.size() == BottomNodeNum(), "ConvResultTransformLayer:bottom size problem."); 49 | utils::Check(top.size() == TopNodeNum(), "ConvResultTransformLayer:top size problem."); 50 | 51 | int batch_size = bottom[0]->data.size(0); 52 | int channel_out = bottom[0]->data.size(1); 53 | int doc_len = bottom[0]->data.size(2); 54 | utils::Check(bottom[0]->data.size(3) == 1, "ConvResultTransformLayer: bottom size problem."); 55 | 56 | top[0]->Resize(batch_size, 1, doc_len, channel_out, true); 57 | 58 | if (show_info) { 59 | bottom[0]->PrintShape("bottom0"); 60 | top[0]->PrintShape("top0"); 61 | } 62 | } 63 | 64 | virtual void Forward(const std::vector*> &bottom, 65 | const std::vector*> &top) { 66 | mshadow::Tensor bottom_data = bottom[0]->data_d3(); 67 | mshadow::Tensor bottom_len = bottom[0]->length; 68 | mshadow::Tensor top_data = top[0]->data; 69 | mshadow::Tensor top_len = top[0]->length; 70 | 71 | for (int i = 0; i < bottom_data.size(0); ++i) { 72 | top_data[i][0] = bottom_data[i].T(); 73 | top_len[i][0] = bottom_len[i][0]; 74 | } 75 | } 76 | 77 | virtual void Backprop(const std::vector*> &bottom, 78 | const std::vector*> &top) { 79 | mshadow::Tensor bottom_diff = bottom[0]->diff_d3(); 80 | mshadow::Tensor top_diff = top[0]->diff; 81 | if (this->prop_error[0]) { 82 | for (int i = 0; i < bottom_diff.size(0); ++i) { 83 | bottom_diff[i] += top_diff[i][0].T(); 84 | } 85 | } 86 | } 87 | }; 88 | } // namespace layer 89 | } // namespace textnet 90 | #endif 91 | 92 | -------------------------------------------------------------------------------- /src/layer/common/cross_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_CROSS_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_CROSS_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "../layer.h" 11 | #include "../op.h" 12 | 13 | namespace textnet { 14 | namespace layer { 15 | 16 | template 17 | class CrossLayer : public Layer{ 18 | public: 19 | CrossLayer(LayerType type) { this->layer_type = type; } 20 | virtual ~CrossLayer(void) {} 21 | 22 | virtual int BottomNodeNum() { return 2; } 23 | virtual int TopNodeNum() { return 1; } 24 | virtual int ParamNodeNum() { return 0; } 25 | 26 | virtual void Require() { 27 | // default value, just set the value you want 28 | 29 | // require value, set to SettingV(), 30 | // it will force custom to set in config 31 | 32 | Layer::Require(); 33 | } 34 | 35 | virtual void SetupLayer(std::map &setting, 36 | const std::vector*> &bottom, 37 | const std::vector*> &top, 38 | mshadow::Random *prnd) { 39 | Layer::SetupLayer(setting, bottom, top, prnd); 40 | 41 | utils::Check(bottom.size() == BottomNodeNum(), 42 | "CrossLayer:bottom size problem."); 43 | utils::Check(top.size() == TopNodeNum(), 44 | "CrossLayer:top size problem."); 45 | 46 | } 47 | 48 | virtual void Reshape(const std::vector*> &bottom, 49 | const std::vector*> &top, 50 | bool show_info = false) { 51 | utils::Check(bottom.size() == BottomNodeNum(), 52 | "CrossLayer:bottom size problem."); 53 | utils::Check(top.size() == TopNodeNum(), 54 | "CrossLayer:top size problem."); 55 | 56 | nbatch = bottom[0]->data.size(0); 57 | channel = bottom[0]->data.size(1); 58 | doc_len = bottom[0]->data.size(2); 59 | 60 | top[0]->Resize(nbatch, channel, doc_len, doc_len, true); 61 | 62 | if (show_info) { 63 | bottom[0]->PrintShape("bottom0"); 64 | bottom[1]->PrintShape("bottom1"); 65 | top[0]->PrintShape("top0"); 66 | } 67 | } 68 | 69 | virtual void CheckReshape(const std::vector*> &bottom, 70 | const std::vector*> &top) { 71 | // Check for reshape 72 | bool need_reshape = false; 73 | if (nbatch != bottom[0]->data.size(0)) { 74 | need_reshape = true; 75 | } 76 | 77 | // Do reshape 78 | if (need_reshape) { 79 | this->Reshape(bottom, top); 80 | } 81 | } 82 | 83 | virtual void Forward(const std::vector*> &bottom, 84 | const std::vector*> &top) { 85 | using namespace mshadow::expr; 86 | mshadow::Tensor bottom0_data = bottom[0]->data_d3(); 87 | mshadow::Tensor bottom1_data = bottom[1]->data_d3(); 88 | mshadow::Tensor top_data = top[0]->data; 89 | 90 | for (int i = 0; i < nbatch; i++) { 91 | for (int j = 0; j < channel; j++) { 92 | top_data[i][j] = broadcast<0>(bottom0_data[i][j], top_data[i][j].shape_) + 93 | broadcast<1>(bottom1_data[i][j], top_data[i][j].shape_); 94 | } 95 | } 96 | 97 | } 98 | 99 | virtual void Backprop(const std::vector*> &bottom, 100 | const std::vector*> &top) { 101 | using namespace mshadow::expr; 102 | mshadow::Tensor bottom0_diff = bottom[0]->diff_d3(); 103 | mshadow::Tensor bottom1_diff = bottom[1]->diff_d3(); 104 | mshadow::Tensor top_diff = top[0]->diff; 105 | 106 | for (int i = 0; i < nbatch; i++) { 107 | for (int j = 0; j < channel; j++) { 108 | bottom0_diff[i][j] += sumall_except_dim<0>(top_diff[i][j]); 109 | bottom1_diff[i][j] += sumall_except_dim<1>(top_diff[i][j]); 110 | } 111 | } 112 | } 113 | 114 | protected: 115 | int doc_len; 116 | int nbatch; 117 | int channel; 118 | 119 | }; 120 | } // namespace layer 121 | } // namespace textnet 122 | #endif // LAYER_CROSS_LAYER_INL_HPP_ 123 | 124 | -------------------------------------------------------------------------------- /src/layer/common/dropout_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_DROPOUT_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_DROPOUT_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "../layer.h" 11 | #include "../op.h" 12 | 13 | namespace textnet { 14 | namespace layer { 15 | 16 | template 17 | class DropoutLayer : public Layer{ 18 | public: 19 | DropoutLayer(LayerType type) { this->layer_type = type; } 20 | virtual ~DropoutLayer(void) {} 21 | 22 | virtual int BottomNodeNum() { return 1; } 23 | virtual int TopNodeNum() { return 1; } 24 | virtual int ParamNodeNum() { return 0; } 25 | 26 | virtual void Require() { 27 | // default value, just set the value you want 28 | this->defaults["rate"] = SettingV(0.5f); 29 | // require value, set to SettingV(), 30 | // it will force custom to set in config 31 | 32 | Layer::Require(); 33 | } 34 | 35 | virtual void SetupLayer(std::map &setting, 36 | const std::vector*> &bottom, 37 | const std::vector*> &top, 38 | mshadow::Random *prnd) { 39 | Layer::SetupLayer(setting, bottom, top, prnd); 40 | 41 | utils::Check(bottom.size() == BottomNodeNum(), 42 | "DropoutLayer:bottom size problem."); 43 | utils::Check(top.size() == TopNodeNum(), 44 | "DropoutLayer:top size problem."); 45 | 46 | rate = setting["rate"].fVal(); 47 | utils::Check(rate >= 0.0 && rate <= 1.0, 48 | "Dropout rate must between 0.0 and 1.0."); 49 | } 50 | 51 | virtual void Reshape(const std::vector*> &bottom, 52 | const std::vector*> &top, 53 | bool show_info = false) { 54 | utils::Check(bottom.size() == BottomNodeNum(), 55 | "DropoutLayer:bottom size problem."); 56 | utils::Check(top.size() == TopNodeNum(), 57 | "DropoutLayer:top size problem."); 58 | 59 | top[0]->Resize(bottom[0]->data.shape_, bottom[0]->length.shape_, true); 60 | mask.Resize(bottom[0]->data.shape_, true); 61 | 62 | if (show_info) { 63 | bottom[0]->PrintShape("bottom0"); 64 | top[0]->PrintShape("top0"); 65 | } 66 | } 67 | 68 | virtual void CheckReshape(const std::vector*> &bottom, 69 | const std::vector*> &top) { 70 | // Check for reshape 71 | bool need_reshape = false; 72 | if (! (bottom[0]->data.shape_ == top[0]->data.shape_)) { 73 | need_reshape = true; 74 | } 75 | 76 | // Do reshape 77 | if (need_reshape) { 78 | this->Reshape(bottom, top); 79 | } 80 | } 81 | 82 | virtual void Forward(const std::vector*> &bottom, 83 | const std::vector*> &top) { 84 | using namespace mshadow::expr; 85 | mshadow::Tensor bottom_data = bottom[0]->data; 86 | mshadow::Tensor top_data = top[0]->data; 87 | top[0]->length = F(bottom[0]->length); 88 | 89 | const float pkeep = 1.0f - rate; 90 | if (this->phrase_type == kTrain) { 91 | mask = F(this->prnd_->uniform(mask.shape_), pkeep); 92 | top_data = bottom_data * mask; 93 | } else { 94 | top_data = bottom_data * pkeep; 95 | } 96 | } 97 | 98 | virtual void Backprop(const std::vector*> &bottom, 99 | const std::vector*> &top) { 100 | using namespace mshadow::expr; 101 | mshadow::Tensor bottom_diff = bottom[0]->diff; 102 | mshadow::Tensor top_diff = top[0]->diff; 103 | if (this->prop_error[0]) { 104 | bottom_diff += top_diff * mask; 105 | } 106 | } 107 | 108 | protected: 109 | float rate; 110 | mshadow::TensorContainer mask; 111 | 112 | }; 113 | } // namespace layer 114 | } // namespace textnet 115 | #endif // LAYER_DROPOUT_LAYER_INL_HPP_ 116 | 117 | -------------------------------------------------------------------------------- /src/layer/common/duplicate4lstm_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_DUPLICATE4LSTM_INL_HPP_ 2 | #define TEXTNET_LAYER_DUPLICATE4LSTM_INL_HPP_ 3 | 4 | #include 5 | #include "../layer.h" 6 | #include "../op.h" 7 | #include "../../utils/utils.h" 8 | 9 | namespace textnet { 10 | namespace layer { 11 | 12 | template 13 | class Duplicate4lstmLayer : public Layer { 14 | public: 15 | Duplicate4lstmLayer(LayerType type) { this->layer_type = type; } 16 | virtual ~Duplicate4lstmLayer(void) {} 17 | 18 | virtual int BottomNodeNum() { return 1; } 19 | virtual int TopNodeNum() { return 1; } 20 | virtual int ParamNodeNum() { return 0; } 21 | 22 | virtual void Require() { 23 | // default value, just set the value you want 24 | 25 | // require value, set to SettingV(), 26 | // it will force custom to set in config 27 | this->defaults["num_duplicate"] = SettingV(); 28 | 29 | Layer::Require(); 30 | } 31 | 32 | virtual void SetupLayer(std::map &setting, 33 | const std::vector*> &bottom, 34 | const std::vector*> &top, 35 | mshadow::Random *prnd) { 36 | Layer::SetupLayer(setting, bottom, top, prnd); 37 | 38 | utils::Check(bottom.size() == BottomNodeNum(), 39 | "Duplicate4lstmLayer:bottom size problem."); 40 | utils::Check(top.size() == TopNodeNum(), 41 | "Duplicate4lstmLayer:top size problem."); 42 | 43 | num_duplicate = setting["num_duplicate"].iVal(); 44 | } 45 | 46 | virtual void Reshape(const std::vector*> &bottom, 47 | const std::vector*> &top, 48 | bool show_info = false) { 49 | utils::Check(bottom.size() == BottomNodeNum(), 50 | "Duplicate4lstmLayer:bottom size problem."); 51 | utils::Check(top.size() == TopNodeNum(), 52 | "Duplicate4lstmLayer:top size problem."); 53 | 54 | mshadow::Shape<4> shape_in = bottom[0]->data.shape_; 55 | mshadow::Shape<4> shape_out = shape_in; 56 | shape_out[2] *= num_duplicate; 57 | 58 | top[0]->Resize(shape_out, true); 59 | 60 | if (show_info) { 61 | bottom[0]->PrintShape("bottom0"); 62 | top[0]->PrintShape("top0"); 63 | } 64 | } 65 | 66 | virtual void Forward(const std::vector*> &bottom, 67 | const std::vector*> &top) { 68 | using namespace mshadow::expr; 69 | mshadow::Tensor bottom_data = bottom[0]->data; 70 | mshadow::Tensor bottom_len = bottom[0]->length; 71 | mshadow::Tensor top_data = top[0]->data; 72 | mshadow::Tensor top_len = top[0]->length; 73 | 74 | for (int batch_idx = 0; batch_idx < bottom_data.size(0); ++batch_idx) { 75 | for (int seq_idx = 0; seq_idx < bottom_data.size(1); ++seq_idx) { 76 | int length = bottom_len[batch_idx][seq_idx]; 77 | top_len[batch_idx][seq_idx] = length * num_duplicate; 78 | for (int m = 0; m < num_duplicate; ++m) { 79 | for (int n = 0; n < length; ++n) { 80 | top_data[batch_idx][seq_idx][m*length+n] = F(bottom_data[batch_idx][seq_idx][n]); 81 | } 82 | } 83 | } 84 | } 85 | } 86 | 87 | virtual void Backprop(const std::vector*> &bottom, 88 | const std::vector*> &top) { 89 | using namespace mshadow::expr; 90 | mshadow::Tensor bottom_diff = bottom[0]->diff; 91 | mshadow::Tensor bottom_len = bottom[0]->length; 92 | mshadow::Tensor top_diff = top[0]->diff; 93 | 94 | for (int batch_idx = 0; batch_idx < bottom_diff.size(0); ++batch_idx) { 95 | for (int seq_idx = 0; seq_idx < bottom_diff.size(1); ++seq_idx) { 96 | int length = bottom_len[batch_idx][seq_idx]; 97 | for (int m = 0; m < num_duplicate; ++m) { 98 | for (int n = 0; n < length; ++n) { 99 | bottom_diff[batch_idx][seq_idx][n] += top_diff[batch_idx][seq_idx][m*length+n]; 100 | } 101 | } 102 | } 103 | } 104 | } 105 | 106 | protected: 107 | /*! \brief random number generator */ 108 | int num_duplicate; 109 | }; 110 | } // namespace layer 111 | } // namespace textnet 112 | #endif 113 | -------------------------------------------------------------------------------- /src/layer/common/elu_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_ELU_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_ELU_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include "../layer.h" 6 | #include "../op.h" 7 | 8 | namespace textnet { 9 | namespace layer { 10 | 11 | template 12 | class ELULayer : public Layer{ 13 | public: 14 | ELULayer(LayerType type) { this->layer_type = type; } 15 | virtual ~ELULayer(void) {} 16 | 17 | virtual int BottomNodeNum() { return 1; } 18 | virtual int TopNodeNum() { return 1; } 19 | virtual int ParamNodeNum() { return 0; } 20 | 21 | virtual void Require() { 22 | // default value, just set the value you want 23 | this->defaults["b"] = SettingV(); 24 | 25 | // require value, set to SettingV(), 26 | // it will force custom to set in config 27 | 28 | Layer::Require(); 29 | } 30 | 31 | virtual void SetupLayer(std::map &setting, 32 | const std::vector*> &bottom, 33 | const std::vector*> &top, 34 | mshadow::Random *prnd) { 35 | Layer::SetupLayer(setting, bottom, top, prnd); 36 | 37 | b = setting["b"].fVal(); 38 | utils::Check(b >= 0.0f, "ELU Layer: parameter b must non-negative."); 39 | } 40 | 41 | virtual void Reshape(const std::vector*> &bottom, 42 | const std::vector*> &top, 43 | bool show_info = false) { 44 | utils::Check(bottom.size() == BottomNodeNum(), 45 | "ELULayer:bottom size problem."); 46 | utils::Check(top.size() == TopNodeNum(), 47 | "ELULayer:top size problem."); 48 | top[0]->Resize(bottom[0]->data.shape_, bottom[0]->length.shape_); 49 | 50 | if (show_info) { 51 | bottom[0]->PrintShape("bottom0"); 52 | top[0]->PrintShape("top0"); 53 | } 54 | } 55 | 56 | virtual void CheckReshape(const std::vector*> &bottom, 57 | const std::vector*> &top) { 58 | // Check for reshape 59 | bool need_reshape = false; 60 | if (! (bottom[0]->data.shape_ == top[0]->data.shape_)) { 61 | need_reshape = true; 62 | } 63 | 64 | // Do reshape 65 | if (need_reshape) { 66 | this->Reshape(bottom, top); 67 | } 68 | } 69 | 70 | virtual void Forward(const std::vector*> &bottom, 71 | const std::vector*> &top) { 72 | using namespace mshadow::expr; 73 | top[0]->length = F(bottom[0]->length); 74 | top[0]->data = F(bottom[0]->data, b); 75 | } 76 | 77 | virtual void Backprop(const std::vector*> &bottom, 78 | const std::vector*> &top) { 79 | using namespace mshadow::expr; 80 | if (this->prop_error[0]) { 81 | bottom[0]->diff += F(top[0]->data, b) * top[0]->diff; 82 | } 83 | } 84 | 85 | protected: 86 | float b; 87 | 88 | }; 89 | } // namespace layer 90 | } // namespace textnet 91 | #endif // LAYER_ELU_LAYER_INL_HPP_ 92 | 93 | -------------------------------------------------------------------------------- /src/layer/common/flatten_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_FLATTEN_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_FLATTEN_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "../layer.h" 11 | #include "../op.h" 12 | 13 | namespace textnet { 14 | namespace layer { 15 | 16 | template 17 | class FlattenLayer : public Layer{ 18 | public: 19 | FlattenLayer(LayerType type) { this->layer_type = type; } 20 | virtual ~FlattenLayer(void) {} 21 | 22 | virtual int BottomNodeNum() { return 1; } 23 | virtual int TopNodeNum() { return 1; } 24 | virtual int ParamNodeNum() { return 0; } 25 | 26 | virtual void Require() { 27 | // default value, just set the value you want 28 | 29 | // require value, set to SettingV(), 30 | // it will force custom to set in config 31 | this->defaults["axis1"] = SettingV(); 32 | this->defaults["axis2"] = SettingV(); 33 | 34 | Layer::Require(); 35 | } 36 | 37 | virtual void SetupLayer(std::map &setting, 38 | const std::vector*> &bottom, 39 | const std::vector*> &top, 40 | mshadow::Random *prnd) { 41 | Layer::SetupLayer(setting, bottom, top, prnd); 42 | 43 | utils::Check(bottom.size() == BottomNodeNum(), 44 | "FlattenLayer:bottom size problem."); 45 | utils::Check(top.size() == TopNodeNum(), 46 | "FlattenLayer:top size problem."); 47 | 48 | axis1 = setting["axis1"].iVal(); 49 | axis2 = setting["axis2"].iVal(); 50 | if (axis1 > axis2) { 51 | int temp = axis1; 52 | axis1 = axis2; 53 | axis2 = temp; 54 | } 55 | utils::Check(axis1 != axis2, "SwapAxisLayer: axis1 == axis2."); 56 | } 57 | 58 | virtual void Reshape(const std::vector*> &bottom, 59 | const std::vector*> &top, 60 | bool show_info = false) { 61 | utils::Check(bottom.size() == BottomNodeNum(), 62 | "FlattenLayer:bottom size problem."); 63 | utils::Check(top.size() == TopNodeNum(), 64 | "FlattenLayer:top size problem."); 65 | 66 | bottom_shape = bottom[0]->data.shape_; 67 | 68 | int j = 0; 69 | for (int i = 0; i < 4; ++i) { 70 | top_shape[i] = 1; 71 | if (i < axis1) { 72 | top_shape[j] = bottom_shape[i]; 73 | j++; 74 | } else if (i <= axis2) { 75 | top_shape[j] *= bottom_shape[i]; 76 | } else { 77 | j++; 78 | top_shape[j] = bottom_shape[i]; 79 | } 80 | } 81 | 82 | top[0]->Resize(top_shape, true); 83 | 84 | if (show_info) { 85 | bottom[0]->PrintShape("bottom0"); 86 | top[0]->PrintShape("top0"); 87 | } 88 | } 89 | 90 | virtual void CheckReshape(const std::vector*> &bottom, 91 | const std::vector*> &top) { 92 | // Check for reshape 93 | bool need_reshape = false; 94 | if (! (bottom[0]->data.shape_ == bottom_shape)) { 95 | need_reshape = true; 96 | } 97 | 98 | // Do reshape 99 | if (need_reshape) { 100 | this->Reshape(bottom, top); 101 | } 102 | } 103 | 104 | virtual void Forward(const std::vector*> &bottom, 105 | const std::vector*> &top) { 106 | using namespace mshadow::expr; 107 | mshadow::Tensor bottom_data = bottom[0]->data; 108 | mshadow::Tensor bottom_len = bottom[0]->length; 109 | mshadow::Tensor top_data = top[0]->data; 110 | mshadow::Tensor top_len = top[0]->length; 111 | 112 | top_data = reshape(bottom_data, top_shape); 113 | 114 | } 115 | 116 | virtual void Backprop(const std::vector*> &bottom, 117 | const std::vector*> &top) { 118 | using namespace mshadow::expr; 119 | mshadow::Tensor bottom_diff = bottom[0]->diff; 120 | mshadow::Tensor top_diff = top[0]->diff; 121 | if (this->prop_error[0]) { 122 | bottom_diff += reshape(top_diff, bottom_shape); 123 | } 124 | } 125 | 126 | protected: 127 | int axis1; 128 | int axis2; 129 | mshadow::Shape<4> top_shape; 130 | mshadow::Shape<4> bottom_shape; 131 | 132 | }; 133 | } // namespace layer 134 | } // namespace textnet 135 | #endif // LAYER_FLATTEN_LAYER_INL_HPP_ 136 | 137 | -------------------------------------------------------------------------------- /src/layer/common/length_fill_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_LENGTH_FILL_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_LENGTH_FILL_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "../layer.h" 11 | #include "../op.h" 12 | 13 | namespace textnet { 14 | namespace layer { 15 | 16 | template 17 | class LengthFillLayer : public Layer{ 18 | public: 19 | LengthFillLayer(LayerType type) { this->layer_type = type; } 20 | virtual ~LengthFillLayer(void) {} 21 | 22 | virtual int BottomNodeNum() { return 2; } 23 | virtual int TopNodeNum() { return 1; } 24 | virtual int ParamNodeNum() { return 0; } 25 | 26 | virtual void Require() { 27 | // default value, just set the value you want 28 | this->defaults["mode"] = SettingV("data"); // data or length 29 | 30 | // require value, set to SettingV(), 31 | // it will force custom to set in config 32 | 33 | 34 | Layer::Require(); 35 | } 36 | 37 | virtual void SetupLayer(std::map &setting, 38 | const std::vector*> &bottom, 39 | const std::vector*> &top, 40 | mshadow::Random *prnd) { 41 | Layer::SetupLayer(setting, bottom, top, prnd); 42 | 43 | mode = setting["mode"].sVal(); 44 | 45 | } 46 | 47 | virtual void Reshape(const std::vector*> &bottom, 48 | const std::vector*> &top, 49 | bool show_info = false) { 50 | utils::Check(bottom.size() == BottomNodeNum(), 51 | "LengthFillLayer:bottom size problem."); 52 | utils::Check(top.size() == TopNodeNum(), 53 | "LengthFillLayer:top size problem."); 54 | 55 | nbatch = bottom[0]->data.size(0); 56 | 57 | top[0]->Resize(nbatch, bottom[0]->data.size(1), bottom[0]->data.size(2), bottom[0]->data.size(3), 58 | bottom[1]->data.size(0), bottom[1]->data.size(1), true); 59 | 60 | if (show_info) { 61 | bottom[0]->PrintShape("bottom0"); 62 | bottom[1]->PrintShape("bottom1"); 63 | top[0]->PrintShape("top0"); 64 | } 65 | } 66 | 67 | virtual void CheckReshape(const std::vector*> &bottom, 68 | const std::vector*> &top) { 69 | // Check for reshape 70 | bool need_reshape = false; 71 | if (nbatch != bottom[0]->data.size(0)) { 72 | need_reshape = true; 73 | } 74 | 75 | // Do reshape 76 | if (need_reshape) { 77 | this->Reshape(bottom, top); 78 | } 79 | } 80 | 81 | virtual void Forward(const std::vector*> &bottom, 82 | const std::vector*> &top) { 83 | using namespace mshadow::expr; 84 | mshadow::Tensor bottom0_data = bottom[0]->data; 85 | mshadow::Tensor bottom1_data = bottom[1]->data_d2(); 86 | mshadow::Tensor bottom1_len = bottom[1]->length; 87 | mshadow::Tensor top_data = top[0]->data; 88 | mshadow::Tensor top_len = top[0]->length; 89 | 90 | // Directly copy data 91 | top_data = F(bottom0_data); 92 | if( mode == "data") { 93 | top_len = F(bottom1_data); 94 | }else if(mode == "length") { 95 | top_len = F(bottom1_len); 96 | }else { 97 | utils::Check(0, "LengthFillLayer: mode should be data or length."); 98 | } 99 | } 100 | 101 | virtual void Backprop(const std::vector*> &bottom, 102 | const std::vector*> &top) { 103 | using namespace mshadow::expr; 104 | mshadow::Tensor bottom_diff = bottom[0]->diff; 105 | mshadow::Tensor top_diff = top[0]->diff; 106 | 107 | // Directly copy data 108 | bottom_diff += F(top_diff); 109 | 110 | } 111 | 112 | protected: 113 | int nbatch; 114 | string mode; 115 | 116 | }; 117 | } // namespace layer 118 | } // namespace textnet 119 | #endif // LAYER_LENGTH_FILL_LAYER_INL_HPP_ 120 | 121 | -------------------------------------------------------------------------------- /src/layer/common/lr2softmax_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_LR2SOFTMAX_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_LR2SOFTMAX_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include "../layer.h" 6 | #include "../op.h" 7 | #include "../../utils/utils.h" 8 | 9 | namespace textnet { 10 | namespace layer { 11 | 12 | // sum aross one axis 13 | template 14 | class Lr2softmaxLayer : public Layer { 15 | public: 16 | Lr2softmaxLayer(LayerType type) { this->layer_type = type; } 17 | virtual ~Lr2softmaxLayer(void) {} 18 | 19 | virtual int BottomNodeNum() { return 1; } 20 | virtual int TopNodeNum() { return 1; } 21 | virtual int ParamNodeNum() { return 1; } 22 | 23 | virtual void Require() { 24 | // default value, just set the value you want 25 | 26 | // require value, set to SettingV(), 27 | // it will force custom to set in config 28 | this->defaults["score_class"] = SettingV(); // the other class will be pad as zero 29 | this->defaults["rescale"] = SettingV(); // this is to rescale the score value 30 | 31 | Layer::Require(); 32 | } 33 | 34 | virtual void SetupLayer(std::map &setting, 35 | const std::vector*> &bottom, 36 | const std::vector*> &top, 37 | mshadow::Random *prnd) { 38 | Layer::SetupLayer(setting, bottom, top, prnd); 39 | 40 | utils::Check(bottom.size() == BottomNodeNum(), "Lr2softmaxLayer:bottom size problem."); 41 | utils::Check(top.size() == TopNodeNum(), "Lr2softmaxLayer:top size problem."); 42 | this->param_file = setting["param_file"].sVal(); 43 | score_class = setting["score_class"].iVal(); 44 | rescale = setting["rescale"].fVal(); 45 | utils::Check(0 == score_class || 1 == score_class, "Lr2softmaxLayer: score class setting error."); 46 | 47 | this->params.resize(1); 48 | this->params[0].Resize(1, 1, 1, 1, true); 49 | std::map &b_setting = *setting["b_filler"].mVal(); 50 | this->params[0].initializer_ = 51 | initializer::CreateInitializer(b_setting["init_type"].iVal(), 52 | b_setting, this->prnd_); 53 | this->params[0].Init(); 54 | 55 | std::map &b_updater = *setting["b_updater"].mVal(); 56 | this->params[0].updater_ = 57 | updater::CreateUpdater(b_updater["updater_type"].iVal(), 58 | b_updater, this->prnd_); 59 | if (!this->param_file.empty()) { 60 | this->LoadParams(); 61 | } 62 | } 63 | 64 | virtual void Reshape(const std::vector*> &bottom, 65 | const std::vector*> &top, 66 | bool show_info = false) { 67 | utils::Check(bottom.size() == BottomNodeNum(), "Lr2softmaxLayer:bottom size problem."); 68 | utils::Check(top.size() == TopNodeNum(), "Lr2softmaxLayer:top size problem."); 69 | 70 | mshadow::Shape<4> shape_in = bottom[0]->data.shape_; 71 | utils::Check(1 == shape_in[1] && 1 == shape_in[2] && 1 == shape_in[3], "Lr2softmaxLayer: input size error."); 72 | mshadow::Shape<4> shape_out= shape_in; 73 | shape_out[1] = 2; 74 | 75 | top[0]->Resize(shape_out, true); 76 | 77 | if (show_info) { 78 | bottom[0]->PrintShape("bottom0"); 79 | top[0]->PrintShape("top0"); 80 | } 81 | } 82 | 83 | virtual void Forward(const std::vector*> &bottom, 84 | const std::vector*> &top) { 85 | mshadow::Tensor bottom_data = bottom[0]->data_d1(); 86 | mshadow::Tensor top_data = top[0]->data_d2(); 87 | mshadow::Tensor b_data = this->params[0].data_d1(); 88 | top_data = 0.f; 89 | int bias_class = score_class == 0 ? 1 : 0; 90 | for (int i = 0; i < bottom_data.size(0); ++i) { 91 | top_data[i][score_class] = bottom_data[i] * rescale; 92 | top_data[i][bias_class] = b_data[0]; 93 | } 94 | } 95 | 96 | virtual void Backprop(const std::vector*> &bottom, 97 | const std::vector*> &top) { 98 | mshadow::Tensor bottom_diff = bottom[0]->diff_d1(); 99 | mshadow::Tensor top_diff = top[0]->diff_d2(); 100 | mshadow::Tensor b_diff = this->params[0].diff_d1(); 101 | int bias_class = score_class == 0 ? 1 : 0; 102 | for (int i = 0; i < bottom_diff.size(0); ++i) { 103 | bottom_diff[i] += top_diff[i][score_class]; 104 | b_diff[0] += top_diff[i][bias_class]; 105 | } 106 | } 107 | protected: 108 | int score_class; 109 | float rescale; 110 | }; 111 | } // namespace layer 112 | } // namespace textnet 113 | #endif 114 | -------------------------------------------------------------------------------- /src/layer/common/match_combine_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_MATCH_COMBINE_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_MATCH_COMBINE_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include "../layer.h" 6 | #include "../op.h" 7 | #include 8 | 9 | namespace textnet { 10 | namespace layer { 11 | 12 | template 13 | class MatchCombineLayer : public Layer{ 14 | public: 15 | MatchCombineLayer(LayerType type) { this->layer_type = type; } 16 | virtual ~MatchCombineLayer(void) {} 17 | 18 | virtual int BottomNodeNum() { return 2; } 19 | virtual int TopNodeNum() { return 1; } 20 | virtual int ParamNodeNum() { return 0; } 21 | 22 | virtual void Require() { 23 | // default value, just set the value you want 24 | // this->defaults["dim"] = SettingV(2); 25 | // this->defaults["is_constraint"] = SettingV(false); 26 | 27 | // require value, set to SettingV(), 28 | // it will force custom to set in config 29 | //this->defaults["k"] = SettingV(); 30 | 31 | Layer::Require(); 32 | } 33 | 34 | virtual void SetupLayer(std::map &setting, 35 | const std::vector*> &bottom, 36 | const std::vector*> &top, 37 | mshadow::Random *prnd) { 38 | Layer::SetupLayer(setting, bottom, top, prnd); 39 | //k = setting["k"].iVal(); 40 | } 41 | 42 | virtual void Reshape(const std::vector*> &bottom, 43 | const std::vector*> &top, 44 | bool show_info = false) { 45 | utils::Check(bottom.size() == BottomNodeNum(), "MatchCombineLayer: bottom size problem."); 46 | utils::Check(top.size() == TopNodeNum(), "MatchCombineLayer: top size problem."); 47 | utils::Check(bottom[0]->data.shape_ == bottom[1]->data.shape_, "MatchCombineLayer: bottom 0 size should be equal to bottom 1 size."); 48 | 49 | mshadow::Shape<4> shape_out = bottom[0]->data.shape_; 50 | mshadow::Shape<2> shape_length = bottom[0]->length.shape_; 51 | top[0]->Resize(shape_out, shape_length, true); 52 | 53 | if (show_info) { 54 | bottom[0]->PrintShape("bottom0"); 55 | bottom[1]->PrintShape("bottom1"); 56 | top[0]->PrintShape("top0"); 57 | } 58 | } 59 | 60 | virtual void CheckReshape(const std::vector*> &bottom, 61 | const std::vector*> &top) { 62 | // Check for reshape 63 | bool need_reshape = false; 64 | 65 | if (top[0]->data.shape_[0] != bottom[0]->data.shape_[0]) { 66 | need_reshape = true; 67 | } 68 | 69 | // Do reshape 70 | if (need_reshape) { 71 | this->Reshape(bottom, top); 72 | } 73 | } 74 | 75 | 76 | typedef mshadow::Tensor Tensor2D; 77 | typedef mshadow::Tensor Tensor2DInt; 78 | 79 | virtual void Forward(const std::vector*> &bottom, 80 | const std::vector*> &top) { 81 | using namespace mshadow::expr; 82 | mshadow::Tensor bottom0_data = bottom[0]->data; 83 | mshadow::Tensor bottom1_data = bottom[1]->data; 84 | mshadow::Tensor top_data = top[0]->data; 85 | top[0]->length = F(bottom[0]->length); 86 | 87 | top_data = 0; 88 | for (index_t batch_idx = 0; batch_idx < bottom0_data.size(0); ++batch_idx) { 89 | for (index_t channel_idx = 0; channel_idx < bottom0_data.size(1); ++channel_idx) { 90 | for( index_t i = 0 ; i < bottom0_data.size(2); ++ i){ 91 | for( index_t j = 0 ; j < bottom0_data.size(3); ++ j){ 92 | if( abs(bottom1_data[batch_idx][channel_idx][i][j] - 1.0) < 1e-4 ){ 93 | top_data[batch_idx][channel_idx][i][j] = bottom1_data[batch_idx][channel_idx][i][j]; 94 | }else{ 95 | top_data[batch_idx][channel_idx][i][j] = bottom0_data[batch_idx][channel_idx][i][j]; 96 | } 97 | } 98 | } 99 | } 100 | } 101 | } 102 | 103 | virtual void Backprop(const std::vector*> &bottom, 104 | const std::vector*> &top) { 105 | using namespace mshadow::expr; 106 | } 107 | 108 | protected: 109 | }; 110 | } // namespace layer 111 | } // namespace textnet 112 | #endif 113 | -------------------------------------------------------------------------------- /src/layer/common/memory_attention_in_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_MEMORY_ATTENTION_IN_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_MEMORY_ATTENTION_IN_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include "../layer.h" 6 | #include "../op.h" 7 | #include "../../utils/utils.h" 8 | 9 | namespace textnet { 10 | namespace layer { 11 | 12 | template 13 | class MemoryAttentionInLayer : public Layer { 14 | public: 15 | MemoryAttentionInLayer(LayerType type) { this->layer_type = type; } 16 | virtual ~MemoryAttentionInLayer(void) {} 17 | 18 | virtual int BottomNodeNum() { return 2; } 19 | virtual int TopNodeNum() { return 1; } 20 | virtual int ParamNodeNum() { return 0; } 21 | 22 | virtual void Require() { 23 | // default value, just set the value you want 24 | 25 | // require value, set to SettingV(), 26 | // it will force custom to set in config 27 | 28 | Layer::Require(); 29 | } 30 | 31 | virtual void SetupLayer(std::map &setting, 32 | const std::vector*> &bottom, 33 | const std::vector*> &top, 34 | mshadow::Random *prnd) { 35 | Layer::SetupLayer(setting, bottom, top, prnd); 36 | 37 | utils::Check(bottom.size() == BottomNodeNum(), "MemoryAttentionInLayer:bottom size problem."); 38 | utils::Check(top.size() == TopNodeNum(), "MemoryAttentionInLayer:top size problem."); 39 | } 40 | 41 | virtual void Reshape(const std::vector*> &bottom, 42 | const std::vector*> &top, 43 | bool show_info = false) { 44 | utils::Check(bottom.size() == BottomNodeNum(), "MemoryAttentionInLayer:bottom size problem."); 45 | utils::Check(top.size() == TopNodeNum(), "MemoryAttentionInLayer:top size problem."); 46 | 47 | mshadow::Shape<4> shape_memory = bottom[0]->data.shape_; 48 | mshadow::Shape<4> shape_query = bottom[1]->data.shape_; 49 | 50 | utils::Check(shape_memory[0] == 1, "MemoryAttentionInLayer: Shared memory batch size should equal to 1."); 51 | utils::Check(shape_memory[3] == shape_query[3], "MemoryAttentionInLayer: feat size need equal."); 52 | 53 | top[0]->Resize(shape_query[0], shape_memory[1], 1, 1, 1, 1, true); 54 | 55 | if (show_info) { 56 | bottom[0]->PrintShape("bottom0"); 57 | bottom[1]->PrintShape("bottom1"); 58 | top[0]->PrintShape("top0"); 59 | } 60 | } 61 | 62 | virtual void Forward(const std::vector*> &bottom, 63 | const std::vector*> &top) { 64 | using namespace mshadow::expr; 65 | mshadow::Tensor bottom0_data = bottom[0]->data_d2_middle(); 66 | mshadow::Tensor bottom1_data = bottom[1]->data_d2(); 67 | mshadow::Tensor top_data = top[0]->data_d2(); 68 | 69 | top_data = dot(bottom1_data, bottom0_data.T()); 70 | } 71 | 72 | virtual void Backprop(const std::vector*> &bottom, 73 | const std::vector*> &top) { 74 | using namespace mshadow::expr; 75 | mshadow::Tensor top_diff = top[0]->diff_d2(); 76 | mshadow::Tensor bottom0_data = bottom[0]->data_d2_middle(); 77 | mshadow::Tensor bottom0_diff = bottom[0]->diff_d2_middle(); 78 | mshadow::Tensor bottom1_data = bottom[1]->data_d2(); 79 | mshadow::Tensor bottom1_diff = bottom[1]->diff_d2(); 80 | 81 | if (this->prop_error[0]) { 82 | bottom0_diff += dot(top_diff.T(), bottom1_data); 83 | } 84 | if (this->prop_error[1]) { 85 | bottom1_diff += dot(top_diff, bottom0_data); 86 | } 87 | 88 | } 89 | }; 90 | } // namespace layer 91 | } // namespace textnet 92 | #endif 93 | -------------------------------------------------------------------------------- /src/layer/common/memory_attention_out_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_MEMORY_ATTENTION_OUT_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_MEMORY_ATTENTION_OUT_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include "../layer.h" 6 | #include "../op.h" 7 | #include "../../utils/utils.h" 8 | 9 | namespace textnet { 10 | namespace layer { 11 | 12 | template 13 | class MemoryAttentionOutLayer : public Layer { 14 | public: 15 | MemoryAttentionOutLayer(LayerType type) { this->layer_type = type; } 16 | virtual ~MemoryAttentionOutLayer(void) {} 17 | 18 | virtual int BottomNodeNum() { return 2; } 19 | virtual int TopNodeNum() { return 1; } 20 | virtual int ParamNodeNum() { return 0; } 21 | 22 | virtual void Require() { 23 | // default value, just set the value you want 24 | 25 | // require value, set to SettingV(), 26 | // it will force custom to set in config 27 | 28 | Layer::Require(); 29 | } 30 | 31 | virtual void SetupLayer(std::map &setting, 32 | const std::vector*> &bottom, 33 | const std::vector*> &top, 34 | mshadow::Random *prnd) { 35 | Layer::SetupLayer(setting, bottom, top, prnd); 36 | 37 | utils::Check(bottom.size() == BottomNodeNum(), "MemoryAttentionOutLayer:bottom size problem."); 38 | utils::Check(top.size() == TopNodeNum(), "MemoryAttentionOutLayer:top size problem."); 39 | } 40 | 41 | virtual void Reshape(const std::vector*> &bottom, 42 | const std::vector*> &top, 43 | bool show_info = false) { 44 | utils::Check(bottom.size() == BottomNodeNum(), "MemoryAttentionOutLayer:bottom size problem."); 45 | utils::Check(top.size() == TopNodeNum(), "MemoryAttentionOutLayer:top size problem."); 46 | 47 | mshadow::Shape<4> shape_memory = bottom[0]->data.shape_; 48 | mshadow::Shape<4> shape_attention = bottom[1]->data.shape_; 49 | 50 | utils::Check(shape_memory[0] == 1, "MemoryAttentionOutLayer: Shared memory batch size should equal to 1."); 51 | utils::Check(shape_memory[1] == shape_attention[1], "MemoryAttentionOutLayer: memory size need equal."); 52 | 53 | top[0]->Resize(shape_attention[0], 1, 1, shape_memory[3], 1, 1, true); 54 | 55 | if (show_info) { 56 | bottom[0]->PrintShape("bottom0"); 57 | bottom[1]->PrintShape("bottom1"); 58 | top[0]->PrintShape("top0"); 59 | } 60 | } 61 | 62 | virtual void Forward(const std::vector*> &bottom, 63 | const std::vector*> &top) { 64 | using namespace mshadow::expr; 65 | mshadow::Tensor bottom0_data = bottom[0]->data_d2_middle(); 66 | mshadow::Tensor bottom1_data = bottom[1]->data_d2(); 67 | mshadow::Tensor top_data = top[0]->data_d2(); 68 | 69 | top_data = dot(bottom1_data, bottom0_data); 70 | } 71 | 72 | virtual void Backprop(const std::vector*> &bottom, 73 | const std::vector*> &top) { 74 | using namespace mshadow::expr; 75 | mshadow::Tensor top_diff = top[0]->diff_d2(); 76 | mshadow::Tensor bottom0_data = bottom[0]->data_d2_middle(); 77 | mshadow::Tensor bottom0_diff = bottom[0]->diff_d2_middle(); 78 | mshadow::Tensor bottom1_data = bottom[1]->data_d2(); 79 | mshadow::Tensor bottom1_diff = bottom[1]->diff_d2(); 80 | 81 | if (this->prop_error[0]) { 82 | bottom0_diff += dot(bottom1_data.T(), top_diff); 83 | } 84 | if (this->prop_error[1]) { 85 | bottom1_diff += dot(top_diff, bottom0_data.T()); 86 | } 87 | 88 | } 89 | }; 90 | } // namespace layer 91 | } // namespace textnet 92 | #endif 93 | -------------------------------------------------------------------------------- /src/layer/common/nbp_gen_lstm_input_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_NBP_GEN_LSTM_INPUT_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_NBP_GEN_LSTM_INPUT_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include "../layer.h" 6 | #include "../op.h" 7 | 8 | namespace textnet { 9 | namespace layer { 10 | 11 | template 12 | class NbpGenLstmInputLayer : public Layer{ 13 | public: 14 | NbpGenLstmInputLayer(LayerType type) { this->layer_type = type; } 15 | virtual ~NbpGenLstmInputLayer(void) {} 16 | 17 | virtual int BottomNodeNum() { return 2; } // embedding, len 18 | virtual int TopNodeNum() { return 1; } 19 | virtual int ParamNodeNum() { return 0; } 20 | 21 | virtual void Require() { 22 | // default value, just set the value you want 23 | 24 | // require value, set to SettingV(), 25 | // it will force custom to set in config 26 | 27 | Layer::Require(); 28 | } 29 | 30 | virtual void SetupLayer(std::map &setting, 31 | const std::vector*> &bottom, 32 | const std::vector*> &top, 33 | mshadow::Random *prnd) { 34 | Layer::SetupLayer(setting, bottom, top, prnd); 35 | } 36 | 37 | virtual void Reshape(const std::vector*> &bottom, 38 | const std::vector*> &top, 39 | bool show_info = false) { 40 | utils::Check(bottom.size() == BottomNodeNum(), "NbpGenLstmInputLayer:bottom size problem."); 41 | utils::Check(top.size() == TopNodeNum(), "NbpGenLstmInputLayer:top size problem."); 42 | 43 | mshadow::Shape<4> shape_in = bottom[0]->data.shape_; 44 | mshadow::Shape<4> shape_out = mshadow::Shape4(shape_in[0], 1, shape_in[1], shape_in[3]); 45 | top[0]->Resize(shape_out, true); 46 | 47 | if (show_info) { 48 | bottom[0]->PrintShape("bottom0"); 49 | bottom[1]->PrintShape("bottom1"); 50 | top[0]->PrintShape("top0"); 51 | } 52 | } 53 | 54 | virtual void Forward(const std::vector*> &bottom, 55 | const std::vector*> &top) { 56 | using namespace mshadow::expr; 57 | mshadow::Tensor bottom_data = bottom[0]->data; 58 | mshadow::Tensor bottom_len = bottom[1]->data; // note: this layer is to merge the length to one node 59 | mshadow::Tensor top_data = top[0]->data; 60 | mshadow::Tensor top_len = top[0]->length; 61 | 62 | top_data = 0; 63 | for (index_t batch_idx = 0; batch_idx < bottom_data.size(0); ++batch_idx) { 64 | top_len[batch_idx][0] = bottom_len[batch_idx][0][0][0]; 65 | utils::Check(top_len[batch_idx][0] <= bottom_data.shape_[1], "NbpGenLstmInputLayer: length error."); 66 | for (index_t i = 0; i < bottom_len[batch_idx][0][0][0]; ++i) { 67 | top_data[batch_idx][0][i] = F(bottom_data[batch_idx][i][0]); 68 | } 69 | } 70 | } 71 | 72 | virtual void Backprop(const std::vector*> &bottom, 73 | const std::vector*> &top) { 74 | using namespace mshadow::expr; 75 | mshadow::Tensor top_diff = top[0]->diff; 76 | mshadow::Tensor top_len = top[0]->length; 77 | mshadow::Tensor bottom_diff = bottom[0]->diff; 78 | 79 | for (index_t batch_idx = 0; batch_idx < top_diff.size(0); ++batch_idx) { 80 | for (index_t i = 0; i < top_len[batch_idx][0]; ++i) { 81 | bottom_diff[batch_idx][i][0] += top_diff[batch_idx][0][i]; 82 | } 83 | } 84 | } 85 | protected: 86 | }; 87 | } // namespace layer 88 | } // namespace textnet 89 | #endif 90 | 91 | -------------------------------------------------------------------------------- /src/layer/common/one_hot_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_ONE_HOT_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_ONE_HOT_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "../layer.h" 11 | #include "../op.h" 12 | 13 | namespace textnet { 14 | namespace layer { 15 | 16 | template 17 | class OneHotLayer : public Layer{ 18 | public: 19 | OneHotLayer(LayerType type) { this->layer_type = type; } 20 | virtual ~OneHotLayer(void) {} 21 | 22 | virtual int BottomNodeNum() { return 1; } 23 | virtual int TopNodeNum() { return 1; } 24 | virtual int ParamNodeNum() { return 0; } 25 | 26 | virtual void Require() { 27 | // default value, just set the value you want 28 | this->defaults["pad_value"] = SettingV(0.f); 29 | // require value, set to SettingV(), 30 | // it will force custom to set in config 31 | this->defaults["word_count"] = SettingV(); 32 | 33 | Layer::Require(); 34 | } 35 | 36 | virtual void SetupLayer(std::map &setting, 37 | const std::vector*> &bottom, 38 | const std::vector*> &top, 39 | mshadow::Random *prnd) { 40 | Layer::SetupLayer(setting, bottom, top, prnd); 41 | 42 | utils::Check(bottom.size() == BottomNodeNum(), "OneHotLayer:bottom size problem."); 43 | utils::Check(top.size() == TopNodeNum(), "OneHotLayer:top size problem."); 44 | 45 | word_count = setting["word_count"].iVal(); 46 | pad_value = setting["pad_value"].fVal(); 47 | } 48 | 49 | virtual void Reshape(const std::vector*> &bottom, 50 | const std::vector*> &top, 51 | bool show_info = false) { 52 | utils::Check(bottom.size() == BottomNodeNum(), 53 | "OneHotLayer:bottom size problem."); 54 | utils::Check(top.size() == TopNodeNum(), 55 | "OneHotLayer:top size problem."); 56 | 57 | max_doc_len = bottom[0]->data.size(3); 58 | doc_count = bottom[0]->data.size(1); 59 | nbatch = bottom[0]->data.size(0); 60 | 61 | top[0]->Resize(nbatch, doc_count, max_doc_len, word_count, true); 62 | 63 | if (show_info) { 64 | bottom[0]->PrintShape("bottom0"); 65 | top[0]->PrintShape("top0"); 66 | } 67 | } 68 | 69 | virtual void Forward(const std::vector*> &bottom, 70 | const std::vector*> &top) { 71 | using namespace mshadow::expr; 72 | mshadow::Tensor bottom_data = bottom[0]->data; 73 | mshadow::Tensor bottom_len = bottom[0]->length; 74 | mshadow::Tensor top_data = top[0]->data; 75 | mshadow::Tensor top_len = top[0]->length; 76 | 77 | // fill all top data to pad_value 78 | top_data = pad_value; 79 | top_len = F(bottom_len); 80 | 81 | int w_idx = -1; 82 | for (int i = 0; i < nbatch; ++i) { 83 | for (int j = 0; j < doc_count; ++j) { 84 | int doc_len = bottom_len[i][j]; 85 | utils::Check(doc_len >= 0, "Embedding layer: length must be inited."); 86 | for (int k = 0; k < doc_len; ++k) { 87 | w_idx = (int)bottom_data[i][j][0][k]; 88 | if (w_idx != -1) { 89 | top_data[i][j][k] = 0.; 90 | top_data[i][j][k][w_idx] = 1; 91 | } 92 | } 93 | } 94 | } 95 | } 96 | 97 | virtual void Backprop(const std::vector*> &bottom, 98 | const std::vector*> &top) { 99 | } 100 | 101 | protected: 102 | int word_count, doc_count, nbatch, max_doc_len; 103 | float pad_value; 104 | }; 105 | } // namespace layer 106 | } // namespace textnet 107 | #endif // LAYER_EMBEDDING_LAYER_INL_HPP_ 108 | 109 | -------------------------------------------------------------------------------- /src/layer/common/sequcence_dim_reduction_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_SEQUENCE_DIM_REDUCTION_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_SEQUENCE_DIM_REDUCTION_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include "../layer.h" 6 | #include "../op.h" 7 | #include "../../utils/utils.h" 8 | 9 | namespace textnet { 10 | namespace layer { 11 | 12 | template 13 | class SequenceDimReductionLayer : public Layer { 14 | public: 15 | SequenceDimReductionLayer(LayerType type) { this->layer_type = type; } 16 | virtual ~SequenceDimReductionLayer(void) {} 17 | 18 | virtual int BottomNodeNum() { return 1; } 19 | virtual int TopNodeNum() { return 1; } 20 | virtual int ParamNodeNum() { return 1; } 21 | 22 | virtual void Require() { 23 | // default value, just set the value you want 24 | // require value, set to SettingV(), 25 | // it will force custom to set in config 26 | this->defaults["num_hidden"] = SettingV(); 27 | this->defaults["w_filler"] = SettingV(); 28 | this->defaults["w_updater"] = SettingV(); 29 | 30 | Layer::Require(); 31 | } 32 | 33 | virtual void SetupLayer(std::map &setting, 34 | const std::vector*> &bottom, 35 | const std::vector*> &top, 36 | mshadow::Random *prnd) { 37 | Layer::SetupLayer(setting, bottom, top, prnd); 38 | 39 | utils::Check(bottom.size() == BottomNodeNum(), "SequenceDimReductionLayer:bottom size problem."); 40 | utils::Check(top.size() == TopNodeNum(), "SequenceDimReductionLayer:top size problem."); 41 | 42 | this->param_file = setting["param_file"].sVal(); 43 | num_hidden = setting["num_hidden"].iVal(); 44 | num_input = bottom[0]->data.size(3); 45 | 46 | this->params.resize(1); 47 | this->params[0].Resize(num_hidden, num_input, 1, 1, true); 48 | 49 | std::map &w_setting = *setting["w_filler"].mVal(); 50 | this->params[0].initializer_ = 51 | initializer::CreateInitializer(w_setting["init_type"].iVal(), 52 | w_setting, this->prnd_); 53 | this->params[0].Init(); 54 | 55 | std::map &w_updater = *setting["w_updater"].mVal(); 56 | this->params[0].updater_ = 57 | updater::CreateUpdater(w_updater["updater_type"].iVal(), 58 | w_updater, this->prnd_); 59 | if (!this->param_file.empty()) { 60 | this->LoadParams(); 61 | } 62 | } 63 | 64 | virtual void Reshape(const std::vector*> &bottom, 65 | const std::vector*> &top, 66 | bool show_info = false) { 67 | utils::Check(bottom.size() == BottomNodeNum(), "SequenceDimReductionLayer:bottom size problem."); 68 | utils::Check(top.size() == TopNodeNum(), "SequenceDimReductionLayer:top size problem."); 69 | 70 | mshadow::Tensor bottom_data = bottom[0]->data; 71 | // utils::Check(bottom_data.size(1) == 1, "SequenceDimReductionLayer:bottom size problem."); 72 | 73 | top[0]->Resize(bottom_data.size(0), bottom_data.size(1), bottom_data.size(2), num_hidden, true); 74 | 75 | if (show_info) { 76 | bottom[0]->PrintShape("bottom0"); 77 | top[0]->PrintShape("top0"); 78 | } 79 | } 80 | 81 | virtual void Forward(const std::vector*> &bottom, 82 | const std::vector*> &top) { 83 | using namespace mshadow::expr; 84 | mshadow::Tensor bottom_data = bottom[0]->data_d2_reverse(); 85 | 86 | top[0]->length = bottom[0]->length; 87 | top[0]->data_d2_reverse() = dot(bottom_data, this->params[0].data_d2().T()); 88 | } 89 | 90 | virtual void Backprop(const std::vector*> &bottom, 91 | const std::vector*> &top) { 92 | using namespace mshadow::expr; 93 | mshadow::Tensor top_diff = top[0]->diff_d2_reverse(); 94 | mshadow::Tensor bottom_data = bottom[0]->data_d2_reverse(); 95 | mshadow::Tensor bottom_diff = bottom[0]->diff_d2_reverse(); 96 | 97 | // if (this->prop_grad[0]) { 98 | this->params[0].diff_d2() += dot(top_diff.T(), bottom_data); 99 | // } 100 | bottom_diff += dot(top_diff, this->params[0].data_d2()); 101 | } 102 | 103 | protected: 104 | /*! \brief random number generator */ 105 | int num_input, num_hidden; 106 | }; 107 | } // namespace layer 108 | } // namespace textnet 109 | #endif 110 | -------------------------------------------------------------------------------- /src/layer/common/xelu_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_XELU_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_XELU_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include "../layer.h" 6 | #include "../op.h" 7 | 8 | namespace textnet { 9 | namespace layer { 10 | 11 | template 12 | class XeLULayer : public Layer{ 13 | public: 14 | XeLULayer(LayerType type) { this->layer_type = type; } 15 | virtual ~XeLULayer(void) {} 16 | 17 | virtual int BottomNodeNum() { return 1; } 18 | virtual int TopNodeNum() { return 1; } 19 | virtual int ParamNodeNum() { return 0; } 20 | 21 | virtual void Require() { 22 | // default value, just set the value you want 23 | this->defaults["b"] = SettingV(); 24 | 25 | // require value, set to SettingV(), 26 | // it will force custom to set in config 27 | 28 | Layer::Require(); 29 | } 30 | 31 | virtual void SetupLayer(std::map &setting, 32 | const std::vector*> &bottom, 33 | const std::vector*> &top, 34 | mshadow::Random *prnd) { 35 | Layer::SetupLayer(setting, bottom, top, prnd); 36 | 37 | b = setting["b"].fVal(); 38 | utils::Check(b >= 0.0f, "XeLU Layer: parameter b must non-negative."); 39 | } 40 | 41 | virtual void Reshape(const std::vector*> &bottom, 42 | const std::vector*> &top, 43 | bool show_info = false) { 44 | utils::Check(bottom.size() == BottomNodeNum(), 45 | "XeLULayer:bottom size problem."); 46 | utils::Check(top.size() == TopNodeNum(), 47 | "XeLULayer:top size problem."); 48 | top[0]->Resize(bottom[0]->data.shape_, bottom[0]->length.shape_); 49 | 50 | if (show_info) { 51 | bottom[0]->PrintShape("bottom0"); 52 | top[0]->PrintShape("top0"); 53 | } 54 | } 55 | 56 | virtual void CheckReshape(const std::vector*> &bottom, 57 | const std::vector*> &top) { 58 | // Check for reshape 59 | bool need_reshape = false; 60 | if (! (bottom[0]->data.shape_ == top[0]->data.shape_)) { 61 | need_reshape = true; 62 | } 63 | 64 | // Do reshape 65 | if (need_reshape) { 66 | this->Reshape(bottom, top); 67 | } 68 | } 69 | 70 | virtual void Forward(const std::vector*> &bottom, 71 | const std::vector*> &top) { 72 | using namespace mshadow::expr; 73 | top[0]->length = F(bottom[0]->length); 74 | top[0]->data = F(bottom[0]->data, b); 75 | } 76 | 77 | virtual void Backprop(const std::vector*> &bottom, 78 | const std::vector*> &top) { 79 | using namespace mshadow::expr; 80 | if (this->prop_error[0]) { 81 | bottom[0]->diff += F(top[0]->data, b) * top[0]->diff; 82 | } 83 | } 84 | 85 | protected: 86 | float b; 87 | 88 | }; 89 | } // namespace layer 90 | } // namespace textnet 91 | #endif // LAYER_XELU_LAYER_INL_HPP_ 92 | 93 | -------------------------------------------------------------------------------- /src/layer/layer_impl.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #define _CRT_SECURE_NO_DEPRECATE 3 | // include the layer, this is where the actual implementations are 4 | 5 | #include "layer_impl-inl.hpp" 6 | // specialize the cpu implementation here 7 | namespace textnet { 8 | namespace layer { 9 | template<> 10 | Layer* CreateLayer(LayerType type) { 11 | return CreateLayer_(type); 12 | } 13 | } // namespace layer 14 | } // namespace textnet 15 | -------------------------------------------------------------------------------- /src/layer/layer_impl.cu: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #define _CRT_SECURE_NO_DEPRECATE 3 | // include the layer, this is where the actual implementations are 4 | #include "layer_impl-inl.hpp" 5 | // specialize the gpu implementation here 6 | namespace textnet { 7 | namespace layer { 8 | template<> 9 | Layer* CreateLayer(LayerType type) { 10 | return CreateLayer_(type); 11 | } 12 | } // namespace layer 13 | } // namespace textnet 14 | 15 | -------------------------------------------------------------------------------- /src/layer/loss/accuracy_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_ACCURACY_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_ACCURACY_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include "../layer.h" 12 | #include "../op.h" 13 | 14 | namespace textnet { 15 | namespace layer { 16 | 17 | template 18 | class AccuracyLayer : public Layer{ 19 | public: 20 | AccuracyLayer(LayerType type) { this->layer_type = type; } 21 | virtual ~AccuracyLayer(void) {} 22 | 23 | virtual int BottomNodeNum() { return 2; } 24 | virtual int TopNodeNum() { return 1; } 25 | virtual int ParamNodeNum() { return 0; } 26 | 27 | virtual void Require() { 28 | // default value, just set the value you want 29 | this->defaults["topk"] = SettingV(1); 30 | // require value, set to SettingV(), 31 | // it will force custom to set in config 32 | 33 | Layer::Require(); 34 | } 35 | 36 | virtual void SetupLayer(std::map &setting, 37 | const std::vector*> &bottom, 38 | const std::vector*> &top, 39 | mshadow::Random *prnd) { 40 | Layer::SetupLayer(setting, bottom, top, prnd); 41 | 42 | utils::Check(bottom.size() == BottomNodeNum(), 43 | "AccuracyLayer:bottom size problem."); 44 | utils::Check(top.size() == TopNodeNum(), 45 | "AccuracyLayer:top size problem."); 46 | 47 | topk = setting["topk"].iVal(); 48 | } 49 | 50 | virtual void Reshape(const std::vector*> &bottom, 51 | const std::vector*> &top, 52 | bool show_info = false) { 53 | utils::Check(bottom.size() == BottomNodeNum(), 54 | "AccuracyLayer:bottom size problem."); 55 | utils::Check(top.size() == TopNodeNum(), 56 | "AccuracyLayer:top size problem."); 57 | nbatch = bottom[0]->data.size(0); 58 | ncategory = bottom[0]->data.size(1); 59 | top[0]->Resize(1, 1, 1, 1, true); 60 | if (show_info) { 61 | top[0]->PrintShape("top0"); 62 | } 63 | } 64 | 65 | virtual void Forward(const std::vector*> &bottom, 66 | const std::vector*> &top) { 67 | using namespace mshadow::expr; 68 | mshadow::Tensor bottom0_data = bottom[0]->data_d2(); 69 | mshadow::Tensor bottom1_data = bottom[1]->data_d2(); 70 | mshadow::Tensor bottom1_len = bottom[1]->length; 71 | mshadow::Tensor top_data = top[0]->data_d1(); 72 | 73 | top_data[0] = 0.0f; 74 | 75 | for (int i = 0; i < nbatch; ++i) { 76 | std::vector > bottom_data_vector; 77 | for (int j = 0; j < ncategory; ++j) { 78 | bottom_data_vector.push_back(std::make_pair( 79 | bottom0_data[i][j], j)); 80 | } 81 | std::partial_sort( 82 | bottom_data_vector.begin(), bottom_data_vector.begin() + topk, 83 | bottom_data_vector.end(), std::greater >()); 84 | for (int j = 0; j < topk; ++j) { 85 | int len = bottom1_len[i][0]; 86 | if (len == -1) len = bottom1_data.size(1); // support multi label, however, softmax layer does not support 87 | for (int k = 0; k < len; ++k) { 88 | int lable_value = static_cast(bottom1_data[i][k]); 89 | if (bottom_data_vector[j].second == lable_value) { 90 | ++top_data[0]; 91 | break; 92 | } 93 | } 94 | } 95 | } 96 | top_data[0] /= (float)(nbatch); 97 | } 98 | 99 | virtual void Backprop(const std::vector*> &bottom, 100 | const std::vector*> &top) { 101 | using namespace mshadow::expr; 102 | 103 | } 104 | 105 | protected: 106 | int nbatch; 107 | int ncategory; 108 | int topk; 109 | 110 | }; 111 | } // namespace layer 112 | } // namespace textnet 113 | #endif // LAYER_HINGELOSS_LAYER_INL_HPP_ 114 | 115 | -------------------------------------------------------------------------------- /src/layer/loss/char_lstm_w2v_loss_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_CHAR_LSTM_W2V_LOSS_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_CHAR_LSTM_W2V_LOSS_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "../layer.h" 11 | #include "../op.h" 12 | 13 | namespace textnet { 14 | namespace layer { 15 | 16 | 17 | // this layer is disigned for trainig char lstm language model 18 | template 19 | class HingeLossLayer : public Layer{ 20 | public: 21 | HingeLossLayer(LayerType type) { this->layer_type = type; } 22 | virtual ~HingeLossLayer(void) {} 23 | 24 | virtual int BottomNodeNum() { return 2; } 25 | virtual int TopNodeNum() { return 1; } 26 | virtual int ParamNodeNum() { return 0; } 27 | 28 | virtual void Require() { 29 | // default value, just set the value you want 30 | 31 | // require value, set to SettingV(), 32 | // it will force custom to set in config 33 | 34 | Layer::Require(); 35 | } 36 | 37 | virtual void SetupLayer(std::map &setting, 38 | const std::vector*> &bottom, 39 | const std::vector*> &top, 40 | mshadow::Random *prnd) { 41 | Layer::SetupLayer(setting, bottom, top, prnd); 42 | 43 | utils::Check(bottom.size() == BottomNodeNum(), 44 | "HingeLossLayer:bottom size problem."); 45 | utils::Check(top.size() == TopNodeNum(), 46 | "HingeLossLayer:top size problem."); 47 | 48 | } 49 | 50 | virtual void Reshape(const std::vector*> &bottom, 51 | const std::vector*> &top, 52 | bool show_info = false) { 53 | utils::Check(bottom.size() == BottomNodeNum(), 54 | "HingeLossLayer:bottom size problem."); 55 | utils::Check(top.size() == TopNodeNum(), 56 | "HingeLossLayer:top size problem."); 57 | nbatch = bottom[0]->data.size(0); 58 | top[0]->Resize(nbatch, 1, 1, 1, true); 59 | if (show_info) { 60 | top[0]->PrintShape("top0"); 61 | } 62 | } 63 | 64 | virtual void Forward(const std::vector*> &bottom, 65 | const std::vector*> &top) { 66 | using namespace mshadow::expr; 67 | mshadow::Tensor bottom0_data = bottom[0]->data_d1(); 68 | mshadow::Tensor bottom1_data = bottom[1]->data_d1(); 69 | mshadow::Tensor top_data = top[0]->data_d1(); 70 | 71 | bottom1_data = 2 * (bottom1_data - 0.5); 72 | top_data = F(1.0f - bottom0_data * bottom1_data); 73 | 74 | for (int i = 1; i < nbatch; ++i) { 75 | top_data[0] += top_data[i]; 76 | } 77 | 78 | top_data[0] /= nbatch; 79 | } 80 | 81 | virtual void Backprop(const std::vector*> &bottom, 82 | const std::vector*> &top) { 83 | using namespace mshadow::expr; 84 | mshadow::Tensor bottom0_data = bottom[0]->data_d1(); 85 | mshadow::Tensor bottom1_data = bottom[1]->data_d1(); 86 | mshadow::Tensor bottom0_diff = bottom[0]->diff_d1(); 87 | 88 | if (this->prop_error[0]) { 89 | bottom0_diff = -1.0f * F(1.0f - bottom0_data * bottom1_data) * bottom1_data; 90 | } 91 | } 92 | 93 | protected: 94 | int nbatch; 95 | 96 | }; 97 | } // namespace layer 98 | } // namespace textnet 99 | #endif // LAYER_HINGELOSS_LAYER_INL_HPP_ 100 | 101 | -------------------------------------------------------------------------------- /src/layer/loss/cross_entropy_loss_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_CROSS_ENTROPY_LOSS_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_CROSS_ENTROPY_LOSS_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "../layer.h" 11 | #include "../op.h" 12 | 13 | namespace textnet { 14 | namespace layer { 15 | 16 | template 17 | class CrossEntropyLossLayer : public Layer{ 18 | public: 19 | CrossEntropyLossLayer(LayerType type) { this->layer_type = type; } 20 | virtual ~CrossEntropyLossLayer(void) {} 21 | 22 | virtual int BottomNodeNum() { return 2; } 23 | virtual int TopNodeNum() { return 1; } 24 | virtual int ParamNodeNum() { return 0; } 25 | 26 | virtual void SetupLayer(std::map &setting, 27 | const std::vector*> &bottom, 28 | const std::vector*> &top, 29 | mshadow::Random *prnd) { 30 | Layer::SetupLayer(setting, bottom, top, prnd); 31 | 32 | utils::Check(bottom.size() == BottomNodeNum(), "CrossEntropyLossLayer:bottom size problem."); 33 | utils::Check(top.size() == TopNodeNum(), "CrossEntropyLossLayer:top size problem."); 34 | } 35 | 36 | virtual void Reshape(const std::vector*> &bottom, 37 | const std::vector*> &top, 38 | bool show_info = false) { 39 | utils::Check(bottom.size() == BottomNodeNum(), "CrossEntropyLossLayer:bottom size problem."); 40 | utils::Check(top.size() == TopNodeNum(), "CrossEntropyLossLayer:top size problem."); 41 | 42 | top[0]->Resize(1, 1, 1, 1, true); 43 | if (show_info) { 44 | top[0]->PrintShape("top0"); 45 | } 46 | } 47 | 48 | virtual void Forward(const std::vector*> &bottom, 49 | const std::vector*> &top) { 50 | using namespace mshadow::expr; 51 | mshadow::Tensor bottom0_data = bottom[0]->data_d2(); 52 | mshadow::Tensor bottom1_data = bottom[1]->data_d1(); 53 | mshadow::Tensor top_data = top[0]->data_d1(); 54 | 55 | top_data = 0.0f; 56 | int batch_size = bottom0_data.size(0); 57 | for (int i = 0; i < batch_size; ++i) { 58 | int k = static_cast(bottom1_data[i]); 59 | if (bottom0_data[i][k] == 0.) { 60 | top_data[0] += 88; // by min float number 61 | } else { 62 | top_data[0] += -log(bottom0_data[i][k]); 63 | } 64 | } 65 | top_data[0] /= batch_size; 66 | } 67 | 68 | virtual void Backprop(const std::vector*> &bottom, 69 | const std::vector*> &top) { 70 | using namespace mshadow::expr; 71 | mshadow::Tensor bottom0_data = bottom[0]->data_d2(); 72 | mshadow::Tensor bottom1_data = bottom[1]->data_d1(); 73 | mshadow::Tensor bottom0_diff = bottom[0]->diff_d2(); 74 | 75 | int batch_size = bottom0_data.size(0); 76 | for (int i = 0; i < batch_size; ++i) { 77 | int k = static_cast(bottom1_data[i]); 78 | if (bottom0_data[i][k] <= 0.000001f) { 79 | utils::Check(false, "CrossEntropyLossLayer: prob zero error."); 80 | } else { 81 | bottom0_diff[i][k] -= (1.0f/bottom0_data[i][k]); 82 | } 83 | } 84 | } 85 | 86 | // protected: 87 | 88 | }; 89 | } // namespace layer 90 | } // namespace textnet 91 | #endif // LAYER_CORSS_ENTROPY_LAYER_INL_HPP_ 92 | 93 | -------------------------------------------------------------------------------- /src/layer/loss/hingeloss_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_HINGELOSS_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_HINGELOSS_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "../layer.h" 11 | #include "../op.h" 12 | 13 | namespace textnet { 14 | namespace layer { 15 | 16 | template 17 | class HingeLossLayer : public Layer{ 18 | public: 19 | HingeLossLayer(LayerType type) { this->layer_type = type; } 20 | virtual ~HingeLossLayer(void) {} 21 | 22 | virtual int BottomNodeNum() { return 2; } 23 | virtual int TopNodeNum() { return 1; } 24 | virtual int ParamNodeNum() { return 0; } 25 | 26 | virtual void Require() { 27 | // default value, just set the value you want 28 | 29 | // require value, set to SettingV(), 30 | // it will force custom to set in config 31 | 32 | Layer::Require(); 33 | } 34 | 35 | virtual void SetupLayer(std::map &setting, 36 | const std::vector*> &bottom, 37 | const std::vector*> &top, 38 | mshadow::Random *prnd) { 39 | Layer::SetupLayer(setting, bottom, top, prnd); 40 | 41 | utils::Check(bottom.size() == BottomNodeNum(), 42 | "HingeLossLayer:bottom size problem."); 43 | utils::Check(top.size() == TopNodeNum(), 44 | "HingeLossLayer:top size problem."); 45 | 46 | } 47 | 48 | virtual void Reshape(const std::vector*> &bottom, 49 | const std::vector*> &top, 50 | bool show_info = false) { 51 | utils::Check(bottom.size() == BottomNodeNum(), 52 | "HingeLossLayer:bottom size problem."); 53 | utils::Check(top.size() == TopNodeNum(), 54 | "HingeLossLayer:top size problem."); 55 | nbatch = bottom[0]->data.size(0); 56 | top[0]->Resize(nbatch, 1, 1, 1, true); 57 | if (show_info) { 58 | bottom[0]->PrintShape("bottom0"); 59 | bottom[1]->PrintShape("bottom1"); 60 | top[0]->PrintShape("top0"); 61 | } 62 | } 63 | 64 | virtual void Forward(const std::vector*> &bottom, 65 | const std::vector*> &top) { 66 | using namespace mshadow::expr; 67 | mshadow::Tensor bottom0_data = bottom[0]->data_d1(); 68 | mshadow::Tensor bottom1_data = bottom[1]->data_d1(); 69 | mshadow::Tensor top_data = top[0]->data_d1(); 70 | 71 | bottom1_data = 2 * (bottom1_data - 0.5); 72 | top_data = F(1.0f - bottom0_data * bottom1_data); 73 | 74 | for (int i = 1; i < nbatch; ++i) { 75 | top_data[0] += top_data[i]; 76 | } 77 | 78 | top_data[0] /= nbatch; 79 | } 80 | 81 | virtual void Backprop(const std::vector*> &bottom, 82 | const std::vector*> &top) { 83 | using namespace mshadow::expr; 84 | mshadow::Tensor bottom0_data = bottom[0]->data_d1(); 85 | mshadow::Tensor bottom1_data = bottom[1]->data_d1(); 86 | mshadow::Tensor bottom0_diff = bottom[0]->diff_d1(); 87 | 88 | if (this->prop_error[0]) { 89 | bottom0_diff += -1.0f/nbatch * F(1.0f - bottom0_data * bottom1_data) * bottom1_data; 90 | } 91 | } 92 | 93 | protected: 94 | int nbatch; 95 | 96 | }; 97 | } // namespace layer 98 | } // namespace textnet 99 | #endif // LAYER_HINGELOSS_LAYER_INL_HPP_ 100 | 101 | -------------------------------------------------------------------------------- /src/layer/loss/logistic_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_LOGISTIC_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_LOGISTIC_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "../layer.h" 11 | #include "../op.h" 12 | 13 | namespace textnet { 14 | namespace layer { 15 | 16 | template 17 | class LogisticLayer : public Layer{ 18 | public: 19 | LogisticLayer(LayerType type) { this->layer_type = type; } 20 | virtual ~LogisticLayer(void) {} 21 | 22 | virtual int BottomNodeNum() { return 2; } 23 | virtual int TopNodeNum() { return 1; } 24 | virtual int ParamNodeNum() { return 0; } 25 | 26 | virtual void SetupLayer(std::map &setting, 27 | const std::vector*> &bottom, 28 | const std::vector*> &top, 29 | mshadow::Random *prnd) { 30 | Layer::SetupLayer(setting, bottom, top, prnd); 31 | 32 | utils::Check(bottom.size() == BottomNodeNum(), "LogisticLayer:bottom size problem."); 33 | utils::Check(top.size() == TopNodeNum(), "LogisticLayer:top size problem."); 34 | } 35 | 36 | virtual void Reshape(const std::vector*> &bottom, 37 | const std::vector*> &top, 38 | bool show_info = false) { 39 | utils::Check(bottom.size() == BottomNodeNum(), "LogisticLayer:bottom size problem."); 40 | utils::Check(top.size() == TopNodeNum(), "LogisticLayer:top size problem."); 41 | 42 | top[0]->Resize(1, 1, 1, 1, true); 43 | if (show_info) { 44 | top[0]->PrintShape("top0"); 45 | } 46 | } 47 | 48 | virtual void Forward(const std::vector*> &bottom, 49 | const std::vector*> &top) { 50 | using namespace mshadow::expr; 51 | mshadow::Tensor bottom0_data = bottom[0]->data_d1(); 52 | mshadow::Tensor bottom1_data = bottom[1]->data_d1(); 53 | mshadow::Tensor top_data = top[0]->data_d1(); 54 | 55 | top_data = 0.0f; 56 | int batch_size = bottom0_data.size(0); 57 | 58 | utils::Check(batch_size==bottom[0]->data.size(0), 59 | "LogisticLayer: Input need only one value."); 60 | 61 | // Apply logistic function 62 | bottom0_data = F(bottom0_data); 63 | 64 | for (int i = 0; i < batch_size; ++i) { 65 | int k = static_cast(bottom1_data[i]); 66 | utils::Check(k==0 || k==1, "LogisticLayer: Only support binary class."); 67 | float prob = 0.0f; 68 | if (k == 0) { 69 | prob = 1.0f - bottom0_data[i]; 70 | } else if (k == 1) { 71 | prob = bottom0_data[i]; 72 | } 73 | prob = max(prob, 1e-20f); 74 | top_data[0] += -log(prob); 75 | } 76 | 77 | top_data[0] /= batch_size; 78 | } 79 | 80 | virtual void Backprop(const std::vector*> &bottom, 81 | const std::vector*> &top) { 82 | using namespace mshadow::expr; 83 | mshadow::Tensor bottom0_data = bottom[0]->data_d1(); 84 | mshadow::Tensor bottom1_data = bottom[1]->data_d1(); 85 | mshadow::Tensor bottom0_diff = bottom[0]->diff_d1(); 86 | 87 | int batch_size = bottom0_data.size(0); 88 | for (int i = 0; i < batch_size; ++i) { 89 | int k = static_cast(bottom1_data[i]); 90 | utils::Check(k==0 || k==1, "LogisticLayer: Only support binary class."); 91 | if (k == 0) { 92 | bottom0_diff[i] += bottom0_data[i]; 93 | } else if (k == 1) { 94 | bottom0_diff[i] += bottom0_data[i] - 1.0; 95 | } 96 | } 97 | } 98 | 99 | // protected: 100 | 101 | }; 102 | } // namespace layer 103 | } // namespace textnet 104 | #endif // LAYER_CORSS_ENTROPY_LAYER_INL_HPP_ 105 | 106 | -------------------------------------------------------------------------------- /src/layer/loss/pair_weighted_hinge_loss_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_PAIT_WEIGHTED_HINGE_LOSS_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_PAIT_WEIGHTED_HINGE_LOSS_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "../layer.h" 11 | #include "../op.h" 12 | 13 | namespace textnet { 14 | namespace layer { 15 | 16 | template 17 | class PairWeightedHingeLossLayer : public Layer{ 18 | public: 19 | PairWeightedHingeLossLayer(LayerType type) { this->layer_type = type; } 20 | virtual ~PairWeightedHingeLossLayer(void) {} 21 | 22 | virtual int BottomNodeNum() { return 3; } 23 | virtual int TopNodeNum() { return 1; } 24 | virtual int ParamNodeNum() { return 0; } 25 | 26 | virtual void Require() { 27 | // default value, just set the value you want 28 | this->defaults["delta"] = SettingV(1.0f); 29 | // require value, set to SettingV(), 30 | // it will force custom to set in config 31 | 32 | Layer::Require(); 33 | } 34 | 35 | virtual void SetupLayer(std::map &setting, 36 | const std::vector*> &bottom, 37 | const std::vector*> &top, 38 | mshadow::Random *prnd) { 39 | Layer::SetupLayer(setting, bottom, top, prnd); 40 | 41 | utils::Check(bottom.size() == BottomNodeNum(), 42 | "PairWeightedHingeLossLayer:bottom size problem."); 43 | utils::Check(top.size() == TopNodeNum(), 44 | "PairWeightedHingeLossLayer:top size problem."); 45 | delta = setting["delta"].fVal(); 46 | 47 | } 48 | 49 | virtual void Reshape(const std::vector*> &bottom, 50 | const std::vector*> &top, 51 | bool show_info = false) { 52 | utils::Check(bottom.size() == BottomNodeNum(), 53 | "PairWeightedHingeLossLayer:bottom size problem."); 54 | utils::Check(top.size() == TopNodeNum(), 55 | "PairWeightedHingeLossLayer:top size problem."); 56 | nbatch = bottom[0]->data.size(0); 57 | utils::Check(nbatch % 2 == 0, "PairWeightedHingeLossLayer:nBatch must be even. Batch size: %d.", nbatch); 58 | top[0]->Resize(1, 1, 1, 1, true); 59 | if (show_info) { 60 | top[0]->PrintShape("top0"); 61 | } 62 | } 63 | 64 | virtual void CheckReshape(const std::vector*> &bottom, 65 | const std::vector*> &top) { 66 | // Check for reshape 67 | nbatch = bottom[0]->data.size(0); 68 | } 69 | 70 | virtual void Forward(const std::vector*> &bottom, 71 | const std::vector*> &top) { 72 | using namespace mshadow::expr; 73 | mshadow::Tensor bottom0_data = bottom[0]->data_d1(); 74 | mshadow::Tensor bottom1_data = bottom[1]->data_d1(); 75 | mshadow::Tensor bottom2_data = bottom[2]->data_d1(); 76 | mshadow::Tensor top_data = top[0]->data_d1(); 77 | 78 | for (int i = 0; i < nbatch; i += 2) { 79 | utils::Check(bottom1_data[i] > bottom1_data[i+1], 80 | "Instances come like x y ... x > y"); 81 | top_data[0] += std::max(0.0f, delta + bottom0_data[i+1] - bottom0_data[i]) * bottom2_data[i]; 82 | } 83 | 84 | top_data[0] /= (nbatch/2); 85 | } 86 | 87 | virtual void Backprop(const std::vector*> &bottom, 88 | const std::vector*> &top) { 89 | using namespace mshadow::expr; 90 | mshadow::Tensor bottom0_data = bottom[0]->data_d1(); 91 | mshadow::Tensor bottom0_diff = bottom[0]->diff_d1(); 92 | mshadow::Tensor bottom2_data = bottom[2]->data_d1(); 93 | 94 | if (this->prop_error[0]) { 95 | for (int i = 0; i < nbatch; i+=2) { 96 | float gate = (delta + bottom0_data[i+1] - bottom0_data[i]) > 0 ? 1 : 0; 97 | bottom0_diff[i] += -gate / nbatch * bottom2_data[i]; 98 | bottom0_diff[i+1] += gate / nbatch * bottom2_data[i+1]; 99 | } 100 | } 101 | 102 | } 103 | 104 | protected: 105 | int nbatch; 106 | float delta; 107 | 108 | }; 109 | } // namespace layer 110 | } // namespace textnet 111 | #endif // LAYER_PAIT_WEIGHTED_HINGE_LOSS_LAYER_INL_HPP_ 112 | 113 | -------------------------------------------------------------------------------- /src/layer/loss/pairhingeloss_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_PAIRHINGELOSS_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_PAIRHINGELOSS_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "../layer.h" 11 | #include "../op.h" 12 | 13 | namespace textnet { 14 | namespace layer { 15 | 16 | template 17 | class PairHingeLossLayer : public Layer{ 18 | public: 19 | PairHingeLossLayer(LayerType type) { this->layer_type = type; } 20 | virtual ~PairHingeLossLayer(void) {} 21 | 22 | virtual int BottomNodeNum() { return 2; } 23 | virtual int TopNodeNum() { return 1; } 24 | virtual int ParamNodeNum() { return 0; } 25 | 26 | virtual void Require() { 27 | // default value, just set the value you want 28 | this->defaults["delta"] = SettingV(1.0f); 29 | // require value, set to SettingV(), 30 | // it will force custom to set in config 31 | 32 | Layer::Require(); 33 | } 34 | 35 | virtual void SetupLayer(std::map &setting, 36 | const std::vector*> &bottom, 37 | const std::vector*> &top, 38 | mshadow::Random *prnd) { 39 | Layer::SetupLayer(setting, bottom, top, prnd); 40 | 41 | utils::Check(bottom.size() == BottomNodeNum(), 42 | "PairHingeLossLayer:bottom size problem."); 43 | utils::Check(top.size() == TopNodeNum(), 44 | "PairHingeLossLayer:top size problem."); 45 | delta = setting["delta"].fVal(); 46 | 47 | } 48 | 49 | virtual void Reshape(const std::vector*> &bottom, 50 | const std::vector*> &top, 51 | bool show_info = false) { 52 | utils::Check(bottom.size() == BottomNodeNum(), 53 | "PairHingeLossLayer:bottom size problem."); 54 | utils::Check(top.size() == TopNodeNum(), 55 | "PairHingeLossLayer:top size problem."); 56 | nbatch = bottom[0]->data.size(0); 57 | utils::Check(nbatch % 2 == 0, "PairHingeLossLayer:nBatch must be even. Batch size: %d.", nbatch); 58 | top[0]->Resize(1, 1, 1, 1, true); 59 | if (show_info) { 60 | top[0]->PrintShape("top0"); 61 | } 62 | } 63 | 64 | virtual void CheckReshape(const std::vector*> &bottom, 65 | const std::vector*> &top) { 66 | // Check for reshape 67 | nbatch = bottom[0]->data.size(0); 68 | } 69 | 70 | virtual void Forward(const std::vector*> &bottom, 71 | const std::vector*> &top) { 72 | using namespace mshadow::expr; 73 | mshadow::Tensor bottom0_data = bottom[0]->data_d1(); 74 | mshadow::Tensor bottom1_data = bottom[1]->data_d1(); 75 | mshadow::Tensor top_data = top[0]->data_d1(); 76 | 77 | for (int i = 0; i < nbatch; i += 2) { 78 | utils::Check(bottom1_data[i] > bottom1_data[i+1], 79 | "Instances come like x y ... x > y"); 80 | top_data[0] += std::max(0.0f, delta + bottom0_data[i+1] - bottom0_data[i]); 81 | } 82 | 83 | top_data[0] /= (nbatch/2); 84 | } 85 | 86 | virtual void Backprop(const std::vector*> &bottom, 87 | const std::vector*> &top) { 88 | using namespace mshadow::expr; 89 | mshadow::Tensor bottom0_data = bottom[0]->data_d1(); 90 | mshadow::Tensor bottom0_diff = bottom[0]->diff_d1(); 91 | 92 | if (this->prop_error[0]) { 93 | for (int i = 0; i < nbatch; i+=2) { 94 | float gate = (delta + bottom0_data[i+1] - bottom0_data[i]) > 0 ? 1 : 0; 95 | bottom0_diff[i] += -gate / nbatch; 96 | bottom0_diff[i+1] += gate / nbatch; 97 | } 98 | } 99 | 100 | } 101 | 102 | protected: 103 | int nbatch; 104 | float delta; 105 | 106 | }; 107 | } // namespace layer 108 | } // namespace textnet 109 | #endif // LAYER_PAIRHINGELOSS_LAYER_INL_HPP_ 110 | 111 | -------------------------------------------------------------------------------- /src/layer/loss/softmax_layer-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_LAYER_SOFTMAX_LAYER_INL_HPP_ 2 | #define TEXTNET_LAYER_SOFTMAX_LAYER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "../layer.h" 11 | #include "../op.h" 12 | 13 | namespace textnet { 14 | namespace layer { 15 | 16 | template 17 | class SoftmaxLayer : public Layer{ 18 | public: 19 | SoftmaxLayer(LayerType type) { this->layer_type = type; } 20 | virtual ~SoftmaxLayer(void) {} 21 | 22 | virtual int BottomNodeNum() { return 2; } 23 | virtual int TopNodeNum() { return 1; } 24 | virtual int ParamNodeNum() { return 0; } 25 | 26 | virtual void Require() { 27 | // default value, just set the value you want 28 | 29 | // require value, set to SettingV(), 30 | // it will force custom to set in config 31 | 32 | Layer::Require(); 33 | } 34 | 35 | virtual void SetupLayer(std::map &setting, 36 | const std::vector*> &bottom, 37 | const std::vector*> &top, 38 | mshadow::Random *prnd) { 39 | Layer::SetupLayer(setting, bottom, top, prnd); 40 | 41 | utils::Check(bottom.size() == BottomNodeNum(), 42 | "SoftmaxLayer:bottom size problem."); 43 | utils::Check(top.size() == TopNodeNum(), 44 | "SoftmaxLayer:top size problem."); 45 | 46 | } 47 | 48 | virtual void Reshape(const std::vector*> &bottom, 49 | const std::vector*> &top, 50 | bool show_info = false) { 51 | utils::Check(bottom.size() == BottomNodeNum(), 52 | "SoftmaxLayer:bottom size problem."); 53 | utils::Check(top.size() == TopNodeNum(), 54 | "SoftmaxLayer:top size problem."); 55 | nbatch = bottom[0]->data.size(0); 56 | top[0]->Resize(1, 1, 1, 1, true); 57 | if (show_info) { 58 | top[0]->PrintShape("top0"); 59 | } 60 | } 61 | 62 | virtual void CheckReshape(const std::vector*> &bottom, 63 | const std::vector*> &top) { 64 | // Check for reshape 65 | nbatch = bottom[0]->data.size(0); 66 | } 67 | 68 | void checkNan(float *p, int l) { 69 | for (int i = 0; i < l; ++i) { 70 | assert(!std::isnan(p[i])); 71 | } 72 | } 73 | 74 | virtual void Forward(const std::vector*> &bottom, 75 | const std::vector*> &top) { 76 | using namespace mshadow::expr; 77 | mshadow::Tensor bottom0_data = bottom[0]->data_d2(); 78 | mshadow::Tensor bottom1_data = bottom[1]->data_d1(); 79 | mshadow::Tensor top_data = top[0]->data_d1(); 80 | 81 | #if DEBUG 82 | checkNan(bottom0_data.dptr_, bottom0_data.size(0) *bottom0_data.size(1)); 83 | #endif 84 | mshadow::Softmax(bottom0_data, bottom0_data); 85 | 86 | top_data[0] = 0.0f; 87 | 88 | for (int i = 0; i < nbatch; ++i) { 89 | int k = static_cast(bottom1_data[i]); 90 | utils::Check(k < bottom0_data.size(1), "SoftmaxLayer: class label overflows. k=%d, max=%d", k, bottom0_data.size(1)); 91 | if (bottom0_data[i][k] == 0.) { 92 | top_data[0] += 88; // by min float number 93 | } else { 94 | top_data[0] += -log(bottom0_data[i][k]); 95 | } 96 | } 97 | top_data[0] /= nbatch; 98 | } 99 | 100 | virtual void Backprop(const std::vector*> &bottom, 101 | const std::vector*> &top) { 102 | using namespace mshadow::expr; 103 | mshadow::Tensor bottom0_data = bottom[0]->data_d2(); 104 | mshadow::Tensor bottom1_data = bottom[1]->data_d1(); 105 | mshadow::Tensor bottom0_diff = bottom[0]->diff_d2(); 106 | 107 | bottom0_diff += bottom0_data / nbatch; 108 | 109 | if (this->prop_error[0]) { 110 | for (int i = 0; i < nbatch; ++i) { 111 | int k = static_cast(bottom1_data[i]); 112 | bottom0_diff[i][k] -= 1.0f / nbatch; 113 | } 114 | } 115 | } 116 | 117 | protected: 118 | int nbatch; 119 | 120 | }; 121 | } // namespace layer 122 | } // namespace textnet 123 | #endif // LAYER_SOFTMAX_LAYER_INL_HPP_ 124 | 125 | 126 | -------------------------------------------------------------------------------- /src/net/multi_train_valid_test_net-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_NET_MULTI_TRAIN_VALID_TEST_NET_INL_HPP_ 2 | #define TEXTNET_NET_MULTI_TRAIN_VALID_TEST_NET_INL_HPP_ 3 | 4 | #include 5 | #include "./net.h" 6 | #include 7 | 8 | namespace textnet { 9 | namespace net { 10 | 11 | template 12 | class MultiTrainValidTestNet : public Net{ 13 | public: 14 | MultiTrainValidTestNet() { this->net_type = kMultiTrainValidTest; } 15 | virtual ~MultiTrainValidTestNet(void) {} 16 | 17 | vector train_tags; 18 | vector valid_tags; 19 | vector test_tags; 20 | 21 | virtual void Start() { 22 | 23 | for (auto it = this->nets.begin(); it != this->nets.end(); ++it) { 24 | string tag = it->first; 25 | if (tag.find("Train") == 0) { 26 | train_tags.push_back(tag); 27 | } else if (tag.find("Valid") == 0) { 28 | valid_tags.push_back(tag); 29 | } else if (tag.find("Test") == 0) { 30 | test_tags.push_back(tag); 31 | } else { 32 | utils::Check(false, "Tag name invalid: %s.", tag.c_str()); 33 | } 34 | } 35 | 36 | utils::Printf("Train tags: \n"); 37 | for (int i = 0; i < (int)train_tags.size(); ++i) { 38 | utils::Printf("[%s]\n", train_tags[i].c_str()); 39 | } 40 | utils::Printf("Valid tags: \n"); 41 | for (int i = 0; i < (int)valid_tags.size(); ++i) { 42 | utils::Printf("[%s]\n", valid_tags[i].c_str()); 43 | } 44 | utils::Printf("Test tags: \n"); 45 | for (int i = 0; i < (int)test_tags.size(); ++i) { 46 | utils::Printf("[%s]\n", test_tags[i].c_str()); 47 | } 48 | 49 | utils::Check(train_tags.size() > 0, 50 | "No [Train] tag in config."); 51 | utils::Check(valid_tags.size() > 0, 52 | "No [Valid] tag in config."); 53 | utils::Check(test_tags.size() > 0, 54 | "No [Test] tag in config."); 55 | 56 | for (int iter = 0; iter < this->max_iters[train_tags[0]]; ++iter) { 57 | if (iter != 0 || (iter == 0 && this->model_save_initial)) { 58 | this->SaveModel(iter); 59 | 60 | this->SaveModelActivation(iter); 61 | } 62 | 63 | if (iter != 0 || (iter == 0 && this->model_test_initial)) { 64 | for (int i = 0; i < (int)valid_tags.size(); ++i) { 65 | string tag = valid_tags[i]; 66 | if (this->display_interval[tag] > 0 && iter % this->display_interval[tag] == 0) { 67 | this->TestAll(tag, iter); 68 | } 69 | } 70 | 71 | for (int i = 0; i < (int)test_tags.size(); ++i) { 72 | string tag = test_tags[i]; 73 | if (this->display_interval[tag] > 0 && iter % this->display_interval[tag] == 0) { 74 | this->TestAll(tag, iter); 75 | } 76 | } 77 | 78 | utils::ShowMemoryUse(); 79 | } 80 | 81 | for (int i = 0; i < (int)train_tags.size(); ++i) { 82 | string tag = train_tags[i]; 83 | this->TrainOneStep(tag); 84 | if (this->display_interval[tag] > 0 && iter % this->display_interval[tag] == 0) { 85 | this->TrainDisplay(tag, iter); 86 | } 87 | } 88 | } 89 | 90 | this->SaveModel(this->max_iters[train_tags[0]], this->model_save_last); 91 | } 92 | }; 93 | } // namespace net 94 | } // namespace textnet 95 | #endif // NET_MULTI_TRAIN_VALID_TEST_NET_INL_HPP_ 96 | 97 | -------------------------------------------------------------------------------- /src/net/net_impl-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_NET_IMPL_INL_HPP_ 2 | #define TEXTNET_NET_IMPL_INL_HPP_ 3 | #pragma once 4 | 5 | #include "./net.h" 6 | #include "./train_valid_net-inl.hpp" 7 | #include "./train_valid_test_net-inl.hpp" 8 | #include "./test_net-inl.hpp" 9 | #include "./multi_train_valid_test_net-inl.hpp" 10 | 11 | namespace textnet { 12 | namespace net { 13 | template 14 | INet* CreateNet_(NetType type) { 15 | switch(type) { 16 | case kTrainValid: return new TrainValidNet(); 17 | case kTrainValidTest: return new TrainValidTestNet(); 18 | // case kCrossValid: return new CrossValidNet(); 19 | case kTestOnly: return new TestNet(); 20 | case kMultiTrainValidTest: return new MultiTrainValidTestNet(); 21 | default: utils::Error("unknown net type id : \"%d\"", type); return NULL; 22 | } 23 | } 24 | 25 | } // namespace net 26 | } // namespace textnet 27 | #endif 28 | -------------------------------------------------------------------------------- /src/net/net_impl.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #define _CRT_SECURE_NO_DEPRECATE 3 | 4 | #include "net_impl-inl.hpp" 5 | // specialize the cpu implementation here 6 | namespace textnet { 7 | namespace net { 8 | INet* CreateNetCPU(NetType type) { 9 | return CreateNet_(type); 10 | } 11 | #if MSHADOW_USE_CUDA == 0 12 | INet* CreateNetGPU(NetType type) { 13 | utils::Error("Set CPU_ONLY to 1, so no gpu models."); 14 | return NULL; 15 | } 16 | #endif 17 | } // namespace net 18 | } // namespace textnet 19 | -------------------------------------------------------------------------------- /src/net/net_impl.cu: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #define _CRT_SECURE_NO_DEPRECATE 3 | 4 | #include "net_impl-inl.hpp" 5 | // specialize the gpu implementation here 6 | namespace textnet { 7 | namespace net { 8 | INet* CreateNetGPU(NetType type) { 9 | return CreateNet_(type); 10 | } 11 | } // namespace net 12 | } // namespace textnet 13 | 14 | -------------------------------------------------------------------------------- /src/net/test_net-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_NET_TEST_NET_INL_HPP_ 2 | #define TEXTNET_NET_TEST_NET_INL_HPP_ 3 | 4 | #include 5 | #include "./net.h" 6 | 7 | using namespace std; 8 | 9 | namespace textnet { 10 | namespace net { 11 | 12 | template 13 | class TestNet : public Net{ 14 | public: 15 | TestNet() { 16 | this->net_type = kTestOnly; 17 | need_activation = false; 18 | } 19 | 20 | TestNet(int per_file_iter_, int max_iter_, vector node_names_, string file_prefix_, string tag_) { 21 | this->net_type = kTestOnly; 22 | need_activation = true; 23 | per_file_iter = per_file_iter_; 24 | max_iter = max_iter_; 25 | node_names = node_names_; 26 | file_prefix = file_prefix_; 27 | tag = tag_; 28 | } 29 | 30 | virtual ~TestNet(void) {} 31 | 32 | virtual void Start() { 33 | 34 | utils::Check(this->nets.count(tag), 35 | "No [%s] tag in config.", tag.c_str()); 36 | if (!need_activation) { 37 | this->TestAll(tag, 0); 38 | } else { 39 | for (int test_iter = 0; test_iter < max_iter; ++test_iter) { 40 | string file_name = file_prefix + "." + int2str(test_iter); 41 | this->SaveModelActivation(tag, node_names, per_file_iter, file_name); 42 | } 43 | } 44 | 45 | } 46 | 47 | bool need_activation; 48 | int per_file_iter; 49 | int max_iter; 50 | vector node_names; 51 | string file_prefix; 52 | string tag; 53 | }; 54 | } // namespace net 55 | } // namespace textnet 56 | #endif // NET_TEST_NET_INL_HPP_ 57 | 58 | -------------------------------------------------------------------------------- /src/net/train_valid_net-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_NET_TRAIN_VALID_NET_INL_HPP_ 2 | #define TEXTNET_NET_TRAIN_VALID_NET_INL_HPP_ 3 | 4 | #include 5 | #include "./net.h" 6 | 7 | namespace textnet { 8 | namespace net { 9 | 10 | template 11 | class TrainValidNet : public Net{ 12 | public: 13 | TrainValidNet() { this->net_type = kTrainValid; } 14 | virtual ~TrainValidNet(void) {} 15 | 16 | virtual void Start() { 17 | 18 | utils::Check(this->nets.count("Train"), 19 | "No [Train] tag in config."); 20 | utils::Check(this->nets.count("Valid"), 21 | "No [Valid] tag in config."); 22 | 23 | for (int iter = 0; iter < this->max_iters["Train"]; ++iter) { 24 | if (iter != 0 || (iter == 0 && this->model_save_initial)) { 25 | this->SaveModel(iter); 26 | 27 | this->SaveModelActivation(iter); 28 | } 29 | 30 | if (iter != 0 || (iter == 0 && this->model_test_initial)) { 31 | if (this->display_interval["Valid"] > 0 && iter % this->display_interval["Valid"] == 0) { 32 | this->TestAll("Valid", iter); 33 | } 34 | } 35 | 36 | this->TrainOneStep("Train"); 37 | 38 | if (this->display_interval["Train"] > 0 && iter % this->display_interval["Train"] == 0) { 39 | this->TrainDisplay("Train", iter); 40 | } 41 | } 42 | if (this->model_save_initial) { 43 | this->SaveModel(this->max_iters["Train"], this->model_save_last); 44 | } 45 | } 46 | }; 47 | } // namespace net 48 | } // namespace textnet 49 | #endif // NET_TRAIN_VALID_NET_INL_HPP_ 50 | 51 | -------------------------------------------------------------------------------- /src/net/train_valid_test_net-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_NET_TRAIN_VALID_TEST_NET_INL_HPP_ 2 | #define TEXTNET_NET_TRAIN_VALID_TEST_NET_INL_HPP_ 3 | 4 | #include 5 | #include "./net.h" 6 | #include 7 | 8 | namespace textnet { 9 | namespace net { 10 | 11 | template 12 | class TrainValidTestNet : public Net{ 13 | public: 14 | TrainValidTestNet() { this->net_type = kTrainValidTest; } 15 | virtual ~TrainValidTestNet(void) {} 16 | 17 | virtual void Start() { 18 | 19 | utils::Check(this->nets.count("Train"), 20 | "No [Train] tag in config."); 21 | utils::Check(this->nets.count("Valid"), 22 | "No [Valid] tag in config."); 23 | utils::Check(this->nets.count("Test"), 24 | "No [Test] tag in config."); 25 | 26 | 27 | time_t begin = 0, end = 0; 28 | time(&begin); 29 | for (int iter = 0; iter < this->max_iters["Train"]; ++iter) { 30 | if (iter != 0 || (iter == 0 && this->model_save_initial)) { 31 | this->SaveModel(iter); 32 | 33 | this->SaveModelActivation(iter); 34 | } 35 | if (iter != 0 || (iter == 0 && this->model_test_initial)) { 36 | if (this->display_interval["Valid"] > 0 && iter % this->display_interval["Valid"] == 0) { 37 | time(&end); 38 | cout << "valid display interval: " << end-begin << "s." << endl; 39 | this->TestAll("Valid", iter); 40 | time(&begin); 41 | } 42 | 43 | if (this->display_interval["Test"] > 0 && iter % this->display_interval["Test"] == 0) { 44 | this->TestAll("Test", iter); 45 | utils::ShowMemoryUse(); 46 | #if TIME_DEBUG 47 | this->PrintClock("Train"); 48 | #endif 49 | } 50 | } 51 | this->TrainOneStep("Train"); 52 | 53 | if (this->display_interval["Train"] > 0 && iter % this->display_interval["Train"] == 0) { 54 | this->TrainDisplay("Train", iter); 55 | } 56 | } 57 | 58 | this->SaveModel(this->max_iters["Train"], this->model_save_last); 59 | } 60 | }; 61 | } // namespace net 62 | } // namespace textnet 63 | #endif // NET_TRAIN_VALID_TEST_NET_INL_HPP_ 64 | 65 | -------------------------------------------------------------------------------- /src/statistic/statistic_impl-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_NET_IMPL_INL_HPP_ 2 | #define TEXTNET_NET_IMPL_INL_HPP_ 3 | #pragma once 4 | 5 | #include "./net.h" 6 | #include "./train_valid_net-inl.hpp" 7 | #include "./train_valid_test_net-inl.hpp" 8 | 9 | namespace textnet { 10 | namespace net { 11 | template 12 | INet* CreateNet_(NetType type) { 13 | switch(type) { 14 | case kTrainValid: return new TrainValidNet(); 15 | case kTrainValidTest: return new TrainValidTestNet(); 16 | // case kCrossValid: return new CrossValidNet(); 17 | // case kTest: return new TestNet(); 18 | default: utils::Error("unknown net type id : \"%d\"", type); return NULL; 19 | } 20 | } 21 | 22 | } // namespace net 23 | } // namespace textnet 24 | #endif 25 | -------------------------------------------------------------------------------- /src/statistic/statistic_impl.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #define _CRT_SECURE_NO_DEPRECATE 3 | 4 | #include "net_impl-inl.hpp" 5 | // specialize the cpu implementation here 6 | namespace textnet { 7 | namespace net { 8 | INet* CreateNetCPU(NetType type) { 9 | return CreateNet_(type); 10 | } 11 | #if MSHADOW_USE_CUDA == 0 12 | INet* CreateNetGPU(NetType type) { 13 | utils::Error("Set CPU_ONLY to 1, so no gpu models."); 14 | return NULL; 15 | } 16 | #endif 17 | } // namespace net 18 | } // namespace textnet 19 | -------------------------------------------------------------------------------- /src/statistic/statistic_impl.cu: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #define _CRT_SECURE_NO_DEPRECATE 3 | 4 | #include "net_impl-inl.hpp" 5 | // specialize the gpu implementation here 6 | namespace textnet { 7 | namespace net { 8 | INet* CreateNetGPU(NetType type) { 9 | return CreateNet_(type); 10 | } 11 | } // namespace net 12 | } // namespace textnet 13 | 14 | -------------------------------------------------------------------------------- /src/textnet_testonly.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #define _CRT_SECURE_NO_DEPRECATE 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "./net/net.h" 15 | #include "./net/test_net-inl.hpp" 16 | #include "./layer/layer.h" 17 | #include "./statistic/statistic.h" 18 | #include "./io/json/json.h" 19 | #include "global.h" 20 | 21 | using namespace std; 22 | using namespace textnet; 23 | using namespace textnet::layer; 24 | using namespace mshadow; 25 | using namespace textnet::net; 26 | 27 | void PrintTensor(const char * name, Tensor x) { 28 | Shape<1> s = x.shape_; 29 | cout << name << " shape " << s[0] << endl; 30 | for (unsigned int d1 = 0; d1 < s[0]; ++d1) { 31 | cout << x[d1] << " "; 32 | } 33 | cout << endl; 34 | } 35 | 36 | void PrintTensor(const char * name, Tensor x) { 37 | Shape<2> s = x.shape_; 38 | cout << name << " shape " << s[0] << "x" << s[1] << endl; 39 | for (unsigned int d1 = 0; d1 < s[0]; ++d1) { 40 | for (unsigned int d2 = 0; d2 < s[1]; ++d2) { 41 | cout << x[d1][d2] << " "; 42 | } 43 | cout << endl; 44 | } 45 | cout << endl; 46 | } 47 | 48 | void PrintTensor(const char * name, Tensor x) { 49 | Shape<3> s = x.shape_; 50 | cout << name << " shape " << s[0] << "x" << s[1] << "x" << s[2] << endl; 51 | for (unsigned int d1 = 0; d1 < s[0]; ++d1) { 52 | for (unsigned int d2 = 0; d2 < s[1]; ++d2) { 53 | for (unsigned int d3 = 0; d3 < s[2]; ++d3) { 54 | cout << x[d1][d2][d3] << " "; 55 | } 56 | cout << ";"; 57 | } 58 | cout << endl; 59 | } 60 | } 61 | 62 | void PrintTensor(const char * name, Tensor x) { 63 | Shape<4> s = x.shape_; 64 | cout << name << " shape " << s[0] << "x" << s[1] << "x" << s[2] << "x" << s[3] << endl; 65 | for (unsigned int d1 = 0; d1 < s[0]; ++d1) { 66 | for (unsigned int d2 = 0; d2 < s[1]; ++d2) { 67 | for (unsigned int d3 = 0; d3 < s[2]; ++d3) { 68 | for (unsigned int d4 = 0; d4 < s[3]; ++d4) { 69 | cout << x[d1][d2][d3][d4] << " "; 70 | } 71 | cout << "|"; 72 | } 73 | cout << ";"; 74 | } 75 | cout << endl; 76 | } 77 | cout << endl; 78 | } 79 | 80 | float SIGMOID_MAX_INPUT = 20.f; 81 | int SIGMOID_TABLE_SIZE = 1000000; 82 | float *p_sigmoid_lookup_table = NULL; 83 | 84 | float TANH_MAX_INPUT = 20.f; 85 | int TANH_TABLE_SIZE = 1000000; 86 | float *p_tanh_lookup_table = NULL; 87 | 88 | int main(int argc, char *argv[]) { 89 | string model_file = ""; 90 | string test_config_file = ""; 91 | 92 | if (argc > 2) { 93 | model_file = string(argv[1]); 94 | test_config_file = string(argv[2]); 95 | } 96 | 97 | Json::Value test_config; 98 | ifstream _if(test_config_file.c_str()); 99 | _if >> test_config; 100 | _if.close(); 101 | 102 | int per_file_iter = test_config["per_file_iter"].asInt(); 103 | int max_iter = test_config["max_iter"].asInt(); 104 | vector node_names; 105 | Json::Value node_names_root = test_config["node_names"]; 106 | for (int i = 0; i < (int)node_names_root.size(); i++) { 107 | node_names.push_back(node_names_root[i].asString()); 108 | } 109 | string file_prefix = test_config["file_prefix"].asString(); 110 | string tag = test_config["tag"].asString(); 111 | 112 | TestNet net = TestNet(per_file_iter, max_iter, node_names, file_prefix, tag); 113 | net.LoadModel(model_file); 114 | net.Start(); 115 | 116 | return 0; 117 | } 118 | 119 | -------------------------------------------------------------------------------- /src/updater/adagrad_updater-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_ADAGRAD_UPDATER_INL_HPP_ 2 | #define TEXTNET_ADAGRAD_UPDATER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include "./updater.h" 7 | 8 | namespace textnet { 9 | namespace updater { 10 | 11 | template 12 | class AdagradUpdater : public Updater{ 13 | public: 14 | AdagradUpdater(std::map &setting, 15 | mshadow::Random* prnd) { 16 | this->prnd_ = prnd; 17 | SetupUpdater(setting); 18 | } 19 | virtual ~AdagradUpdater(void) {} 20 | 21 | virtual void Require(std::map &setting) { 22 | // default value, just set the value you want 23 | this->defaults["eps"] = SettingV(0.1f); 24 | this->defaults["l2"] = SettingV(0.0f); 25 | this->defaults["max_iter"] = SettingV(-1); 26 | this->defaults["lr_decay_factor"] = SettingV(1.f); 27 | this->defaults["lr_decay_interval"] = SettingV(0); 28 | 29 | // require value, set to SettingV(), 30 | // it will force custom to set in config 31 | this->defaults["lr"] = SettingV(); 32 | 33 | Updater::Require(setting); 34 | } 35 | 36 | virtual void SetupUpdater(std::map &setting) { 37 | Updater::SetupUpdater(setting); 38 | 39 | this->updater_type = setting["updater_type"].iVal(); 40 | eps = setting["eps"].fVal(); 41 | lr = setting["lr"].fVal(); 42 | max_iter = setting["max_iter"].iVal(); 43 | wd = setting["l2"].fVal(); 44 | lr_decay_interval = setting["lr_decay_interval"].iVal(); 45 | lr_decay_factor = setting["lr_decay_factor"].fVal(); 46 | 47 | iter = 0; 48 | } 49 | 50 | struct square_root { 51 | MSHADOW_XINLINE static real_t Map(real_t a) { 52 | return sqrt(a); 53 | } 54 | }; 55 | 56 | virtual void Update(mshadow::Tensor data, 57 | mshadow::Tensor diff) { 58 | 59 | if (iter == 0 || ((max_iter > 0) && (iter % max_iter == 0))) { 60 | sumGradSquare.Resize(data.shape_, 0.); 61 | } 62 | if ((iter > 0) && (lr_decay_interval > 0) && (iter % lr_decay_interval == 0)) { 63 | lr *= lr_decay_factor; 64 | } 65 | 66 | ++iter; 67 | 68 | if (wd > 0.) { 69 | diff += wd * data; 70 | } 71 | 72 | sumGradSquare += diff * diff; 73 | data -= lr * (diff / (mshadow::expr::F(sumGradSquare) + eps)); 74 | // if (wd > 0.) { 75 | // data -= (wd*lr) * data; 76 | // } 77 | } 78 | 79 | virtual void UpdateSparse(mshadow::Tensor data, 80 | mshadow::Tensor diff, 81 | mshadow::Tensor idx) { 82 | 83 | if (iter == 0 || ((max_iter > 0) && (iter % max_iter == 0))) { 84 | sumGradSquare.Resize(data.shape_, 0.); 85 | } 86 | if ((iter > 0) && (lr_decay_interval > 0) && (iter % lr_decay_interval == 0)) { 87 | lr *= lr_decay_factor; 88 | } 89 | 90 | ++iter; 91 | 92 | 93 | int w_idx = -1; 94 | for (int i = 0; i < idx.size(0); ++i) { 95 | w_idx = idx[i]; 96 | utils::Assert(w_idx >= 0 && w_idx < data.size(0), "Adagrad Sparse Update index error."); 97 | 98 | mshadow::Tensor sumGradSquareRow = sumGradSquare.Slice(w_idx, w_idx+1); 99 | mshadow::Tensor diffRow = diff.Slice(i, i+1); 100 | mshadow::Tensor dataRow = data.Slice(w_idx, w_idx+1); 101 | 102 | if (wd > 0.) { 103 | diffRow += wd * dataRow; 104 | } 105 | sumGradSquareRow += diffRow * diffRow; 106 | dataRow -= (lr * (diffRow / ((mshadow::expr::F(sumGradSquareRow)) + eps))); 107 | // if (wd > 0.) { 108 | // dataRow -= (wd*lr) * dataRow; 109 | // } 110 | } 111 | } 112 | protected: 113 | int iter, max_iter, lr_decay_interval; 114 | mshadow::TensorContainer sumGradSquare; 115 | float eps, lr, wd, lr_decay_factor; 116 | 117 | }; 118 | } // namespace updater 119 | } // namespace textnet 120 | #endif // TEXTNET_CONSTANT_INIT_INL_HPP_ 121 | 122 | -------------------------------------------------------------------------------- /src/updater/sgd_updater-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_SGD_UPDATER_INL_HPP_ 2 | #define TEXTNET_SGD_UPDATER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include "./updater.h" 7 | 8 | namespace textnet { 9 | namespace updater { 10 | 11 | template 12 | class SGDUpdater : public Updater{ 13 | public: 14 | SGDUpdater(std::map &setting, 15 | mshadow::Random* prnd) { 16 | this->prnd_ = prnd; 17 | SetupUpdater(setting); 18 | } 19 | virtual ~SGDUpdater(void) {} 20 | 21 | virtual void Require(std::map &setting) { 22 | // default value, just set the value you want 23 | this->defaults["decay"] = SettingV(0.0f); 24 | this->defaults["momentum"] = SettingV(0.0f); 25 | this->defaults["l2"] = SettingV(0.0f); 26 | this->defaults["batch_size"] = SettingV(1); 27 | 28 | // require value, set to SettingV(), 29 | // it will force custom to set in config 30 | this->defaults["lr"] = SettingV(); 31 | 32 | Updater::Require(setting); 33 | } 34 | 35 | virtual void SetupUpdater(std::map &setting) { 36 | Updater::SetupUpdater(setting); 37 | 38 | this->updater_type = setting["updater_type"].iVal(); 39 | batch_size = setting["batch_size"].iVal(); 40 | base_lr = setting["lr"].fVal(); 41 | decay = setting["decay"].fVal(); 42 | momentum = setting["momentum"].fVal(); 43 | l2 = setting["l2"].fVal(); 44 | iteration = 0; 45 | lr = base_lr; 46 | } 47 | 48 | virtual void Update(mshadow::Tensor data, 49 | mshadow::Tensor diff) { 50 | if (momentum != 0.0 && iteration == 0) { 51 | history.Resize(data.shape_, 0); 52 | } 53 | if (batch_size > 1) { 54 | diff /= float(batch_size); 55 | } 56 | 57 | AdaptLearningRate(); 58 | iteration++; 59 | 60 | if (momentum == 0.0) { 61 | data -= lr * (diff + l2 * data); 62 | } else { 63 | history = lr * (diff + l2 * data) + momentum * history; 64 | data -= history; 65 | } 66 | } 67 | 68 | virtual void UpdateSparse(mshadow::Tensor data, 69 | mshadow::Tensor diff, 70 | mshadow::Tensor idx) { 71 | if (momentum != 0.0 && iteration == 0) { 72 | history.Resize(data.shape_, 0); 73 | } 74 | if (batch_size > 1) { 75 | diff /= float(batch_size); 76 | } 77 | 78 | AdaptLearningRate(); 79 | iteration++; 80 | 81 | if (momentum == 0.0) { 82 | int w_idx = -1; 83 | for (int i = 0; i < idx.size(0); ++i) { 84 | w_idx = idx[i]; 85 | data[w_idx] -= lr * (diff[i] + l2 * data[w_idx]); 86 | } 87 | } else { 88 | int w_idx = -1; 89 | for (int i = 0; i < idx.size(0); ++i) { 90 | w_idx = idx[i]; 91 | history[w_idx] = lr * (diff[i] + l2 * data[w_idx]) + momentum * history[w_idx]; 92 | data[w_idx] -= history[w_idx]; 93 | } 94 | } 95 | } 96 | 97 | virtual void AdaptLearningRate() { 98 | if (lr < 0.1 * base_lr) return; 99 | lr = base_lr * (1.0 - decay * iteration); 100 | } 101 | 102 | protected: 103 | float momentum; 104 | mshadow::TensorContainer history; 105 | int iteration, batch_size; 106 | float lr; 107 | float base_lr; 108 | float decay; 109 | float l2; 110 | }; 111 | } // namespace updater 112 | } // namespace textnet 113 | #endif // TEXTNET_CONSTANT_INIT_INL_HPP_ 114 | 115 | -------------------------------------------------------------------------------- /src/updater/sgdstep_updater-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_SGDSTEP_UPDATER_INL_HPP_ 2 | #define TEXTNET_SGDSTEP_UPDATER_INL_HPP_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "./updater.h" 9 | 10 | namespace textnet { 11 | namespace updater { 12 | 13 | template 14 | class SGDStepUpdater : public Updater{ 15 | public: 16 | SGDStepUpdater(std::map &setting, 17 | mshadow::Random* prnd) { 18 | this->prnd_ = prnd; 19 | SetupUpdater(setting); 20 | } 21 | virtual ~SGDStepUpdater(void) {} 22 | 23 | virtual void Require(std::map &setting) { 24 | // default value, just set the value you want 25 | this->defaults["decay"] = SettingV(0.1f); 26 | this->defaults["momentum"] = SettingV(0.9f); 27 | this->defaults["l2"] = SettingV(0.0f); 28 | this->defaults["steps"] = SettingV(""); 29 | this->defaults["steps_lr"] = SettingV(""); 30 | 31 | // require value, set to SettingV(), 32 | // it will force custom to set in config 33 | this->defaults["lr"] = SettingV(); 34 | 35 | Updater::Require(setting); 36 | } 37 | 38 | virtual void SetupUpdater(std::map &setting) { 39 | Updater::SetupUpdater(setting); 40 | 41 | this->updater_type = setting["updater_type"].iVal(); 42 | base_lr = setting["lr"].fVal(); 43 | decay = setting["decay"].fVal(); 44 | momentum = setting["momentum"].fVal(); 45 | l2 = setting["l2"].fVal(); 46 | steps_str = setting["steps"].sVal(); 47 | steps_lr_str = setting["steps_lr"].sVal(); 48 | 49 | int s = 0; 50 | istringstream iss; 51 | iss.str(steps_str); 52 | while (iss >> s) { 53 | steps.push_back(s); 54 | } 55 | 56 | float f = 0; 57 | istringstream iss_lr; 58 | iss_lr.str(steps_lr_str); 59 | while (iss_lr >> f) { 60 | steps_lr.push_back(f); 61 | } 62 | 63 | cur_step = 0; 64 | 65 | iteration = 0; 66 | lr = base_lr; 67 | 68 | // for debug 69 | cout << "base_lr: " << base_lr << endl; 70 | cout << "decay: " << decay << endl; 71 | cout << "momentum: " << momentum << endl; 72 | cout << "l2: " << l2 << endl; 73 | cout << steps[0] << steps[1] < data, 77 | mshadow::Tensor diff) { 78 | if (momentum != 0.0 && iteration == 0) { 79 | history.Resize(data.shape_, 0); 80 | } 81 | 82 | AdaptLearningRate(); 83 | iteration++; 84 | 85 | if (momentum == 0.0) { 86 | data -= lr * (diff + l2 * data); 87 | } else { 88 | history = lr * (diff + l2 * data) + momentum * history; 89 | data -= history; 90 | } 91 | } 92 | 93 | virtual void UpdateSparse(mshadow::Tensor data, 94 | mshadow::Tensor diff, 95 | mshadow::Tensor idx) { 96 | if (momentum != 0.0 && iteration == 0) { 97 | history.Resize(data.shape_, 0); 98 | } 99 | 100 | AdaptLearningRate(); 101 | iteration++; 102 | 103 | if (momentum == 0.0) { 104 | int w_idx = -1; 105 | for (int i = 0; i < idx.size(0); ++i) { 106 | w_idx = idx[i]; 107 | data[w_idx] -= lr * (diff[i] + l2 * data[w_idx]); 108 | } 109 | } else { 110 | int w_idx = -1; 111 | for (int i = 0; i < idx.size(0); ++i) { 112 | w_idx = idx[i]; 113 | history[w_idx] = lr * (diff[i] + l2 * data[w_idx]) + momentum * history[w_idx]; 114 | data[w_idx] -= history[w_idx]; 115 | } 116 | } 117 | } 118 | 119 | virtual void AdaptLearningRate() { 120 | if (cur_step >= steps.size()) return; 121 | if (iteration == steps[cur_step]) { 122 | if (steps_lr.size() == 0) { 123 | lr *= decay; 124 | ++cur_step; 125 | } else { 126 | lr = steps_lr[cur_step]; 127 | ++cur_step; 128 | } 129 | } 130 | } 131 | 132 | protected: 133 | float momentum; 134 | mshadow::TensorContainer history; 135 | int iteration; 136 | float lr; 137 | float base_lr; 138 | float decay; 139 | float l2; 140 | vector steps; 141 | vector steps_lr; 142 | int cur_step; 143 | string steps_str; 144 | string steps_lr_str; 145 | }; 146 | } // namespace updater 147 | } // namespace textnet 148 | #endif // TEXTNET_CONSTANT_INIT_INL_HPP_ 149 | 150 | -------------------------------------------------------------------------------- /src/updater/updater.h: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_UPDATER_UPDATER_H_ 2 | #define TEXTNET_UPDATER_UPDATER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "../global.h" 9 | #include "../utils/utils.h" 10 | #include "../utils/io.h" 11 | #include "../utils/settingv.h" 12 | 13 | /*! \brief namespace of textnet */ 14 | namespace textnet { 15 | /*! \brief namespace of layer defintiion */ 16 | namespace updater { 17 | 18 | /*! \brief use integer to encode layer types */ 19 | typedef int UpdaterType; 20 | 21 | /*! \brief these are enumeration */ 22 | const int kSGD = 0; 23 | const int kAdagrad = 1; 24 | const int kAdam = 2; 25 | const int kSGDSparse = 3; 26 | const int kAdaDelta = 4; 27 | const int kSGDStep = 5; 28 | 29 | template 30 | class Updater { 31 | public: 32 | Updater(void) {} 33 | virtual ~Updater(void) {} 34 | 35 | // To implement this function you need call base function in the end 36 | virtual void Require(std::map &setting) { 37 | defaults["updater_type"] = SettingV(kSGD); 38 | for (std::map::iterator it = defaults.begin(); 39 | it != defaults.end(); ++it) { 40 | std::string name = it->first; 41 | if (defaults[name].value_type == SET_NONE) { 42 | utils::Check(setting.count(name), 43 | "\tSetting [%s] needed for this layer.\n", name.c_str()); 44 | } else { 45 | if (!setting.count(name)) { 46 | setting[name] = defaults[name]; 47 | utils::Printf("\tSetting [%s] set to default value.\n", name.c_str()); 48 | } 49 | } 50 | } 51 | } 52 | 53 | virtual void SetupUpdater(std::map &setting) { 54 | updater_type = 0; 55 | this->Require(setting); 56 | } 57 | 58 | virtual void Update(mshadow::Tensor data, 59 | mshadow::Tensor diff) = 0; 60 | 61 | virtual void UpdateSparse(mshadow::Tensor data, 62 | mshadow::Tensor diff, 63 | mshadow::Tensor idx) = 0; 64 | 65 | 66 | virtual UpdaterType GetUpdaterType() { return updater_type; } 67 | 68 | protected: 69 | UpdaterType updater_type; 70 | mshadow::Random* prnd_; 71 | // required setting 72 | std::map defaults; 73 | 74 | }; 75 | 76 | template 77 | Updater* CreateUpdater(UpdaterType type, std::map &setting, 78 | mshadow::Random* prnd); 79 | 80 | } // namespace updater 81 | } // namespace textnet 82 | #endif // TEXTNET_UPDATER_UPDATER_H_ 83 | -------------------------------------------------------------------------------- /src/updater/updater_impl-inl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_UPDATER_IMPL_INL_HPP_ 2 | #define TEXTNET_UPDATER_IMPL_INL_HPP_ 3 | 4 | #include "./updater.h" 5 | #include "./sgd_updater-inl.hpp" 6 | #include "./sgdstep_updater-inl.hpp" 7 | // #include "./sgdsparse_updater-inl.hpp" 8 | #include "./adagrad_updater-inl.hpp" 9 | #include "./adadelta_updater-inl.hpp" 10 | #include "./adam_updater-inl.hpp" 11 | 12 | namespace textnet { 13 | namespace updater { 14 | template 15 | Updater* CreateUpdater_(UpdaterType type, std::map &setting, 16 | mshadow::Random* prnd) { 17 | switch(type) { 18 | case kSGD: return new SGDUpdater(setting, prnd); 19 | case kAdagrad: return new AdagradUpdater(setting, prnd); 20 | case kAdaDelta: return new AdaDeltaUpdater(setting, prnd); 21 | case kSGDStep: return new SGDStepUpdater(setting, prnd); 22 | case kAdam: return new AdamUpdater(setting, prnd); 23 | // case kSGDSparse: return new SGDSparseInitializer(setting); 24 | default: utils::Error("unknown updater type id : \"%d\"", type); return NULL; 25 | } 26 | } 27 | 28 | } // namespace updater 29 | } // namespace textnet 30 | #endif 31 | -------------------------------------------------------------------------------- /src/updater/updater_impl.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #define _CRT_SECURE_NO_DEPRECATE 3 | // include the layer, this is where the actual implementations are 4 | 5 | #include "updater_impl-inl.hpp" 6 | // specialize the cpu implementation here 7 | namespace textnet { 8 | namespace updater { 9 | template<> 10 | Updater* CreateUpdater(UpdaterType type, std::map &setting, 11 | mshadow::Random* prnd) { 12 | return CreateUpdater_(type, setting, prnd); 13 | } 14 | template<> 15 | Updater* CreateUpdater(UpdaterType type, std::map &setting, 16 | mshadow::Random* prnd) { 17 | return CreateUpdater_(type, setting, prnd); 18 | } 19 | template<> 20 | Updater* CreateUpdater(UpdaterType type, std::map &setting, 21 | mshadow::Random* prnd) { 22 | return CreateUpdater_(type, setting, prnd); 23 | } 24 | template<> 25 | Updater* CreateUpdater(UpdaterType type, std::map &setting, 26 | mshadow::Random* prnd) { 27 | return CreateUpdater_(type, setting, prnd); 28 | } 29 | } // namespace updater 30 | } // namespace textnet 31 | -------------------------------------------------------------------------------- /src/updater/updater_impl.cu: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #define _CRT_SECURE_NO_DEPRECATE 3 | // include the layer, this is where the actual implementations are 4 | 5 | #include "updater_impl-inl.hpp" 6 | // specialize the gpu implementation here 7 | namespace textnet { 8 | namespace updater { 9 | template<> 10 | Updater* CreateUpdater(UpdaterType type, std::map &setting, 11 | mshadow::Random* prnd) { 12 | return CreateUpdater_(type, setting, prnd); 13 | } 14 | template<> 15 | Updater* CreateUpdater(UpdaterType type, std::map &setting, 16 | mshadow::Random* prnd) { 17 | return CreateUpdater_(type, setting, prnd); 18 | } 19 | template<> 20 | Updater* CreateUpdater(UpdaterType type, std::map &setting, 21 | mshadow::Random* prnd) { 22 | return CreateUpdater_(type, setting, prnd); 23 | } 24 | template<> 25 | Updater* CreateUpdater(UpdaterType type, std::map &setting, 26 | mshadow::Random* prnd) { 27 | return CreateUpdater_(type, setting, prnd); 28 | } 29 | } // namespace updater 30 | } // namespace textnet -------------------------------------------------------------------------------- /src/utils/decoder.h: -------------------------------------------------------------------------------- 1 | #ifndef CXXNET_UTILS_DECODER_H_ 2 | #define CXXNET_UTILS_DECODER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "./utils.h" 10 | #if CXXNET_USE_OPENCV 11 | #include 12 | #endif 13 | 14 | namespace cxxnet { 15 | namespace utils { 16 | 17 | struct JpegDecoder { 18 | public: 19 | JpegDecoder(void) { 20 | cinfo.err = jpeg_std_error(&jerr.base); 21 | jerr.base.error_exit = jerror_exit; 22 | jerr.base.output_message = joutput_message; 23 | jpeg_create_decompress(&cinfo); 24 | } 25 | // destructor 26 | ~JpegDecoder(void) { 27 | jpeg_destroy_decompress(&cinfo); 28 | } 29 | 30 | inline void Decode(unsigned char *ptr, size_t sz, 31 | mshadow::TensorContainer *p_data) { 32 | if(setjmp(jerr.jmp)) { 33 | jpeg_destroy_decompress(&cinfo); 34 | utils::Error("Libjpeg fail to decode"); 35 | } 36 | this->jpeg_mem_src(&cinfo, ptr, sz); 37 | utils::Check(jpeg_read_header(&cinfo, TRUE) == JPEG_HEADER_OK, "libjpeg: failed to decode"); 38 | utils::Check(jpeg_start_decompress(&cinfo) == true, "libjpeg: failed to decode"); 39 | p_data->Resize(mshadow::Shape3(cinfo.output_height, cinfo.output_width, cinfo.output_components)); 40 | JSAMPROW jptr = &((*p_data)[0][0][0]); 41 | while (cinfo.output_scanline < cinfo.output_height) { 42 | utils::Check(jpeg_read_scanlines(&cinfo, &jptr, 1) == true, "libjpeg: failed to decode"); 43 | jptr += cinfo.output_width * cinfo.output_components; 44 | } 45 | utils::Check(jpeg_finish_decompress(&cinfo) == true, "libjpeg: failed to decode"); 46 | } 47 | private: 48 | struct jerror_mgr { 49 | jpeg_error_mgr base; 50 | jmp_buf jmp; 51 | }; 52 | 53 | METHODDEF(void) jerror_exit(j_common_ptr jinfo) { 54 | jerror_mgr* err = (jerror_mgr*)jinfo->err; 55 | longjmp(err->jmp, 1); 56 | } 57 | 58 | METHODDEF(void) joutput_message(j_common_ptr) {} 59 | 60 | static boolean mem_fill_input_buffer_ (j_decompress_ptr cinfo) { 61 | utils::Error("JpegDecoder: bad jpeg image"); 62 | return true; 63 | } 64 | 65 | static void mem_skip_input_data_ (j_decompress_ptr cinfo, long num_bytes_) { 66 | jpeg_source_mgr *src = cinfo->src; 67 | size_t num_bytes = static_cast(num_bytes_); 68 | if (num_bytes > 0) { 69 | src->next_input_byte += num_bytes; 70 | utils::Assert(src->bytes_in_buffer >= num_bytes, "fail to decode"); 71 | src->bytes_in_buffer -= num_bytes; 72 | } else { 73 | utils::Error("JpegDecoder: bad jpeg image"); 74 | 75 | } 76 | } 77 | 78 | static void mem_term_source_ (j_decompress_ptr cinfo) {} 79 | static void mem_init_source_ (j_decompress_ptr cinfo) {} 80 | static boolean jpeg_resync_to_restart_(j_decompress_ptr cinfo, int desired) { 81 | utils::Error("JpegDecoder: bad jpeg image"); 82 | return true; 83 | } 84 | void jpeg_mem_src (j_decompress_ptr cinfo, void* buffer, long nbytes) { 85 | src.init_source = mem_init_source_; 86 | src.fill_input_buffer = mem_fill_input_buffer_; 87 | src.skip_input_data = mem_skip_input_data_; 88 | src.resync_to_restart = jpeg_resync_to_restart_; 89 | src.term_source = mem_term_source_; 90 | src.bytes_in_buffer = nbytes; 91 | src.next_input_byte = static_cast(buffer); 92 | cinfo->src = &src; 93 | } 94 | 95 | private: 96 | jpeg_decompress_struct cinfo; 97 | jpeg_source_mgr src; 98 | jerror_mgr jerr; 99 | }; 100 | 101 | #if CXXNET_USE_OPENCV 102 | struct OpenCVDecoder { 103 | void Decode(unsigned char *ptr, size_t sz, mshadow::TensorContainer *p_data) { 104 | // can be improved without memcpy buf 105 | buf.resize(sz); 106 | memcpy(&buf[0], ptr, sz); 107 | cv::Mat res = cv::imdecode(buf, 1); 108 | utils::Assert(res.data != NULL, "decoding fail"); 109 | p_data->Resize(mshadow::Shape3(res.rows, res.cols, 3)); 110 | for (int y = 0; y < res.rows; ++y) { 111 | for (int x = 0; x < res.cols; ++x) { 112 | cv::Vec3b bgr = res.at(y, x); 113 | // store in RGB order 114 | (*p_data)[y][x][2] = bgr[0]; 115 | (*p_data)[y][x][1] = bgr[1]; 116 | (*p_data)[y][x][0] = bgr[2]; 117 | } 118 | } 119 | res.release(); 120 | } 121 | private: 122 | std::vector buf; 123 | }; 124 | #endif 125 | } // namespace utils 126 | } // namespace cxxnet 127 | 128 | #endif // DECODER_H 129 | -------------------------------------------------------------------------------- /src/utils/random.h: -------------------------------------------------------------------------------- 1 | #ifndef CXXNET_UTILS_GLOBAL_RANDOM_H_ 2 | #define CXXNET_UTILS_GLOBAL_RANDOM_H_ 3 | /*! 4 | * \file global_random.h 5 | * \brief global random number utils, used for some preprocessing 6 | * \author Tianqi Chen 7 | */ 8 | #include 9 | #include 10 | #include 11 | #include "./utils.h" 12 | 13 | namespace textnet { 14 | namespace utils { 15 | /*! \brief simple thread dependent random sampler */ 16 | class RandomSampler { 17 | public: 18 | RandomSampler(void) : rseed_(0) { 19 | } 20 | /*! 21 | * \brief seed random number 22 | * \param seed the random number seed 23 | */ 24 | inline void Seed(unsigned seed) { 25 | this->rseed_ = seed; 26 | } 27 | /*! \brief return a real number uniform in [0,1) */ 28 | inline double NextDouble() { 29 | return static_cast(rand_r(&rseed_)) / 30 | (static_cast(RAND_MAX) + 1.0); 31 | } 32 | /*! \brief return a random number in n */ 33 | inline uint32_t NextUInt32(uint32_t n) { 34 | return static_cast(floor(NextDouble() * n)); 35 | } 36 | /*! \brief random shuffle data */ 37 | template 38 | inline void Shuffle(T *data, size_t sz) { 39 | if(sz == 0) return; 40 | for(uint32_t i = (uint32_t)sz - 1; i > 0; i--) { 41 | std::swap(data[i], data[NextUInt32(i+1)]); 42 | } 43 | } 44 | /*!\brief random shuffle data in */ 45 | template 46 | inline void Shuffle(std::vector &data) { 47 | Shuffle(&data[0], data.size()); 48 | } 49 | 50 | private: 51 | unsigned rseed_; 52 | }; 53 | } // namespace utils 54 | } // namespace textnet 55 | #endif 56 | -------------------------------------------------------------------------------- /src/utils/settingv.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "settingv.h" 5 | 6 | namespace textnet { 7 | std::map SettingV::SettingIntMap = std::map(); 8 | std::map SettingV::SettingBoolMap = std::map(); 9 | 10 | // Access data interface 11 | bool SettingV::bVal() { 12 | switch(value_type) { 13 | case SET_NONE: 14 | utils::Error("\tCan not convert [none] to [bool].\n"); 15 | return b_val; 16 | case SET_INT: 17 | utils::Error("\tCan not convert [int] to [bool].\n"); 18 | return b_val; 19 | case SET_FLOAT: 20 | utils::Error("\tCan not convert [float] to [bool].\n"); 21 | return b_val; 22 | case SET_BOOL: 23 | return b_val; 24 | case SET_STRING: 25 | utils::Printf("\tConvert [string] to [bool].\n"); 26 | return SettingBoolMap[s_val]; 27 | case SET_MAP: 28 | utils::Error("\tCan not convert [map] to [bool].\n"); 29 | return b_val; 30 | } 31 | return b_val; 32 | } 33 | int SettingV::iVal() { 34 | switch(value_type) { 35 | case SET_NONE: 36 | utils::Error("\tCan not convert [none] to [int].\n"); 37 | return i_val; 38 | case SET_INT: 39 | return i_val; 40 | case SET_FLOAT: 41 | utils::Printf("\tConvert [float] to [int].\n"); 42 | return static_cast(f_val); 43 | case SET_BOOL: 44 | utils::Printf("\tConvert [bool] to [int].\n"); 45 | return static_cast(b_val); 46 | case SET_STRING: 47 | utils::Printf("\tConvert [string] to [int].\n"); 48 | return SettingIntMap[s_val]; 49 | case SET_MAP: 50 | utils::Error("\tCan not convert [map] to [int].\n"); 51 | return i_val; 52 | } 53 | return i_val; 54 | } 55 | float SettingV::fVal() { 56 | switch(value_type) { 57 | case SET_NONE: 58 | utils::Error("\tCan not convert [none] to [float].\n"); 59 | return f_val; 60 | case SET_INT: 61 | utils::Printf("\tConvert [int] to [float].\n"); 62 | return static_cast(i_val); 63 | case SET_FLOAT: 64 | return f_val; 65 | case SET_BOOL: 66 | utils::Error("\tCan not convert [bool] to [float].\n"); 67 | return f_val; 68 | case SET_STRING: 69 | utils::Error("\tCan not convert [string] to [float].\n"); 70 | break; 71 | case SET_MAP: 72 | utils::Error("\tCan not convert [map] to [float].\n"); 73 | return f_val; 74 | } 75 | return f_val; 76 | } 77 | std::string SettingV::sVal() { 78 | switch(value_type) { 79 | case SET_NONE: 80 | utils::Error("\tCan not convert [none] to [string].\n"); 81 | return s_val; 82 | case SET_INT: 83 | utils::Error("\tCan not convert [int] to [string].\n"); 84 | return s_val; 85 | case SET_FLOAT: 86 | utils::Error("\tCan not convert [float] to [string].\n"); 87 | return s_val; 88 | case SET_BOOL: 89 | utils::Error("\tCan not convert [bool] to [string].\n"); 90 | return s_val; 91 | case SET_STRING: 92 | return s_val; 93 | case SET_MAP: 94 | utils::Error("\tCan not convert [map] to [string].\n"); 95 | return s_val; 96 | } 97 | return s_val; 98 | } 99 | std::map* SettingV::mVal() { 100 | switch(value_type) { 101 | case SET_NONE: 102 | utils::Error("\tCan not convert [none] to [map].\n"); 103 | return m_val; 104 | case SET_INT: 105 | utils::Error("\tCan not convert [int] to [map].\n"); 106 | return m_val; 107 | case SET_FLOAT: 108 | utils::Error("\tCan not convert [float] to [map].\n"); 109 | return m_val; 110 | case SET_BOOL: 111 | utils::Error("\tCan not convert [bool] to [map].\n"); 112 | return m_val; 113 | case SET_STRING: 114 | utils::Error("\tCan not convert [string] to [map].\n"); 115 | return m_val; 116 | case SET_MAP: 117 | return m_val; 118 | } 119 | return m_val; 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/utils/settingv.h: -------------------------------------------------------------------------------- 1 | #ifndef TEXTNET_SETTINGV_H_ 2 | #define TEXTNET_SETTINGV_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include "./utils.h" 8 | 9 | namespace textnet { 10 | 11 | typedef int SetValueType; 12 | 13 | const int SET_NONE = 0; 14 | const int SET_INT = 1; 15 | const int SET_FLOAT = 2; 16 | const int SET_BOOL = 3; 17 | const int SET_STRING = 4; 18 | const int SET_MAP = 5; 19 | 20 | /*! \brief Setting structure used to store net settings */ 21 | struct SettingV { 22 | bool b_val; 23 | int i_val; 24 | float f_val; 25 | std::string s_val; 26 | std::map* m_val; 27 | 28 | SetValueType value_type; 29 | 30 | // String to enum dictionary 31 | static std::map SettingIntMap; 32 | // String to bool dictiionary 33 | static std::map SettingBoolMap; 34 | 35 | // Constructor 36 | SettingV() { value_type = SET_NONE; } 37 | SettingV(int i) { i_val = i; value_type = SET_INT; } 38 | SettingV(float f) { f_val = f; value_type = SET_FLOAT; } 39 | SettingV(bool b) { b_val = b; value_type = SET_BOOL; } 40 | SettingV(std::string s) { s_val = s; value_type = SET_STRING; } 41 | SettingV(const char* c) { s_val = c; value_type = SET_STRING; } 42 | SettingV(std::map* m) { m_val = m; value_type = SET_MAP; } 43 | 44 | // Access data interface 45 | bool bVal(); 46 | int iVal(); 47 | float fVal(); 48 | std::string sVal(); 49 | std::map* mVal(); 50 | }; //SettingV 51 | } 52 | #endif //TEXTNET_SETTINGV_H_ 53 | -------------------------------------------------------------------------------- /src/utils/thread.h: -------------------------------------------------------------------------------- 1 | #ifndef CXXNET_UTILS_THREAD_H_ 2 | #define CXXNET_UTILS_THREAD_H_ 3 | /*! 4 | * \file thread.h 5 | * \brief this header include the minimum necessary resource for multi-threading 6 | * \author Tianqi Chen 7 | * Acknowledgement: this file is adapted from SVDFeature project, by same author. 8 | * The MAC support part of this code is provided by Artemy Kolchinsky 9 | */ 10 | #ifdef _MSC_VER 11 | #include "utils.h" 12 | #include 13 | #include 14 | namespace textnet { 15 | namespace utils { 16 | /*! \brief simple semaphore used for synchronization */ 17 | class Semaphore { 18 | public : 19 | inline void Init(int init_val) { 20 | sem = CreateSemaphore(NULL, init_val, 10, NULL); 21 | utils::Assert(sem != NULL, "create Semaphore error"); 22 | } 23 | inline void Destroy(void) { 24 | CloseHandle(sem); 25 | } 26 | inline void Wait(void) { 27 | utils::Assert(WaitForSingleObject(sem, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject error"); 28 | } 29 | inline void Post(void) { 30 | utils::Assert(ReleaseSemaphore(sem, 1, NULL) != 0, "ReleaseSemaphore error"); 31 | } 32 | private: 33 | HANDLE sem; 34 | }; 35 | /*! \brief simple thread that wraps windows thread */ 36 | class Thread { 37 | private: 38 | HANDLE thread_handle; 39 | unsigned thread_id; 40 | public: 41 | inline void Start(unsigned int __stdcall entry(void*), void *param) { 42 | thread_handle = (HANDLE)_beginthreadex(NULL, 0, entry, param, 0, &thread_id); 43 | } 44 | inline int Join(void) { 45 | WaitForSingleObject(thread_handle, INFINITE); 46 | return 0; 47 | } 48 | }; 49 | /*! \brief exit function called from thread */ 50 | inline void ThreadExit(void *status) { 51 | _endthreadex(0); 52 | } 53 | #define CXXNET_THREAD_PREFIX unsigned int __stdcall 54 | } // namespace utils 55 | } // namespace cxxnet 56 | #else 57 | // thread interface using g++ 58 | #include 59 | #include 60 | namespace cxxnet { 61 | namespace utils { 62 | /*!\brief semaphore class */ 63 | class Semaphore { 64 | #ifdef __APPLE__ 65 | private: 66 | sem_t* semPtr; 67 | char sema_name[20]; 68 | private: 69 | inline void GenRandomString(char *s, const int len) { 70 | static const char alphanum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ; 71 | for (int i = 0; i < len; ++i) { 72 | s[i] = alphanum[rand() % (sizeof(alphanum) - 1)]; 73 | } 74 | s[len] = 0; 75 | } 76 | public: 77 | inline void Init(int init_val) { 78 | sema_name[0]='/'; 79 | sema_name[1]='s'; 80 | sema_name[2]='e'; 81 | sema_name[3]='/'; 82 | GenRandomString(&sema_name[4], 16); 83 | if((semPtr = sem_open(sema_name, O_CREAT, 0644, init_val)) == SEM_FAILED) { 84 | perror("sem_open"); 85 | exit(1); 86 | } 87 | utils::Assert(semPtr != NULL, "create Semaphore error"); 88 | } 89 | inline void Destroy(void) { 90 | if (sem_close(semPtr) == -1) { 91 | perror("sem_close"); 92 | exit(EXIT_FAILURE); 93 | } 94 | if (sem_unlink(sema_name) == -1) { 95 | perror("sem_unlink"); 96 | exit(EXIT_FAILURE); 97 | } 98 | } 99 | inline void Wait(void) { 100 | sem_wait(semPtr); 101 | } 102 | inline void Post(void) { 103 | sem_post(semPtr); 104 | } 105 | #else 106 | private: 107 | sem_t sem; 108 | public: 109 | inline void Init(int init_val) { 110 | sem_init(&sem, 0, init_val); 111 | } 112 | inline void Destroy(void) { 113 | sem_destroy(&sem); 114 | } 115 | inline void Wait(void) { 116 | sem_wait(&sem); 117 | } 118 | inline void Post(void) { 119 | sem_post(&sem); 120 | } 121 | #endif 122 | }; 123 | /*!\brief simple thread class */ 124 | class Thread { 125 | private: 126 | pthread_t thread; 127 | public : 128 | inline void Start(void * entry(void*), void *param) { 129 | pthread_attr_t attr; 130 | pthread_attr_init(&attr); 131 | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 132 | pthread_create(&thread, &attr, entry, param); 133 | } 134 | inline int Join(void) { 135 | void *status; 136 | return pthread_join(thread, &status); 137 | } 138 | }; 139 | inline void ThreadExit(void *status) { 140 | pthread_exit(status); 141 | } 142 | } // namespace utils 143 | } // namespace textnet 144 | #define CXXNET_THREAD_PREFIX void * 145 | #endif 146 | #endif 147 | -------------------------------------------------------------------------------- /src/utils/timer.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file timer.h 3 | * \brief This file defines the utils for timing 4 | * \author Tianqi Chen 5 | */ 6 | #ifndef CXXNET_TIMER_H_ 7 | #define CXXNET_TIMER_H_ 8 | #include 9 | #include 10 | #ifdef __MACH__ 11 | #include 12 | #include 13 | #endif 14 | namespace textnet { 15 | namespace utils { 16 | inline double GetTime(void) { 17 | // Adapted from: https://gist.github.com/jbenet/1087739 18 | #ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time 19 | clock_serv_t cclock; 20 | mach_timespec_t mts; 21 | host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); 22 | utils::Check(clock_get_time(cclock, &mts) == 0, "failed to get time"); 23 | mach_port_deallocate(mach_task_self(), cclock); 24 | return static_cast(mts.tv_sec) + static_cast(mts.tv_nsec) * 1e-9; 25 | #else 26 | timespec ts; 27 | utils::Check(clock_gettime(CLOCK_REALTIME, &ts) == 0, "failed to get time"); 28 | return static_cast(ts.tv_sec) + static_cast(ts.tv_nsec) * 1e-9; 29 | #endif 30 | } 31 | } 32 | } 33 | #endif 34 | -------------------------------------------------------------------------------- /test_data/data1.wid: -------------------------------------------------------------------------------- 1 | L1 4 1 2 3 4 2 | L2 3 2 3 4 3 | L3 3 1 5 6 4 | L4 3 1 2 3 5 | -------------------------------------------------------------------------------- /test_data/data2.wid: -------------------------------------------------------------------------------- 1 | S1 4 1 2 3 4 2 | S2 3 1 2 3 3 | S3 3 9 9 9 4 | -------------------------------------------------------------------------------- /test_data/feature.dat: -------------------------------------------------------------------------------- 1 | S1 1 2 1 2 1 2 1 2 1 2 1 2 2 | S2 2 3 2 3 2 3 2 3 2 3 2 3 3 | S3 3 4 3 4 3 4 3 4 3 4 3 4 4 | -------------------------------------------------------------------------------- /test_data/feature1.dat: -------------------------------------------------------------------------------- 1 | S1 1 2 2 | S2 2 3 3 | S3 3 4 4 | -------------------------------------------------------------------------------- /test_data/rel.dat: -------------------------------------------------------------------------------- 1 | 2 L1 S1 2 | 1 L1 S2 3 | 0 L1 S3 4 | 0 L1 S3 5 | 1 L2 S1 6 | 0 L2 S2 7 | 0 L2 S3 8 | 0 L3 S3 9 | -------------------------------------------------------------------------------- /test_data/word_trigram.txt: -------------------------------------------------------------------------------- 1 | 0 8 9 2 | 1 0 1 2 3 | 2 0 2 3 4 | 3 1 4 5 5 | 4 6 6 | 5 9 7 | 6 7 8 8 | --------------------------------------------------------------------------------