Как засолить пользовательский слой Keras?

Я пишу пользовательский класс слоев, расширяемый классом Layer, затем я хочу выбрать историю для дальнейшего анализа, но когда я перезагружаю объект pickle из файла, python вызывает ошибку:

Неизвестный слой: Внимание.

Итак, как я могу это исправить?

Я оба пробовал get_config, __getstate__ и __setstate__, но это не удалось. Я просто хочу выбрать историю keras, но не модель, поэтому, пожалуйста, не говорите мне методы сохранения модели с параметрами custom_object.

Ответ 1

Эта проблема возникает из-за того, что при сбрасывании истории не удаляется полная модель. Поэтому при загрузке он не может найти пользовательский класс.

Я заметил, что объект keras.callbacks.History имеет model атрибутов, и неполный дамп является причиной этой проблемы.

И ты сказал:

Я просто хочу мариновать историю Кераса, но не модель

Итак, следующее решение:

hist = model.fit(X, Y, ...)
hist.model = None

Просто установив атрибут model на None, и вы сможете успешно выгружать и загружать свой объект истории!

Ниже приводится MVCE:

from keras.models import Sequential
from keras.layers import Conv2D, Dense, Flatten, Layer
import keras.backend as K
import numpy as np
import pickle

# MyLayer from https://keras.io/layers/writing-your-own-keras-layers/
class MyLayer(Layer):

    def __init__(self, output_dim, **kwargs):
        self.output_dim = output_dim
        super(MyLayer, self).__init__(**kwargs)

    def build(self, input_shape):
        # Create a trainable weight variable for this layer.
        self.kernel = self.add_weight(name='kernel', 
                                      shape=(input_shape[1], self.output_dim),
                                      initializer='uniform',
                                      trainable=True)
        super(MyLayer, self).build(input_shape)  # Be sure to call this at the end

    def call(self, x):
        return K.dot(x, self.kernel)

    def compute_output_shape(self, input_shape):
        return (input_shape[0], self.output_dim)

model = Sequential()
model.add(Conv2D(filters=32, kernel_size=(3,3), input_shape=(28,28,3), activation='sigmoid'))
model.add(Flatten())
model.add(MyLayer(10))
model.add(Dense(3, activation='softmax'))

model.compile(loss='sparse_categorical_crossentropy', metrics=['accuracy'], optimizer='adam')

model.summary()

X = np.random.randn(64, 28, 28, 3)
Y = np.random.randint(0, high=2, size=(64,1))

hist = model.fit(X, Y, batch_size=8)

hist.model = None

with open('hist.pkl', 'wb') as f:
    pickle.dump(hist, f)

with open('hist.pkl', 'rb') as f:
    hist_reloaded = pickle.load(f)

print(hist.history)
print(hist_reloaded.history)

Выход:

{'acc': [0.484375], "убыток": [6.140302091836929]}

{'acc': [0.484375], "убыток": [6.140302091836929]}

PS Если кто-то хочет сохранить модель keras с помощью пользовательского слоя, это должно быть полезно.