机器学习手册学习笔记--模型评估

350 阅读7分钟

仅供自己复习回顾使用,若有侵权可删除

Hold-out 验证

数据(特征值和目标向量)被分成训练集和测试集两部分

这种方法有两大缺点 :首先,模型的性能高度依赖于所选取的测试集 ; 其次,模型在训练和评估时都没有充分利用所有可用数据。

交叉验证模型

K折需要考虑:

  1. KFCV 假定每个样本都是独立于其他样本的(即IID)。 如果数据是独立同分布的,最好在数据分组前将其顺序打乱。在 scikit-learn 中,可以通过设置 shuffle =True 来打乱数据

  2. 当我们使用 KFCV 来评估分类器时,通常将每一类数据大致平均地分配到 k 组数据中(这被称为分层 k 折)。 在 scikit-learn 中,可以用StratifiedKFold 替换 KFold 来使用分层 k 折交叉验证

  3. 使用 Hold-out 验证或交叉验证时,应该基于训练集对数据进行预处理,然后将这些预转换同时应用于训练集和测试集

# 使用训练集计算标准化参数
standardizer.fit(features_train)
# 将标准化操作应用到训练集和测试集
features_train_std = standardizer.transform(features_train)
features_test_std = standardizer.transform(features_test)

from sklearn.model_selection import KFold, cross_val_score

kf = KFold(n_splits=10, shuffle=True, random_state=1)

cross_val_score()

from sklearn import metrics
from sklearn.model_selection import KFold, cross_val_score
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler

standardizer = StandardScaler()
logit = LogisticRegression()

# 创建包含数据标准化和逻辑回归的流水线
pipeline = make_pipeline(standardizer, logit)
# 创建 k 折交叉验证对象
kf = KFold(n_splits=10, shuffle=True, random_state=1)
# 执行 k 折交叉验证
cv_results = cross_val_score(pipeline, # 流水线
                             features, # 特征矩阵
                             target, # 目标向量
                             cv=kf, # 交叉验证方法
                             scoring="accuracy", # 损失函数
                             n_jobs=-1) # 使用所有的 CPU 核
cv_results.mean()

创建一个基准回归模型

通常用这种方法来模拟某个产品或系统中已有的原始预测系统。

# 加载库
from sklearn.dummy import DummyRegressor
# 创建 DummyRegressor 对象
dummy = DummyRegressor(strategy='mean') #设置所使用的预测方法,或中位数
# 训练回归模型
dummy.fit(features_train, target_train)
# 计算 R 方得分
dummy.score(features_test, target_test) #默认情况下, score 方法返回的是决定系数(R-squared, R2 得分)

创建一个基准分类模型

一种常用的衡量分类模型(也即分类器)性能的标准是将分类器的准确率与随机猜测的分类结果进行对比

from sklearn.dummy import DummyClassifier

# 创建 DummyClassifier
dummy = DummyClassifier(strategy='uniform', random_state=1) 
#第一个是 stratified 方法,它使预测结果与训练集中数据类别的比例相同
#第二个是uniform 方法,它随机生成均匀的预测
# 训练模型
dummy.fit(features_train, target_train)
# 计算模型的得分
dummy.score(features_test, target_test)

评估二元分类器

准确率(accuracy)是一种常见的性能指标,它表示被正确预测的样本数占参与预测的样本总数的比例

精确度(precision)是所有被预测为正类的样本中被正确预测的样本的百分比,一种衡量预测结果中的噪声的指标。 精确度高 == 仅在非常确定时才会预测样本为正类 召回率是“真阳性”样本占所有正类样本的比例。召回率衡量的是模型识别正类样本的能力 召回率高 == 比较容易将样本预测为正类 F1 分数是衡量正类预测的正确程度(correctness)的指标,代表在被标记为正类的样本中,确实是正类的样本所占的比例 F1 分数是调和平均值(一种用于概率数据的平均数)

from sklearn.model_selection import cross_val_score
# 使用准确率对模型进行交叉验证
cross_val_score(logit, X, y, scoring="accuracy")
cross_val_score(logit, X, y, scoring="precision")
cross_val_score(logit, X, y, scoring="recall")
cross_val_score(logit, X, y, scoring="f1")

评估二元分类器的阈值

受试者工作特征(Receiving Operating Characteristic,ROC)曲线是评估二元分类器质量的常用方法。 ROC 曲线会对每一个概率阈值(即用来区分样本属于正类或负类的概率值)比较其真阳性和假阳性的比例。 假阳性率是被错误预测为负类的样本数和所有被预测为负类的样本数之比

真阳性率是被正确预测的正类样本数与所有被预测为正类的样本数之比

ROC 曲线表示每个概率阈值下相应的 TPR 和 FPR 值

# 加载库
import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve, roc_auc_score

# 计算真阳性和假阳性的概率
false_positive_rate, true_positive_rate, threshold =roc_curve(target_test,target_probabilities)
# 画出 ROC 曲线
plt.title("Receiver Operating Characteristic")
plt.plot(false_positive_rate, true_positive_rate)
plt.plot([0, 1], ls="--")
plt.plot([0, 0], [1, 0] , c=".7"), plt.plot([1, 1] , c=".7")
plt.ylabel("True Positive Rate")
plt.xlabel("False Positive Rate")
plt.show()

