3

Hi I have a model which is based on this https://github.com/igormq/asr-study/tree/keras-2 that is able to just about save okay but is unable to load (either full mode or json/weights) due to the fact the loss isn't defined properly.

inputs = Input(name='inputs', shape=(None, num_features))
...
o = TimeDistributed(Dense(num_hiddens))(inputs)

# Output layer
outputs = TimeDistributed(Dense(num_classes))(o)

# Define placeholders
labels = Input(name='labels', shape=(None,), dtype='int32', sparse=True)
inputs_length = Input(name='inputs_length', shape=(None,), dtype='int32')

# Define a decoder
dec = Lambda(ctc_utils.decode, output_shape=ctc_utils.decode_output_shape,
             arguments={'is_greedy': True}, name='decoder')
y_pred = dec([output, inputs_length])

loss = ctc_utils.ctc_loss(output, labels, input_length)


model = Model(input=[inputs, labels, inputs_length], output=y_pred)
model.add_loss(loss)

opt = Adam(lr=args.lr, clipnorm=args.clipnorm)

 # Compile with dummy loss
 model.compile(optimizer=opt, loss=None, metrics=[metrics.ler])

This will compile and run (note it uses the add_loss function which isn't very well documented). It can even be convinced to save with a bit of work - as this post hints (https://github.com/fchollet/keras/issues/5179) you can make it save by forcing the graph to be complete. I did this by making a dummy lambda loss function to bring in the inputs that weren't fully part of the graph, now this appears to work.

#this captures all the dangling nodes so will now save
fake_dummy_loss = Lambda(fake_ctc_loss,output_shape(1,),name=ctc)([y_pred,labels,inputs_length])

def fake_ctc_loss(args):
return tf.Variable(tf.zeros([1]),name="fakeloss")

We can add this to the model like so:

model = Model(input=[inputs, labels, inputs_length], output=[y_pred, fake_dummy_loss])

Now the loss when trying to load, says that it cannot due to the fact that it is missing a loss function (i guess this is because it's set to None despite add_loss being used.

Any help here appreciated

robmsmt
  • 1,389
  • 11
  • 19

1 Answers1

0

I faced a similar problem in a project of mine in which add_loss is used to manually add a custom loss function to my model. You can see my model here: Keras Loss Function with Additional Dynamic Parameter As you found, loading the model with load_model fails, complaining about a missing loss function.

Anyway, my solution was to save and load the model's weights rather than the whole model. The Model class has a save_weights method, which is discussed here: https://keras.io/models/about-keras-models/ Likewise, there's a load_weights method. Using these methods, you should be able to save and load the model just fine. The downside is that you have to define the model upfront, and then load the weights. In my project that wasn't an issue and only involved a small refactor.

Hope that helps.

benbotto
  • 2,291
  • 1
  • 20
  • 32