2017-03-03 2 views
0

したがって、hereからいくつかのコードを解読しようとしています。以下は、私が実際に理解していない関連コードをコピーして貼り付けたものです。デコレータでこのPythonコードを理解する

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のような言語ではより一般的ですが、Pythonでもそうすることができます。

0

にアクセスすることができています。

したがって、このチェーンを開始するときは、オブジェクトselfを呼び出して、メソッドfeed()を実行します。ソースコードを調べると、selfが返されます。しかし、それは変更された自己です。だからこの時点でfeed()は '消費され'、あなたは(modified)self.prelu()....のようなものが残っています。これは別の方法で繰り返されます。そしてコールが残らなくなるまで繰り返されます。

関連する問題