大师兄的Python机器学习笔记:实现评估模型

大师兄的Python机器学习笔记:数据重抽样
大师兄的Python机器学习笔记:Pandas库

一、混淆矩阵

1. 关于混淆矩阵(Confusion Matrix)
  • 混淆矩阵是数据科学、数据分析和机器学习中总结分类模型预测结果的情形分析表,以矩阵形式将数据集中的记录按照真实的类别与分类模型作出的分类判断两个标准进行汇总。
  • 每一列代表了预测类别 ,每一列的总数表示预测为该类别的数据的数目。
  • 每一行代表了数据的真实归属类别 ,每一行的数据总数表示该类别的数据实例的数目。
  • 左上至右下的对角线为预测准确的值(TP+TN)。
实际值/预测值 相关(Relevant),正类 无关(NonRelevant),负类
被检索到(Retrieved) 正类判断为正类(TP) 负类判断为正类(FP)
未被检索到(Not Retrieved) 正类判断为负类(FN) 负类判断为负类(TN)

例:二分类混淆矩阵

  • 比如有一群动物包含猫和狗,现在希望取出一只猫作为样本:
  • 如果将猫判断为猫,即为TP。
  • 如果将猫判断为非猫,即为FN。
  • 如果将狗判断为猫,即为FP。
  • 如果将狗判断为非猫,即为TN。
2. 混淆矩阵的特性
3. 案例及代码实现

例:多分类混淆矩阵

  • 比如有一群动物,包括20只猫、50只狗和30只兔子。
  • 现在挑选出60只猫,其中包括20只猫,还错把20只狗和20只兔子作为猫挑出来了。
实际/预测 兔子
20 0 0
20 30 0
兔子 20 0 10
  • 自己写算法实现:
>>>import numpy as np

>>>def base_data():
>>>    # 100只动物包含猫、狗和兔子
>>>    cats = np.asanyarray(['cat']*20)
>>>    dogs = np.asanyarray(['dog']*50)
>>>    rabbits = np.asanyarray(['rabbit']*30)
>>>    return np.concatenate((cats,dogs,rabbits))

>>>def actual_data(base_data):
>>>    # 随机抽取60只动物
>>>    return np.random.choice(base_data,60)

>>>def predicted_data(base_data):
>>>    # 预测挑出了60只猫
>>>    return np.random.choice(base_data,60)

>>>def confusion_maxtrix(actual_data,predicted_data):
>>>    # 生成一个混淆矩阵
>>>    unique_class_in_data = set(actual_data)
>>>    matrix = [list() for x in range(len(unique_class_in_data))]
>>>    for i in range(len(unique_class_in_data)):
>>>        matrix[i] = [0 for x in range(len(unique_class_in_data))]
>>>    indexing_our_class = dict()

>>>    # 贴标签
>>>    for i ,class_value in enumerate(unique_class_in_data):
>>>        indexing_our_class[class_value] = i

>>>    for i in range(len(actual_data)):
>>>        col=indexing_our_class[actual_data[i]]
>>>        row=indexing_our_class[predicted_data[i]]
>>>        matrix[row][col] +=1
>>>    return unique_class_in_data,matrix

>>>def pretty_confusion_matrix(unique_class_in_data,matrix):
>>>    # 输出到控制台
>>>    print('(A/P)' +' '.join(str(x) for x in unique_class_in_data))
>>>    for i,x in enumerate(unique_class_in_data):
>>>        print(f"{x} | {' '.join(str(x) for x in matrix[i])}")

>>>if __name__ == '__main__':
>>>    ad = actual_data(base_data())
>>>    pd = predicted_data(base_data())
>>>    index,matrix = confusion_maxtrix(ad,pd)
>>>    pretty_confusion_matrix(index,matrix)
(A/P)cat rabbit dog
cat | 1 4 9
rabbit | 5 5 14
dog | 7 3 12
  • 使用sklearn包实现:
>>>from sklearn.metrics import confusion_matrix
>>>import sklearn.metrics
>>>import itertools
>>>import matplotlib.pyplot as plt
>>>import numpy as np

>>>def base_data():
>>>    # 100只动物包含猫、狗和兔子
>>>    cats = np.asanyarray(['cat']*20)
>>>    dogs = np.asanyarray(['dog']*50)
>>>    rabbits = np.asanyarray(['rabbit']*30)
>>>    return np.concatenate((cats,dogs,rabbits))

>>>def actual_data(base_data):
>>>    # 随机抽取60只动物
>>>    return np.random.choice(base_data,60)

>>>def predicted_data(base_data):
>>>    # 预测挑出了60只猫
>>>    return np.random.choice(base_data,60)

>>>def confusion_maxtrix(actual_data,predicted_data):
>>>    # 生成一个混淆矩阵
>>>    return confusion_matrix(actual_data, predicted_data, labels=["cat", "dog", "rabbit"])

>>>def get_report(actual_data,predicted_data):
>>>    # 生成报告
>>>    return sklearn.metrics.classification_report(actual_data, predicted_data,target_names=["cat", "dog", "rabbit"])

>>>def pretty_confusion_matrix(confusion_box):
>>>    # 生成图片
>>>    classes = ['cat','dog','rabbit']
>>>    plt.imshow(confusion_box,interpolation='nearest',cmap=plt.cm.get_cmap('rainbow',1000))
>>>    plt.title('confusion matrix demo')
>>>    plt.colorbar()
>>>    tick_marks = np.arange(len(classes))
>>>    plt.xticks(tick_marks,classes,rotation=0)
>>>    plt.yticks(tick_marks,classes)

