LayerPtr createCTCLayer(string name,
                        size_t numClasses,
                        bool useGpu,
                        bool normByTimes,
                        LayerPtr dataLayer,
                        LayerPtr labelLayer) {
  LayerMap layerMap;
  layerMap[dataLayer->getName()] = dataLayer;
  layerMap[labelLayer->getName()] = labelLayer;

  ParameterMap parameterMap;

  LayerConfig layerConfig;
  layerConfig.set_name(name);
  layerConfig.set_type("ctc");
  layerConfig.set_size(numClasses);
  layerConfig.set_norm_by_times(normByTimes);

  layerConfig.add_inputs();
  LayerInputConfig& input0 = *(layerConfig.mutable_inputs(0));
  input0.set_input_layer_name(dataLayer->getName());

  layerConfig.add_inputs();
  LayerInputConfig& input1 = *(layerConfig.mutable_inputs(1));
  input1.set_input_layer_name(labelLayer->getName());

  LayerPtr layer = LayerPtr(new CTCLayer(layerConfig));
  layerMap[layer->getName()] = layer;
  layer->init(layerMap, parameterMap);

  ActivationFunction* softmaxActivation = ActivationFunction::create("softmax");

  softmaxActivation->forward(dataLayer->getOutput()).check();
  layer->forward(PASS_GC);

  layer->backward();
  softmaxActivation->backward(dataLayer->getOutput()).check();

  return layer;
}
LayerPtr createWarpCTCLayer(string name,
                            size_t numClasses,
                            bool useGpu,
                            bool normByTimes,
                            LayerPtr dataLayer,
                            LayerPtr labelLayer) {
  LayerMap layerMap;
  layerMap[dataLayer->getName()] = dataLayer;
  layerMap[labelLayer->getName()] = labelLayer;

  ParameterMap parameterMap;

  LayerConfig layerConfig;
  layerConfig.set_name(name);
  layerConfig.set_type("warp_ctc");
  layerConfig.set_size(numClasses);
  layerConfig.set_blank(numClasses - 1);
  layerConfig.set_norm_by_times(normByTimes);

  layerConfig.add_inputs();
  LayerInputConfig& input0 = *(layerConfig.mutable_inputs(0));
  input0.set_input_layer_name(dataLayer->getName());

  layerConfig.add_inputs();
  LayerInputConfig& input1 = *(layerConfig.mutable_inputs(1));
  input1.set_input_layer_name(labelLayer->getName());

  LayerPtr layer = LayerPtr(new WarpCTCLayer(layerConfig));
  layerMap[layer->getName()] = layer;
  layer->init(layerMap, parameterMap);

  layer->forward(PASS_GC);
  layer->backward();

  return layer;
}