在Tensorflow中为Tensorboard的混淆矩阵添加文本标签

我正在自定义Tensorflow的示例代码retrain.py,通过添加额外的密集层、dropout、动量梯度下降等方法来训练我自己的图像数据。

我想在Tensorboard中添加一个混淆矩阵,所以我按照这个帖子中的第一个答案(Jerod的回答)进行操作(我也尝试了第二个答案,但遇到了一些调试问题),并在add_evaluation_step函数中添加了几行代码。现在它看起来像这样:

def add_evaluation_step(result_tensor, ground_truth_tensor):  with tf.name_scope('accuracy'):    with tf.name_scope('correct_prediction'):      prediction = tf.argmax(result_tensor, 1)      correct_prediction = tf.equal(          prediction, tf.argmax(ground_truth_tensor, 1))    with tf.name_scope('accuracy'):      evaluation_step = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))  tf.summary.scalar('accuracy', evaluation_step)  print('prediction shape :: {}'.format(ground_truth_tensor))  #Add confusion matrix  batch_confusion = tf.confusion_matrix(tf.argmax(ground_truth_tensor, 1), prediction,                                             num_classes=7,                                             name='batch_confusion')  # Create an accumulator variable to hold the counts  confusion = tf.Variable( tf.zeros([7,7],                                           dtype=tf.int32 ),                                 name='confusion' )  # Create the update op for doing a "+=" accumulation on the batch  confusion_update = confusion.assign( confusion + batch_confusion )  # Cast counts to float so tf.summary.image renormalizes to [0,255]  confusion_image = tf.reshape( tf.cast( confusion_update, tf.float32),                                 [1, 7, 7, 1])  tf.summary.image('confusion',confusion_image)  return evaluation_step, prediction

这让我得到了:混淆矩阵

我的问题是如何在行(实际类别)和列(预测类别)上添加标签,以获得类似于下面的结果:

所需的混淆矩阵


回答:

Jerod的回答几乎包含了你需要的所有内容,另外例如yauheni_selivonchyk的另一个回答展示了如何向Tensorboard添加自定义图像。

然后只需将所有内容整合在一起,即:

  1. 实现将绘制的图像传递给摘要的方法(作为RGB数组)
  2. 实现将矩阵数据转换为美化的混淆图像的方法
  3. 定义你的运行评估操作以获取混淆矩阵数据(以及其他指标),并准备一个占位符和摘要来接收绘制的图像
  4. 将所有内容结合使用

1. 实现将绘制的图像传递给摘要的方法

import matplotlibimport matplotlib.pyplot as pltimport pandas as pdimport seaborn as snsimport numpy as npimport tensorflow as tf# Inspired by yauheni_selivonchyk on SO (https://stackoverflow.com/a/42815564/624547)def get_figure(figsize=(10, 10), dpi=300):    """    返回一个pyplot图形    :param figsize:    :param dpi:    :return:    """    fig = plt.figure(num=0, figsize=figsize, dpi=dpi)    fig.clf()    return figdef fig_to_rgb_array(fig, expand=True):    """    将图形转换为RGB数组    :param fig:         PyPlot图形    :param expand:      是否扩展标志    :return:            RGB数组    """    fig.canvas.draw()    buf = fig.canvas.tostring_rgb()    ncols, nrows = fig.canvas.get_width_height()    shape = (nrows, ncols, 3) if not expand else (1, nrows, ncols, 3)    return np.fromstring(buf, dtype=np.uint8).reshape(shape)def figure_to_summary(fig, summary, place_holder):    """    将图形转换为TF摘要    :param fig:             图形    :param summary:         要评估的摘要    :param place_holder:    摘要图像占位符    :return:                摘要    """    image = fig_to_rgb_array(fig)    return summary.eval(feed_dict={place_holder: image})

2. 将矩阵数据转换为美化的混淆图像

(这里是一个示例,但具体取决于你的需求)

def confusion_matrix_to_image_summary(confusion_matrix, summary, place_holder,                                       list_classes, figsize=(9, 9)):    """    绘制混淆矩阵并返回为TF摘要    :param matrix:          混淆矩阵(N x N)    :param filename:        文件名    :param list_classes:    类别列表(N)    :param figsize:         Pyplot图形大小    :return:                /    """    fig = get_figure(figsize=(9, 9))    df = pd.DataFrame(confusion_matrix, index=list_classes, columns=list_classes)    ax = sns.heatmap(df, annot=True, fmt='.0%')    # 你想要的任何装饰:    plt.title('混淆矩阵')    plt.xticks(rotation=90)    plt.yticks(rotation=0)    image_sum = figure_to_summary(fig, summary, place_holder)    return image_sum

