keras: Loading model with custom loss function: ValueError: 'Unknown loss function'
I trained and saved a model that uses a custom loss function (Keras version: 2.0.2):
model.compile(optimizer=adam, loss=SSD_Loss(neg_pos_ratio=neg_pos_ratio, alpha=alpha).compute_loss)
When I try to load the model, I get this error:
ValueError: ('Unknown loss function', ':compute_loss')
This is the stack trace:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-76-52ca495a8e09> in <module>()
----> 1 model, layer_dict, classifier_sizes = load_model('./model_0.h5')
/Users/pierluigiferrari/anaconda/envs/carnd-term1/lib/python3.5/site-packages/keras/models.py in load_model(filepath, custom_objects)
258 metrics=metrics,
259 loss_weights=loss_weights,
--> 260 sample_weight_mode=sample_weight_mode)
261
262 # Set optimizer weights.
/Users/pierluigiferrari/anaconda/envs/carnd-term1/lib/python3.5/site-packages/keras/engine/training.py in compile(self, optimizer, loss, metrics, loss_weights, sample_weight_mode, **kwargs)
738 loss_functions = [losses.get(l) for l in loss]
739 else:
--> 740 loss_function = losses.get(loss)
741 loss_functions = [loss_function for _ in range(len(self.outputs))]
742 self.loss_functions = loss_functions
/Users/pierluigiferrari/anaconda/envs/carnd-term1/lib/python3.5/site-packages/keras/losses.py in get(identifier)
88 if isinstance(identifier, six.string_types):
89 identifier = str(identifier)
---> 90 return deserialize(identifier)
91 elif callable(identifier):
92 return identifier
/Users/pierluigiferrari/anaconda/envs/carnd-term1/lib/python3.5/site-packages/keras/losses.py in deserialize(name, custom_objects)
80 module_objects=globals(),
81 custom_objects=custom_objects,
---> 82 printable_module_name='loss function')
83
84
/Users/pierluigiferrari/anaconda/envs/carnd-term1/lib/python3.5/site-packages/keras/utils/generic_utils.py in deserialize_keras_object(identifier, module_objects, custom_objects, printable_module_name)
155 if fn is None:
156 raise ValueError('Unknown ' + printable_module_name,
--> 157 ':' + function_name)
158 return fn
159 else:
ValueError: ('Unknown loss function', ':compute_loss')
-
Check that you are up-to-date with the master branch of Keras. You can update with: pip install git+git://github.com/fchollet/keras.git --upgrade --no-deps
-
If running on TensorFlow, check that you are up-to-date with the latest version. The installation instructions can be found here.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 38
- Comments: 60 (1 by maintainers)
I solved this problem by adding ‘custom_bojects’
my loss function:
Hi, the same problem here. One ugly solution that worked for me is to include the custom objective into keras:
import keras.losses
keras.losses.custom_loss = custom_loss
This is a know issue on keras 1 #3977. On keras 2.0 you have to replace
keras.objectives
tokeras.losses
.If you load model to continue training, you need to define your custom loss function:
If you load model only for prediction (without training), you need to set compile flag to
False
:and you don`t need to define your custom_loss, because the loss function is not necessary for prediction only.
@caocao1989 I’d guess you’re using the CTC ocr example here, too. I was able to use
custom_objects = {'<lambda>': lambda y_true, y_pred: y_pred}
as a work-around. I hope this helps!This PR should have fixed this issue.
Can use:
Hi @pigna90 , the easiest way is to define a python function in the form:
Then you pass it as your loss in
model.compile(loss=custom_loss_function, [...])
.Hi, I have a similar problem with:
model.compile( loss=lambda x,y: custom_loss_function(x,y,third_argument), optimizer=optimizer)
Keras 2.0.3 (Python 2.7.6) gives me the error:('Unknown loss function', ':<lambda>')
Does anyone can help me ? Many thanks!
@weilinapple you reading comprehension is way below required minimum for an engineer, consider a different career path.
Stop posting into this thread!!! There’s an answer above, and you’re making it hard to find!
WORKAROUND
None of the above worked for me, but this did:
Load the model with
compile=False
and then compile it manually.Checkout functools.partial This is really basic Python, so I think this is not the appropriate forum to discuss it.
On Tue, May 30, 2017, 8:55 AM Alessandro Romano notifications@github.com wrote:
I did this as a work around:
This is the most elegant solution I’ve seen, thanks a lot!
@ZY0422 You want
custom_objects={'sorenson_dice': sorenson_dice}
I have a similar problem I compile my model like this: model.compile(loss={‘ctc’: lambda y_true, y_pred: y_pred}, optimizer=sgd, metrics=[‘accuracy’]) when load_model(‘model.hdf5’, custom_objects={‘ctc’: lambda y_true, y_pred: y_pred}) it raise "Unknown loss function: ‘<lambda>’ Can anyone help me ,thank U very much!!!
Thanks @dluvizon, but I need three parameters as I wrote in my first post. How can I handle it? The error is raised only when I try to reload the model that has been saved.
@Demetrio92 your communication and social skills are below required minimum for an engineer, consider a different career path.
I use 2.0.1
Thank you so much. It works! Hope you have a nice day!
Custom objects should be called while compiling, so they should not be called in load_model. The above code piece is not the right answer, sorry. It should be:
model=load_model(model_path, compile=False) \\ model.compile(loss=lambda y_true, y_pred: my_loss(y_true, y_pred, lambda_const,i,T), optimizer="adam", metrics=["acc"])
Thank you so much! But it didn’t work. I still got this Unknown loss function:<lambda>
You first need to load your model with compile=False, then compile it. Like this:
model=load_model(model_path_old,custom_objects={'angle bracket lambda angle bracket': lambda y_true, y_pred : my_loss(y_true, y_pred, lambda_const,i,T)}, compile=False) \\ model.compile(loss=lambda y_true, y_pred: my_loss(y_true, y_pred, lambda_const,i,T), optimizer="adam", metrics=["acc"])
could anyone solve this problem please? This is the definition of my loss function:
def my_loss(y_true,y_pred,lambda_const,i,T,task_size=2): y_trueSoft=y_true[:,:(i)*task_size]
y_predSoft=y_pred[:,:(i)*task_size]/T y_trueHard=y_true[:,(i)*task_size:]
y_predHard=y_pred[:,(i)*task_size:]
return lambda_const*categorical_crossentropy(y_trueSoft,y_predSoft) + (1-lambda_const)*categorical_crossentropy(y_trueHard,y_predHard)
model_final.compile(loss=lambda y_true, y_pred: my_loss(y_true, y_pred, lambda_const,i,T), optimizer=“adam”, metrics=[“acc”])
And when I want to load this model , I got this error,ValueError: Unknown loss function:<lambda>. I have changed the way I load this model, it writes below, but I still got the same error, I am so confused
model_tmp=load_model(model_path_old,custom_objects={‘angle bracket lambda angle bracket’: lambda y_true, y_pred : my_loss(y_true, y_pred, lambda_const,i,T)})
Can anyone help me ? Thanks a lot
When I load my model, I have this error: ValueError: Unknown loss function:<lambda>, any help please???
pad each output label to maximum text length
train_padded_txt = pad_sequences(training_txt, maxlen=max_label_len, padding=‘post’, value = len(char_list)) valid_padded_txt = pad_sequences(valid_txt, maxlen=max_label_len, padding=‘post’, value = len(char_list))
input with shape of height=32 and width=128
input with shape of height=32 and width=128
inputs = Input(shape=(32,128,1))
convolution layer with kernel size (3,3)
conv_1 = Conv2D(64, (3,3), activation = ‘relu’, padding=‘same’)(inputs)
poolig layer with kernel size (2,2)
pool_1 = MaxPool2D(pool_size=(2, 2), strides=2)(conv_1)
conv_2 = Conv2D(128, (3,3), activation = ‘relu’, padding=‘same’)(pool_1) pool_2 = MaxPool2D(pool_size=(2, 2), strides=2)(conv_2)
conv_3 = Conv2D(256, (3,3), activation = ‘relu’, padding=‘same’)(pool_2)
conv_4 = Conv2D(256, (3,3), activation = ‘relu’, padding=‘same’)(conv_3)
poolig layer with kernel size (2,1)
pool_4 = MaxPool2D(pool_size=(2, 1))(conv_4)
conv_5 = Conv2D(512, (3,3), activation = ‘relu’, padding=‘same’)(pool_4)
Batch normalization layer
batch_norm_5 = BatchNormalization()(conv_5)
conv_6 = Conv2D(512, (3,3), activation = ‘relu’, padding=‘same’)(batch_norm_5) batch_norm_6 = BatchNormalization()(conv_6) pool_6 = MaxPool2D(pool_size=(2, 1))(batch_norm_6)
conv_7 = Conv2D(512, (2,2), activation = ‘relu’)(pool_6)
squeezed = Lambda(lambda x: K.squeeze(x, 1))(conv_7)
bidirectional LSTM layers with units=128
blstm_1 = Bidirectional(LSTM(128, return_sequences=True, dropout = 0.2))(squeezed) blstm_2 = Bidirectional(LSTM(128, return_sequences=True, dropout = 0.2))(blstm_1)
outputs = Dense(len(char_list)+1, activation = ‘softmax’)(blstm_2)
model to be used at test time
act_model = Model(inputs, outputs)
act_model.summary()
#the CTC loss fnction is to predict the output text, it is very helpfull for the #text recognition topic. labels = Input(name=‘the_labels’, shape=[max_label_len], dtype=‘float32’) input_length = Input(name=‘input_length’, shape=[1], dtype=‘int64’) label_length = Input(name=‘label_length’, shape=[1], dtype=‘int64’)
def ctc_lambda_func(args): y_pred, labels, input_length, label_length = args
loss_out = Lambda(ctc_lambda_func, output_shape=(1,), name=‘ctc’)([outputs, labels, input_length, label_length])
#model to be used at training time model = Model(inputs=[inputs, labels, input_length, label_length], outputs=loss_out)
#train the model
model.compile(loss={‘ctc’: lambda y_true, y_pred: y_pred}, optimizer = ‘adam’) filepath= “/home/yosra/Downloads/best_model.hdf5” checkpoint = ModelCheckpoint(filepath=filepath, monitor=‘val_loss’, verbose=1, save_best_only=True, mode=‘auto’)
callbacks_list = [checkpoint] training_img = np.array(training_img) train_input_length = np.array(train_input_length) train_label_length = np.array(train_label_length)
valid_img = np.array(valid_img) valid_input_length = np.array(valid_input_length) valid_label_length = np.array(valid_label_length)
model.fit(x=[training_img, train_padded_txt, train_input_length, train_label_length], y=np.zeros(len(training_img)), batch_size=batch_size, epochs = epochs, validation_data = ([valid_img, valid_padded_txt, valid_input_length, valid_label_length],[np.zeros(len(valid_img))]), verbose = 1, callbacks = callbacks_list)
model.save(filepath)
#test the model from keras.models import load_model
load the saved best model weights
new_model = load_model(filepath)
I have a problem when I load this model: ValueError: Unknown loss function:<lambda> can you help me please.
import numpy as np # linear algebra import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
Input data files are available in the “…/input/” directory.
For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory
import matplotlib.pyplot as plt import os
Imports
import os import fnmatch import cv2 import numpy as np import string import time
from keras.preprocessing.sequence import pad_sequences from keras.layers import Dense, LSTM, Reshape, BatchNormalization, Input, Conv2D from keras.layers import MaxPool2D, Lambda, Bidirectional from keras.models import Model from keras.activations import relu, sigmoid, softmax import keras.backend as K from keras.utils import to_categorical from keras.callbacks import ModelCheckpoint
import tensorflow as tf from tensorflow.python.client import device_lib import xml.etree.ElementTree as ET
#read xml file
doc = ET.parse(“/home/yosra/Downloads/IAMDataset/xml/a01-000u.xml”)
root = doc.getroot()
dic = [] label = []
for i in root.iter(‘word’):
dic.append(i.get(‘id’))
label.append(i.get(‘text’))
print(dic, ’ ’ ,label)
Global Variables
char_list = string.ascii_letters + string.digits print("Character List: ", char_list)
#function to decode the text into indice of char list def encode_to_labels(text): # We encode each output word into digits digit_list = [] for index, character in enumerate(text): try: digit_list.append(char_list.index(character)) except: print("Error in finding index for character ", character) #End For return digit_list
#preprocess the data #read the image from IAM Dataset n_samples = len(os.listdir(‘/home/yosra/Desktop/imagetest’))
#Number of samples in xml file
xml_samples = len(dic)
#list of trining_set
training_img = [] training_txt=[] train_input_length = [] train_label_length = [] orig_txt = []
#lists for validation dataset valid_img = [] valid_txt = [] valid_input_length = [] valid_label_length = [] valid_orig_txt = []
max_label_len = 0
Training Variables
batch_size = 256 epochs = 10
k=1
for i, pic in enumerate(os.listdir(‘/home/yosra/Desktop/imagetest’)): # Read image as grayscale img = cv2.imread(os.path.join(‘/home/yosra/Desktop/imagetest’, pic), cv2.IMREAD_GRAYSCALE)
print(‘kamlna’)
pad each output label to maximum text length
train_padded_txt = pad_sequences(training_txt, maxlen=max_label_len, padding=‘post’, value = len(char_list)) valid_padded_txt = pad_sequences(valid_txt, maxlen=max_label_len, padding=‘post’, value = len(char_list))
input with shape of height=32 and width=128
input with shape of height=32 and width=128
inputs = Input(shape=(32,128,1))
convolution layer with kernel size (3,3)
conv_1 = Conv2D(64, (3,3), activation = ‘relu’, padding=‘same’)(inputs)
poolig layer with kernel size (2,2)
pool_1 = MaxPool2D(pool_size=(2, 2), strides=2)(conv_1)
conv_2 = Conv2D(128, (3,3), activation = ‘relu’, padding=‘same’)(pool_1) pool_2 = MaxPool2D(pool_size=(2, 2), strides=2)(conv_2)
conv_3 = Conv2D(256, (3,3), activation = ‘relu’, padding=‘same’)(pool_2)
conv_4 = Conv2D(256, (3,3), activation = ‘relu’, padding=‘same’)(conv_3)
poolig layer with kernel size (2,1)
pool_4 = MaxPool2D(pool_size=(2, 1))(conv_4)
conv_5 = Conv2D(512, (3,3), activation = ‘relu’, padding=‘same’)(pool_4)
Batch normalization layer
batch_norm_5 = BatchNormalization()(conv_5)
conv_6 = Conv2D(512, (3,3), activation = ‘relu’, padding=‘same’)(batch_norm_5) batch_norm_6 = BatchNormalization()(conv_6) pool_6 = MaxPool2D(pool_size=(2, 1))(batch_norm_6)
conv_7 = Conv2D(512, (2,2), activation = ‘relu’)(pool_6)
squeezed = Lambda(lambda x: K.squeeze(x, 1))(conv_7)
bidirectional LSTM layers with units=128
blstm_1 = Bidirectional(LSTM(128, return_sequences=True, dropout = 0.2))(squeezed) blstm_2 = Bidirectional(LSTM(128, return_sequences=True, dropout = 0.2))(blstm_1)
outputs = Dense(len(char_list)+1, activation = ‘softmax’)(blstm_2)
model to be used at test time
act_model = Model(inputs, outputs)
act_model.summary()
#the CTC loss fnction is to predict the output text, it is very helpfull for the #text recognition topic. labels = Input(name=‘the_labels’, shape=[max_label_len], dtype=‘float32’) input_length = Input(name=‘input_length’, shape=[1], dtype=‘int64’) label_length = Input(name=‘label_length’, shape=[1], dtype=‘int64’)
def ctc_lambda_func(args): y_pred, labels, input_length, label_length = args
loss_out = Lambda(ctc_lambda_func, output_shape=(1,), name=‘ctc’)([outputs, labels, input_length, label_length])
#model to be used at training time model = Model(inputs=[inputs, labels, input_length, label_length], outputs=loss_out)
#train the model
model.compile(loss={‘ctc’: lambda y_true, y_pred: y_pred}, optimizer = ‘adam’) filepath= “/home/yosra/Downloads/best_model.hdf5” checkpoint = ModelCheckpoint(filepath=filepath, monitor=‘val_loss’, verbose=1, save_best_only=True, mode=‘auto’)
callbacks_list = [checkpoint] training_img = np.array(training_img) train_input_length = np.array(train_input_length) train_label_length = np.array(train_label_length)
valid_img = np.array(valid_img) valid_input_length = np.array(valid_input_length) valid_label_length = np.array(valid_label_length)
model.fit(x=[training_img, train_padded_txt, train_input_length, train_label_length], y=np.zeros(len(training_img)), batch_size=batch_size, epochs = epochs, validation_data = ([valid_img, valid_padded_txt, valid_input_length, valid_label_length],[np.zeros(len(valid_img))]), verbose = 1, callbacks = callbacks_list)
model.save(filepath)
#test the model from keras.models import load_model
load the saved best model weights
new_model = load_model(filepath)
@sayZeeel Try in your loss function to give it a name:
and then:
@Bisgates Hi, I tried your way but sadly it doesn’t work. It just gives me the same error message:
File "/home/gnahzuy/.conda/envs/gpu/lib/python3.5/site-packages/keras/losses.py", line 94, in deserialize printable_module_name='loss function') File "/home/gnahzuy/.conda/envs/gpu/lib/python3.5/site-packages/keras/utils/generic_utils.py", line 159, in deserialize_keras_object ':' + function_name) ValueError: Unknown loss function:sorenson_dice
I compile my model like:
model.compile(optimizer='adam', loss=sorenson_dice)
and I load my model like:model = keras.models.load_model('/home/gnahzuy/U-net/scripts/val_loss=.-0.88.hdf5',custom_objecta={'val_loss': sorenson_dice})
I define the loss function in the same file.I think that might because I give the worry name ‘val_loss’? I tried ‘loss’ but it doesn’t work too.
Do you have any idea about that? Thanks
@piccolbo actually I’m using also functools.partial, but I need to execute the following code in save/serialization time and in loading time:
custom_loss_partial = functools.partial(custom_loss_function, third_argument=third_argument) custom_loss_partial.__name__ = "custom_loss_function"
I’m searching for a way that allows me to load the model without declare custom_loss_partial two times.I hope that my issue it’s relevant and clear.
It looks like its trying to find the fn in generic_utils.py for a function_name which is binary_PTA which isnt found in custom_objects. @fchollet How do we add our metric to custom_objects?