diff --git a/doc/build/contribute_to_paddle.md b/doc/build/contribute_to_paddle.md index b3d5fa7c9ff5f0b879e15b8017d029bc23e9ada8..10d5d86311333c223d1024f520fccddcb4c5050d 100644 --- a/doc/build/contribute_to_paddle.md +++ b/doc/build/contribute_to_paddle.md @@ -25,7 +25,7 @@ repo or just head straight to the command line: ```shell # Clone your fork to your local machine -git clone git@github.com:USERNAME/paddle.git +git clone git@github.com:USERNAME/Paddle.git ``` Then you can start to develop. @@ -52,7 +52,7 @@ To do this, you'll need to add a remote at first: # see the current configured remote repository git remote -v # add upstream repository -git remote add upstream https://github.com/paddle/paddle.git +git remote add upstream https://github.com/baidu/Paddle.git # verify the new upstream git remote -v ``` diff --git a/paddle/gserver/evaluators/CTCErrorEvaluator.cpp b/paddle/gserver/evaluators/CTCErrorEvaluator.cpp index cd4ed19c2ca45c310032c834da4cad56fb1cbdff..e397c71c877dce8c34aefac12481373a037510f6 100644 --- a/paddle/gserver/evaluators/CTCErrorEvaluator.cpp +++ b/paddle/gserver/evaluators/CTCErrorEvaluator.cpp @@ -207,7 +207,7 @@ public: real err = 0; err = editDistance( output.value->getData() + output.value->getWidth() * outputStarts[i], - output.value->getHeight(), output.value->getWidth(), + outputStarts[i+1] - outputStarts[i], output.value->getWidth(), label.ids->getData() + labelStarts[i], labelStarts[i + 1] - labelStarts[i]); @@ -224,6 +224,9 @@ public: for (const std::string& name : config_.input_layers()) { arguments.push_back(nn.getLayer(name)->getOutput()); } + } + + virtual void updateSamplesNum(const std::vector& arguments) { numSequences_ += arguments[1].getNumSequences(); } diff --git a/paddle/gserver/tests/test_Evaluator.cpp b/paddle/gserver/tests/test_Evaluator.cpp index 8e857781468fed694dbd061d896263bf05303260..3a591a316b8bafccac9c59ff28e57b4e27f8377a 100644 --- a/paddle/gserver/tests/test_Evaluator.cpp +++ b/paddle/gserver/tests/test_Evaluator.cpp @@ -87,18 +87,31 @@ void testEvaluator(TestConfig testConf, string testEvaluatorName, return; } + ICpuGpuVectorPtr sequenceStartPositions; + if (testConf.inputDefs[i].inputType == INPUT_SEQUENCE_DATA || + testConf.inputDefs[i].inputType == INPUT_SEQUENCE_LABEL) { + if (!sequenceStartPositions) { + generateSequenceStartPositions(batchSize, sequenceStartPositions); + } + data.sequenceStartPositions = sequenceStartPositions; + } + arguments.push_back(data); } Evaluator* testEvaluator = Evaluator::create(testConf.evaluatorConfig); double totalScore = 0.0; + testEvaluator->start(); totalScore += testEvaluator->evalImp(arguments); testEvaluator->updateSamplesNum(arguments); + testEvaluator->finish(); LOG(INFO) << *testEvaluator; double totalScore2 = 0.0; if (testConf.testAccumulate) { + testEvaluator->start(); totalScore2 += testEvaluator->evalImp(arguments); + testEvaluator->finish(); EXPECT_LE(fabs(totalScore - totalScore2), 1.0e-5); } } @@ -202,6 +215,15 @@ TEST(Evaluator, precision_recall) { false); } +TEST(Evaluator, ctc_error_evaluator) { + TestConfig config; + config.evaluatorConfig.set_type("ctc_edit_distance"); + + config.inputDefs.push_back({INPUT_SEQUENCE_DATA, "output", 32}); + config.inputDefs.push_back({INPUT_SEQUENCE_LABEL, "label", 1}); + testEvaluatorAll(config, "ctc_error_evaluator", 100); +} + int main(int argc, char** argv) { initMain(argc, argv); FLAGS_thread_local_rand_use_global_seed = true; diff --git a/python/paddle/trainer_config_helpers/evaluators.py b/python/paddle/trainer_config_helpers/evaluators.py index 956bedadd75e5f389c25c37c1a466a0c3cb97430..179a3a053a961126adcb750519c399f28a441867 100644 --- a/python/paddle/trainer_config_helpers/evaluators.py +++ b/python/paddle/trainer_config_helpers/evaluators.py @@ -94,7 +94,7 @@ def evaluator_base( Batch=200 samples=20000 AvgCost=0.679655 CurrentCost=0.662179 Eval: classification_error_evaluator=0.4486 CurrentEval: ErrorRate=0.3964 - + :param input: Input layers, a object of LayerOutput or a list of LayerOutput. :type input: list|LayerOutput @@ -296,6 +296,7 @@ def precision_recall_evaluator( @wrap_name_default() def ctc_error_evaluator( input, + label, name=None, ): """ @@ -305,16 +306,19 @@ def ctc_error_evaluator( .. code-block:: python - eval = ctc_error_evaluator(input) + eval = ctc_error_evaluator(input=input, label=lbl) :param name: Evaluator name. :type name: None|basestring :param input: Input Layer. :type input: LayerOutput + :param label: input label, which is a data_layer. + :type label: LayerOutput """ evaluator_base(name=name, type="ctc_edit_distance", - input=input) + input=input, + label=label) @evaluator(EvaluatorAttribute.FOR_CLASSIFICATION) @wrap_name_default() diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index f3f0077f9798f7e2097ae8cd4f39ce270a49b28f..47eadf5d04e50c817413c63ab6b45ba24f39c5f4 100644 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -2944,7 +2944,7 @@ def linear_comb_layer(weights, vectors, size, name=None): .. math:: - z = x^T Y + z = x^\mathrm{T} Y In this formular: - :math:`x`: weights @@ -3064,6 +3064,17 @@ def ctc_layer(input, label, size, name=None, norm_by_times=False): classication task. That is, for sequence labeling problems where the alignment between the inputs and the target labels is unknown. + More details can be found by referring to `Connectionist Temporal + Classification: Labelling Unsegmented Sequence Data with Recurrent + Neural Networks `_ + + Note: + Considering the 'blank' label needed by CTC, you need to use + (num_classes + 1) as the input size. num_classes is the category number. + And the 'blank' is the last category index. So the size of 'input' layer, such as + fc_layer with softmax activation, should be num_classes + 1. The size of ctc_layer + should also be num_classes + 1. + The simple usage: .. code-block:: python @@ -3077,7 +3088,7 @@ def ctc_layer(input, label, size, name=None, norm_by_times=False): :type input: LayerOutput :param label: The data layer of label with variable length. :type label: LayerOutput - :param size: category numbers. + :param size: category numbers + 1. :type size: int :param name: The name of this layer, which can not specify. :type name: string|None diff --git a/python/paddle/trainer_config_helpers/tests/layers_test_config.py b/python/paddle/trainer_config_helpers/tests/layers_test_config.py index ec171fc6013f454da78570c96e64240017e849b9..d479fb263fb66e67a56d23d9d4c1e21ca9052699 100644 --- a/python/paddle/trainer_config_helpers/tests/layers_test_config.py +++ b/python/paddle/trainer_config_helpers/tests/layers_test_config.py @@ -34,6 +34,15 @@ out = fc_layer(input=[cos1, cos3, linear_comb], outputs(classification_cost(out, data_layer(name="label", size=num_classes))) +# for ctc +tmp = fc_layer(input=x1, + size=num_classes + 1, + act=SoftmaxActivation()) +ctc = ctc_layer(input=tmp, + label=y, + size=num_classes + 1) +ctc_eval = ctc_error_evaluator(input=ctc, label=y) + settings( batch_size=10, learning_rate=2e-3,