【问题标题】:How to get other metrics in Tensorflow 2.0 (not only accuracy)?如何在 Tensorflow 2.0 中获取其他指标(不仅是准确性)?
【发布时间】:2020-06-22 07:18:22
【问题描述】:

我是 Tensorflow 领域的新手,我正在研究 mnist 数据集分类的简单示例。我想知道除了准确性和损失(并可能显示它们)之外,我如何获得其他指标(例如精度、召回率等)。这是我的代码:

from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
from tensorflow.keras.callbacks import ModelCheckpoint
from tensorflow.keras.callbacks import TensorBoard
import os 

#load mnist dataset
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()

#create and compile the model
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)), 
  tf.keras.layers.Dense(128, activation='relu'), 
  tf.keras.layers.Dropout(0.2), 
  tf.keras.layers.Dense(10, activation='softmax') 
])
model.summary()

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

#model checkpoint (only if there is an improvement)

checkpoint_path = "logs/weights-improvement-{epoch:02d}-{accuracy:.2f}.hdf5"

cp_callback = ModelCheckpoint(checkpoint_path, monitor='accuracy',save_best_only=True,verbose=1, mode='max')

#Tensorboard
NAME = "tensorboard_{}".format(int(time.time())) #name of the model with timestamp
tensorboard = TensorBoard(log_dir="logs/{}".format(NAME))

#train the model
model.fit(x_train, y_train, callbacks = [cp_callback, tensorboard], epochs=5)

#evaluate the model
model.evaluate(x_test,  y_test, verbose=2)

既然我只得到准确率和损失,我怎样才能得到其他指标? 提前谢谢你,如果这是一个简单的问题,或者如果已经在某个地方得到回答,我很抱歉。

