Faster RCNN [series] @layer decorator

I see Faster RCNN code reuse existing code: https: //github.com/smallcorgi/Faster-RCNN_TF

About ./lib/networks/network.py there are so piece of code:

def layer(op):
    """Decorator for composable network layers."""

    def layer_decorated(self, *args, **kwargs):
        # Automatically set a name if not provided.
        name = kwargs.setdefault('name', self.get_unique_name(op.__name__))
        # Figure out the layer inputs.
        if len(self.inputs) == 0:
            raise RuntimeError('No input variables found for layer %s.' % name)
        elif len(self.inputs) == 1:
            layer_input = self.inputs[0]
        else:
            layer_input = list(self.inputs)
        # Perform the operation and get the output.
        layer_output = op(self, layer_input, *args, **kwargs)

        # Add to layer LUT.
        self.layers[name] = layer_output  # 添加到layers这个字典中
        # This output is now the input for the next layer.
        self.feed(layer_output)
        # Return self for chained calls.
        return self  # 返回可以进行:a.func2().func3()
    return layer_decorated

 

You will find this folder below each function with a @layer, first I do not know what it was, what his works, this is how the code in use.

 

 

0. functions are objects, objects and functions can be assigned to variables, so, through variable can also call the function.

For example :

DEF now ():
 Print ( ' 2015-3-12 ' ) 

IF  the __name__ == ' __main__ ' : 
F = now # Here now is an object assigned to the variable f, f a function can be called. 
F ()
 Print (now. the __class__ ) # <class 'function'>

 

1. What is a decorator?

Enhanced without changing the definition of the function itself in function of the function, i.e., to increase the dynamic mode function during operation of the code, called "decorator" (Decorator). Essentially, decorator is a function that returns higher-order functions.

DEF log (FUNC):   # since log is a decorator, so it can function accepts as a parameter a 
    DEF warpper (* args, ** kW):
         Print ( ' Call% S (): ' .% FUNC the __name__ )
         return FUNC (* args, ** kW)
     return warpper 

@log 
DEF now ():
     Print ( ' 2015-3-12 ' ) 

IF  the __name__ == ' __main__ ' : 
    F = now # corresponds now = log = F (now) 
    F ()   # this is equivalent to the implementation of the f () = now () = log (now ())

 

Since the log () is a decorator, returns a function, so the original now () function is still there but now the same name now variable to point to a new function, so call now () will implement the new function, namely log () function returned warpper () function. warpper () function is defined in parameter (* args, ** kw), therefore, wrapper () function can accept calls of any parameter. [Note 1]. If you need to return other custom Log text, you need three nested decorator: https: //www.liaoxuefeng.com/wiki/1016959663602400/1017451662295584

 

All of the above can be seen on the website Liao Xuefeng teacher, I also reprinted from his website. But I still was not able to in-depth understanding decorator, let's re-read the following layer decorator function codes:

DEF Layer (OP):   # OP corresponds to input FUNC 
    DEF layer_decorated (self, args *, ** kwargs):   # added to self decorative Method in decorator 
        # the Automatically SET A Not Provided IF name. 
        = kwargs.setdefault name ( ' name ' , self.get_unique_name (OP. the __name__ )) # OP .__ name__ function name that the various operations, such as CONV, max_pool 
        # Figure OUT the inputs layer. confirm the input layer, and if it is 0 returns an error, if it is 1, that is, the inputs [0], is greater than 1, the conversion to List 
        IF len (self.inputs) == 0:
             the raise a RuntimeError ( ' . No Layer INPUT Variables found for S% ' % name)
        elif len(self.inputs) == 1:
            layer_input = self.inputs[0]
        else:
            layer_input = list(self.inputs)
        # Perform the operation and get the output.
        layer_output = op(self, layer_input, *args, **kwargs)  # 输出即layer_output=方法(self, layer_input, *args, **kwargs)
        # Add to layer LUT.
        self.layers[name] = layer_output # 将输出添加到layers[name]这个字典中,因为有 self.layers = dict(inputs)
        # This output is now the input for the next layer.
        self.feed(layer_output)  #The last execution feed method, ie the output layer as the next layer of input. , 
        # The Return chained Calls for Self. 
        Return Self    # returns the class is accounted for right-values can be used for Call chained 
    return layer_decorated

 

