Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loading model with custom loss function: ValueError: 'Unknown loss function' #5916

Closed
2 tasks done
pierluigiferrari opened this issue Mar 21, 2017 · 60 comments
Closed
2 tasks done

Comments

@pierluigiferrari
Copy link

pierluigiferrari commented Mar 21, 2017

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.

@isaacgerg
Copy link

isaacgerg commented Mar 22, 2017

I have this exact same error and just noticed this morning.

My metrics are very simple:

#-----------------------------------------------------------------------------------------------------------------------------------------------------
# PFA, prob false alert for binary classifier
def binary_PFA(y_true, y_pred):
    # N = total number of negative labels
    N = K.sum(1 - K.round(y_true))
    # FP = total number of false alerts, alerts from the negative class labels
    FP = K.sum(K.round(y_pred) - K.round(y_pred) * K.round(y_true))    
    return FP/N
#-----------------------------------------------------------------------------------------------------------------------------------------------------
# P_TA prob true alerts for binary classifier
def binary_PTA(y_true, y_pred):
    # P = total number of positive labels
    P = K.sum(K.round(y_true))
    # TP = total number of correct alerts, alerts from the positive class labels
    TP = K.sum(K.round(y_pred) * K.round(y_true))    
    return TP/P
#-----------------------------------------------------------------------------------------------------------------------------------------------------

myOptimizer = keras.optimizers.adadelta(lr=1.0)
model.compile(loss='binary_crossentropy', optimizer = myOptimizer, metrics=[keras.metrics.binary_accuracy, metrics.binary_PTA, metrics.binary_PFA])

@isaacgerg
Copy link

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?

@isaacgerg
Copy link

I did this as a work around:

model = model_from_json(open(modelFile).read())
model.load_weights(os.path.join(os.path.dirname(modelFile), 'model_weights.h5'))

@pierluigiferrari pierluigiferrari changed the title Loading model with custom loss function: UnboundLocalError: local variable 'class_name' referenced before assignment Loading model with custom loss function: ValueError: 'Unknown loss function' Mar 22, 2017
@pierluigiferrari
Copy link
Author

@isaacgerg what Keras version are you running? I got the error described in the old title in Keras 2.0.0, now after updating to 2.0.2 I'm getting a new error (as described in the new title).

But yeah, for the moment, saving and loading the weights separately is the way to go as a workaround.

@isaacgerg
Copy link

I use 2.0.1

@dluvizon
Copy link

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 to keras.losses.

@isaacgerg
Copy link

My work around is to load the json first and then load the weights. I keep my load function in a local lib with the rest of my keras workarounds ;)

@joeyearsley
Copy link
Contributor

This PR should have fixed this issue.

Can use:

from keras.utils.generic_utils import get_custom_objects
import SSD_Loss

loss = SSD_Loss(neg_pos_ratio=neg_pos_ratio, alpha=alpha)
get_custom_objects().update({"SSD_Loss": loss.computeloss})

@inspiralpatterns
Copy link

inspiralpatterns commented Apr 28, 2017

Same here.
I tried @joeyearsley's workaround and seems loading correctly.

@Bisgates
Copy link

Bisgates commented May 9, 2017

I solved this problem by adding 'custom_bojects'

model = load_model('model/multi_task/try.h5', custom_objects={'loss_max': loss_max})

my loss function:

def loss_max(y_true, y_pred):
    from keras import backend as K
    return K.max(K.abs(y_pred - y_true), axis=-1)

@piccolbo
Copy link

My workaround is like @dluvizon except I assigned keras.losses.loss. That was the missing function name according to the error message.

/Users/apiccolboni/anaconda/lib/python2.7/site-packages/keras/utils/generic_utils.pyc 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', ':loss')

keras 2.0.4

@pigna90
Copy link

pigna90 commented May 30, 2017

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!

@dluvizon
Copy link

Hi @pigna90 , the easiest way is to define a python function in the form:

def custom_loss_function(y_true, y_pred):
    # Compute loss
    return loss

Then you pass it as your loss in model.compile(loss=custom_loss_function, [...]).

@pigna90
Copy link

pigna90 commented May 30, 2017

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.

@piccolbo
Copy link

piccolbo commented May 30, 2017 via email

@pigna90
Copy link

pigna90 commented May 30, 2017

@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.

@ZY0422
Copy link

