【问题标题】:Keras - All layer names should be uniqueKeras - 所有图层名称都应该是唯一的
【发布时间】:2017-09-13 03:04:17
【问题描述】:

我将 keras 中的两个 VGG 网络组合在一起进行分类任务。当我运行程序时,它显示一个错误:

RuntimeError:名称“predictions”在模型中使用了 2 次。所有图层名称都应该是唯一的。

我很困惑,因为我在代码中只使用了一次prediction 层:

from keras.layers import Dense
import keras
from keras.models import  Model
model1 = keras.applications.vgg16.VGG16(include_top=True, weights='imagenet',
                                input_tensor=None, input_shape=None,
                                pooling=None,
                                classes=1000)
model1.layers.pop()

model2 =  keras.applications.vgg16.VGG16(include_top=True, weights='imagenet',
                                input_tensor=None, input_shape=None,
                                pooling=None,
                                classes=1000)
model2.layers.pop()
for layer in model2.layers:
    layer.name = layer.name + str("two")
model1.summary()
model2.summary()
featureLayer1 = model1.output
featureLayer2 = model2.output
combineFeatureLayer = keras.layers.concatenate([featureLayer1, featureLayer2])
prediction = Dense(1, activation='sigmoid', name='main_output')(combineFeatureLayer)

model = Model(inputs=[model1.input, model2.input], outputs= prediction)
model.summary()

感谢@putonspectacles 的帮助,我按照他的指示找到了一些有趣的部分。如果你使用model2.layers.pop(),并使用“model.layers.keras.layers.concatenate([model1.output, model2.output])”组合两个模型的最后一层,你会发现最后一层信息仍然使用model.summary()显示。但实际上它们并不存在于结构中。因此,您可以使用model.layers.keras.layers.concatenate([model1.layers[-1].output, model2.layers[-1].output])。它看起来很棘手,但它确实有效。我认为这是关于日志和结构同步的问题。

【问题讨论】:

    标签: python keras vgg-net


    【解决方案1】:

    例子:

    # Network for affine transform estimation
    affine_transform_estimator = MobileNet(
                                input_tensor=None,
                                input_shape=(config.IMAGE_H // 2, config.IMAGE_W //2, config.N_CHANNELS),
                                alpha=1.0,
                                depth_multiplier=1,
                                include_top=False,
                                weights='imagenet'
                                )
    affine_transform_estimator.name = 'affine_transform_estimator'
    for layer in affine_transform_estimator.layers:
        layer.name = layer.name + str("_1")
    
    # Network for landmarks regression
    landmarks_regressor = MobileNet(
                            input_tensor=None,
                            input_shape=(config.IMAGE_H // 2, config.IMAGE_W // 2, config.N_CHANNELS),
                            alpha=1.0,
                            depth_multiplier=1,
                            include_top=False,
                            weights='imagenet'
                            )
    landmarks_regressor.name = 'landmarks_regressor'
    for layer in landmarks_regressor.layers:
        layer.name = layer.name + str("_2")
    
    input_image = Input(shape=(config.IMAGE_H, config.IMAGE_W, config.N_CHANNELS))
    downsampled_image = MaxPooling2D(pool_size=(2,2))(input_image)
    x1 = affine_transform_estimator(downsampled_image)
    x2 = landmarks_regressor(downsampled_image)
    x3 = add([x1,x2])
    
    model = Model(inputs=input_image, outputs=x3)
    optimizer = Adadelta()
    model.compile(optimizer=optimizer, loss=mae_loss_masked)
    

    【讨论】:

      【解决方案2】:

      你可以在keras中改变层的名字,不要使用'tensorflow.python.keras'。

      这是我的示例代码:

      from keras.layers import Dense, concatenate
      from keras.applications import vgg16
      
      num_classes = 10
      
      model = vgg16.VGG16(include_top=False, weights='imagenet', input_tensor=None, input_shape=(64,64,3), pooling='avg')
      inp = model.input
      out = model.output
      
      model2 = vgg16.VGG16(include_top=False,weights='imagenet', input_tensor=None, input_shape=(64,64,3), pooling='avg')
      
      for layer in model2.layers:
          layer.name = layer.name + str("_2")
      
      inp2 = model2.input
      out2 = model2.output
      
      merged = concatenate([out, out2])
      merged = Dense(1024, activation='relu')(merged)
      merged = Dense(num_classes, activation='softmax')(merged)
      
      model_fusion = Model([inp, inp2], merged)
      model_fusion.summary()
      

      【讨论】:

      • 我创建了一个这样的模型,但是当我将layer.name = layer.name + str("_2") 添加到第二个模型的性能变化时。我不知道为什么?
      • 确认在执行model.get_config() 时此方法对于 TF 2.0 失败,因为相应的层名称未在 model._network_nodes 中重命名。
      • @NicholasLeonard 如果你使用这个方法怎么办? stackoverflow.com/a/57794744/2794625
      【解决方案3】:

      首先,根据您发布的代码,您有 no 个具有名称属性“预测”的图层,因此此错误与您的图层无关 Denseprediction:即:

      prediction = Dense(1, activation='sigmoid', 
                   name='main_output')(combineFeatureLayer)
      

      VGG16 模型有一个Dense 层和name predictions。特别是这一行:

      x = Dense(classes, activation='softmax', name='predictions')(x)
      

      由于您使用其中两个模型,因此您的图层名称重复。

      您可以做的是将第二个模型中的层重命名为预测以外的其他名称,可能是predictions_1,如下所示:

      model2 =  keras.applications.vgg16.VGG16(include_top=True, weights='imagenet',
                                      input_tensor=None, input_shape=None,
                                      pooling=None,
                                      classes=1000)
      
      # now change the name of the layer inplace.
      model2.get_layer(name='predictions').name='predictions_1'
      

      【讨论】:

      • 感谢您的解释。我打印了模型 1 和模型 2 的所有层,但没有名称为“预测”的层。我想你的意思是VGG的最后一层,但我已经弹出了最后一层的原点。您能对此添加解释吗?
      • 如果您使用的是最新的 keras,此链接将引用名为“predictions”的层 github.com/fchollet/keras/blob/…
      • 并且基于错误,您肯定有名为预测的层。你试过我的建议了吗?
      • 嗨,你的建议是对的,但我在合并两个 VGG 之前弹出最后一层。但你是对的,我只是更新解决方案并编辑我的问题。你会看到的..
      • AttributeError: 无法设置属性“名称”,可能是因为它与对象的现有只读@property 冲突。请选择其他名称。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-13
      • 1970-01-01
      • 2020-12-31
      • 2012-03-09
      • 2018-09-17
      • 1970-01-01
      相关资源
      最近更新 更多