概念
为什么要计算F1:避免样本分布带来的偏差,综合考量分类效果,假如有100个样本,其中1个正样本,99个负样本,如果模型的预测只输出0,那么正确率是99%,这时候用正确率来衡量模型的好坏显然是不对的。
真实 1 | 真实 0 | |
预测 1 | True Positive(TP) | False Positive(FP) |
预测 0 | False Negative(FN) | True Negative(TN) |
- 查准率(precision),预测正确的样本在所有预测为1的样本中的比例,该值反映有多少其他类被错误的归为该类。
- 召回率(recall),预测正确的样本在所有真实为1的样本中的比例,该值反映有多少该类被预测为其他类了。
- F1(F1-Score), 精准率和召回率的调和平均数。
Micro-F1与Macro-F1
针对多标签分类而言衡量分类效果
- Micro-F1:直接计算所有类别的Precision和Recall,然后计算F1。(类别有权重,分到样本数多的类别有更大的影响力)
- Macro-F1:计算出每一个类的Precision和Recall并分别计算F1,最后将F1平均。(各类别的F1权重相同)
代码实现
二分类
def f1(y_hat, y_true): ''' 输入张量y_hat是输出层经过sigmoid激活的张量 y_true是label{0,1}的集和 model指的是如果是多任务分类,single会返回每个分类的f1分数,multi会返回所有类的平均f1分数(Marco-F1) 如果只是单个二分类任务,则可以忽略model ''' epsilon = 1e-7 y_hat = tf.round(y_hat)#将经过sigmoid激活的张量四舍五入变为0,1输出 # 输入的数据是矩阵,标签为单行矩阵,预测值为单列矩阵,如果不是需要转换 tp = tf.cast(tf.matmul(y_true,y_hat), 'float') #tn = tf.sum(tf.cast((1-y_hat)<em>(1-y_true), 'float'), axis=0) fp = tf.cast(tf.matmul(1-y_true,y_hat), 'float') fn = tf.cast(tf.matmul(y_true,1-y_hat), 'float') print('tp: ', tp[0][0].numpy(),'fp: ', fp[0][0].numpy(),'fn: ', fn[0][0].numpy()) p = tp/(tp+fp+epsilon)#epsilon的意义在于防止分母为0,否则当分母为0时python会报错 r = tp/(tp+fn+epsilon) f1 = 2</em>p<em>r/(p+r+epsilon) result = [f1[0][0].numpy(), p[0][0].numpy(), r[0][0].numpy()] return result
多标签
import tensorflow as tf def f1(y_hat, y_true, model='multi'): ''' 输入张量y_hat是输出层经过sigmoid激活的张量 y_true是label{0,1}的集和 model指的是如果是多任务分类,single会返回每个分类的f1分数,multi会返回所有类的平均f1分数(Marco-F1) 如果只是单个二分类任务,则可以忽略model ''' epsilon = 1e-7 y_hat = tf.round(y_hat)#将经过sigmoid激活的张量四舍五入变为0,1输出 #tf.cast()转换张量数据类型 tp = tf.reduce_sum(tf.cast(y_hat</em>y_true, 'float'), axis=0) #取axis维数据求和 #tn = tf.sum(tf.cast((1-y_hat)<em>(1-y_true), 'float'), axis=0) fp = tf.reduce_sum(tf.cast((1-y_hat)</em>y_true, 'float'), axis=0) fn = tf.reduce_sum(tf.cast(y_hat<em>(1-y_true), 'float'), axis=0) p = tp/(tp+fp+epsilon)#epsilon的意义在于防止分母为0,否则当分母为0时python会报错 r = tp/(tp+fn+epsilon) f1 = 2</em>p*r/(p+r+epsilon) f1 = tf.where(tf.is_nan(f1), tf.zeros_like(f1), f1) if model == 'single': return f1 if model == 'multi': return tf.reduce_mean(f1)
参考
https://blog.csdn.net/zjn295771349/article/details/84961596