我正在尝试实施ResNet模型。我想用一个函数来生成" base" layer(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)
在谷歌搜索后,我发现这是正确的语法:
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?
答案 0 :(得分:2)
标准"风格" Keras的意思是:首先定义一个图层,然后应用它。所以你提供的代码是 not 正确的风格,这就是你感到困惑的原因。
正确的风格是:
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
将共享两个调用之间的所有参数。使用示例中的语法,这是不可能的。