>>>    thresh = confusion_box.max()/2.
>>>    for i,j in >>>itertools.product(range(confusion_box.shape[0]),range(confusion_box.shape[1])):
>>>        plt.text(j,i,confusion_box[i,j],horizontalalignment="center", color="white" if confusion_box[i,j] > thresh else "black")
>>>    plt.tight_layout()
>>>    plt.ylabel("True value")
>>>    plt.xlabel("Predicted value")
>>>    plt.show()

>>>if __name__ == '__main__':
>>>    ad = actual_data(base_data())
>>>    pd = predicted_data(base_data())
>>>    matrix_box = confusion_maxtrix(ad,pd)
>>>    print(f"矩阵值:{'*'*20}\n", matrix_box)
>>>    print(f"矩阵属性:{'*'*20}\n",get_report(ad,pd))
>>>    pretty_confusion_matrix(matrix_box)
矩阵值:********************
 [[ 2  3  2]
 [ 7  9 11]
 [ 8 10  8]]
矩阵属性:********************
               precision    recall  f1-score   support

         cat       0.12      0.29      0.17         7
         dog       0.41      0.33      0.37        27
      rabbit       0.38      0.31      0.34        26

    accuracy                           0.32        60
   macro avg       0.30      0.31      0.29        60
weighted avg       0.36      0.32      0.33        60

二、准确度、精确度和召回率

1. 准确度(Accuracy)
  • 准确度是对于给定的测试数据集,分类器正确分类的样本数与总样本数之比。

例:

  • 比如有一群动物,包括20只猫、50只狗和30只兔子。
  • 现在挑选出60只猫,其中包括20只猫,还错把20只狗和20只兔子作为猫挑出来了。
  • 准确度 = (20 + (50-30) + (30-20) / 100 = 50%
2. 精确度(Precision)
  • 精确度是所有"正确被检索的item(TP)"占所有"实际被检索到的(TP+FP)"的比例.

例:

  • 比如有一群动物,包括20只猫、50只狗和30只兔子。
  • 现在挑选出60只猫,其中包括20只猫,还错把20只狗和20只兔子作为猫挑出来了。
  • 精确度 = 20 / 20+20+20 = 33%
3.召回率(Recall)
  • 召回率是所有"正确被检索的item(TP)"占所有"应该检索到的item(TP+FN)"的比例。

例:

  • 比如有一群动物,包括20只猫、50只狗和30只兔子。
  • 现在挑选出60只猫,其中包括20只猫,还错把20只狗和20只兔子作为猫挑出来了。
  • 召回率 = 20 / 20 = 100%
>>>import numpy as np
>>>from collections import Counter

>>>def base_data():
>>>    # 100只动物包含猫、狗和兔子
>>>    cats = np.asanyarray(['cat']*20)
>>>    dogs = np.asanyarray(['dog']*50)
>>>    rabbits = np.asanyarray(['rabbit']*30)
>>>    return np.concatenate((cats,dogs,rabbits))

>>>def actual_data(base_data):
>>>    # 随机抽取60只动物
>>>    return np.random.choice(base_data,60)

>>>def predicted_data():
>>>    # 预测挑出了60只猫
>>>    return np.asanyarray(['cat']*60)

>>>def calculate_the_accuracy_of_prediction(actual_data,predicted_data,base_data):
>>>    # 计算准确率
>>>    correct_num = 0
>>>    correct_left = (Counter(base_data).get('dog')- Counter(actual_data).get('dog'))+ (Counter(base_data).get('rabbit')- Counter(actual_data).get('rabbit')) # 计算没有被选入的狗和兔子
>>>    for i in range(len(actual_data)):
>>>        if actual_data[i]==predicted_data[i]:
>>>            correct_num +=1
>>>    return (correct_num+correct_left)/float(len(base_data))

>>>def calculate_the_precision_of_prediction(actual_data,predicted_data):
>>>    # 计算精确率
>>>    correct_num = 0
>>>    for i in range(len(actual_data)):
>>>        if actual_data[i]==predicted_data[i]:
>>>            correct_num +=1
>>>    return correct_num/float(len(actual_data))

>>>def calculate_the_recall_of_prediction(actual_data,predicted_data,base_data):
>>>    # 计算召回率
>>>    correct_num = 0
>>>    correct_not_retrieved = (Counter(base_data).get('cat')- Counter(actual_data).get('cat'))
>>>    for i in range(len(actual_data)):
>>>        if actual_data[i]==predicted_data[i]:
>>>            correct_num +=1
>>>    return correct_num/(correct_num+correct_not_retrieved)

>>>def show_data(ad,pd):
>>>    for a,p in zip(ad,pd):
>>>        print(f"实际值:{a},预测值:{p},结果:{a==p}")

>>>if __name__ == '__main__':
>>>    bd = base_data()
>>>    ad = actual_data(bd)
>>>    pd = predicted_data()
>>>    print(f"准确率为:{calculate_the_accuracy_of_prediction(ad,pd,bd)}")
>>>    print(f"精确率为:{calculate_the_precision_of_prediction(ad,pd)}")
>>>    print(f"召回率为:{calculate_the_recall_of_prediction(ad,pd,bd)}")
>>>    print(f'{"*"*20}')
>>>    show_data(ad,pd)
准确率为:0.4
精确率为:0.16666666666666666
召回率为:0.5
********************
实际值:dog,预测值:cat,结果:False
实际值:dog,预测值:cat,结果:False
实际值:rabbit,预测值:cat,结果:False
实际值:cat,预测值:cat,结果:True
... ...
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335