#python #keras
#python #keras
Вопрос:
Я создал пользовательское ограничение для моего keras GRU-NN и смог обучить свою сеть с его помощью. Ограничение выглядит следующим образом:
import keras.backend as K
from keras.constraints import Constraint
class WeightClip(Constraint):
def __init__(self, mn=0.1, mx=1.0):
self.mn = mn
self.mx = mx
def __call__(self, p):
return K.clip(p, self.mn, self.mx)
def get_config(self):
return {
'name': self.__class__.__name__,
'minimum': self.mn,
'maximum': self.mx
}
После сохранения модели и попытки перезагрузить ее с
model = keras.models.load_model(modelFile, custom_objects={'WeightClip': WeightClip})
Я получил это сообщение об ошибке:
TypeError: __init__() got an unexpected keyword argument 'name'
Сама модель выглядит следующим образом:
model = Sequential()
model.add(GRU(
params.recurrent_units,
activation='linear',
input_shape=(pr.n_features, pr.feature_size),
dropout=params.dropout, name='net',
kernel_constraint=WeightClip(0.1, 1.0),
bias_constraint=WeightClip(0.1, 1.0)
))
model.add(Dense(
1,
activation='sigmoid',
kernel_constraint=WeightClip(0.1, 1.0),
bias_constraint=WeightClip(0.1, 1.0)
))
Ссылаясь на другие подобные вопросы по stackoverflow, которые в большинстве случаев связаны с пользовательскими показателями, я пробовал разные комбинации параметра custom_objects, но, похоже, ничего не помогает. Спасибо за любую помощь!
Комментарии:
1. Кажется, теперь работает. Вместо возврата фактической конфигурации в функции get_config я возвращаю пустые фигурные скобки. Понятия не имею, влияет ли это на поведение модели при составлении прогнозов, но на данный момент это меня не беспокоит. Если кто-нибудь хочет объяснить, я все равно был бы рад!
Ответ №1:
Что происходит за кулисами
Когда вы сохраняете модель, содержащую custom_object
в keras
, она сохранит ссылку на имя класса, а также словарь, содержащий текущую конфигурацию объектов. Это делается путем вызова .get_config()
метода экземпляра пользовательского объекта. Для этого этот метод должен возвращать словарь со всем необходимым для воссоздания экземпляра.
После вызова keras.models.load()
, keras
загрузит вашу модель и создаст экземпляры ваших пользовательских объектов, используя сохраненные словари. Давайте на мгновение предположим, что old_object_configuration = weight_clip_instance.get_config()
. keras
теперь будем создавать новый экземпляр с помощью new_weight_clip_instance = WeightClip(**old_object_configuration)
. Когда вы возвращаете параметр name
в вашем .get_config()
методе, но в сигнатуре WeightClip.__init__()
параметра name отсутствует, будет выдана ошибка, которую вы видите.
Влияет ли возврат пустого dict на вашу модель?
Используя знания, приведенные выше, теперь мы можем предсказать, что произойдет, если ваш .get_config()
метод вернет пустой словарь. Это приводит к вызову new_weight_clip_instance = WeightClip({})
. Новый экземпляр будет иметь значения по умолчанию для mn=0.1
и mx=1.0
, что не является желаемым поведением и приводит к труднодоступным ошибкам.
Рабочий пример
import keras
import keras.backend as K
from keras import Sequential
from keras.constraints import Constraint
from keras.layers import GRU, Dense
RECURRENT_UNITS = 10
N_FEATURES = 10
FEATURE_SIZE = 50
DROPOUT = 0.5
class WeightClip(Constraint):
def __init__(self, minimum=0.1, maximum=1.0):
self.minimum = minimum
self.maximum = maximum
def __call__(self, p):
return K.clip(p, self.minimum, self.maximum)
def get_config(self):
return {
'minimum': self.minimum,
'maximum': self.maximum
}
model = Sequential()
model.add(GRU(
RECURRENT_UNITS,
activation='linear',
input_shape=(N_FEATURES, FEATURE_SIZE),
dropout=DROPOUT,
name='net',
kernel_constraint=WeightClip(0.1, 1.0),
bias_constraint=WeightClip(0.1, 1.0)
))
model.add(Dense(
1,
activation='sigmoid',
kernel_constraint=WeightClip(0.1, 1.0),
bias_constraint=WeightClip(0.1, 1.0)
))
model.save('mymodel')
model = keras.models.load_model('mymodel', custom_objects={'WeightClip': WeightClip})