首页 » 技术分享 » 模型评估之“鱼网捞鱼”

模型评估之“鱼网捞鱼”

 

模型评估之“鱼网捞鱼”

整理文档时找到了模型评估的学习笔记,当时在群里跟朋友们聊到了模型评估时,用“池塘捞鱼”做了一个例子,整理出来,温故知新。

问题描述

如下图所示,在一个池塘里(矩形)有很多的鱼(三角形)和虾(棱形), 现在有一个模型,也就是一个用来捞鱼的网(圆形虚线),一网下去捞中了一些鱼,同时也捞中了一些虾。现在要对这个鱼网(模型)进行评价一下,鱼网做得好不好呢?
鱼网捞鱼示意图
现在来分析一下:
池塘:总共的大小是20,其中鱼P=10, 虾N=10
模型就是一张网下去,捞了9个鱼和3个虾。(注意,网里的都是“被认为是鱼”的才被捞上来。)

捞到的网里正确的是鱼的:TP=9,
捞到的网里是虾被误认为是鱼的: FP=3
网的大小:P’ = 9+3=12
现在注意了:池塘里那些没有被网上来的,就是认为全是虾。这一部分叫N’

下面做一个表格来表示一下:

认为是鱼的(鱼网) 认为是虾(鱼网外) 小计
真正是鱼 TP=9 FN=1 P=10
真正是虾 FP=3 TN=7 N=10
小计 鱼网里的:P’=12 鱼网外的N’ = 8 池塘大小=20

“鱼网”模型指标计算

正确率(Acc):(TP+TN )/(P+N) = (9+7) /(20) = 0.8
速记:分的鱼和虾,占池塘大小的比例

精确率(precision): TP/(TP+FP) = 9/12= 0.75
速记: 鱼网里有多少鱼

召回率(recall):TP/P = 9/10 = 0.9
速记: 捞到 (召回) 的鱼占全部鱼的比例

综合分类率:F1

F1 = 2 * (precision) * recall/(precision+recall)
	   = 2 * 0.75 * 0.9/(0.75+0.9)
	   = 0.8181

代码实现与验证

首先用一个列表来表示池塘,用1表示"鱼",用0表示"虾",
池塘里总共有10只鱼和10只虾,语句是这样子:

