import tensorflow as tf
class MultiLabelConfusionMatrix(object):
"""
Attention Please:
y_true and y_pred are must to be two-dimensional matrix,
and their shape are [batch_size, time_steps].
"""
def __init__(self, classes_num, pad_type='pre'):
self.classes_num = classes_num
self.pad_type = pad_type
self.select_matrix = tf.expand_dims(
tf.expand_dims(
tf.one_hot([i for i in range(self.classes_num)], self.classes_num)
, 1)
, 1)
#
self.true_positives = tf.zeros(shape=self.classes_num)
self.false_positives = tf.zeros(shape=self.classes_num)
self.true_negatives = tf.zeros(shape=self.classes_num)
self.false_negatives = tf.zeros(shape=self.classes_num)
#
def update_state(self, y_true, y_pred):
y_true = tf.reduce_sum(
tf.expand_dims(tf.one_hot(y_true, 3), 0) * self.select_matrix
, -1
)
y_pred = tf.reduce_sum(
tf.expand_dims(tf.one_hot(y_pred, 3), 0) * self.select_matrix
, -1
)
self.true_positives += tf.reduce_sum(
tf.where(tf.logical_and(y_pred == 1, y_true == 1), 1., 0.), [1, 2]
)
self.false_positives += tf.reduce_sum(
tf.where(tf.logical_and(y_pred == 1, y_true == 0), 1., 0.), [1, 2]
)
self.true_negatives += tf.reduce_sum(
tf.where(tf.logical_and(y_pred == 0, y_true == 0), 1., 0.), [1, 2]
)
self.false_negatives += tf.reduce_sum(
tf.where(tf.logical_and(y_pred == 0, y_true == 1), 1., 0.), [1, 2]
)
#
def result(self, reduction='mean', class_weights=None):
"""
reduction = 'none', 'mean' or 'weighting'
"""
true_positives = self.true_positives[1:] if self.pad_type == 'pre' else self.true_positives[:-1]
false_positives = self.false_positives[1:] if self.pad_type == 'pre' else self.false_positives[:-1]
false_negatives = self.false_negatives[1:] if self.pad_type == 'pre' else self.false_negatives[:-1]
precision = true_positives / (true_positives + false_positives)
recall = true_positives / (true_positives + false_negatives)
f1score = 2 * precision * recall / (precision + recall)
if reduction == 'none':
pass
elif reduction == 'weighting':
class_weights = tf.ones_like(precision) if class_weights is None else class_weights
precision = tf.reduce_sum(precision * class_weights).numpy() / (self.classes_num - 1)
recall = tf.reduce_sum(recall * class_weights).numpy() / (self.classes_num - 1)
f1score = tf.reduce_sum(f1score * class_weights).numpy() / (self.classes_num - 1)
else:
precision = tf.reduce_sum(precision).numpy() / (self.classes_num - 1)
recall = tf.reduce_sum(recall).numpy() / (self.classes_num - 1)
f1score = tf.reduce_sum(f1score).numpy() / (self.classes_num - 1)
return precision, recall, f1score
#
def reset_states(self):
self.true_positives = tf.zeros(shape=self.classes_num)
self.false_positives = tf.zeros(shape=self.classes_num)
self.true_negatives = tf.zeros(shape=self.classes_num)
self.false_negatives = tf.zeros(shape=self.classes_num)
tensorflow 2.x 多分类混淆矩阵及评价指标计算方法(精确率、召回率、f1分数)
于 2022-06-11 13:42:54 首次发布