早停机制忽略了我定义的自定义指标。Keras模型。

4

我正在尝试使用Keras模型对信用卡欺诈进行分类。由于数据集不平衡,我需要使用f1_score来提高召回率。

显然,它不接受f1函数定义。如何在每个时期监控我的新指标?如果使用val_loss,早停止可以正常工作,但是对于定义的指标则不行。我收到以下消息:

Train on 139554 samples, validate on 59810 samples
Epoch 1/10

7s - loss: 0.3585 - acc: 0.9887 - val_loss: 0.0560 - val_acc: 0.9989
/home/libardo/anaconda3/lib/python3.6/site-packages/keras/callbacks.py:526: RuntimeWarning: Early stopping conditioned on metric f1s which is not available. Available metrics are: val_loss,val_acc,loss,acc
(self.monitor, ','.join(list(logs.keys()))), RuntimeWarning

EarlyStopping无视我定义的自定义度量#10018

备注:很抱歉,我无法在此处粘贴我的代码。

1个回答

5

我知道这篇文章已经发表很久了,但是当我搜索相同的答案时,我找到了这个问题并最终自己解决了它。 简而言之,您需要记住在定义EarlyStopping回调的度量时,同时将其作为编译模型的度量

好的,所以你已经使用类似于以下内容的代码定义了自定义损失函数或指标(取自https://github.com/keras-team/keras/issues/10018,该代码本身取自https://dev59.com/41cP5IYBdhLWcg3w-Opz#45305384):

#https://dev59.com/41cP5IYBdhLWcg3w-Opz#45305384
def f1_metric(y_true, y_pred):

    def recall(y_true, y_pred):
        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
        possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
        recall = (true_positives + K.epsilon()) / (possible_positives + K.epsilon())
        return recall

    def precision(y_true, y_pred):
        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
        predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
        precision = (true_positives + K.epsilon()) / (predicted_positives + K.epsilon())
        return precision

    precision = precision(y_true, y_pred)
    recall = recall(y_true, y_pred)
    return 2*((precision*recall)/(precision+recall+K.epsilon()))

现在,您可以将其作为一个字符串提供给EarlyStopping Callback使用,例如EarlyStopping(monitor='f1_metric'),或者,如果要针对验证进行监控,则使用EarlyStopping(monitor='val_f1_metric')

但这还不够!如果你停在那里,你会得到你得到的错误。当你使用model.compile(metrics=[f1_metric])编译你的模型时,你需要同时提供实际的函数作为参数。请注意缺少引号 - 你正在引用函数本身。

如果你通过使用metrics关键字包含该函数来编译模型,并且还包括EarlyStopping Callback,那么它应该可以干净地工作。


嗨Matt,将ε添加到召回率和精度的分子中是否更有意义?想象一下没有相关文档的批次:一个完美的系统会预测没有文档(在我看来是正确的答案),但它被惩罚为召回率为0 / ε = 0,而不是更合适的得分为ε / ε = 1。对于精度也是同样的道理:没有预测文档=没有虚假文档=完美的精度。 - lenz
啊!是的,它会。我只是从原帖中复制了代码,但这绝对是一种改进。当没有预测和0个案例时,应该像你建议的那样是ε/ε=1。我已经编辑了我的答案。 - Matt
嘿,与此同时,我想出了为什么通常要这样做的原因。F-score的问题在于,如果您在整个数据集上计算它或者从每个批次的F-score平均值中计算(微观vs.宏观平均值,但批次不是有意义的单位),则会得到不同的结果。使用0/ε会导致低估,而ε/ε倾向于高估全局计算的F-score。无论哪种方式,都是一个粗略的近似。 - lenz
这并没有解决我的问题。模型使用上述自定义指标进行编译,并在训练时显示,但是一旦到达了停止训练的轮数(耐心值+1),早期停止机制就会崩溃。您有其他想法吗? - Mike_K
@Mike_K很不幸,我可能必须看到错误和相关代码才能确定。 我的直觉是,它试图在那一点停止训练,并导致某些故障。 如果这是原因,则可能存在多个问题:
  1. 它似乎在“耐心”时期从未有所改善(此时不应该有所改善吗?)2. 它不能正确停止。
- Matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接