前面我们已经介绍了不少机器学习的算法,已经可以执行像回归、分类、聚类等任务,比如对于一个分类问题而言,到底哪个算法更好呢?或者同样的算法下训练出的不同的模型,到底哪个更好呢?这就需要用到模型评估了,本节的内容我们以二分类为例,通常多分类问题都可以转化为多个二分类问题,后面我们再介绍其他的任务类型。
在介绍模型评估的指标签之前,先介绍预测结果和正确结果之间的四种类型:
第一个是TP,即True Positive,它表示正确预测了结果为正类的样本。
第二个是TN,即True Negative,它表示正确预测了结果为负类的样本。
第三个是FP,即False Positive,它表示错误地把负类预测为正类,样本属于负类,这就属于误报。
第四个是FN,即False Negative,它表示错误地把正类预测为负类,样本属于正类,这就属于漏报。
不同的业务形态对于漏报和误报的容忍程度是不一样的,有时候我们可能宁可误报也不能漏报,有时候则是可以接受一定程度的漏报但是不能接受误报。
基于上面的理论分析,我们来看几个具体的评估指标:
第一个是准确率,即Accuracy,它表示预测正确的比例,即TP+TN除以所有数据,它反应的是我们分类的整体效果。
第二个是精确率,即Precision,它表示预测为正类的样本占实际为正类的比例,即TP除以TP+FP,它表示预测结果的可靠性,就是减少误报。如果这个数太低,说明把很多应该找到的数据没有找到。
第三个是召回率,即Recall,它表示在模型预测的正确样本占所有正确样本的比例,即TP除以TP+FN,如果这个数据太低,说明很多应该找到的数据都没有找到。
第四个是F1分数,它表示精确率和召回率的调和平均,是一个相对平衡的指标。
讲了这么多理论,我们就用SVM这个算法来进行分类,然后通过cross_validate即交叉验证的方式来评估指标,代码如下:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_validate
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
# 生成自定义数据
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5,
n_redundant=0, n_clusters_per_class=1, random_state=42)
# 创建分类器
clf = SVC(kernel='linear', C=1)
# 定义要计算的指标
scoring = ['accuracy', 'precision_macro', 'recall_macro', 'f1_macro']
# 进行交叉验证
cv_results = cross_validate(clf, X, y, cv=5, scoring=scoring, return_train_score=False)
# 提取各项指标的结果
accuracy_scores = cv_results['test_accuracy']
precision_scores = cv_results['test_precision_macro']
recall_scores = cv_results['test_recall_macro']
f1_scores = cv_results['test_f1_macro']
# 打印各项指标的数据
print(f"训练时间: {cv_results['fit_time']}")
print(f"预测时间: {cv_results['score_time']}")
print(f"准确率: {accuracy_scores}")
print(f"精确率: {precision_scores}")
print(f"召回率: {recall_scores}")
print(f"F1分数: {f1_scores}")
# 可视化交叉验证结果
metrics = ['Accuracy', 'Precision', 'Recall', 'F1-score']
mean_scores = [np.mean(accuracy_scores), np.mean(precision_scores), np.mean(recall_scores), np.mean(f1_scores)]
plt.figure(figsize=(10, 6))
plt.bar(metrics, mean_scores)
plt.ylabel('Score')
plt.title('Cross-validation Results')
plt.ylim(0, 1)
for i, v in enumerate(mean_scores):
plt.text(i, v + 0.01, f'{v:.2f}', ha='center')
plt.show()
由于机器学习的内容很多已经讲过了,这里就不再赘述了,上面的代码通过SVM算法进行了分类,然后依次打印训练时间、预测时间、准确率、精确率、召回率、F1分数等,看一下在控制台的输出如下:
然后我们用画图的方式展示了平均数据,如下所示:
可以看到我们这里的数据基本在97%和98%左右波动,在具体的业务场景中还是要结合实际情况进行分析。