Ошибка значения: Неизвестный слой: Слой капсул

#python #tensorflow #keras #bayesian-networks #tensorflow-model-analysis

Вопрос:

Я определил пользовательский слой с именем CapsuleLayer . Фактическая модель была определена в отдельном классе. Я загрузил веса в фактическую модель и сохранил модель в .h5 файле. Однако, когда я пытаюсь загрузить модель с помощью load_model(filepath) , я получаю ошибку

Ошибка значения: Неизвестный слой: Слой капсул

Как я могу включить пользовательский слой в свою модель при загрузке сохраненной модели.

Ответ №1:

C. f. Часто задаваемые вопросы по Keras, «Обработка пользовательских слоев (или других пользовательских объектов) в сохраненных моделях»:

Если модель, которую вы хотите загрузить, включает пользовательские слои или другие пользовательские классы или функции, вы можете передать их механизму загрузки с помощью аргумента 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}) следует решить вашу проблему.

Комментарии:

1. Я думаю, мне тоже нужно импортировать класс.

2. Точный. custom_objects Параметр в основном предназначен для передачи вашего пользовательского класса и его имени load_model() , чтобы он мог распознавать и восстанавливать его из сохраненных файлов.

3. Я получаю сообщение об ошибке. Ошибка типа: __init__() принимает по крайней мере 3 аргумента (1 задан). В чем может быть проблема.?

4. Ваш пользовательский слой, вероятно, нуждается в 3 аргументах для инициализации, но не получает их. Возможно, вам придется добавить get_config() к нему метод. Ответ на этот вопрос может вам помочь, а также код для основных слоев, например, здесь .

Ответ №2:

Просто для полноты картины я добавляю немного поверх ответа Бенджамина Планша. Если у вашего пользовательского слоя 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 И когда вы его загрузите, загрузчик будет знать, как инициализировать внутреннее состояние вашего пользовательского слоя.

Комментарии:

1. что такое idx_init и idx_end, пожалуйста

2. Исправлено, это парам1 и 2. В методе get_config вы должны сохранить все атрибуты слоя, необходимые для его работы (для того, чтобы позже загрузить слой с правильной конфигурацией).