ZY0422 commented Jul 23, 2017

@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

@wkm
Copy link

wkm commented Aug 3, 2017

@ZY0422 You want custom_objects={'sorenson_dice': sorenson_dice}

@stale
Copy link

stale bot commented Nov 1, 2017

This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 30 days if no further activity occurs, but feel free to re-open a closed issue if needed.

@caocao1989
Copy link

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: ''
Can anyone help me ,thank U very much!!!

@SimulatedANeal
Copy link

SimulatedANeal commented Jan 10, 2018

@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!

@caocao1989
Copy link

@SimulatedANeal
Yes,Thanks for your reply,I have solved the problem like your answer

@LCorleone
Copy link

@SimulatedANeal
Wow, great! But i wanna to know why this can work? I never see such kind of custom_objects structure before. Where did you see it?

@marxmit7
Copy link

marxmit7 commented Jul 21, 2018

@SimulatedANeal I am using ssd_keras loss from keras_loss_function.keras_ssd_loss import SSDLoss and again while loading the model I'm getting this error ValueError: Unknown loss function:compute_loss . I tried above methods to resolve but none of these worked. I am using Keras 2.1.3 .

@sirius0503
Copy link

sirius0503 commented Jun 10, 2019

I solved this problem by adding 'custom_bojects'

model = load_model('model/multi_task/try.h5', custom_objects={'loss_max': loss_max})

my loss function:

def loss_max(y_true, y_pred):
    from keras import backend as K
    return K.max(K.abs(y_pred - y_true), axis=-1)

@Bisgates I'm loading my model using the weights as such:

model = yolo_body(Input(shape=(None, None, 3)), 3, num_classes)
model.load_weights('logs/000/trained_weights_stage_1.h5')
model.compile(optimizer=Adam(lr=1e-4), loss={'yolo_loss': lambda y_true, y_pred: y_pred})

I can't add custom objects, is there a way to add yolo_loss, when loading the model using load_weights.
I am using https://github.com/qqwweee/keras-yolo3 github repository, with yolo_body and yolo_loss defined in yolov3.models.py file.

@sirius0503
Copy link

sirius0503 commented Jun 10, 2019

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 to keras.losses.

@dluvizon: Can you elaborate on how to add the custom_loss in keras2.0?

@lminer
Copy link

lminer commented Jun 16, 2019

@TanmayParekh @shuaiw24, this is how you do it.

def sparse_weighted_loss_func(weights):
    
    def sparse_weighted_loss(target, output):
        return tf.multiply(tf.keras.backend.sparse_categorical_crossentropy(target, output), weights)
    return sparse_weighted_loss

model.compile(loss=sparse_weighted_loss_func(weights), ...)

# during loading time, it will expect sparse_weighted_loss not sparse_weighted_loss_func
model = load_model('pathtomodel',
                   custom_objects: {'sparse_weighted_loss': sparse_weighted_loss_func(weights)})

@khushal1996
Copy link

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.

The following code worked for me --

generator.compile(loss='mse', optimizer=opt, metrics=[perceptual_distance])
model = load_model("../input/srresnet-epoch-120/pretrain/model00000120.h5", custom_objects={'perceptual_distance': perceptual_distance})
weights = model.get_weights()
generator.set_weights(weights)

@CA4GitHub
Copy link

@ajaceves
Copy link

I solved this problem by adding 'custom_bojects'

model = load_model('model/multi_task/try.h5', custom_objects={'loss_max': loss_max})

my loss function:

def loss_max(y_true, y_pred):
    from keras import backend as K
    return K.max(K.abs(y_pred - y_true), axis=-1)

My loss function is like this.
def custom_loss_function(inputs):

def custom_loss(y_true, y_pred):
    print (inputs.shape, y_true.shape, y_pred.shape)
    x =  k.exp(inputs[:,12,:])
    y_t = k.log(k.exp(y_true)*x)
    y_p = k.log(k.exp(y_pred)*x)
    # y_p[y_p==0] = 1e-6
    l = y_t - y_p
    return k.square(l)

return custom_loss

I am getting the following error
model=load_model('lstm_fftm_custom_loss.h5', custom_objects={'custom_loss':custom_loss})
NameError: name 'custom_loss' is not defined
Can you please help?

@sayZeeel Try in your loss function to give it a name:

