diff --git a/doc/api/v2/fluid/layers.rst b/doc/api/v2/fluid/layers.rst index f1e4e753c5234e03294e154a59d4c5e4d6acca1d..2ae68d01d34a8cc786ab04d8325b8378c3b037ea 100644 --- a/doc/api/v2/fluid/layers.rst +++ b/doc/api/v2/fluid/layers.rst @@ -500,7 +500,7 @@ swish .. autofunction:: paddle.v2.fluid.layers.swish :noindex: -edit_distance_error +edit_distance --------------- .. autofunction:: paddle.v2.fluid.layers.edit_distance_error :noindex: diff --git a/python/paddle/v2/fluid/evaluator.py b/python/paddle/v2/fluid/evaluator.py index adf174a07daeea521fa3a1c97273ec68b3a9a67f..336d25929ec8dc6d137d30bcf16eb84265bbcfe1 100644 --- a/python/paddle/v2/fluid/evaluator.py +++ b/python/paddle/v2/fluid/evaluator.py @@ -204,3 +204,35 @@ class ChunkEvaluator(Evaluator): [precision], dtype='float32'), np.array( [recall], dtype='float32'), np.array( [f1_score], dtype='float32') + + +class EditDistance(Evaluator): + """ + Average edit distance error for multiple mini-batches. + """ + + def __init__(self, input, label, k=1, **kwargs): + super(EditDistance, self).__init__("edit_distance", **kwargs) + main_program = self.helper.main_program + if main_program.current_block().idx != 0: + raise ValueError("You can only invoke Evaluator in root block") + + self.total_error = self.create_state( + dtype='int64', shape=[1], suffix='total') + self.batch_num = 0 + error = layers.edit_distance(input=input, label=label) + mean_error = layers.mean(input=error) + layers.sums(input=[self.total_error, mean_error], out=self.total_error) + self.metrics.append(mean_error) + + def eval(self, executor, eval_program=None): + self.batch_num += 1 + if eval_program is None: + eval_program = Program() + block = eval_program.current_block() + with program_guard(main_program=eval_program): + total_error = _clone_var_(block, self.total_error) + batch_num = layers.fill_constant( + shape=[1], value=self.batch_num, dtype="float32") + out = layers.elementwise_div(x=total_error, y=batch_num) + return np.array(executor.run(eval_program, fetch_list=[out])[0]) diff --git a/python/paddle/v2/fluid/layers/nn.py b/python/paddle/v2/fluid/layers/nn.py index 0c77b890656182dedabe93e4a807a5d251eff50c..8383e43dea099a38183049e144d9e6023567521f 100644 --- a/python/paddle/v2/fluid/layers/nn.py +++ b/python/paddle/v2/fluid/layers/nn.py @@ -28,8 +28,7 @@ __all__ = [ 'batch_norm', 'beam_search_decode', 'conv2d_transpose', 'sequence_expand', 'lstm_unit', 'reduce_sum', 'reduce_mean', 'reduce_max', 'reduce_min', 'sequence_first_step', 'sequence_last_step', 'dropout', 'split', - 'ctc_greedy_decoder', 'edit_distance_error', 'l2_normalize', 'matmul', - 'warpctc' + 'ctc_greedy_decoder', 'edit_distance', 'l2_normalize', 'matmul', 'warpctc' ] @@ -1768,7 +1767,7 @@ def matmul(x, y, transpose_x=False, transpose_y=False, name=None): return out -def edit_distance_error(input, label, normalized=False, name=None): +def edit_distance(input, label, normalized=False, name=None): """ EditDistance operator computes the edit distances between a batch of hypothesis strings and their references.Edit distance, also called Levenshtein distance, measures how dissimilar two strings are by counting the minimum number of operations to transform one string into anthor. Here the operations include insertion, deletion, and substitution. For example, given hypothesis string A = "kitten" and reference B = "sitting", the edit distance is 3 for A will be transformed into B at least after two substitutions and one insertion: @@ -1795,9 +1794,9 @@ def edit_distance_error(input, label, normalized=False, name=None): x = fluid.layers.data(name='x', shape=[8], dtype='float32') y = fluid.layers.data(name='y', shape=[7], dtype='float32') - cost = fluid.layers.edit_distance_error(input=x,label=y) + cost = fluid.layers.edit_distance(input=x,label=y) """ - helper = LayerHelper("edit_distance_error", **locals()) + helper = LayerHelper("edit_distance", **locals()) # edit distance op edit_distance_out = helper.create_tmp_variable(dtype="int64")