机器学习--模型选择与评估

机器学习–模型选择与评估

摘要

本周探讨了机器学习中的模型选择与评估技术,重点介绍了交叉验证方法,用于评估模型的泛化能力。通过k折交叉验证和随机排列交叉验证等技术,可以有效地评估模型在未见数据上的性能。同时,还介绍了如何通过网格搜索和随机搜索来调整模型的超参数,以找到最优配置。最后,文中还提到了如何调整分类器的决策阈值以及使用不同的评分指标来量化预测质量。

abstract

This week we explored model selection and evaluation techniques in machine learning, focusing on cross-validation methods for evaluating the generalization ability of models. The performance of the model on unseen data can be evaluated effectively by K-fold cross-validation and random permutation cross-validation. At the same time, it also introduces how to adjust the hyperparameters of the model through grid search and random search to find the optimal configuration. Finally, the paper also mentions how to adjust the decision threshold of the classifier and how to quantify the prediction quality by using different scoring indicators.

1.交叉验证(评估估计器性能)

学习预测函数的参数并在同样的数据上进行测试是一种方法上的错误:一个模型如果只是重复它刚看到的样本的标签,虽然得分满分,但在未见过的数据上却无法做出任何有用的预测。这种情况被称为过拟合。为了避免这种情况,在进行(监督式)机器学习实验时,通常会将一部分可用数据保留作为测试集 X_test, y_test。下面是模型训练中典型交叉验证工作流程的流程图。最佳参数可以通过网格搜索技术来确定。
在这里插入图片描述
在scikit-learn中,可以快速通过train_test_split辅助函数将数据随机划分为训练集和测试集。加载鸢尾花数据集,然后在上面拟合一个线性支持向量机:

import numpy as np
from sklearn.model_selection import train_test_split
from sklearn import datasets
from sklearn import svm
# 加载数据集
X, y = datasets.load_iris(return_X_y=True)
X.shape, y.shape
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.4, random_state=0)

X_train.shape, y_train.shape
X_test.shape, y_test.shape
# 拟合并计算分数
clf = svm.SVC(kernel='linear', C=1).fit(X_train, y_train)
clf.score(X_test, y_test)

在评估不同的设置(“超参数”)时,例如必须手动为支持向量机(SVM)设置的C值,仍然存在在测试集上过拟合的风险,因为参数可以被调整,直到估计器表现最佳。这样,关于测试集的知识可能会“泄漏”到模型中,评估指标不再反映泛化性能。为了解决这个问题,可以将数据集的另一部分保留为所谓的“验证集”:在训练集上进行训练,然后在验证集上进行评估,当实验看起来成功时,再在测试集上进行最终评估。
然而,通过将可用数据分成三部分,大大减少了可用于学习模型的样本数量,结果可能依赖于特定的(训练,验证)集的随机选择。

解决这个问题的一种方法是称为交叉验证(简称CV)的程序。测试集仍应保留用于最终评估,但在进行CV时不再需要验证集。在基本方法中,称为k折交叉验证,训练集被分成k个较小的集合。对于每个k个“折”,遵循以下程序:
1.使用𝑘−1个折作为训练数据训练模型;
2.将得到的模型在剩下的数据部分进行验证(即,将其用作测试集来计算性能度量,例如准确性)。
k折交叉验证报告的性能度量是循环中计算值的平均值。这种方法可能计算开销较大,但不会浪费太多数据(就像固定任意验证集时那样),这在样本非常小的逆推断等问题中是一个主要优势。

1.1 计算交叉验证的指标

使用交叉验证的最简单方法是在估计器和数据集上调用cross_val_score辅助函数。
下面的例子演示了如何在虹膜数据集上估计线性核支持向量机的精度,方法是将数据分割,拟合模型,并连续5次(每次不同的分割)计算分数:

from sklearn.model_selection import cross_val_score
clf = svm.SVC(kernel='linear', C=1, random_state=42)
scores = cross_val_score(clf, X, y, cv=5)
# 平均值和标准差
print("%0.2f accuracy with a standard deviation of %0.2f" % (scores.mean(), scores.std()))
# 默认情况下,每次CV迭代计算的分数是估计器的分数方法。可以通过使用scoring参数来改变这一点
from sklearn import metrics
scores = cross_val_score(
    clf, X, y, cv=5, scoring='f1_macro')

在Iris数据集的情况下,样本在目标类之间是平衡的,因此准确性和f1分数几乎相等。
当cv参数为整数时,cross_val_score默认使用KFold或StratifiedKFold策略,如果估计器派生自ClassifierMixin,则使用后者。
也可以通过传递交叉验证迭代器来使用其他交叉验证策略,例如:

