I am using Mask R-CNN model with tensorflow version 2.13. The code works fine till training. When I run training, I am facing this KerasTensor error which is due to my loss functions, I think.
This is the compile part - def compile(self, learning_rate, momentum): """Compiles the Mask R-CNN model by adding losses and metrics.""" # Check if the model is built before compiling if not hasattr(self, 'keras_model') or self.keras_model is None: print("⚠️ Model not built. Building now...") self.keras_model = self.build(mode="training", config=self.config)
# Optimizer setup
optimizer = tf.keras.optimizers.SGD(
learning_rate=learning_rate,
momentum=momentum,
clipnorm=self.config.GRADIENT_CLIP_NORM
)
loss_names = [
"rpn_class_loss", "rpn_bbox_loss",
"mrcnn_class_loss", "mrcnn_bbox_loss", "mrcnn_mask_loss"
]
print(f"✅ Available layers: {[layer.name for layer in self.keras_model.layers]}")
for loss_name in loss_names:
try:
loss_layer = self.keras_model.get_layer(loss_name)
loss_value = tf.reduce_mean(loss_layer.output)
print(f"✅ Loss layer {loss_name} found in model: {loss_value}")
#loss_value = tf.convert_to_tensor(loss_value, dtype=tf.float32)
@tf.function
def compute_loss():
return tf.reduce_mean(loss_layer.output)
loss_value = compute_loss()
print(f"✅ Loss layer {loss_name} converted from KerasTensor to normal tensor: {loss_value}")
self.keras_model.add_loss(lambda: loss_value)
print(f"✅ Added loss: {loss_name}")
except ValueError:
print(f"❌ Warning: Loss layer {loss_name} not found in model!")
config_dict = {k: v for k, v in self.config.__dict__.items() if not k.startswith('__')}
# Compile the model
self.keras_modelpile(
optimizer=optimizer,
loss=None, # Mask R-CNN defines its own loss layers
run_eagerly=True,
experimental_run_tf_function=False
)
print("✅ Model compiled successfully!")
this is the build part where I add the losses - rpn_class_loss = RPNClassLoss(name="rpn_class_loss")([input_rpn_match, rpn_class_logits]) self.add_loss(tf.reduce_mean(rpn_class_loss)) rpn_bbox_loss = RPNBBoxLoss(name="rpn_bbox_loss")([config, input_rpn_bbox, input_rpn_match, rpn_bbox]) self.add_loss(tf.reduce_mean(rpn_bbox_loss)) mrcnn_class_loss = MRCNNClassLoss(name="mrcnn_class_loss")([target_class_ids, mrcnn_class_logits, active_class_ids]) self.add_loss(tf.reduce_mean(mrcnn_class_loss)) mrcnn_bbox_loss = MRCNNBBoxLoss(name="mrcnn_bbox_loss")([target_bbox, target_class_ids, mrcnn_bbox]) self.add_loss(tf.reduce_mean(mrcnn_bbox_loss)) mrcnn_mask_loss = MRCNNMaskLoss(name="mrcnn_mask_loss")([target_mask, target_class_ids, mrcnn_mask]) self.add_loss(tf.reduce_mean(mrcnn_mask_loss))
this is the custom loss functions -
class SmoothL1Loss(Layer): @tf.function def call(self, inputs): """Computes Smooth-L1 loss.""" y_true, y_pred = inputs # Expecting two tensors: [batch, N, 4]
diff = tf.abs(y_true - y_pred)
less_than_one = tf.cast(tf.less(diff, 1.0), tf.float32)
loss = (less_than_one * 0.5 * tf.square(diff)) + ((1.0 - less_than_one) * (diff - 0.5))
return tf.reduce_mean(loss) # ✅ Ensures numerical value
class RPNClassLoss(Layer): @tf.function def call(self, inputs): rpn_match, rpn_class_logits = inputs # Shapes: [batch, anchors, 1] and [batch, proposals, 2, 2]
rpn_match = tf.squeeze(rpn_match, -1) # Shape: [batch, anchors]
# Convert -1/+1 labels to 0/1 format
anchor_class = tf.where(rpn_match == 1, 1, 0) # Shape: [batch, anchors]
# ✅ Ensure indices do not exceed the available range
max_proposals = tf.shape(rpn_class_logits)[1] # Get the actual number of proposals
valid_indices = tf.where(
tf.logical_and(tf.not_equal(rpn_match, 0), tf.range(tf.shape(rpn_match)[1]) < max_proposals)
) # Shape: [num_valid, 2]
# ✅ Gather only valid anchors
rpn_class_logits = tf.gather_nd(rpn_class_logits, valid_indices) # Shape: [num_valid, 2, 2]
anchor_class = tf.gather_nd(anchor_class, valid_indices) # Shape: [num_valid]
#