# 结果集 10个1表示10个鱼,10个0表示10个虾
y_test =      [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

再来看下鱼网的表示,“鱼网”抓住了12只动物,有9只是鱼,3只是虾,其它的没抓到。
这时需要与池塘的动物对应,可以认为前面9个鱼抓到了(是1),第10只鱼没抓到(是0),
接着有3只虾抓到了(是1),剩下的7只没有抓到(是0)。
表示的语句是这样的:

# 预测结果: 前面9个鱼正确,有1个鱼预测为虾,3个虾预测为鱼,7个虾预测为虾
y_pred = [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]

接着使用代码来计算一下模型的各个指标,

# 模型评估报告
def model_score (y_test, y_pred):
    # 开始计算指标
    ACC = accuracy_score(y_test, y_pred) 
    PRECISION = precision_score (y_test, y_pred) #, average='macro' average='binary' 'weighted' 
    RECALL = recall_score (y_test, y_pred) #, average='macro'
    F1 = f1_score (y_test, y_pred) #, average='macro'

    ret = ""
    ret += "准确度: %2.3f\n" % ( ACC )
    ret += "精确度: %2.3f\n" % ( PRECISION )
    ret += "召回率: %2.3f\n" % ( RECALL )
    ret += "F1得分: %2.3f\n" % ( F1) 
    # 得到评价矩阵,注意这个结果与PPT中的表格不一样,是行列倒的,需要用.T转换一下
    ret += str(confusion_matrix(y_test, y_pred).T) + '\n'

    # 得到评价报告 
    ret += str(classification_report(y_test, y_pred))
    return ret
    
report = model_score(y_test, y_pred)
print('模型评估报告'.center(40,'-')+'\n'+report)

运行结果如下图:

运行结果图

混淆矩阵热力图

最后使用代码来生成混淆矩阵的热力图:

def model_map (y_true, y_pred):
    ## 字体问题
    sns.set(font='SimHei')
    fig = plt.figure(figsize=(6,6))
    ##y轴显示真实值 
    y_true = ['鱼' if x else '虾' for x in y_true]
    ###显示预测值 
    y_pred = ['鱼' if x else '虾' for x in y_pred]
    ##分类标识
    labels=['鱼','虾']
    ##构建混淆矩阵
    C2= confusion_matrix(y_true, y_pred, labels=labels ) 
    ##print(C2)
    ##显示成热力图
    ax=sns.heatmap(C2, annot=True, cmap='Greens', fmt='d', xticklabels=labels, yticklabels=labels)
    ax.set_ylabel("真实")
    ax.set_xlabel("预测")
    ax.xaxis.set_label_position('top') 
    ax.xaxis.tick_top()
    ax.set_title('混淆矩阵热力图', verticalalignment='bottom')
    plt.savefig('map.png')
    plt.show()

生成的热力图(如下图)与上面的分析表格一致,非常直观。

在这里插入图片描述

完整代码

最后附上完整的代码

#!/usr/bin/env python3
#coding:utf-8

__author__ = 'xmxoxo<xmxoxo@qq.com>'

# 模型评估指标 例子
import warnings
warnings.filterwarnings("ignore")

import numpy as np
import seaborn as sns;
from matplotlib import pyplot as plt

from sklearn.metrics import accuracy_score, precision_score, recall_score
from sklearn.metrics import f1_score, confusion_matrix, classification_report


# y_test = list('1'*10) + list('0'*10)
# 结果集 10个1表示10个鱼,10个0表示10个虾
y_test =      [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# 预测结果: 前面9个鱼正确,有1个鱼预测为虾,3个虾预测为鱼,7个虾预测为虾
y_pred = [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]

def model_map (y_true, y_pred):
    ## 字体问题
    sns.set(font='SimHei')
    fig = plt.figure(figsize=(6,6))
    ##y轴显示真实值 
    y_true = ['鱼' if x else '虾' for x in y_true]
    ###显示预测值 
    y_pred = ['鱼' if x else '虾' for x in y_pred]
    ##分类标识
    labels=['鱼','虾']
    ##构建混淆矩阵
    C2= confusion_matrix(y_true, y_pred, labels=labels ) 
    ##print(C2)
    ##显示成热力图
    ax=sns.heatmap(C2, annot=True, cmap='Greens', fmt='d', xticklabels=labels, yticklabels=labels)
    ax.set_ylabel("真实")
    ax.set_xlabel("预测")
    ax.xaxis.set_label_position('top') 
    ax.xaxis.tick_top()
    ax.set_title('混淆矩阵热力图', verticalalignment='bottom')
    plt.savefig('map.png')
    plt.show()


# 模型评估报告
def model_score (y_test, y_pred):
    # 开始计算指标
    ACC = accuracy_score(y_test, y_pred) 
    PRECISION = precision_score (y_test, y_pred) #, average='macro' average='binary' 'weighted' 
    RECALL = recall_score (y_test, y_pred) 
    F1 = f1_score (y_test, y_pred) 

    ret = ""
    ret += "准确度: %2.3f\n" % ( ACC )
    ret += "精确度: %2.3f\n" % ( PRECISION )
    ret += "召回率: %2.3f\n" % ( RECALL )
    ret += "F1得分: %2.3f\n" % ( F1) 
    # 得到评价矩阵,注意这个结果与PPT中的表格不一样,是行列倒的,需要用.T转换一下
    ret += str(confusion_matrix(y_test, y_pred).T) + '\n'

    # 得到评价报告 
    ret += str(classification_report(y_test, y_pred))
    return ret

report = model_score(y_test, y_pred)
print('模型评估报告'.center(40,'-')+'\n'+report)

model_map (y_test, y_pred)

if __name__ == '__main__':
    pass

最后欢迎到 QQ群来沟通学习
在这里插入图片描述

转载自原文链接, 如需删除请联系管理员。

原文链接:模型评估之“鱼网捞鱼”,转载请注明来源!

0