from sklearn.model_selection import ShuffleSplit
n_samples = X.shape[0]
cv = ShuffleSplit(n_splits=5, test_size=0.3, random_state=0)
cross_val_score(clf, X, y, cv=cv)

另一种选择是使用可迭代对象生成(train, test)分割作为索引数组,例如:

def custom_cv_2folds(X):
    n = X.shape[0]
    i = 1
    while i <= 2:
        idx = np.arange(n * (i - 1) / 2, n * i / 2, dtype=int)
        yield idx, idx
        i += 1
custom_cv = custom_cv_2folds(X)
cross_val_score(clf, X, y, cv=custom_cv)

就像在训练数据上测试预测器很重要一样,预处理(如标准化、特征选择等)和类似的数据转换也应该从训练集中学习,并应用于预测数据:

from sklearn import preprocessing
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.4, random_state=0)
scaler = preprocessing.StandardScaler().fit(X_train)
X_train_transformed = scaler.transform(X_train)
clf = svm.SVC(C=1).fit(X_train_transformed, y_train)
X_test_transformed = scaler.transform(X_test)
clf.score(X_test_transformed, y_test)

Pipeline使得组合估算器更容易,在交叉验证下提供了这种行为:

from sklearn.pipeline import make_pipeline
clf = make_pipeline(preprocessing.StandardScaler(), svm.SVC(C=1))
cross_val_score(clf, X, y, cv=cv)

1.2 交叉验证迭代器

1.2.1 id数据的交叉验证迭代器

假设一些数据是独立同分布的(Independent and same Distributed, i.i.d),即假设所有样本都来自同一个生成过程,并且生成过程对过去生成的样本没有记忆。

1.2.1.1 K-fold

K-fold将所有样本分成两部分组的样本。预测函数是用折叠,并将留下的折叠用于测试。在包含4个样本的数据集上进行2次交叉验证的示例:

import numpy as np
from sklearn.model_selection import KFold

X = ["a", "b", "c", "d"]
kf = KFold(n_splits=2)
for train, test in kf.split(X):
    print("%s %s" % (train, test))

这是交叉验证行为的可视化。注意,KFold不受类或组的影响。
在这里插入图片描述

1.2.1.2 随机排列交叉验证

ShuffleSplit迭代器将生成用户定义的独立训练/测试数据集分割的数量。首先对样本进行洗牌,然后将其分成一对训练集和测试集。可以通过显式地播random_state伪随机数生成器来控制结果的可再现性的随机性。
下面是一个用法示例:

from sklearn.model_selection import ShuffleSplit
X = np.arange(10)
ss = ShuffleSplit(n_splits=5, test_size=0.25, random_state=0)
for train_index, test_index in ss.split(X):
    print("%s %s" % (train_index, test_index))

这是交叉验证行为的可视化。ShuffleSplit不受类或组的影响。
在这里插入图片描述
ShuffleSplit是KFold交叉验证的一个很好的替代方案,它可以更好地控制迭代次数和训练/测试分割的每一边的样本比例。

2.调整估计器的超参数

超参数是在估计器中不直接学习的参数。在scikit-learn中,它们作为参数传递给估计器类的构造函数。典型的例子包括支持向量分类器的C、kernel和gamma, Lasso的alpha等。

2.1 穷举网格搜索

GridSearchCV提供的网格搜索从param_grid参数指定的参数值网格中详尽地生成候选项。例如,下面的param_grid:

param_grid = [
  {'C': [1, 10, 100, 1000], 'kernel': ['linear']},
  {'C': [1, 10, 100, 1000], 'gamma': [0.001, 0.0001], 'kernel': ['rbf']},
 ]

2.2 随机参数优化

虽然使用参数设置网格是目前使用最广泛的参数优化方法,但其他搜索方法具有更有利的特性。RandomizedSearchCV实现了对参数的随机搜索,其中每个设置都是从可能参数值的分布中采样。与穷举搜索相比,这有两个主要好处:预算的选择可以独立于参数的数量和可能的值。
1. 添加不影响性能的参数不会降低效率。
2. 指定如何采样参数是通过ui完成的。
指定如何采样参数是使用字典完成的,非常类似于为GridSearchCV指定参数。此外,使用n_iter参数指定计算预算,即采样候选项或采样迭代的数量。对于每个参数,可以指定可能值的分布或离散选择列表(将进行均匀抽样):