【问题讨论】:

    标签: python tensorflow machine-learning keras tensorflow2.x


    【解决方案1】:

    我正在添加另一个答案,因为这是在您的测试集上正确计算这些指标的最简洁方法(截至 2020 年 3 月 22 日)。

    您需要做的第一件事是创建一个自定义回调,您可以在其中发送测试数据:

    import tensorflow as tf
    from tensorflow.keras.callbacks import Callback
    from sklearn.metrics import classification_report 
    
    class MetricsCallback(Callback):
        def __init__(self, test_data, y_true):
            # Should be the label encoding of your classes
            self.y_true = y_true
            self.test_data = test_data
            
        def on_epoch_end(self, epoch, logs=None):
            # Here we get the probabilities
            y_pred = self.model.predict(self.test_data))
            # Here we get the actual classes
            y_pred = tf.argmax(y_pred,axis=1)
            # Actual dictionary
            report_dictionary = classification_report(self.y_true, y_pred, output_dict = True)
            # Only printing the report
            print(classification_report(self.y_true,y_pred,output_dict=False)              
               
    

    在您的 main 中,您可以在其中加载数据集并添加回调:

    metrics_callback = MetricsCallback(test_data = my_test_data, y_true = my_y_true)
    ...
    ...
    #train the model
    model.fit(x_train, y_train, callbacks = [cp_callback, metrics_callback,tensorboard], epochs=5)
    
             
    

    【讨论】:

    • 感谢您的宝贵时间和回答!我检查了代码,并创建了对象 metrics_callback = MetricsCallback(test_data=x_train, y_true=y_train)。但是,当我拟合模型时,即使我传递了参数,我也会收到错误:“report_dictionary = classification_report(y_true, y_pred, output_dict=True)”上的“name 'y_true' is not defined”:(
    • 我们忘记传递“自我”。 :D。所以应该是 self.y_true
    • 谢谢 Timbus!很有帮助,你是最棒的。
    • 很高兴看到您解决了您的问题。既然您接受了答案,您能否也请投票?谢谢你,很高兴能帮助你。
    • @TimbusCalin,我正在尝试将 metrics_callback 用于我的用例,但是当我尝试 model.fit 时,我收到“NameError:name 'classification_report' is not defined”。请帮帮我。
    【解决方案2】:

    Keras 文档中有可用指标的列表。包括recallprecision等。

    例如,recall:

    model.compile('adam', loss='binary_crossentropy', 
        metrics=[tf.keras.metrics.Recall()])
    

    【讨论】:

    • 您提供的链接指向 Keras 文档,这与 TensorFlow 中的 Keras 文档不同。此外,实施它们的人清楚地表明它们更具误导性而不是有用。
    • 为其他内置指标创建自定义 callback 对我来说没有任何意义。我认为这应该是公认的答案。
    【解决方案3】:

    从 TensorFlow 2.X 开始,precisionrecall 都可以作为内置指标使用。

    因此,您无需手动实现它们。除此之外,它们之前在 Keras 2.X 版本中被删除,因为它们具有误导性——因为它们是以批量方式计算的,精度和召回率的全局(真实)值实际上是不同的。

    你可以看这里:https://www.tensorflow.org/api_docs/python/tf/keras/metrics/Recall

    现在他们有一个内置的累加器,可以确保正确计算这些指标。

    model.compile(optimizer='adam',
                  loss='binary_crossentropy',
                  metrics=['accuracy',tf.keras.metrics.Precision(),tf.keras.metrics.Recall()])
    

    【讨论】:

    • 谢谢!在这种情况下,我的问题不是二进制分类,因为我有 10 个类,因此出现错误。有没有办法为多类问题计算精度/召回率或其他有用的指标?谢谢
    • @Diane.95 我今天会在工作日结束后回来回答。
    【解决方案4】:

    我无法得到 Timbus 的答案,我找到了一个非常有趣的解释 here

    它说: The meaning of 'accuracy' depends on the loss function. The one that corresponds to sparse_categorical_crossentropy is tf.keras.metrics.SparseCategoricalAccuracy(), not tf.metrics.Accuracy(). 这很有意义。

    因此,您可以使用哪些指标取决于您选择的损失。例如。在 SparseCategoricalAccuracy 的情况下,使用度量“TruePositives”将不起作用,因为这种损失意味着您正在使用超过 1 个类,这反过来意味着无法定义 True Positives,因为它仅用于二进制分类问题。

    tf.keras.metrics.CategoricalCrossentropy() 这样的损失会起作用,因为它的设计考虑了多个类!示例:

    from __future__ import absolute_import, division, print_function, unicode_literals
    import tensorflow as tf
    from tensorflow.keras.callbacks import ModelCheckpoint
    from tensorflow.keras.callbacks import TensorBoard
    import time
    import os 
    
    #load mnist dataset
    mnist = tf.keras.datasets.mnist
    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    
    #create and compile the model
    model = tf.keras.models.Sequential([
      tf.keras.layers.Flatten(input_shape=(28, 28)), 
      tf.keras.layers.Dense(128, activation='relu'), 
      tf.keras.layers.Dropout(0.2), 
      tf.keras.layers.Dense(10, activation='softmax') 
    ])
    model.summary()
    
    # This will work because it makes sense
    model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=[tf.keras.metrics.SparseCategoricalAccuracy(),
                           tf.keras.metrics.CategoricalCrossentropy()])
    
    # This will not work because it isn't designed for the multiclass classification problem
    model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=[tf.keras.metrics.SparseCategoricalAccuracy(),
                           tf.keras.metrics.TruePositives()])
    
    #model checkpoint (only if there is an improvement)
    
    checkpoint_path = "logs/weights-improvement-{epoch:02d}-{accuracy:.2f}.hdf5"
    
    cp_callback = ModelCheckpoint(checkpoint_path,
                                  monitor='accuracy',
                                  save_best_only=True,
                                  verbose=1,
                                  mode='max')
    
    #Tensorboard
    NAME = "tensorboard_{}".format(int(time.time())) # name of the model with timestamp
    tensorboard = TensorBoard(log_dir="logs/{}".format(NAME))
    
    #train the model
    model.fit(x_train, y_train, epochs=5)
    
    #evaluate the model
    model.evaluate(x_test,  y_test, verbose=2)
    

    在我的情况下,其他 2 个答案给了我形状不匹配的问题。

    【讨论】:

    • 感谢您的帮助,它正在工作!我尝试了其他人的 cmets,但我得到了一个错误,因为我的不是二元分类问题,因为我有 10 个类,因此我得到了精度和召回错误。有机会计算它们吗?谢谢
    • @Diane.95 今天工作日结束后我会回来给你一个好的答案。
    • @Victor Sonck btw 我上面的答案现在适用于多类,如果你想检查它(简短提醒,因为我不知道你在哪里使用线程):D
    【解决方案5】:

    有关支持的指标列表,请参阅:

    tf.keras Metrics

    model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy',tf.keras.metrics.Precision(),tf.keras.metrics.Recall()])
    

    【讨论】:

    • 这行不通,因为您无法使用 sparse_categorical_crossentropy 计算精度和召回率,因为(我认为)它们是为二进制分类问题而设计的。
    猜你喜欢
    • 2021-01-06
    • 2021-08-02
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-24
    • 1970-01-01
    相关资源
    最近更新 更多