【问题标题】:How to get precision for class 0 in tensorflow?如何在张量流中获得 0 类的精度?
【发布时间】:2023-03-28 10:34:02
【问题描述】:

有没有办法使用tf.keras.metrics.Precision 获得二元分类模型中 0 类的精度?

我尝试将 class_id 设置为 0,但它仍然提供 1 类的精度。

我想使用回调来保存具有最佳 0 类精度值的模型,这就是我需要一个编译精度指标的原因。

我使用tf.keras.preprocessing.image_dataset_from_directory 创建我的数据集,训练/验证/测试集的代码看起来相同(当然训练和验证集是混洗的):

ds_test = tf.keras.preprocessing.image_dataset_from_directory(
        directory = test_path,
        batch_size = my_batch_size,
        image_size = (img_height, img_width),
        shuffle = False
    )

在compile方法中添加精度度量:

model.compile(loss = tf.keras.losses.BinaryCrossentropy(),
              optimizer = tf.keras.optimizers.Adam(...),
              metrics = ["accuracy",
                         tf.keras.metrics.Precision(class_id = 0, name = "precision_0")
                        ]
              )

使用 tensorflow model.evaluate 评估模型时,我得到的是 1 类而不是 0 类的精度:

   precision_0: 0.9556

使用 sklearn.metrics.classification_report 我得到了两个类的精度:

           precision
       0     0.9723
       1     0.9556

我也想获得 tensorflow 中 0 类的精度,在本例中为 0.9723。有任何想法吗? 提前致谢!

【问题讨论】:

    标签: python tensorflow keras classification


    【解决方案1】:

    您可以为此编写自定义指标。如果您使用的是sigmoid 激活,那么作为预测结果,您将得到 概率 为 1 类。

    一旦你继承tf.keras.metrics.Metric,你就可以改变它:

    class my_precision_class_0(tf.keras.metrics.Metric):
        def __init__(self, name='my_precision_class_0', **kwargs):
            super(my_precision_class_0, self).__init__(name=name, **kwargs)
            self.true_positives = self.add_weight(name='tp', initializer='zeros')
            self.false_positives = self.add_weight(name='fp', initializer='zeros')
    
        def update_state(self, y_true, y_pred, sample_weight=None):
            # Get corresponding labels
            y_true_cls = tf.cast(tf.equal(y_true[:, 0], 0), tf.int64)
            # Get the prediction for the class 0.
            y_pred_cls = tf.cast(tf.less_equal(y_pred[:, 0], 0.5), tf.int64)
    
            true_positives = tf.math.count_nonzero(y_true_cls * y_pred_cls)
            false_positives = tf.math.count_nonzero(y_pred_cls * (1 - y_true_cls))
    
            self.true_positives.assign_add(tf.cast(true_positives, tf.float32))
            self.false_positives.assign_add(tf.cast(false_positives, tf.float32))
    
        def result(self):
            return self.true_positives / (self.true_positives + self.false_positives)
    
        def reset_states(self):
            self.true_positives.assign(0)
            self.false_positives.assign(0)
    

    当使用tf.less_equal 时,y_pred_cls 会发生以下情况,同样的情况也适用于y_true_cls

    x = tf.constant([0.4, 4.0, 6.0])
    y = tf.constant([0.5])
    r = tf.math.less_equal(x, y) # --> [True, False, False]
    tf.cast(r, tf.int64) # --> [1, 0, 0]
    

    我们可以在编译时使用这个指标:

    model = tf.keras.Sequential([
        tf.keras.layers.Dense(10, activation='relu'),
        tf.keras.layers.Dense(1, activation='sigmoid')
    ])
    
    model.compile(optimizer='adam', loss='binary_crossentropy', 
                  metrics=['accuracy', my_precision_class_0(),                                                
                           tf.keras.metrics.Precision()])
    
    model.fit(X, y, epochs=16)
    model.evaluate(X, y, batch_size = 1)
    # --> loss: 0.3370 - accuracy: 0.8790 - my_precision_class_0: 0.8983 - precision: 0.8617
    
    from sklearn.metrics import classification_report
    
    y_hat = (model.predict(X) > 0.5).astype(int)
    print(classification_report(y, y_hat, digits=4))
    
                  precision    recall  f1-score   support
               0     0.8983    0.8531    0.8751       497
               1     0.8617    0.9046    0.8826       503
        accuracy                         0.8790      1000
       macro avg     0.8800    0.8788    0.8789      1000
    weighted avg     0.8799    0.8790    0.8789      1000
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多