2017-03-03 3 views
0

그래서 here에서 일부 코드를 해독하려고합니다. 아래에는 필자가 실제로 이해하지 못하는 관련 코드를 복사하여 붙여 넣었습니다. 나는 아래의 코드를 이해하려고 노력 약간의 문제를 가진 적이 있지만 데코레이터로이 파이썬 코드를 이해하십시오

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.terminals) == 0: 
      raise RuntimeError('No input variables found for layer %s.' % name) 
     elif len(self.terminals) == 1: 
      layer_input = self.terminals[0] 
     else: 
      layer_input = list(self.terminals) 
     # Perform the operation and get the output. 
     layer_output = op(self, layer_input, *args, **kwargs) 
     # Add to layer LUT. 
     self.layers[name] = layer_output 
     # This output is now the input for the next layer. 
     self.feed(layer_output) 
     # Return self for chained calls. 
     return self 

    return layer_decorated 

class Network(object): 

    def __init__(self, inputs, trainable=True): 
     # The input nodes for this network 
     self.inputs = inputs 
     print(self.inputs) 
     # The current list of terminal nodes 
     self.terminals = [] 
     # Mapping from layer names to layers 
     self.layers = dict(inputs) 
     print(self.layers) 
     # If true, the resulting variables are set as trainable 
     self.trainable = trainable 

    … 

    def feed(self, *args): 
     '''Set the input(s) for the next operation by replacing the terminal nodes. 
     The arguments can be either layer names or the actual layers. 
     ''' 
     assert len(args) != 0 
     self.terminals = [] 
     for fed_layer in args: 
      if isinstance(fed_layer, string_types): 
       try: 
        fed_layer = self.layers[fed_layer] 
       except KeyError: 
        raise KeyError('Unknown layer name fed: %s' % fed_layer) 
      self.terminals.append(fed_layer) 
     return self 

.... 

# equivalent to max_pool = layer(max_pool) 
    @layer 
    def max_pool(self, inp, k_h, k_w, s_h, s_w, name, padding='SAME'): 
     self.validate_padding(padding) 
     return tf.nn.max_pool(inp, 
           ksize=[1, k_h, k_w, 1], 
           strides=[1, s_h, s_w, 1], 
           padding=padding, 
           name=name) 

내가, 위의 코드를 이해 : 특히

class PNet(Network): 
    def setup(self): 
     (self.feed('data') 
      .conv(3, 3, 10, 1, 1, padding='VALID', relu=False, name='conv1') 
      .prelu(name='PReLU1') 
      .max_pool(2, 2, 2, 2, name='pool1') 
      .conv(3, 3, 16, 1, 1, padding='VALID', relu=False, name='conv2') 
      .prelu(name='PReLU2') 
      .conv(3, 3, 32, 1, 1, padding='VALID', relu=False, name='conv3') 
      .prelu(name='PReLU3') 
      .conv(1, 1, 2, 1, 1, relu=False, name='conv4-1') 
      .softmax(3,name='prob1')) 

     (self.feed('PReLU3') #pylint: disable=no-value-for-parameter 
      .conv(1, 1, 4, 1, 1, relu=False, name='conv4-2')) 

을, 나는 코드의이 부분에서 혼란 스러워요 작동 :

self.feed('data') 
      .conv(3, 3, 10, 1, 1, padding='VALID', relu=False, name='conv1') 
      .prelu(name='PReLU1') 
      .max_pool(2, 2, 2, 2, name='pool1') 
      .conv(3, 3, 16, 1, 1, padding='VALID', relu=False, name='conv2') 
      .prelu(name='PReLU2') 
      .conv(3, 3, 32, 1, 1, padding='VALID', relu=False, name='conv3') 
      .prelu(name='PReLU3') 
      .conv(1, 1, 2, 1, 1, relu=False, name='conv4-1') 
      .softmax(3,name='prob1')) 
이도 같이 쓸 수있다

: self.feed('data').conv(3, 3, 10, 1, 1, padding='VALID', relu=False, name='conv1').prelu(name='PReLU1')...

는 그리고 이것은 내가 이해하지 못하는 것, feed 자체가 Network 클래스의 방법이지만, 어떻게 정말 아주 간단 등 feed의 방법

+0

이것은 데코레이터와는 아무런 관련이 없습니다. 아마도'feed()'에는'return self '가있다. 아마도 다른 방법들과 같을 것이다. 'self'는 현재 인스턴스에 대한 또 다른 참조 일 뿐이므로 체인의 다음 메소드는'self'에서 다시 호출되므로 다른 메소드 등을 호출 할 수 있습니다. 데코레이터 역시'self'를 반환합니다. –

답변

1

이것은 데코레이터와 관련이 없습니다.

feed 방법 - 아마도, convprelu 방법 - 반환 self. 즉, 해당 메서드를 호출 한 결과에 대해 메서드를 계속 호출 할 수 있습니다.

"방법 연결"이라고합니다. Ruby와 같은 언어에서 더 일반적이지만, 파이썬에서도 그렇게 할 수 있습니다.

0

에 액세스 할 수있게되었습니다.

그래서이 체인을 시작할 때 객체 self을 호출하면이 메소드는 feed() 메서드를 호출하고 소스 코드를 보면 self을 반환합니다. 그러나 그것은 수정 된 자아입니다. 그래서이 시점에서 feed()은 '소비'되고 당신은 (modified)self.prelu()....과 같은 것을 남겨 둡니다. 그리고 이것은 또 다른 방법으로 반복됩니다. 그리고 통화가 남아 있지 않을 때까지 반복됩니다.

관련 문제