def custom_loss_function(inputs):
 def custom_loss(y_true, y_pred):
     print (inputs.shape, y_true.shape, y_pred.shape)
     x =  k.exp(inputs[:,12,:])
     y_t = k.log(k.exp(y_true)*x)
     y_p = k.log(k.exp(y_pred)*x)
     # y_p[y_p==0] = 1e-6
     l = y_t - y_p
     return k.square(l)
 custom_loss.__name__ = "Custom Loss"
 return custom_loss

and then:

model = load_model('model/multi_task/try.h5', custom_objects={'Custom Loss': custom_loss_function})

Giving the custom loss a name was the only thing that worked in tf 2.1

@blvz
Copy link

blvz commented Feb 28, 2020

None of the above worked for me, but this did:

Load the model with compile=False and then compile it manually.

import tensorflow as tf
import tensorflow_hub as hub
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import Adam

IMG_WIDTH = 224
IMG_HEIGHT = IMG_WIDTH
CHANNELS = 3
LEARNING_RATE = 1e-5
NUM_LABELS = 128

def create_model():
  feature_extractor_url = 'https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/feature_vector/4'
  feature_extractor_layer = hub.KerasLayer(feature_extractor_url,
                                           input_shape=(IMG_HEIGHT, IMG_WIDTH, CHANNELS))
  feature_extractor_layer.trainable = False

  return Sequential([
    feature_extractor_layer,
    Dense(1024, activation='relu', name='hidden_layer'),
    Dense(NUM_LABELS, activation='sigmoid', name='output')
  ])

def load_model(model_dir):
  # got the compile=False idea from @Pepslee's comment:
  # https://github.com/keras-team/keras/issues/5916#issuecomment-457624404
  return tf.keras.models.load_model(model_dir,
                                    compile=False,
                                    custom_objects={'KerasLayer': hub.KerasLayer})
                                    # this didn't work.
                                    # neither did the custom_loss_function with __name__ thing.
                                    # custom_objects={'KerasLayer': hub.KerasLayer,
                                    #                 'custom_loss': custom_loss,
                                    #                 'custom_metric': custom_metric})

def train(prev_model):
  # the trick is to load the model with compile=False
  if prev_model:
    model = load_model(prev_model)
  else:
    model = create_model()

  # and then compile manually,
  # the same way it does with a new model.
  model.compile(
    optimizer=Adam(learning_rate=LEARNING_RATE),
    loss=custom_loss,
    metrics=[custom_metric]
  )

  # model.fit ...

# def custom_loss(y_true, y_pred):
#   ...

# def custom_metric(y_true, y_pred, threshold=0.5):
#   ...

@yosraammar
Copy link

I have a problem when I load this model: ValueError: Unknown loss function: 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)

    pic_target = pic[:-4]
    # convert each image of shape (32, 128, 1)
    w, h = img.shape

    if h > 128 or w > 32:
        continue
    # endif

    # Process the images to bring them to scale
    if w < 32:
        add_zeros = np.ones((32-w, h))*255
        img = np.concatenate((img, add_zeros))
    # endif
    if h < 128:
        add_zeros = np.ones((32, 128-h))*255
        img = np.concatenate((img, add_zeros), axis=1)
    # endif    

    img = np.expand_dims(img , axis = 2)

    # Normalise the image
    img = img/255.

    # Get the text for the image
    txt = pic_target.split('_')[1]
            
    # compute maximum length of the text
    if len(txt) > max_label_len:
        max_label_len = len(txt)

    if k%10 == 0:     
        valid_orig_txt.append(txt)   
        valid_label_length.append(len(txt))
        valid_input_length.append(31)
        valid_img.append(img)
        valid_txt.append(encode_to_labels(txt))
    else:
        orig_txt.append(txt)   
        train_label_length.append(len(txt))
        train_input_length.append(31)
        training_img.append(img)
        training_txt.append(encode_to_labels(txt))
    k+=1

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

return K.ctc_batch_cost(labels, y_pred, input_length, label_length)

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)

@yosraammar
Copy link

When I load my model, I have this error: ValueError: Unknown loss function:, 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

return K.ctc_batch_cost(labels, y_pred, input_length, label_length)

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)

@Demetrio92
Copy link

Stop posting into this thread!!! There's an answer above, and you're making it hard to find!

WORKAROUND

model = tf.keras.models.load_model(path_here, compile=False)

@weilinapple
Copy link

