Python 如何在Tensorflow 2.0中获得其他指标(不仅仅是准确性)?

Python 如何在Tensorflow 2.0中获得其他指标(不仅仅是准确性)?,python,tensorflow,machine-learning,keras,tensorflow2.x,Python,Tensorflow,Machine Learning,Keras,Tensorflow2.x,我是Tensorflow领域的新手,正在研究mnist数据集分类的简单示例。我想知道,除了准确度和损失(并可能显示)之外,我如何获得其他指标(例如精度、召回率等)。这是我的密码: from __future__ import absolute_import, division, print_function, unicode_literals import tensorflow as tf from tensorflow.keras.callbacks import ModelCheckpoin

我是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)
既然我只得到准确度和损失,我怎么能得到其他指标?
提前感谢您,如果这是一个简单的问题,或者已经在某个地方得到了回答,我很抱歉。

文档中有可用指标的列表。它包括
召回
精度

例如:


从TensorFlow 2.X开始,
precision
recall
都是内置的度量标准

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

您可以在这里查看:

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

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

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


我无法得到Timbus的工作答案,我发现了一个非常有趣的解释

它说:
准确度的含义取决于损失函数。与稀疏分类交叉熵相对应的是tf.keras.metrics.SparseCategoricalAccuracy(),而不是tf.metrics.accurity()。
这很有道理

因此,您可以使用什么标准取决于您选择的损失。例如,在SparseCategoricalAccuracy的情况下,使用度量“真正数”不起作用,因为这种损失意味着您使用的是多个类,这反过来意味着不能定义真正数,因为它仅用于二进制分类问题

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)

在我的例子中,其他两个答案给了我形状不匹配的问题。

我添加了另一个答案,因为这是在测试集上正确计算这些度量的最干净的方法(截至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中,加载数据集并添加回调:
您提供的链接指向Keras文档,这与TensorFlow中的Keras文档不同。此外,实现它们的一个例子清楚地表明,它们更多的是误导,而不是帮助。为其他内置指标创建自定义的
回调对我来说没有任何意义。我想这应该是公认的答案。谢谢你的帮助,它起作用了!我尝试了其他人的评论,但我得到了一个错误,因为我的不是一个二进制分类问题,因为我有10个类,因此我在精确度和召回率方面得到了一个错误。是否有机会计算它们?感谢you@Diane.95今天工作日结束后,我会带着一个好的答案回来。@Victor Sonck顺便说一句,如果你想查看的话,我上面的答案现在适用于multiclass(简短的提醒,因为我不知道你的线程在哪里):谢谢!在这种情况下,我的问题不是二进制分类,因为我有10个类,所以我得到一个错误。是否有一种方法可以计算多类问题的精确度/召回率或其他有用指标?感谢you@Diane.95今天,在工作日结束后,我会回来给你一个答案。这不起作用,因为你不能用稀疏分类交叉熵计算精度和召回率,因为(我认为)它们是为二进制分类问题设计的。谢谢你的时间和答案!我检查了代码,创建了对象metrics\u callback=MetricsCallback(test\u data=x\u train,y\u true=y\u train)。但是,当我拟合模型时,我得到一个错误:“report\u dictionary=classification\u report(y\u true,y\u pred,output\u dict=true)”上的“name'y\u true'未定义”,即使我正在传递参数:(我们忘了通过“self”。:D.所以应该是self.y_-True谢谢Timbus!这非常有帮助,你是最棒的。很高兴看到你解决了你的问题。既然你接受了答案,请你也投票好吗?谢谢你,很高兴帮助了你。@TimbusCalin,我正在尝试使用metrics_回调作为我的用例,但当我尝试model.fit时我收到“名称错误:名称‘分类报告’未定义”。请帮助我。
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)
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)              
           
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)