【问题标题】:Using the output of intermediate layers in a loss function in TF2在 TF2 的损失函数中使用中间层的输出
【发布时间】:2020-07-02 16:55:59
【问题描述】:

我正在尝试在 Tensorflow 2 中复制 OpenPose 的训练,作为我 TF2 学习的一部分,但为了能够做到这一点,我需要在我的损失函数中使用 S、L 中间层的输出。

我尝试使用功能 API,但似乎无法从 S/L 层获取输出,以便能够根据需要在损失函数中使用它们。我可以看到子类化是如何实现的,但这会增加复杂性并且不适合调试。在我学习的这个阶段,调试和易用性可能是一个巨大的优势。

有什么方法可以用函数式 API 或顺序模型来做这种类型的模型?

【问题讨论】:

    标签: tensorflow machine-learning tensorflow2.0


    【解决方案1】:

    是的,功能和顺序 keras 模型都支持这一点。您始终可以传递一个dict,其中包含层名称作为键和损失函数作为值。这是一个演示这一点的代码。

    如果您想从头开始构建模型,只需将图层添加为模型的输出之一即可。

    import tensorflow as tf
    
    img = tf.keras.Input([128, 128, 3], name='image')
    conv_1 = tf.keras.layers.Conv2D(16, 3, 1, name='conv_1')(img)
    conv_2 = tf.keras.layers.Conv2D(16, 3, 1, name='conv_2')(conv_1)
    conv_3 = tf.keras.layers.Conv2D(16, 3, 1, name='conv_3')(conv_2)
    conv_4 = tf.keras.layers.Conv2D(16, 3, 1, name='conv_4')(conv_3)
    conv_5 = tf.keras.layers.Conv2D(16, 3, 1, name='conv_5')(conv_4)
    avg_pool = tf.keras.layers.GlobalAvgPool2D(name='avg_pool')(conv_5)
    output = tf.keras.layers.Dense(1, activation='sigmoid')(avg_pool)
    
    model = tf.keras.Model(inputs=[img], outputs=[output, conv_5])
    print(model.outputs)
    

    输出:

    [<tf.Tensor 'dense/Sigmoid:0' shape=(None, 1) dtype=float32>,
    <tf.Tensor 'conv_5/BiasAdd:0' shape=(None, 118, 118, 16) dtype=float32>]
    

    但如果您正在使用已构建的模型,您可以使用 model.get_layer 方法访问层并创建新模型:

    intermediate_layer = model.get_layer('avg_pool').output
    new_model = tf.keras.Model(inputs=model.inputs, outputs=model.outputs + [intermediate_layer])
    print(new_model.outputs)
    

    输出:

    
    [<tf.Tensor 'dense/Sigmoid:0' shape=(None, 1) dtype=float32>,
    <tf.Tensor 'conv_5/BiasAdd:0' shape=(None, 118, 118, 16) dtype=float32>,
    <tf.Tensor 'avg_pool/Mean:0' shape=(None, 16) dtype=float32>]
    

    然后编译您的模型并为模型的每个输出指定单独的损失。如果这些损失是 Keras 提供的默认损失,则这些损失可以是字符串,也可以是实现损失函数的可调用函数。

    new_model.compile(optimizer='sgd',
                  loss={
                      'dense': 'binary_crossentropy',
                      'conv_5': 'mse',
                      'avg_pool': 'mae'
                  })
    

    一些虚拟数据和标签

    images = tf.random.normal([100, 128, 128, 3])
    conv_3_labels = tf.random.normal([100, 118, 118, 16])
    avg_pool_labels =  tf.random.normal([100, 16])
    class_labels = tf.random.uniform([100], 0, 2, tf.float32)
    
    dataset = tf.data.Dataset.from_tensor_slices(
        (images, (class_labels, conv_3_labels, avg_pool_labels))
    )
    dataset = dataset.batch(4, drop_remainder=True)
    

    培训

    new_model.fit(dataset)
    

    输出:

    25/25 [==============================] - 2s 79ms/step - loss: 2.4339
    - dense_loss: 0.3904 - conv_5_loss: 1.2367 - avg_pool_loss: 0.8068
    
    

    【讨论】:

    • 谢谢,很好的回答@Srihari。该模型是由我构建的,因此我可以使用任何一种方法。使用多个模型/new_model.outputs 方法是否有很多开销或性能缺陷,或者它是否全部生成到单个图形中?最初的方法似乎更简单,但是我必须返回 7 层输出,这在一个输出 = [] 中似乎有点混乱。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2020-11-14
    • 2021-02-19
    • 2021-04-23
    • 1970-01-01
    • 1970-01-01
    • 2018-06-28
    • 1970-01-01
    • 2018-07-13
    相关资源
    最近更新 更多