weilinapple commented Jul 22, 2020

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:.
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

@cememreakbas
Copy link

cememreakbas commented Jul 22, 2020

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:.
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

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"])

@weilinapple
Copy link

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:.
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

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"])

Thank you so much! But it didn't work. I still got this Unknown loss function:

@cememreakbas
Copy link

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:.
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

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"])

Thank you so much! But it didn't work. I still got this Unknown loss function:

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"])

@weilinapple
Copy link

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:.
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

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"])

Thank you so much! But it didn't work. I still got this Unknown loss function:

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. It works! Hope you have a nice day!

@Demetrio92
Copy link

@weilinapple you reading comprehension is way below required minimum for an engineer, consider a different career path.

@r0l1
Copy link

r0l1 commented Oct 11, 2020

@Demetrio92 your communication and social skills are below required minimum for an engineer, consider a different career path.

@SirErnestt
Copy link

model.compile(optimizer='adam', metrics=['accuracy'],
loss=tf.keras.losses.SparseCategoricalCrossentropy())

this code works

tallamjr added a commit to tallamjr/astronet that referenced this issue Dec 9, 2020
Specifically with custom objects such as the WeightedLogLoss function

It is expected that to load the saved model correctly, one will need to
use:

    >>> model = load_model('model.hdf5', custom_objects={'custom_loss': custom_loss})

Linked to #41

Refs:
    - keras-team/keras#5916 (comment)

	new file:   astronet/t2/tests/func/test_model_save_load_predict.py
@Green-16
Copy link

Green-16 commented Sep 27, 2021

None of the above worked for me, because my sense is the my model is mmoe , multi-task learning.
So I use the pickle package to avoid the problem.
with open(model_path + 'model_pickle.h5', 'wb') as f:
pickle.dump(mmoeObj.model, f)

ps:
If you model is not serialize object: such as TypeError: can't pickle CompiledFFI objects ,
The answer is here tensorflow/tensorflow#34697

@Aliktk
Copy link

Aliktk commented Nov 15, 2021

many people try to find this issue. This problem is for the loss during training.
Here I solved this issue by using compile false:

model = load_model("lc_model.h5", compile=False)
Source

@GHE001
Copy link

GHE001 commented Dec 22, 2021

I solved this problem by adding 'custom_bojects'

model = load_model('model/multi_task/try.h5', custom_objects={'loss_max': loss_max})

my loss function:

def loss_max(y_true, y_pred):
    from keras import backend as K
    return K.max(K.abs(y_pred - y_true), axis=-1)

That really helped! Thank you!!!

@dovanhuong
Copy link

@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!

Dear expert!
Thank you for your recommendation, I applied by your instruction and it can through to load_model. Unfortunately, it had an error related to ctc type of tensor as below:

Traceback (most recent call last):
File "convert_keras_to_onnx.py", line 46, in
onnx_model = keras2onnx.convert_keras(model, model.name)
File "/home/ai_dev/anaconda3/envs/korean_ocr/lib/python3.6/site-packages/keras2onnx/main.py", line 80, in convert_keras
parse_graph(topology, tf_graph, target_opset, output_names, output_dict)
File "/home/ai_dev/anaconda3/envs/korean_ocr/lib/python3.6/site-packages/keras2onnx/parser.py", line 841, in parse_graph
) if is_tf2 and is_tf_keras else _parse_graph_core(
File "/home/ai_dev/anaconda3/envs/korean_ocr/lib/python3.6/site-packages/keras2onnx/parser.py", line 729, in _parse_graph_core_v2
_on_parsing_tf_nodes(graph, layer_info.nodelist, varset, topology.debug_mode)
File "/home/ai_dev/anaconda3/envs/korean_ocr/lib/python3.6/site-packages/keras2onnx/parser.py", line 323, in on_parsing_tf_nodes
var_type = infer_variable_type(i
, varset.target_opset)
File "/home/ai_dev/anaconda3/envs/korean_ocr/lib/python3.6/site-packages/keras2onnx/_parser_tf.py", line 48, in infer_variable_type
"Unable to find out a correct type for tensor type = {} of {}".format(tensor_type, tensor.name))
ValueError: Unable to find out a correct type for tensor type = 0 of ctc/scan/while/TensorArrayReadV3/Enter:0

base on your expertise, could you please advice to me some solutions?
Warmly thank you so much,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests