【问题标题】:ValueError: Unknown layer: CapsuleLayerValueError:未知层:CapsuleLayer
【发布时间】:2018-11-23 01:33:41
【问题描述】:

我已经定义了一个名为CapsuleLayer 的自定义层。实际模型已在单独的类中定义。我已将权重加载到实际模型中,并将模型保存在 .h5 文件中。但是,当我尝试使用 load_model(filepath) 加载模型时,我收到错误

ValueError:未知层:CapsuleLayer

如何在加载保存的模型时将自定义层合并到我的模型中。

【问题讨论】:

    标签: python keras keras-layer


    【解决方案1】:

    参考Keras 常见问题解答,"Handling custom layers (or other custom objects) in saved models"

    如果您要加载的模型包含自定义图层或其他自定义 类或函数,您可以通过 custom_objects 参数:

    from keras.models import load_model
    # Assuming your model includes instance of an "AttentionLayer" class
    model = load_model('my_model.h5', custom_objects={'AttentionLayer': AttentionLayer})
    

    或者,您可以使用自定义对象范围:

    from keras.utils import CustomObjectScope
    
    with CustomObjectScope({'AttentionLayer': AttentionLayer}):
        model = load_model('my_model.h5')
    

    自定义对象的处理方式与 load_model 相同, model_from_json、model_from_yaml:

    from keras.models import model_from_json
    model = model_from_json(json_string, custom_objects={'AttentionLayer': AttentionLayer})
    

    在您的情况下,model = load_model('my_model.h5', custom_objects={'CapsuleLayer': CapsuleLayer}) 应该可以解决您的问题。

    【讨论】:

    • 我猜我也需要导入这个类。
    • 准确。 custom_objects 参数主要用于将您的自定义类及其名称传递给load_model(),以便它可以识别并从保存的文件中恢复它。
    • 我收到一个错误。 TypeError: __init__() 接受至少 3 个参数(1 个给定)。可能是什么问题?
    • 您的自定义层可能需要 3 个参数来初始化,但没有接收到它们。您可能需要向其添加 get_config() 方法。这个issue's answer 可以帮助你,以及核心层的代码,例如here.
    【解决方案2】:

    为了完整起见,我只是在 benjaminplanche 的答案之上添加了一些内容。如果您的自定义层AttentionLayer 有任何配置其行为的初始参数,您需要实现该类的get_config 方法。否则将无法加载。我写这篇文章是因为我在如何加载带有参数的自定义层时遇到了很多麻烦,所以我将把它留在这里。

    例如,您的层的虚拟实现:

    class AttentionLayer(Layer):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
    
        def build(self, input_shape):
            return super().build(input_shape)
    
        def call(self, x):
            # Implementation about how to look with attention!
            return x
    
        def compute_output_shape(self, input_shape):
            return input_shape
    

    这将加载 benjaminplanche 的答案中详述的任何方法,即使用 custom_objects={'AttentionLayer': AttentionLayer}。但是,如果您的图层有一些参数,则加载将失败。

    想象你的类的 init 方法有 2 个参数:

    class AttentionLayer(Layer):
        def __init__(self, param1, param2, **kwargs):
            self.param1 = param1
            self.param2 = param2
            super().__init__(**kwargs)
    

    然后,当你加载它时:

    model = load_model('my_model.h5', custom_objects={'AttentionLayer': AttentionLayer})
    

    它会抛出这个错误:

    Traceback (most recent call last):
      File "/path/to/file/cstm_layer.py", line 62, in <module>
        h = AttentionLayer()(x)
    TypeError: __init__() missing 2 required positional arguments: 'param1' and 'param2'
    

    为了解决它,您需要在自定义层类中实现get_config 方法。一个例子:

    class AttentionLayer(Layer):
        def __init__(self, param1, param2, **kwargs):
            self.param1 = param1
            self.param2 = param2
            super().__init__(**kwargs)
    
        # ...
    
        def get_config(self):
            # For serialization with 'custom_objects'
            config = super().get_config()
            config['param1'] = self.param1
            config['param2'] = self.param2
            return config
    

    因此,当您保存模型时,保存例程将调用 get_config 并序列化您的自定义层的内部状态,即self.params。当你加载它时,加载器会知道如何初始化你的自定义层的内部状态。

    【讨论】:

    • 请问idx_init和idx_end是什么
    • 已修复,它是 param1 和 2。在 get_config 方法中,您应该存储与其操作相关的任何图层属性(以便稍后使用正确的配置加载图层)
    猜你喜欢
    • 2021-02-22
    • 1970-01-01
    • 2020-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-24
    相关资源
    最近更新 更多