복붙노트

[PYTHON] TensorBoard의 Tensorflow 혼란 매트릭스

PYTHON

TensorBoard의 Tensorflow 혼란 매트릭스

나는 tensorboard에 혼란 행렬의 시각을 갖고 싶습니다. 이를 위해 Tensorflow Slim의 평가 예를 수정하려고합니다. https://github.com/tensorflow/models/blob/master/slim/eval_image_classifier.py

이 예제 코드에서는 Accuracy가 이미 제공되었지만 스트리밍 중이 지 않아서 "혼동 행렬"메트릭을 직접 추가 할 수는 없습니다.

스트리밍 통계와 비 스트리밍 통계의 차이점은 무엇입니까?

따라서 다음과 같이 추가하려고했습니다.

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 사이에서 정규화되어야합니다.

의미있는 혼란 행렬을 어떻게 만들 수 있습니까? 다중 배치 평가 프로세스는 어떻게 처리합니까?

해결법

  1. ==============================

    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)
    

    혼란스러워 !!!

  2. ==============================

    2.다음은 테스트 코드에 대한 "스트리밍"혼용 행렬을 생성하고 표시하는 방법입니다 (반환 된 test_op는 테스트 할 각 배치에 대해 평가됩니다).

    다음은 테스트 코드에 대한 "스트리밍"혼용 행렬을 생성하고 표시하는 방법입니다 (반환 된 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 (혼동)을 사용하여 최종 혼란 행렬을 조회 할 수 있습니다.

  3. ==============================

    3.여기 tf.contrib.metrics.MetricSpec (Estimator를 사용할 때)과 함께 작동하는 무언가가 있습니다. Jerod의 대답과 metric_op.py 소스 파일에서 영감을 얻었습니다. 비율로 스트리밍 된 혼란 행렬을 얻습니다.

    여기 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)를 사용하여 인쇄하는 것이 좋습니다.

  4. ==============================

    4.다시 : 귀하의 이미지가 의미가없는 - tf.summary.image에 대한 문서에 따르면 uint8 값은 변경되지 않으며 (정규화되지 않음) 범위 [0, 255]로 해석됩니다. [0,1] 대신 [0,255]로 이미지를 다시 정규화 해 보셨습니까?

    다시 : 귀하의 이미지가 의미가없는 - tf.summary.image에 대한 문서에 따르면 uint8 값은 변경되지 않으며 (정규화되지 않음) 범위 [0, 255]로 해석됩니다. [0,1] 대신 [0,255]로 이미지를 다시 정규화 해 보셨습니까?

  5. from https://stackoverflow.com/questions/41617463/tensorflow-confusion-matrix-in-tensorboard by cc-by-sa and MIT license