tensorflow - tensorflow 中的自定义 f1_score 指标

标签 tensorflow machine-learning keras metrics

我想为 tf.keras 实现 f1_score 指标。

from tensorflow.keras.models import Model, Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.losses import binary_crossentropy
from tensorflow.keras.metrics import Accuracy, BinaryAccuracy
from sklearn.metrics import accuracy_score
import numpy as np
import tensorflow as tf

class F1_Score(tf.keras.metrics.Metric):

    def __init__(self, name='f1_score', **kwargs):
        super().__init__(name=name, **kwargs)
        self.f1 = self.add_weight(name='f1', initializer='zeros')

    def update_state(self, y_true, y_pred, sample_weight=None):
        p = Precision(thresholds=0.5)(y_true, y_pred)
        r = Recall(thresholds=0.5)(y_true, y_pred)
        self.f1 = 2 * ((p * r) / (p + r + 1e-6))

    def result(self):
        return self.f1

    def reset_states(self):
        self.f1.assign(0)
        
model = Sequential([
  Dense(64, activation='relu', input_shape=(784,)),
  Dense(64, activation='relu'),
  Dense(4, activation='sigmoid'),
])
x = np.random.normal(size=(10, 784))
y = np.random.choice(2, size=(10, 4))
model.compile(optimizer=Adam(0.001), loss='binary_crossentropy',
                  metrics=['accuracy', , F1_Score()])
model.fit(x[:1], y[:1], batch_size=1, epochs=1, verbose=1)
我有一个错误:

ValueError: tf.function-decorated function tried to create variables on non-first call.

最佳答案

你得到这个错误是因为你想实例化一些 tf.Variable s 在 update_state 函数期间。从 Precision 和 Recall 类实例化对象时,您正在创建一些 tf.Variable s。
在构造函数中实例化对象,并在 update_state 函数中调用它们:

class F1_Score(tf.keras.metrics.Metric):

    def __init__(self, name='f1_score', **kwargs):
        super().__init__(name=name, **kwargs)
        self.f1 = self.add_weight(name='f1', initializer='zeros')
        self.precision_fn = Precision(thresholds=0.5)
        self.recall_fn = Recall(thresholds=0.5)

    def update_state(self, y_true, y_pred, sample_weight=None):
        p = self.precision_fn(y_true, y_pred)
        r = self.recall_fn(y_true, y_pred)
        # since f1 is a variable, we use assign
        self.f1.assign(2 * ((p * r) / (p + r + 1e-6)))

    def result(self):
        return self.f1

    def reset_states(self):
        # we also need to reset the state of the precision and recall objects
        self.precision_fn.reset_states()
        self.recall_fn.reset_states()
        self.f1.assign(0)

行为说明:
Tensorflow 允许仅在 tf.function 的第一次调用时创建变量,见 documentation :

tf.function only allows creating new tf.Variable objects when it is called for the first time


Keras 指标包含在 tf.function 中以允许与 tensorflow v1 兼容。您可以在 code 中找到此评论

If update_state is not in eager/tf.function and it is not from a built-in metric, wrap it in tf.function. This is so that users writing custom metrics in v1 need not worry about control dependencies and return ops.


您的类(class)中还有另一个错误,就是您覆盖了 f1 tf.Variable您通过计算 f1 分数创建的。要更新变量的值,您需要使用 assign .我们一定不要忘记重置正在使用的 Precision 和 Recall Metrics 对象的状态!

关于tensorflow - tensorflow 中的自定义 f1_score 指标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64474463/

相关文章:

python - 在 Keras 层中重置权重

python - Keras model.fit() 与 tf.dataset 失败,而使用 tf.train 工作正常

python - tensorflow 多项式数组

python - Tensorflow 2.0 拥抱人脸变压器、TFBertForSequenceClassification、推理中意外的输出维度

python - 如何在numpy中实现两层Keras conv1d?

python - 如何将图像数据从存储桶加载到AWS sagemaker笔记本?

algorithm - 找到属于具有最大值的区域的最大值如何近似该区域的边界?

python - Tensorflow,喂养 Estimator.fit(batch)

machine-learning - 如何训练人工神经网络使用视觉输入玩《暗黑破坏神 2》?

tensorflow - keras.layers.InputLayer 和 keras.Input 之间的区别