如何匹配tensorflow(python)函数的参数

时间:2018-06-27 11:29:47

标签: python tensorflow convolutional-neural-network function-parameter

https://github.com/davidsandberg/facenet/blob/master/src/align/detect_face.py

请参考上面的python代码。

我发现网络函数conv类的原型与其调用部分不匹配

@layer
def conv(self,
         inp,
         k_h,
         k_w,
         c_o,
         s_h,
         s_w,
         name,
         relu=True,
         padding='SAME',
         group=1,
         biased=True):

&致电转化

class PNet(Network):
def setup(self):
    (self.feed('data') #pylint: disable=no-value-for-parameter, no-member
         .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'))

注意

  1. 自我
  2. inp-> 它来自哪里?
  3. ....

我知道自我可以被忽略; inp,          k_h,          k_w,          c_o,          s_h,          s_w, 可以与位置匹配,例如:3、3、10、1、1 其他参数是按名称分配的。

但是,我无法确定inp的来源吗?

它与我熟悉的C&C ++编程语言非常矛盾。

有人可以帮助解释吗?

谢谢。

2 个答案:

答案 0 :(得分:1)

Pnet是执行许多卷积的网络。您可以将图像传递到输入层,并对其进行许多卷积。 输入层的名称为“数据”。输入层是接受图像的张量。

data = tf.placeholder(tf.float32, (None,None,None,3), 'input')
pnet = PNet({'data':data})

考虑

out = pnet(img_y)

img_y放在Pnet的“数据”层上,

被馈送到卷积层。

.conv(3, 3, 10, 1, 1, padding='VALID', relu=False, name='conv1')

k_h(内核高度)= 3

k_w(内核宽度)= 3

c_o(过滤器​​数量)= 10

s_h(步幅高度)= 1

s_w(步幅)= 1

inp是上一层的输出,即我们的图像数据层。

应用prelu和max pool,然后将输出作为下一个卷积层的输入。

.conv(3, 3, 16, 1, 1, padding='VALID', relu=False, name='conv2')

以此类推。

要更好地理解卷积神经网络,请参阅CNN

答案 1 :(得分:1)

您确实应该注意到,尽管函数签名将输入层inp作为其第一个参数,但是在调用函数时不会传递该签名。

技巧是通过将function decorator @layer放在函数定义之前来实现的。这是layer装饰器的定义:

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.
        # [!] Here it passes the `inp` parameter, and all the other ones
        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

它将通过op参数输入一个函数/方法作为输入,并返回另一个layer_decorated,它将替换op的原始定义。 PNet.conv = layer(Pnet.conv)这样。如果查看layer_decorated的定义,就会发现它实质上是建立op函数的第一个参数,即layer_input(与[!]对齐)。它还会做一些簿记工作,以根据其名称来知道将哪个层用作输入。

为简化起见,这允许程序员使用链接的方法调用而无需重复自己。它将转换为:

 x = self.feed('data') #pylint: disable=no-value-for-parameter, no-member
 x = self.conv(x, 3, 3, 10, 1, 1, padding='VALID', relu=False, name='conv1')
 x = self.prelu(x, name='PReLU1')
 x = self.max_pool(x, 2, 2, 2, 2, name='pool1')

对此:

x = (self.feed('data') #pylint: disable=no-value-for-parameter, no-member
     .conv(3, 3, 10, 1, 1, padding='VALID', relu=False, name='conv1')
     .prelu(name='PReLU1')
     .max_pool(2, 2, 2, 2, name='pool1')
 )