基于MobileNet v2的猫狗多输出模型添加指标报错求助
解决多输出猫狗分类+检测模型中MeanIoU指标报错问题
问题根源
你混淆了Keras内置MeanIoU的适用场景:
- 内置
MeanIoU是为语义分割、分类任务设计的,要求输入是离散的类别ID(整数),用来计算不同类别区域的交并比。 - 你的检测输出是连续的边界框坐标值(浮点数),和
MeanIoU的输入要求完全不匹配,这才导致了各种类型/形状错误。
解决方案:自定义边界框IoU指标
检测任务中评估边界框回归的正确指标是边界框IoU(交并比),需要自己实现针对坐标回归的IoU计算逻辑,作为自定义指标添加到模型中。
1. 实现自定义边界框IoU指标类
import tensorflow as tf from tensorflow.keras.metrics import Metric class BoundingBoxIoU(Metric): def __init__(self, name='bbox_iou', **kwargs): super().__init__(name=name, **kwargs) # 初始化累计IoU和样本计数 self.total_iou = self.add_weight(name='total_iou', initializer='zeros') self.count = self.add_weight(name='count', initializer='zeros') def update_state(self, y_true, y_pred, sample_weight=None): # 拆分边界框坐标:[x1, y1, x2, y2] true_x1, true_y1, true_x2, true_y2 = tf.split(y_true, 4, axis=-1) pred_x1, pred_y1, pred_x2, pred_y2 = tf.split(y_pred, 4, axis=-1) # 计算交集区域的坐标 inter_x1 = tf.maximum(true_x1, pred_x1) inter_y1 = tf.maximum(true_y1, pred_y1) inter_x2 = tf.minimum(true_x2, pred_x2) inter_y2 = tf.minimum(true_y2, pred_y2) # 计算交集面积(避免负数) inter_area = tf.maximum(0.0, inter_x2 - inter_x1) * tf.maximum(0.0, inter_y2 - inter_y1) # 计算真实框和预测框的面积 true_area = (true_x2 - true_x1) * (true_y2 - true_y1) pred_area = (pred_x2 - pred_x1) * (pred_y2 - pred_y1) # 计算IoU,加1e-7防止除以0 iou = inter_area / (true_area + pred_area - inter_area + 1e-7) # 更新累计值 self.total_iou.assign_add(tf.reduce_sum(iou)) self.count.assign_add(tf.cast(tf.shape(iou)[0], tf.float32)) def result(self): # 返回平均IoU return self.total_iou / self.count def reset_state(self): # 重置指标状态(每个epoch后自动调用) self.total_iou.assign(0.0) self.count.assign(0.0)
2. 修改模型编译代码
因为是多输出模型,需要给每个输出分别指定对应的指标(用嵌套列表):
from tensorflow.keras.metrics import Accuracy # 原有的损失定义不变 classloss = tf.keras.losses.BinaryCrossentropy() regressloss = localization_loss opt = tf.keras.optimizers.Adam(learning_rate=0.0001, decay=0.001) model.compile( optimizer=opt, loss=[classloss, regressloss], # 分类输出用Accuracy,检测输出用自定义的边界框IoU metrics=[[Accuracy()], [BoundingBoxIoU()]] ) hist = model.fit(train, epochs=10, validation_data=valid)
为什么之前的报错会出现
- 使用
metrics=["accuracy", "meaniou"]时,Keras会将"meaniou"绑定到检测输出,但检测输出是连续浮点数,MeanIoU内部需要处理整数类别标签,导致形状解析错误,抛出ValueError: as_list() is not defined on an unknown TensorShape。 - 使用
metrics=[Accuracy(), MeanIoU(2)]时,MeanIoU尝试处理连续坐标输入,内部计算类别相关逻辑时出现NoneType和整数的比较,导致TypeError: '>' not supported between instances of 'NoneType' and 'int'。
内容的提问来源于stack exchange,提问作者Divelix
相关产品推荐
相关产品推荐

