简体   繁体   中英

Custom loss problem: inputs to eager execution function cannot be keras symbolic tensors but found

My code to use tensorflow keras custom loss (using additional input data to calculate loss) is as follows:

inp = Input(shape=(inp_seq_len,feature_size))
w = Input(shape=(1))
# code ommitted

def custom_loss(w):
    def loss(y_true,y_pred):
        return -y_true*y_pred*w
    return loss

model = Model(
  inputs=[inp, w],
  outputs=[pred],
)
model.compile(loss=custom_loss(w), optimizer='adam')

When doing model.fit(), I got error: Inputs to eager execution function cannot be Keras symbolic tensors, but found: tf.Tensor 'input_19:0 shape=[None,1], dtype=float32

Following https://github.com/tensorflow/tensorflow/issues/34944 , I did: tf.config.experimental_run_functions_eagerly(True)

Then I got error: Cannot convert a symbolic Tensor (truediv_20:0) to a numpy array

Please note that I followed Inputs to eager execution function cannot be Keras symbolic tensors to change my code.

My original code is (unpack inp and w from one inpA):

inpA = Input(shape=(inp_seq_len,feature_size+1))
inp = Lambda(lambda x: x[:,:,:feature_size])(inpA)
w = Flatten()(Lambda(lambda x: x[:,-1,feature_size])(inpA))

def custom_loss(w):
    def loss(y_true,y_pred):
        return -y_true*y_pred*w
    return loss

model = Model(
  inputs=[inpA],
  outputs=[pred],
)
model.compile(loss=custom_loss(w), optimizer='adam')

The error I got with/without tf.config.experimental_run_functions_eagerly(True) is same as above.

What I can do?

Thanks.

Update: got this error when using code from the below post:

WARNING:tensorflow:Output dense_3 missing from loss dictionary. We assume this was done on purpose. The fit and evaluate APIs will not be expecting any data to be passed to dense_3.
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-5-1f23bd570780> in <module>()
     19 m.add_loss( mse( true, out, sample_weight ) )
     20 m.compile(loss=None, optimizer='adam')
---> 21 history = m.fit([X, y, W], y, epochs=10)
     22 
     23 # final fitted model to compute predictions

/nfs/anaconda2/lib/python2.7/site-packages/tensorflow_core/python/keras/engine/training.pyc in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_freq, max_queue_size, workers, use_multiprocessing, **kwargs)
    817         max_queue_size=max_queue_size,
    818         workers=workers,
--> 819         use_multiprocessing=use_multiprocessing)
    820 
    821   def evaluate(self,

/nfs/anaconda2/lib/python2.7/site-packages/tensorflow_core/python/keras/engine/training_v2.pyc in fit(self, model, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_freq, max_queue_size, workers, use_multiprocessing, **kwargs)
    233           max_queue_size=max_queue_size,
    234           workers=workers,
--> 235           use_multiprocessing=use_multiprocessing)
    236 
    237       total_samples = _get_total_number_of_samples(training_data_adapter)

/nfs/anaconda2/lib/python2.7/site-packages/tensorflow_core/python/keras/engine/training_v2.pyc in _process_training_inputs(model, x, y, batch_size, epochs, sample_weights, class_weights, steps_per_epoch, validation_split, validation_data, validation_steps, shuffle, distribution_strategy, max_queue_size, workers, use_multiprocessing)
    591         max_queue_size=max_queue_size,
    592         workers=workers,
--> 593         use_multiprocessing=use_multiprocessing)
    594     val_adapter = None
    595     if validation_data:

/nfs/anaconda2/lib/python2.7/site-packages/tensorflow_core/python/keras/engine/training_v2.pyc in _process_inputs(model, mode, x, y, batch_size, epochs, sample_weights, class_weights, shuffle, steps, distribution_strategy, max_queue_size, workers, use_multiprocessing)
    644     standardize_function = None
    645     x, y, sample_weights = standardize(
--> 646         x, y, sample_weight=sample_weights)
    647   elif adapter_cls is data_adapter.ListsOfScalarsDataAdapter:
    648     standardize_function = standardize

/nfs/anaconda2/lib/python2.7/site-packages/tensorflow_core/python/keras/engine/training.pyc in _standardize_user_data(self, x, y, sample_weight, class_weight, batch_size, check_steps, steps_name, steps, validation_split, shuffle, extract_tensors_from_dataset)
   2381         is_dataset=is_dataset,
   2382         class_weight=class_weight,
-> 2383         batch_size=batch_size)
   2384 
   2385   def _standardize_tensors(self, x, y, sample_weight, run_eagerly, dict_inputs,

/nfs/anaconda2/lib/python2.7/site-packages/tensorflow_core/python/keras/engine/training.pyc in _standardize_tensors(self, x, y, sample_weight, run_eagerly, dict_inputs, is_dataset, class_weight, batch_size)
   2467           shapes=None,
   2468           check_batch_axis=False,  # Don't enforce the batch size.
-> 2469           exception_prefix='target')
   2470 
   2471       # Generate sample-wise weight values given the `sample_weight` and

/nfs/anaconda2/lib/python2.7/site-packages/tensorflow_core/python/keras/engine/training_utils.pyc in standardize_input_data(data, names, shapes, check_batch_axis, exception_prefix)
    494       raise ValueError(
    495           'Error when checking model ' + exception_prefix + ': '
--> 496           'expected no data, but got:', data)
    497     return []
    498   if data is None:

ValueError: ('Error when checking model target: expected no data, but got:', array([3.39102071e-01, 1.23122638e-01, 7.54209531e-01, 8.10110230e-01,

this is a workaround to pass additional arguments to a custom loss function, in your case an array of weights. the trick consists in using fake inputs which are useful to build and use the loss in the correct ways. don't forget that keras handles fixed batch dimension

I provide a dummy example in a regression problem. this can be easily modified according to your needs

def mse(y_true, y_pred, sample_weight):

    error = y_true-y_pred

    return K.mean(K.sqrt(error)*sample_weight)


X = np.random.uniform(0,1, (1000,10))
y = np.random.uniform(0,1, 1000)
W = np.random.uniform(1,2, 1000)

inp = Input((10,))
true = Input((1,))
sample_weight = Input((1,))
x = Dense(32, activation='relu')(inp)
out = Dense(1)(x)

m = Model([inp,true, sample_weight], out)
m.add_loss( mse( true, out, sample_weight ) )
m.compile(loss=None, optimizer='adam')
history = m.fit([X, y, W], y, epochs=10)

# final fitted model to compute predictions
final_m = Model(inp, out)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM