数值错误:未知层:胶囊层。

15
我定义了一个名为的自定义层。实际模型已在单独的类中定义。我已将权重加载到实际模型中并将模型保存在
文件中。但是,当我尝试使用加载模型时,出现错误

ValueError: 未知层:CapsuleLayer

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

2个回答

28

参见Keras FAQ,"在保存的模型中处理自定义层(或其他自定义对象)":

如果要加载的模型包含自定义层或其他自定义类或函数,则可以通过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})应该能够解决您的问题。

我猜我也需要导入这个类。 - Sounak Ray
“Exact”。custom_objects参数的基本目的是将您的自定义类及其名称传递给load_model(),以便它可以从保存的文件中识别和恢复它。 - benjaminplanche
我遇到了一个错误。TypeError: init() 至少需要3个参数(但只提供了1个)。可能是什么问题? - Sounak Ray
1
你的自定义层可能需要3个参数来初始化,但是没有接收到它们。你可能需要添加一个 get_config() 方法。这个问题的答案可能会对你有所帮助,以及核心层的代码,例如这里 - benjaminplanche

6

为了完整起见,我在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方法有两个参数:
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是什么? - nassim
固定的,它是param1和2。在get_config方法中,您应该存储任何与其操作相关的层属性(以便稍后使用正确的配置加载该层)。 - JVGD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接