我希望在张量板中有一个混淆矩阵的视觉效果.为此,我正在修改Tensorflow Slim的评估示例:https://github.com/tensorflow/models/blob/master/slim/eval_image_classifier.py
在此示例代码中,Accuracy已经提供但是不可能直接添加"confusion matrix"度量标准,因为它不是流式传输.
流媒体指标和非流媒体指标有什么区别?
因此,我试图像这样添加它:
c_matrix = slim.metrics.confusion_matrix(predictions, labels) #These operations needed for image summary c_matrix = tf.cast(c_matrix, uint8) c_matrix = tf.expand_dims(c_matrix, 2) c_matrix = tf.expand_dims(c_matrix, 0) op = tf.image_summary("confusion matrix", c_matrix, collections=[]) tf.add_to_collection(tf.GraphKeys.SUMMARIES, op)
这会在tensorboard中创建一个图像,但可能存在格式问题.矩阵应在0-1之间归一化,以便产生有意义的图像.
我怎样才能产生有意义的混淆矩阵?我该如何处理多批评估过程?
这是我把它放在一起的东西,它运作得相当好.仍然需要调整一些事情,如刻度线位置等.
这个函数几乎可以为你做所有事情.
from textwrap import wrap import re import itertools import tfplot import matplotlib import numpy as np from sklearn.metrics import confusion_matrix def plot_confusion_matrix(correct_labels, predict_labels, labels, title='Confusion matrix', tensor_name = 'MyFigure/image', normalize=False): ''' Parameters: correct_labels : These are your true classification categories. predict_labels : These are you predicted classification categories labels : This is a lit of labels which will be used to display the axix labels title='Confusion matrix' : Title for your matrix tensor_name = 'MyFigure/image' : Name for the output summay tensor Returns: summary: TensorFlow summary Other itema to note: - Depending on the number of category and the data , you may have to modify the figzie, font sizes etc. - Currently, some of the ticks dont line up due to rotations. ''' cm = confusion_matrix(correct_labels, predict_labels, labels=labels) if normalize: cm = cm.astype('float')*10 / cm.sum(axis=1)[:, np.newaxis] cm = np.nan_to_num(cm, copy=True) cm = cm.astype('int') np.set_printoptions(precision=2) ###fig, ax = matplotlib.figure.Figure() fig = matplotlib.figure.Figure(figsize=(7, 7), dpi=320, facecolor='w', edgecolor='k') ax = fig.add_subplot(1, 1, 1) im = ax.imshow(cm, cmap='Oranges') classes = [re.sub(r'([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))', r'\1 ', x) for x in labels] classes = ['\n'.join(wrap(l, 40)) for l in classes] tick_marks = np.arange(len(classes)) ax.set_xlabel('Predicted', fontsize=7) ax.set_xticks(tick_marks) c = ax.set_xticklabels(classes, fontsize=4, rotation=-90, ha='center') ax.xaxis.set_label_position('bottom') ax.xaxis.tick_bottom() ax.set_ylabel('True Label', fontsize=7) ax.set_yticks(tick_marks) ax.set_yticklabels(classes, fontsize=4, va ='center') ax.yaxis.set_label_position('left') ax.yaxis.tick_left() for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])): ax.text(j, i, format(cm[i, j], 'd') if cm[i,j]!=0 else '.', horizontalalignment="center", fontsize=6, verticalalignment='center', color= "black") fig.set_tight_layout(True) summary = tfplot.figure.to_summary(fig, tag=tensor_name) return summary#
以下是您需要调用此函数的其余代码.
''' confusion matrix summaries ''' img_d_summary_dir = os.path.join(checkpoint_dir, "summaries", "img") img_d_summary_writer = tf.summary.FileWriter(img_d_summary_dir, sess.graph) img_d_summary = plot_confusion_matrix(correct_labels, predict_labels, labels, tensor_name='dev/cm') img_d_summary_writer.add_summary(img_d_summary, current_step)
混淆!!!
以下是我为测试代码生成并显示"流式"混淆矩阵的方法(test_op
对每个批次进行评估返回以进行测试).
def _get_streaming_metrics(prediction,label,num_classes): with tf.name_scope("test"): # the streaming accuracy (lookup and update tensors) accuracy,accuracy_update = tf.metrics.accuracy(label, prediction, name='accuracy') # Compute a per-batch confusion batch_confusion = tf.confusion_matrix(label, prediction, num_classes=num_classes, name='batch_confusion') # Create an accumulator variable to hold the counts confusion = tf.Variable( tf.zeros([num_classes,num_classes], 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, tf.float32), [1, num_classes, num_classes, 1]) # Combine streaming accuracy and confusion matrix updates in one op test_op = tf.group(accuracy_update, confusion_update) tf.summary.image('confusion',confusion_image) tf.summary.scalar('accuracy',accuracy) return test_op,accuracy,confusion
通过运行处理所有数据批处理后test_op
,您可以通过confusion.eval()
或者sess.eval(confusion)
根据需要查找最终的混淆矩阵(在您的会话中).
这是适用于tf.contrib.metrics.MetricSpec的东西(当你使用Estimator时).它的灵感来自Jerod的答案和metric_op.py源文件.你得到一个带有百分比的流式混淆矩阵:
from tensorflow.python.framework import ops,dtypes from tensorflow.python.ops import array_ops,variables def _createLocalVariable(name, shape, collections=None, validate_shape=True, dtype=dtypes.float32): """Creates a new local variable. """ # Make sure local variables are added to # tf.GraphKeys.LOCAL_VARIABLES collections = list(collections or []) collections += [ops.GraphKeys.LOCAL_VARIABLES] return variables.Variable( initial_value=array_ops.zeros(shape, dtype=dtype), name=name, trainable=False, collections=collections, validate_shape=validate_shape) def streamingConfusionMatrix(label, prediction, weights=None,num_classes=None): """ Compute a streaming confusion matrix :param label: True labels :param prediction: Predicted labels :param weights: (Optional) weights (unused) :param num_classes: Number of labels for the confusion matrix :return: (percentConfusionMatrix,updateOp) """ # Compute a per-batch confusion batch_confusion = tf.confusion_matrix(label, prediction, num_classes=num_classes, name='batch_confusion') count = _createLocalVariable(None,(),dtype=tf.int32) confusion = _createLocalVariable('streamConfusion',[num_classes, num_classes],dtype=tf.int32) # Create the update op for doing a "+=" accumulation on the batch countUpdate = count.assign(count + tf.reduce_sum(batch_confusion)) confusionUpdate = confusion.assign(confusion + batch_confusion) updateOp = tf.group(confusionUpdate,countUpdate) percentConfusion = 100 * tf.truediv(confusion,count) return percentConfusion,updateOp
然后,您可以通过以下方式将其用作评估指标:
from tensorflow.contrib import learn,metrics #[...] evalMetrics = {'accuracy': learn.MetricSpec(metric_fn=metrics.streaming_accuracy), 'confusionMatrix':learn.MetricSpec(metric_fn= lambda label,prediction,weights=None: streamingConfusionMatrix( label,prediction,weights,num_classes=nLabels))}
我建议你使用numpy.set_printoptions(precision = 2,suppress = True)将其打印出来.