{'C': scipy.stats.expon(scale=100), 'gamma': scipy.stats.expon(scale=.1),
  'kernel': ['rbf'], 'class_weight':['balanced', None]}

3.调整类预测的决策阈值

分类最好分为两部分:
1. 学习一个模型来预测,理想情况下,类概率的统计问题;
2. 基于这些概率预测采取具体行动的决策问题。
通过预测得到与标签相对应的决策。在二元分类中,决策规则或操作通过分数的阈值来定义,从而导致对每个样本的单个类标签的预测。对于scikit-learn中的二元分类,类标签预测是通过硬编码的截止规则获得的:当条件概率为大于0.5(通过predict_proba获得),或者决策分数大于0(通过decision_function获得)。
在这里,展示一个例子来说明条件概率估计之间的关系
类标签:

from sklearn.datasets import make_classification
from sklearn.tree import DecisionTreeClassifier
X, y = make_classification(random_state=0)
classifier = DecisionTreeClassifier(max_depth=2, random_state=0).fit(X, y)
classifier.predict_proba(X[:4])
classifier.predict(X[:4])

4.指标与评分(量化预测的质量)

有3种不同的api用于评估模型预测的质量:
评估器评分方法:评估器有一个评分方法,为它们要解决的问题提供默认的评估标准。这在本页中没有讨论,但在每个评估器的文档中都有讨论。
评分参数:使用交叉验证的模型评估工具(例如model_selection)。cross_val_score和model_selection.GridSearchCV)依赖于内部评分策略。这将在评分参数一节中讨论:定义模型评估规则。
度量函数:sklearn。Metrics模块实现了针对特定目的评估预测误差的功能。这些指标在分类指标、多标签排名指标、回归指标和聚类指标中有详细介绍。

4.1 评分参数:定义模型评价规则

4.1.1 常见情况:预定义值

对于最常见的用例,使用scoring参数指定一个计分器对象。所有得分对象都遵循这样的约定,即返回值越高越好。因此度量模型和数据之间距离的度量,比如度量。Mean_squared_error,作为neg_mean_squared_error可用,它返回度量的负值。
下面是一个用例:

from sklearn import svm, datasets
from sklearn.model_selection import cross_val_score
X, y = datasets.load_iris(return_X_y=True)
clf = svm.SVC(random_state=0)
cross_val_score(clf, X, y, cv=5, scoring='recall_macro')

4.1.2 从度量函数定义得分策略

下面的指标函数没有被实现为命名分数,有时是因为它们需要额外的参数,比如fbeta_score。它们不能传递给评分参数;相反,它们的可调用对象需要与用户可设置参数的值一起传递给make_scorer。

FunctionParameter
Classification
metrics.fbeta_scorebeta
Regression
metrics.mean_tweedie_deviancepower
metrics.mean_pinball_lossalpha
metrics.d2_tweedie_scorealpower
metrics.d2_pinball_scorealpha

一个典型的用例是将库中的现有度量函数包装为其参数的非默认值,例如fbeta_score函数的beta参数:

from sklearn.metrics import fbeta_score, make_scorer
ftwo_scorer = make_scorer(fbeta_score, beta=2)
from sklearn.model_selection import GridSearchCV
from sklearn.svm import LinearSVC
grid = GridSearchCV(LinearSVC(), param_grid={'C': [1, 10]},
                    scoring=ftwo_scorer, cv=5)

模块sklearn.Metrics还提供了一组简单的函数,用于测量给定基础真理和预测的预测误差:
1. 以_score结尾的函数返回一个值,值越高越好。
2. 以_error、_loss或_deviance结尾的函数返回一个要最小化的值,越小越好。当使用make_scorer转换为分数对象时,将greater_is_better参数设置为False(默认为True;参见下面的参数说明)。# 5.验证曲线(绘制分数评估模型)

5.总结

本周详细介绍了机器学习中的模型选择与评估方法。首先,通过交叉验证(CV)技术评估模型的泛化能力,包括k折交叉验证和随机排列交叉验证,这些方法能够帮助减少过拟合风险,并提供对模型性能更为可靠的估计。其次,也学习了如何使用网格搜索(Grid Search)和随机搜索(Randomized Search)来寻找最优的超参数设置,这两种方法可以显著提升模型性能。此外,本周还分析了如何调整分类器的决策阈值以改善预测效果,并介绍了如何利用多种评分指标(如准确率、F1分数等)来量化预测质量。综合这些方法和技术,可以有效地评估和选择最佳模型,以应对实际问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值