3. In-depth understanding of decorators and chained calls

Obviously, I read the contents of the above basic understanding of what is the role of decorator, but he gave decorative function, in the end is what kind of workflow do? Why should we return self return to class? Here is my own writing test code. My decorator function is to class property age + 3. And print age. fun1 is not added to the decorator function, fun2 added a decorator but did not make changes to the age property, fun3 added a decorator and age + 1.

DEF Layer (FUNC):
     DEF layer_decorator (Self, Arg *, ** kw): 
        self.func1 (self.age) 
        # func1 (Self, self.age) # The python you do not know who is 
        # self.func (self.age) # this is a function of the function func decorative layer instead of the above classes: AttributeError: 'agecnt' Object attribute has NO 'func' 
        self.age self.age + =. 3 
        Age = self.age 
        output_layer = func (Self, Age)
         IF isinstance (output_layer, tf.Tensor):
             Print (of the type (output_layer))
         return Self
     return layer_decorator 


class agecnt ():
     #  __init__ should return None,so it shouldn't have decorator return self
    def __init__(self, age):
        self.name = self.__class__
        self.age = age
        print(str(sys._getframe().f_lineno),"line:execute __init__ funcof {}".format(self.name))

    def func1(self, num):
        print('func1(without decorator) age:', num)

    @layer
    def func2(self,age):
        print('func2 age: {}'.format(age))
        returntf.constant ( ' Hello ' ) 


    @layer 
    DEF func3 (Self, Age): 
        Age = Age +. 1
         Print ( ' func3 Age: {} ' .format (Age))
         return 123 IF the __name__ == ' __main__ ' : 
    A = agecnt (1 ) 
    A = a.func2 (). func3 ()   # this is the chain calls, if there is no return self above, so you can not write ~ # a.func3 ()

 

    

 

In my own experiments we found that:

  1 .__ init__ constructor can not use a decorator, in fact the constructor does not seem to need to use the constructor.

  2. The first instance of a class, and then call func2 func3 at the same time. But in fact not call func2 and func3, but calls the decorator function, while the decorator function parameters are func2 and func3.

  3. The func2, func3 is returned if the return self, can be chain calls, if not returned, it can not be written "a.func2 () func3 ()." This form, can be written: "a = a. func2 (); a = a.func3 () "form.

 

These are my personal call on decorators and chain (chain return) understanding.

 

 

Note 1: * args parameter used to pack into a tuple to the body of the function call; and Packing ** kwargs dict keyword parameter to the function to call the body

Precautions: Parameter arg, * args, ** position kwargs three parameters must be certain. It must be (arg, * args, ** kwargs) in this order, otherwise the program error.

def function(arg,*args,**kwargs):
print(arg,args,kwargs)


function(6,7,8,9,a=1, b=2, c=3  # 6 (7,8,9) {'c':3,'a':1,'b':2}

Python, * args and ** kwargs difference:

https://blog.csdn.net/u011596455/article/details/82702301
https://www.cnblogs.com/cwind/p/8996000.html

 

Note 2: The design pattern decorative pattern: the stuff inside the assembled, and then out in the real world, but it is different from the model builder, the builder pattern is very stable
decorative pattern that we need to put the required functions in series in the correct order control.
Decorator (decorator): dynamically add some additional responsibilities to an object, you add functionality, the decorative pattern is more flexible than the production of sub-classes.

 

https://blog.csdn.net/pihailailou/article/details/82813374
https://www.cnblogs.com/Josie-chen/p/8707322.html
https://blog.csdn.net/qq_33297776/article/details/81591592

 

Reference blog:

https://www.liaoxuefeng.com/wiki/1016959663602400/1017451662295584

 

Guess you like

Origin www.cnblogs.com/SsoZhNO-1/p/11248621.html