You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Keras中自定义年龄范围准确率指标?

解决年龄范围准确率的自定义评估方法

首先明确:你不能直接修改model.compile()函数本身,但Keras/TensorFlow提供了自定义指标的扩展能力,完全可以实现你要的「预测年龄在指定范围内就算正确」的准确率计算。结合你用的年龄性别估计项目(年龄任务是分类任务,输出0-100岁的类别概率),我给你两种实用的实现方式:

方式一:简单函数式自定义指标

适合快速验证需求,代码简洁直观。我们直接写一个函数,计算真实年龄和预测年龄的差值是否在容忍范围内(比如±2岁):

import tensorflow as tf

def age_range_accuracy(y_true, y_pred, tolerance=2):
    # 从预测概率中取出最可能的年龄类别
    pred_age = tf.argmax(y_pred, axis=1)
    # 计算真实年龄与预测年龄的绝对差
    age_diff = tf.abs(y_true - pred_age)
    # 判断差值是否在容忍范围内,转换为float后计算均值(即准确率)
    is_correct = tf.less_equal(age_diff, tolerance)
    return tf.reduce_mean(tf.cast(is_correct, tf.float32))

然后在模型编译时,把原来的"accuracy"替换成这个自定义函数(可以用lambda指定容忍度):

model.compile(optimizer=opt,
              loss={"age_output": "sparse_categorical_crossentropy",
                    "gender_output": "binary_crossentropy"},
              metrics={"age_output": lambda y_true, y_pred: age_range_accuracy(y_true, y_pred, tolerance=2),
                       "gender_output": "accuracy"})

方式二:继承Metric类的可跟踪指标

如果需要更严谨的累计计算(比如跨batch统计整个epoch的准确率,支持样本权重),推荐用这种方式,它是Keras官方推荐的自定义指标实现方式:

import tensorflow as tf

class AgeRangeAccuracy(tf.keras.metrics.Metric):
    def __init__(self, tolerance=2, name='age_range_accuracy', **kwargs):
        super().__init__(name=name, **kwargs)
        self.tolerance = tolerance
        # 初始化累计变量:总样本数、正确样本数
        self.total_samples = self.add_weight(name='total', initializer='zeros')
        self.correct_samples = self.add_weight(name='correct', initializer='zeros')

    def update_state(self, y_true, y_pred, sample_weight=None):
        # 获取预测的年龄类别
        pred_age = tf.argmax(y_pred, axis=1)
        # 计算年龄差并判断是否正确
        age_diff = tf.abs(y_true - pred_age)
        is_correct = tf.cast(tf.less_equal(age_diff, self.tolerance), tf.float32)

        # 处理样本权重(如果有的话)
        if sample_weight is not None:
            sample_weight = tf.cast(sample_weight, tf.float32)
            is_correct = tf.multiply(is_correct, sample_weight)
            self.total_samples.assign_add(tf.reduce_sum(sample_weight))
        else:
            self.total_samples.assign_add(tf.cast(tf.shape(y_true)[0], tf.float32))
        
        # 累计正确样本数
        self.correct_samples.assign_add(tf.reduce_sum(is_correct))

    def result(self):
        # 返回当前累计的准确率
        return self.correct_samples / self.total_samples

    def reset_state(self):
        # 每个epoch结束后重置累计变量
        self.total_samples.assign(0.0)
        self.correct_samples.assign(0.0)

然后在编译时传入这个类的实例即可:

model.compile(optimizer=opt,
              loss={"age_output": "sparse_categorical_crossentropy",
                    "gender_output": "binary_crossentropy"},
              metrics={"age_output": AgeRangeAccuracy(tolerance=2),
                       "gender_output": "accuracy"})

补充说明

  • 你可以根据需求修改tolerance参数,比如改成3就代表±3岁的范围;
  • 原项目中年龄任务是分类任务(输出0-100的类别概率),所以我们用tf.argmax()获取预测年龄;如果是回归任务(输出连续年龄值),直接比较y_true和y_pred的差值即可,逻辑类似;
  • 这种自定义指标的方式完全符合Keras的设计规范,不会破坏原有项目的训练流程。

内容的提问来源于stack exchange,提问作者Adam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:12:46