'ValueError: No gradients provided for any variable - Custom loss function

I am trying to implement a custom loss function for the some time series, but receive the following error when I try to fit my model.

def mvmt_loss(y_true, y_pred):
    
    # Make sure float32 (for metric calculations)
    y_true = tf.cast(y_true, dtype=tf.float32)
    y_pred = tf.cast(y_pred, dtype=tf.float32)
    
    #extract the "next day's price" of tensor
    y_true_next = y_true[HORIZON:]
    y_pred_next = y_pred[HORIZON:]
    
    #extract the "today's price" of tensor
    y_true_tdy = y_true[:-HORIZON]
    y_pred_tdy = y_pred[:-HORIZON]
    
    #substract to get up/down movement of the two tensors
    y_true_diff = tf.subtract(y_true_next, y_true_tdy)
    y_pred_diff = tf.subtract(y_pred_next, y_pred_tdy)
    
    #create a standard tensor with zero value for comparison
    standard = tf.zeros_like(y_pred_diff)
    
    #compare with the standard; if true, UP; else DOWN
    y_true_move = tf.greater_equal(y_true_diff, standard)
    y_pred_move = tf.greater_equal(y_pred_diff, standard)
    
    #find indices where the directions are not the same
    condition = tf.not_equal(y_true_move, y_pred_move)
    indices_pred = tf.where(condition)*1
    
    pred_sum = tf.math.reduce_sum(indices_pred)    
    
    #extract the "next day's price" of tensor
    y_naive_next = y_pred[HORIZON:] + HORIZON*0.05
    
    #extract the "today's price" of tensor
    y_naive_tdy = y_pred[:-HORIZON]
    
    #substract to get up/down movement of the two tensors
    y_naive_diff = tf.subtract(y_naive_next, y_naive_tdy)
    
    #create a standard tensor with zero value for comparison
    standard = tf.zeros_like(y_naive_diff)
    
    #compare with the standard; if true, UP; else DOWN
    y_naive_move = tf.greater_equal(y_naive_diff, standard)
    
    #find indices where the directions are not the same
    condition = tf.not_equal(y_true_move, y_naive_move)
    indices_naive = tf.where(condition)*1
    
    naive_sum = tf.math.reduce_sum(indices_naive)
    
    mvmt_loss = tf.divide(naive_sum, pred_sum)
    
    loss = tf.cast(mvmt_loss, dtype=tf.float32)

    return loss  


---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [59], in <module>
     13 SPY_Dense_MV.compile(loss=mvmt_loss,
     14                 optimizer=tf.keras.optimizers.Adam(),
     15                 metrics=['mae','mape'],)
     17 # Fit
---> 18 SPY_Dense_MV.fit(X_train, y_train,
     19             epochs=100,
     20             batch_size=128,
     21             verbose=0, # only print 1 line per epoch
     22             validation_data=(X_test, y_test),
     23             callbacks=[create_model_checkpoint(model_name=SPY_Dense_MV.name)])

File /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/keras/utils/traceback_utils.py:67, in filter_traceback.<locals>.error_handler(*args, **kwargs)
     65 except Exception as e:  # pylint: disable=broad-except
     66   filtered_tb = _process_traceback_frames(e.__traceback__)
---> 67   raise e.with_traceback(filtered_tb) from None
     68 finally:
     69   del filtered_tb

File /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/tensorflow/python/framework/func_graph.py:1147, in func_graph_from_py_func.<locals>.autograph_handler(*args, **kwargs)
   1145 except Exception as e:  # pylint:disable=broad-except
   1146   if hasattr(e, "ag_error_metadata"):
-> 1147     raise e.ag_error_metadata.to_exception(e)
   1148   else:
   1149     raise

ValueError: in user code:

    File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/keras/engine/training.py", line 1021, in train_function  *
        return step_function(self, iterator)
    File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/keras/engine/training.py", line 1010, in step_function  **
        outputs = model.distribute_strategy.run(run_step, args=(data,))
    File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/keras/engine/training.py", line 1000, in run_step  **
        outputs = model.train_step(data)
    File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/keras/engine/training.py", line 863, in train_step
        self.optimizer.minimize(loss, self.trainable_variables, tape=tape)
    File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/keras/optimizer_v2/optimizer_v2.py", line 532, in minimize
        return self.apply_gradients(grads_and_vars, name=name)
    File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/keras/optimizer_v2/optimizer_v2.py", line 633, in apply_gradients
        grads_and_vars = optimizer_utils.filter_empty_gradients(grads_and_vars)
    File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/keras/optimizer_v2/utils.py", line 73, in filter_empty_gradients
        raise ValueError(f"No gradients provided for any variable: {variable}. "

    ValueError: No gradients provided for any variable: (['dense_28/kernel:0', 'dense_28/bias:0', 'dense_29/kernel:0', 'dense_29/bias:0', 'dense_30/kernel:0', 'dense_30/bias:0', 'dense_31/kernel:0', 'dense_31/bias:0'],). Provided `grads_and_vars` is ((None, <tf.Variable 'dense_28/kernel:0' shape=(465, 128) dtype=float32>), (None, <tf.Variable 'dense_28/bias:0' shape=(128,) dtype=float32>), (None, <tf.Variable 'dense_29/kernel:0' shape=(128, 128) dtype=float32>), (None, <tf.Variable 'dense_29/bias:0' shape=(128,) dtype=float32>), (None, <tf.Variable 'dense_30/kernel:0' shape=(128, 128) dtype=float32>), (None, <tf.Variable 'dense_30/bias:0' shape=(128,) dtype=float32>), (None, <tf.Variable 'dense_31/kernel:0' shape=(128, 1) dtype=float32>), (None, <tf.Variable 'dense_31/bias:0' shape=(1,) dtype=float32>)).

If I run my custom loss function as a standalone, this is my output (FYI, I created some predicted values by using the 'mse' loss function):

mvmt_ratio = mvmt_loss(y_test,y_pred)
    
mvmt_ratio 

<tf.Tensor: shape=(), dtype=float32, numpy=0.98119444>

I'm not sure what the problem is because I have another custom loss function that produces similarly formatted output to the above and the model fits without issue.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source