# 获取预测的概率
logit.predict_proba(features_test)[0:1]
# 计算 ROC 曲线下方的面积
roc_auc_score(target_test, target_probabilities)

评估多元分类器

分类数据均衡(比如,每个分类的样本数大致相等),准确率是评估模型性能的一个简单且可解释的指标

# 加载库
from sklearn.model_selection import cross_val_score

# 使用准确率作为指标进行交叉验证
cross_val_score(logit, features, target, scoring='accuracy') 
# macro 计算每个分类的得分,然后取加权平均值,每个分类的权值相同
# weighted 计算每个分类的得分,然后取加权平均值,权值为每个分类的样本数占总样本数的比例。
# micro 计算每个样本分类组合的得分,然后取平均值。

分类器性能的可视化

首先,一个完美的模型,其混淆矩阵应该只有对角线上才有值,而其他位置应全为零

其次,混淆矩阵不仅可以显示模型将哪些样本的分类预测错了,还可以显示它是怎么分错的,即误分类的模式

最后,对于任意数量的分类,混淆矩阵都适用

import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import confusion_matrix
import pandas as pd

# 创建目标分类的名称列表
class_names = iris.target_names
# 创建混淆矩阵
matrix = confusion_matrix(target_test, target_predicted)
# 创建一个 pandas DataFrame
dataframe = pd.DataFrame(matrix, index=class_names, columns=class_names)
# 绘制热力图
sns.heatmap(dataframe, annot=True, cbar=None, cmap="Blues")
plt.title("Confusion Matrix"), plt.tight_layout()
plt.ylabel("True Class"), plt.xlabel("Predicted Class")
plt.show()

评估回归模型

from sklearn.model_selection import cross_val_score
cross_val_score(ols, features, target, scoring='r2')
# scoring='neg_mean_squared_error'

评估聚类模型

“好”的聚类中同类别样本间的距离非常小(即稠密聚类),不同类别的样本之间距离非常大(即分离得很彻底)。

轮廓系数可以用一个值同时评估这两种特性。

轮廓系数的值介于-1和1间,其中1表示内部密集、分离彻底(指与其他聚类的间隔较远)的聚类

#评估模型

from sklearn.metrics import silhouette_score
silhouette_score(features, target_predicted)

创建自定义评估指标

from sklearn.metrics import make_scorer, r2_score
def custom_metric(target_test, target_predicted):
    # 计算 R 方得分
    r2 = r2_score(target_test, target_predicted)
    return r2
# 创建评分函数(评分器),并且定义分数越高代表模型越好
score = make_scorer(custom_metric, greater_is_better=True) #指定较高的分数代表模型性能较好
# 应用自定义评分器
score(model, features_test, target_test)

可视化训练集规模的影响

使用交叉验证为不同规模的训练集计算训练和测试得分

学习曲线将模型在训练集上和交叉验证时的性能(例如准确率、召回率)以及与训练集 样本数量之间的关系可视化地表达出来

# 加载库
import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_digits
from sklearn.model_selection import learning_curve

train_sizes, train_scores, test_scores =learning_curve(RandomForestClassifier(),
                                        features,target,cv=10,scoring='accuracy',
                                     n_jobs=-1,train_sizes=np.linspace(0.01,1.0,50))
# 计算训练集得分的平均值和标准差
train_mean = np.mean(train_scores, axis=1)
train_std = np.std(train_scores, axis=1)
# 计算测试集得分的平均值和标准差
test_mean = np.mean(test_scores, axis=1)
test_std = np.std(test_scores, axis=1)
# 画线
plt.plot(train_sizes, train_mean, '--', color="#111111", label="Training score")
plt.plot(train_sizes, test_mean, color="#111111", label="Cross-validation score")
# 画带状图
plt.fill_between(train_sizes, train_mean - train_std,train_mean + train_std, color="#DDDDDD")
plt.fill_between(train_sizes, test_mean - test_std,test_mean + test_std, color="#DDDDDD")
# 创建图
plt.title("Learning Curve")
plt.xlabel("Training Set Size"), plt.ylabel("Accuracy Score"),
plt.legend(loc="best")
plt.tight_layout()
plt.show()

生成对评估指标的报告

# 生成分类器的性能报告
from sklearn.metrics import classification_report
print(classification_report(target_test,target_predicted,target_names=class_names))

可视化超参数值的效果

大多数情况下,超参数的值是在模型选择阶段确定的

# 创建参数的变化范围
param_range = np.arange(1, 250, 2)
# 对区间内的参数值分别计算模型在训练集和测试集上的准确率
train_scores, test_scores = validation_curve(RandomForestClassifier(), # 分类器
                                features,target, param_name="n_estimators", # 要查看的超参数
                                param_range=param_range, # 超参数值的范围
                                cv=3,scoring="accuracy",n_jobs=-1)
'''
param_name 是需要变化的超参数的名字。
param_range 是超参数取值的区间。
scoring 是模型的评估指标。
'''