Keras: How to update Loss Function parameter during Training?

Created on 8 Mar 2018  路  9Comments  路  Source: keras-team/keras

Hello,
I used following custom loss function.

def w_categorical_crossentropy(y_true, y_pred, weights):
  nb_cl = len(weights)
  final_mask = K.zeros_like(y_pred[:, 0])
  y_pred_max = K.max(y_pred, axis=1)
  y_pred_max = K.reshape(y_pred_max, (K.shape(y_pred)[0], 1))
  y_pred_max_mat = K.cast(K.equal(y_pred, y_pred_max), K.floatx())
  for c_p, c_t in product(range(nb_cl), range(nb_cl)):
      final_mask += (weights[c_t, c_p] * y_pred_max_mat[:, c_p] * y_true[:, c_t])
  return K.categorical_crossentropy(y_pred, y_true) * final_mask

I need to change weight parameters after every epoch.

ncce = functools.partial(w_categorical_crossentropy, weights=w_array)
model.compile(loss=ncce, optimizer=sgd, metrics=['accuracy'])

However, when i call to above codes, optimizers state is lost, therefore training doesn't continue from previous epoch.

Are there any way for updating loss function without effecting training?

Most helpful comment

I agree with @Dref360's solution. You can change your model architecture to incorporate a new input which corresponds to "weights" (Probably you cannot define a sequential model in this case). It should resolve your problem. Please let us know if your problem is solved.

All 9 comments

Maybe you can try following code after each epoch:
from keras import backend as K
K.clear_session()
Then you need recompile everything (you may also need define optimizers before every epoch) as well as update your loss function before running next epoch.
Just a thought.

@yushuinanrong, Problem is already redefining optimizers. When i done this, the state of the optimizer, allowing to resume training exactly where you left off, is lost. I shouldn' t lose optimizer state to continue training.

Are you using a dynamic optimizer? And what you mean of "state of the optimizer"?

https://keras.io/getting-started/faq/ , Under the title of "How can I save a Keras model?" , it refers state of optimizer and this is my optimizer codes:
sgd = SGD(lr=lrate, momentum=0.9, decay=0.0001, nesterov=False)

Create a new input to your Model with the weights and feed the weights for each batch.

I agree with @Dref360's solution. You can change your model architecture to incorporate a new input which corresponds to "weights" (Probably you cannot define a sequential model in this case). It should resolve your problem. Please let us know if your problem is solved.

Thank for your suggestion. I try to implement but i have still a problem. I wrote following codes for implementing your idea, but i can not complete it because of giving multiple input.

def w_categorical_crossentropy(weights):
  def loss(y_true, y_pred)
    print(weights)
    print("----")
    final_mask = K.zeros_like(y_pred[:, 0])
    y_pred_max = K.max(y_pred, axis=1)
    y_pred_max = K.reshape(y_pred_max, (K.shape(y_pred)[0], 1))
    y_pred_max_mat = K.cast(K.equal(y_pred, y_pred_max), K.floatx())
    return K.categorical_crossentropy(y_pred, y_true)
  return loss

input = Input(shape=(10,))
w_array = Input(shape=(1,))
x1=model.add(Dense(512, activation='relu'))(input)
x2=model.add(Dropout(0.2))(x1)
x3=model.add(Dense(512, activation='relu'))(x2)
x4=model.add(Dropout(0.2))(x3)
out= model.add(Dense(num_classes, activation='softmax'))(x4)
model = Model([input,w_array], out)
model.compile(loss=w_categorical_crossentropy(w_array),
              optimizer=sgd(),
              metrics=['accuracy'])

for i in range(15):  
 // following will give error probably
  history = model.fit(x_train, y_train,    
                    batch_size=batch_size,
                    epochs=1,
                    verbose=1,
                    validation_data=(x_test, y_test))

How can i acces and change w_array? Also , how can i call fit function with two input?

@e181978 Please check the multi-input multi-output example in Keras's document:
https://keras.io/getting-started/functional-api-guide/#multi-input-and-multi-output-models
Note you need use functional API to define your model instead of constructing a sequential model.
"model.add()" is something used in a sequential model.

Closing as this is resolved

Was this page helpful?
0 / 5 - 0 ratings