Skip to content

Commit 8deff48

Browse files
authored
Merge pull request #11081 from reyoung/feature/python_doc
Add document to random crop operator
2 parents e3cb0dc + 59d75bd commit 8deff48

File tree

3 files changed

+106
-13
lines changed

3 files changed

+106
-13
lines changed

paddle/fluid/operators/random_crop_op.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ class RandomCropOpMaker : public framework::OpProtoAndCheckerMaker {
3636
AddInput("Seed", "The random seed.");
3737
AddOutput("Out", "The cropped instance batch.");
3838
AddOutput("SeedOut", "The random seed after random cropping.")
39-
.AsDispensable();
39+
.AsIntermediate();
4040
AddAttr<std::vector<int>>("shape", "The shape of a cropped instance.");
4141
AddComment(R"DOC(
42-
This operator takes a batch of instance, and do random cropping on each instance.
43-
It means that cropping positions differs on each instance, which is determined
42+
This operator takes a batch of instance, and do random cropping on each instance.
43+
It means that cropping positions differs on each instance, which is determined
4444
by an uniform random generator. All cropped instances have the same shape, which
4545
is determined by the operator's attribute 'shape'.
4646
)DOC");

python/paddle/fluid/layers/layer_function_generator.py

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,13 @@
1515
import cStringIO
1616
import functools
1717
import warnings
18+
import string
1819

1920
from ..proto import framework_pb2
2021
from ..framework import OpProtoHolder, Variable
2122
from ..layer_helper import LayerHelper
2223

23-
__all__ = [
24-
'deprecated',
25-
'generate_layer_fn',
26-
'autodoc',
27-
]
24+
__all__ = ['deprecated', 'generate_layer_fn', 'autodoc', 'templatedoc']
2825

2926

3027
def _convert_(name):
@@ -43,6 +40,10 @@ def _convert_(name):
4340
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
4441

4542

43+
def _type_to_str_(tp):
44+
return framework_pb2.AttrType.Name(tp)
45+
46+
4647
def _generate_doc_string_(op_proto):
4748
"""
4849
Generate docstring by OpProto
@@ -54,9 +55,6 @@ def _generate_doc_string_(op_proto):
5455
str: the document string
5556
"""
5657

57-
def _type_to_str_(tp):
58-
return framework_pb2.AttrType.Name(tp)
59-
6058
if not isinstance(op_proto, framework_pb2.OpProto):
6159
raise TypeError("OpProto should be `framework_pb2.OpProto`")
6260

@@ -224,3 +222,49 @@ def __impl__(func):
224222
return func
225223

226224
return __impl__
225+
226+
227+
def templatedoc():
228+
"""
229+
Decorator of layer function. It will use the docstring from the layer
230+
function as the template. The template arguments are:
231+
232+
* ${comment}: The operator comment written in CPP.
233+
* ${{name}_comment}: The comment of ${name} written with AddAttr, AddOutput,
234+
and AddInput. The ${name} is Python snake style. i.e., xxx_xxx.
235+
* ${{name}_type}: The type of ${name}.
236+
237+
Returns:
238+
Decorated function.
239+
"""
240+
241+
def __impl__(func):
242+
op_proto = OpProtoHolder.instance().get_op_proto(func.__name__)
243+
tmpl = string.Template(func.__doc__)
244+
245+
comment_lines = op_proto.comment.split("\n")
246+
comment = ""
247+
for line in comment_lines:
248+
line = line.lstrip()
249+
comment += line
250+
comment += "\n"
251+
252+
args = {"comment": comment}
253+
for each_input in op_proto.inputs:
254+
input_name = _convert_(each_input.name)
255+
args["{0}_comment".format(input_name)] = each_input.comment
256+
args["{0}_type".format(input_name)] = "Variable"
257+
for each_attr in op_proto.attrs:
258+
input_name = _convert_(each_attr.name)
259+
args["{0}_comment".format(input_name)] = each_attr.comment
260+
args["{0}_type".format(input_name)] = _type_to_str_(each_attr.type)
261+
262+
for each_opt in op_proto.outputs:
263+
output_name = _convert_(each_opt.name)
264+
args["{0}_comment".format(output_name)] = each_opt.comment
265+
args["{0}_type".format(output_name)] = "Variable"
266+
267+
func.__doc__ = tmpl.substitute(args)
268+
return func
269+
270+
return __impl__

python/paddle/fluid/layers/nn.py

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@
1919
from ..initializer import Normal, Constant
2020
from ..framework import Variable
2121
from ..param_attr import ParamAttr
22-
from layer_function_generator import autodoc
22+
from layer_function_generator import autodoc, templatedoc
2323
from tensor import concat
2424
import utils
25+
import random
2526

2627
__all__ = [
2728
'fc',
@@ -801,7 +802,22 @@ def gru_unit(input,
801802
return updated_hidden, reset_hidden_pre, gate
802803

803804

805+
@templatedoc()
804806
def linear_chain_crf(input, label, param_attr=None):
807+
"""
808+
Linear Chain CRF.
809+
810+
${comment}
811+
812+
Args:
813+
input(${emission_type}): ${emission_comment}
814+
label(${label_type}): ${label_comment}
815+
param_attr(ParamAttr): The attribute of the learnable parameter.
816+
817+
Returns:
818+
${log_likelihood_comment}
819+
820+
"""
805821
helper = LayerHelper('linear_chain_crf', **locals())
806822
size = input.shape[1]
807823
transition = helper.create_parameter(
@@ -827,7 +843,19 @@ def linear_chain_crf(input, label, param_attr=None):
827843
return log_likelihood
828844

829845

846+
@templatedoc()
830847
def crf_decoding(input, param_attr, label=None):
848+
"""
849+
${comment}
850+
851+
Args:
852+
input(${emission_type}): ${emission_comment}
853+
param_attr(ParamAttr): The parameter attribute for training.
854+
label(${label_type}): ${label_comment}
855+
856+
Returns:
857+
${viterbi_path_comment}
858+
"""
831859
helper = LayerHelper('crf_decoding', **locals())
832860
transition = helper.get_parameter(param_attr.name)
833861
viterbi_path = helper.create_tmp_variable(dtype=helper.input_dtype())
@@ -4107,10 +4135,31 @@ def gather(input, index):
41074135
return out
41084136

41094137

4110-
def random_crop(input, shape, seed=1):
4138+
@templatedoc()
4139+
def random_crop(x, shape, seed=None):
4140+
"""
4141+
${comment}
4142+
4143+
Examples:
4144+
>>> img = fluid.layers.data("img", [3, 256, 256])
4145+
>>> cropped_img = fluid.layers.random_crop(img, shape=[3, 224, 224])
4146+
4147+
Args:
4148+
x(${x_type}): ${x_comment}
4149+
shape(${shape_type}): ${shape_comment}
4150+
seed(int|${seed_type}|None): ${seed_comment} By default, the seed will
4151+
get from `random.randint(-65536, 65535)`.
4152+
4153+
Returns:
4154+
${out_comment}
4155+
4156+
"""
41114157
helper = LayerHelper("random_crop", **locals())
41124158
dtype = helper.input_dtype()
41134159
out = helper.create_tmp_variable(dtype)
4160+
if seed is None:
4161+
seed = random.randint(-65536, 65535)
4162+
41144163
if isinstance(seed, int):
41154164
seed_value = seed
41164165
seed = helper.create_tmp_variable(dtype="int64")

0 commit comments

Comments
 (0)