首页 文章

为什么Keras图层定义使用嵌套函数?

提问于
浏览
2

我正在尝试实现ResNet模型 . 我想使用一个函数来生成“基础”层(将conv-relu-conv-relu添加到未修改的输入中),这样我就可以通过编程方式快速增加图层 . 然而,当我将图层作为函数参数传递给函数时,它表示它不是keras张量 . 第一部分是我的函数定义,第二部分是调用,其中x_in是图层对象,y是残差块的输出 . 我使用“x”作为上一层和下一层的名称 .

def ResBlock(x_in, n_filt, l_filt, pool):
    ...
    return y

x = ResBlock(x, 32, 16, 0)

在google上搜索一下后,我发现这是正确的语法:

def ResBlock(n_filt, l_filt, pool):
    def unit(x_in):
        x = Conv1D(n_filt, l_filt, padding='same')(x_in)
        x = BatchNormalization()(x)
        x = relu(x)
        x = Dropout(0.1)(x)
        x = Conv1D(n_filt, l_filt, padding='same')(x)
        if pool:
            x = MaxPooling1D()(x)
            x_in = MaxPooling1D()(x_in)
        y = keras.layers.add([x, x_in])    
        return y
    return unit

x = ResBlock(32, 16, 0)(x)

任何人都可以解释为什么这是正确的方法?具体来说,我想知道为什么我们需要层对象的嵌套def?

1 回答

  • 2

    Keras的标准"style"是:首先定义一个图层,然后应用它 . 所以你给的代码不是正确的风格,这就是为什么你感到困惑 .

    合适的风格是:

    def ResBlock(n_filt, l_filt, pool):
        conv_1 = Conv1D(n_filt, l_filt, padding='same')
        bn = BatchNormalization()
        dropout = Dropout(0.1)
        conv_2 = Conv1D(n_filt, l_filt, padding='same')
        maxpool_1 = MaxPooling1D()
        maxpool_2 = MaxPooling1D()
    
        def unit(x_in):
            x = conv_1(x_in)
            x = bn(x)
            x = relu(x)
            x = dropout(x)
            x = conv_2(x)
            if pool:
                x = maxpool_1(x)
                x_in = maxpool_2(x_in)
            y = keras.layers.add([x, x_in])    
            return y
    
        return unit
    
    x = ResBlock(32, 16, 0)(x)
    

    我们编写这样的代码的原因是允许重复使用图层 . 也就是说,如果我们这样称呼它

    resblock = ResBlock(32, 16, 0)
    
    x = resblock(x)
    x = resblock(x)
    

    resblock 将共享两个调用之间的所有参数 . 使用示例中的语法,这是不可能的 .

相关问题