大师兄的Python机器学习笔记:实现评估模型
2020-05-15 本文已影响0人
superkmi
大师兄的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
... ...