3. 定义你的评估操作和准备占位符

# Inspired by Jerod's answer on SO (https://stackoverflow.com/a/42857070/624547)    def add_evaluation_step(result_tensor, ground_truth_tensor, num_classes, confusion_matrix_figsize=(9, 9)):    """    设置评估操作,计算运行准确率和混淆图像    :param result_tensor:               输出张量    :param ground_truth_tensor:         目标类别张量    :param num_classes:                 类别数量    :param confusion_matrix_figsize:    混淆图像的Pyplot图形大小    :return:                            TF操作、摘要和占位符(见下面的使用)    """    scope = "evaluation"    with tf.name_scope(scope):        predictions = tf.argmax(result_tensor, 1, name="prediction")        # 流式准确率(查找和更新张量):        accuracy, accuracy_update = tf.metrics.accuracy(ground_truth_tensor, predictions, name='accuracy')        # 每批次的混淆矩阵:        batch_confusion = tf.confusion_matrix(ground_truth_tensor, predictions, num_classes=num_classes,                                              name='batch_confusion')        # 聚合混淆矩阵:        confusion_matrix = tf.Variable(tf.zeros([num_classes, num_classes], dtype=tf.int32),                                       name='confusion')        confusion_update = confusion_matrix.assign(confusion_matrix + batch_confusion)        # 我们假设每个批次包含一个完整的类别,直接按其大小进行归一化:        evaluate_streaming_metrics_op = tf.group(accuracy_update, confusion_update)        # 从矩阵生成混淆图像(需要扩展维度并转换为float,以便tf.summary.image重新归一化为[0,255]):        confusion_image = tf.reshape(tf.cast(confusion_update, tf.float32), [1, num_classes, num_classes, 1])        # 摘要:        tf.summary.scalar('accuracy', accuracy, collections=[scope])        summary_op = tf.summary.merge_all(scope)        # 为混淆图像准备占位符(以便我们可以将绘制的图像传递给它):        #      (我们基本上预分配一个绘图图形,并将其RGB数组传递给占位符)        confusion_image_placeholder = tf.placeholder(tf.uint8,                                                     fig_to_rgb_array(get_figure(figsize=confusion_matrix_figsize)).shape)        confusion_image_summary = tf.summary.image('confusion_image', confusion_image_placeholder)    # 隔离度量操作存储的所有变量:    running_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope=scope)    running_vars += tf.get_collection(tf.GraphKeys.LOCAL_VARIABLES, scope=scope)    # 初始化操作以启动/重置运行变量    reset_streaming_metrics_op = tf.variables_initializer(var_list=running_vars)    return evaluate_streaming_metrics_op, reset_streaming_metrics_op, summary_op, confusion_image_summary, \           confusion_image_placeholder, confusion_image

4. 将所有内容整合在一起

一个快速示例,展示如何使用这些内容,尽管需要根据你的训练过程等进行调整。

classes = ["obj1", "obj2", "obj3"]num_classes = len(classes)model = your_network(...)evaluate_streaming_metrics_op, reset_streaming_metrics_op, summary_op,confusion_image_summary,  confusion_image_placeholder, confusion_image = \add_evaluation_step(model.output, model.target, num_classes)def evaluate(session, model, eval_data_gen):    """    评估模型    :param session:         TF会话    :param eval_data_gen:   用于评估的数据    :return:                Tensorboard的评估摘要    """    # 重置流式变量:    session.run(reset_streaming_metrics_op)    # 在完整的评估数据集上评估运行操作,例如:    for batch in eval_data_gen:        feed_dict = {model.inputs: batch}        session.run(evaluate_streaming_metrics_op, feed_dict=feed_dict)    # 获取最终结果:    summary_str, confusion_results = session.run([summary_op, confusion_image])    # 将混淆数据转换为绘图并生成摘要:    confusion_img_str = confusion_matrix_to_image_summary(        confusion_results[0,:,:,0], confusion_image_summary, confusion_image_placeholder, classes)    summary_str += confusion_img_str    return summary_str # 传递给SummaryWriter

Related Posts

Keras Dense层输入未被展平

这是我的测试代码: from keras import…

无法将分类变量输入随机森林

我有10个分类变量和3个数值变量。我在分割后直接将它们…

如何在Keras中对每个输出应用Sigmoid函数?

这是我代码的一部分。 model = Sequenti…

如何选择类概率的最佳阈值?

我的神经网络输出是一个用于多标签分类的预测类概率表: …

在Keras中使用深度学习得到不同的结果

我按照一个教程使用Keras中的深度神经网络进行文本分…

‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

我写了一个简单的TensorFlow代码,但不断遇到T…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注