在Sklearn中的K折交叉验证

在Sklearn中的K折交叉验证

从数据收集中创建用于训练和验证模型的数据集是提高模型性能最常见的机器学习方法。数据集的拆分比例可以是70:30或80:20。保留法是最常见的交叉验证方法。

这种方法的问题在于我们不能确定模型的良好验证准确度分数是否代表一个好模型。如果我们使用数据集中的某一部分作为验证数据集,我们的模型是否仍会给出高准确度分数?K折交叉验证提供了对这些问题的一些解决方案。

什么是交叉验证

当我们需要对一个性能得分良好的机器学习模型进行训练时,将数据集分成训练集和验证集是一项基础且重要的操作。我们必须在一组未见过的数据集(验证集)上测试我们的模型,以评估其是否过拟合。

如果模型在验证数据集上没有良好的准确度分数,那么当提供真实的实时数据时,该模型将会给出低性能分数。鉴于这个想法,交叉验证可能是保证我们模型的鲁棒性最关键的机器学习概念之一。

交叉验证实质上是一个简单地将数据集的一部分设置为验证和测试模型的过程,而剩余的数据集用于模型的训练。

使用交叉验证的好处

  • 它帮助我们评估模型并确定其准确性。
  • 有助于确定模型是否成功地推广到数据。
  • 确定模型是否过度拟合或欠拟合。
  • 最后,它允许我们选择性能最佳的模型。

许多类型的交叉验证

  1. K折交叉验证
  2. 分层K折交叉验证
  3. 留P出交叉验证
  4. 留一出交叉验证
  5. 时间序列交叉验证
  6. 随机分割交叉验证

什么是K折交叉验证

K折交叉验证方法广泛用于计算机器学习模型在验证数据集上的性能如何。

虽然10是常见的k值选择,但我们如何确信这个折叠对于数据集和模型是合适的?

一种方法是研究不同k选择对估计模型性能的影响,并将其与理想测试条件进行比较。这可以帮助选择正确的折数。

一旦确定了k值,我们可以使用它来评估数据集上的不同模型。然后,我们可以将分数的模式与相同模型在理想测试情况下的分数进行对比,以查看它们是否强相关。如果结果相关,则确认选择的配置是对理想测试环境的可靠近似。

本教程将教读者如何设置和评估K折交叉验证的设置。

K折交叉验证方法的步骤

作为一般的步骤,具体如下:

  1. 随机打乱完整数据集。
  2. 算法将数据集划分为k个组,即k折数据。
  3. 对于每个不同的组:
  4. 使用数据集作为留存数据集来验证模型。
  5. 使用其他组的数据集来训练模型。
  6. 在训练数据集上拟合模型,然后在留存或验证数据集上进行评估。
  7. 保留评估结果,但弃用生成的模型。
  8. 通过模型评估得分的结果,总结模型的性能。

每个数据集中的每个项目都被赋予一个唯一的组,并在整个过程中保持不变。这表明每个数据样本在训练数据集中有k次机会成为一部分,并在留存或验证数据集中有k次机会。

在拟合模型之前,所有的数据准备工作都必须在循环的CV分配的训练数据集上进行,而不是更大的数据集。这也适用于任何超参数调整。如果不在循环内执行这些步骤,可能会发生数据泄漏和对模型技能的夸大评估。

K折交叉验证测试的示例

代码

# Python program to perform kfold cross-validation test on breast cancer dataset

#Importing required libraries
from sklearn.datasets import load_breast_cancer
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import KFold 
from sklearn.metrics import accuracy_score

#Loading the dataset
data = load_breast_cancer(as_frame = True)
df = data.frame

# Segregating dependent and independent features
X = df.iloc[:,:-1] 
Y = df.iloc[:,-1]

#Implementing k-fold cross-validation

k = 5
k_fold = KFold(n_splits = k, random_state = None)
Lr = LogisticRegression(solver = 'liblinear')

acc_scores = []

# Looping over each split to get the accuracy score of each split
for training_index, testing_index in k_fold.split(X):
    X_train, X_test = X.iloc[training_index,:], X.iloc[testing_index,:]
    Y_train, Y_test = Y.iloc[training_index] , Y.iloc[testing_index]

    # Fitting training data to the model
    Lr.fit(X_train,Y_train)

    # Predicting values for the testing dataset
    Y_pred = Lr.predict(X_test)

    # Calculatinf accuracy score using in-built sklearn accuracy_score method 
    acc = accuracy_score(Y_pred , Y_test)
    acc_scores.append(acc)

# Calculating mean accuracy score
mean_acc_score = sum(acc_scores) / k

print("Accuracy score of each fold: ", acc_scores)
print("Mean accuracy score: ", mean_acc_score)

输出:

Accuracy score of each fold:  [0.9122807017543859, 0.9473684210526315, 0.9736842105263158, 0.9736842105263158, 0.9557522123893806]
Mean accuracy score:  0.952553951249806

使用cross_val_score()进行交叉验证

我们可以使用cross_val_score类方法来缩短上述代码

代码

# Python program to perform kfold cross-validation test on breast cancer dataset

#Importing required libraries
from sklearn.datasets import load_breast_cancer
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import KFold 
from sklearn.model_selection import cross_val_score

#Loading the dataset
data = load_breast_cancer(as_frame = True)
df = data.frame

# Segregating dependent and independent features
X = df.iloc[:,:-1] 
Y = df.iloc[:,-1]

#Implementing k-fold cross validation
k = 5
k_fold = KFold(n_splits = k, random_state = None)
Lr = LogisticRegression(solver = 'liblinear')
Lr.fit(X, Y)

# Finding accuracy scores using cross_val_score methods
score = cross_val_score(Lr, X, Y, cv = k_fold)

# Calculating mean accuracy score
mean_acc_score = sum(score) / len(score)

print("Accuracy score of each fold: ", acc_scores)
print("Mean accuracy score: ", mean_acc_score)

输出:

Accuracy score of each fold:  [0.9122807017543859, 0.9473684210526315, 0.9736842105263158, 0.9736842105263158, 0.9557522123893806]
Mean accuracy score:  0.952553951249806

K-fold交叉验证方法有助于在较小的数据集上训练我们的模型。如果我们的数据收集非常广泛,则可能不需要K-fold交叉验证。其原因是我们的验证数据集包含足够的记录,可以验证我们的机器学习模型的性能。在大规模数据集上使用K-fold交叉验证测试需要很长时间。

此外,使用更多的折叠来验证我们的模型会消耗更多的计算资源。对于较大的K值,模型的训练时间会更长。如果K等于5,则模型会经历使用验证数据集的五个不同折叠进行的五次独立训练运行。如果K等于10,则模型会进行十次运行。

K的敏感度分析

K-fold交叉验证测试中最重要的参数是K值,它指定将给定数据集分成多少折。

对于一个平均大小的数据集,一般选择K=3、K=5和K=10。观察到K=10在评估我们训练模型性能时最广泛使用。选择这个特定值的原因是因为研究表明K=10在计算开销较低和评估模型性能时具有适度偏差之间提供了合理的平衡。

在对我们的数据集样本进行测试时,我们如何确定使用哪个K值?

虽然K=10是一个选择,但如何确保它对我们的数据集公正?

回答这个问题的一种方法是运行敏感度分析,尝试不同的K值。换句话说,比较在相同的数据集上使用不同K值训练的相同模型的结果。

假设小的K值会产生嘈杂的模型性能预测,而大的K值会产生较少噪声的预测。

与什么相比较嘈杂?

当我们通过未见过的数据将其传递到模型中时,我们无法获取模型的真实性能。如果我们知道了模型的真实性能,我们可以将其应用于模型的评估。

然而,我们可以选择一个测试条件,作为对模型性能的“理想”或最接近理想估计的预测。

一种策略是使用所有可用的数据来训练模型,然后使用不同的大样本保留数据集来估算其性能。保留数据上的性能会指示模型的“实际”性能。相比之下,训练数据集上的任何交叉验证得分都是对这个真实分数的估计。我们提到的方法很少可行,因为我们常常缺乏将一部分主要数据集用作测试数据集的数据。

留一交叉验证(LOOCV)是交叉验证的一种计算密集型修改方法,其中K=N,N为训练数据集中的样本总数。我们可以选择使用它来模拟这种情况。换句话说,为验证数据集中的每个集合提供训练数据集中的单个样本。在给定适当的数据的情况下,它可以生成对模型性能的良好估计,但由于高计算成本,它很少在大型数据集上使用。

然后,使用相同的数据集进行LOOCV,我们可以评估LOOCV过程的平均分类准确率,并与不同K值的平均分类准确率进行对比。分数之间的差异提供了一个粗略的近似,用于确定K值与理想模型性能测试条件的接近程度。

让我们看一下如何进行k折交叉验证过程的敏感性分析。

  1. 让我们首先开发一个构建数据集的函数。这样我们可以选择用任何数据集替换它。
  2. 然后,我们可以定义用于构建要评估的模型的数据集。再次强调,这种区分使我们能够根据我们的需求定制模型。
  3. 随后,我们可以创建一个使用测试条件在验证数据集上验证模型的函数。测试条件可以是LeaveOneOut的示例,表示我们理想的测试条件,也可以是使用特定k值参数化的KFold对象。该函数除了提供平均分类准确度外,还提供了各折的最小和最大分类准确度值。可以使用最小值和最大值总结得分的范围。
  4. 然后,我们将使用LOOCV方法来计算模型性能。
  5. 然后,我们可以定义进行分析的k值。在本例中,我们将测试2到20之间的数字。然后,我们可以逐个分析每个值并记录结果。

代码

# Python program to perform kfold cross-validation sensitivity analysis
from numpy import mean
from sklearn.datasets import make_classification
from sklearn.model_selection import LeaveOneOut, KFold, cross_val_score
from sklearn.linear_model import LogisticRegression

# creating the dataset
def get_dataset(number_samples=1000):
    X, Y = make_classification(n_samples=number_samples, n_features=27, n_informative=20, n_redundant=6, random_state=10)
    return X, Y

# getting the model object to be used for evaluation
def get_model():
    model = LogisticRegression()
    return model

# evaluating the model performance using a test condition
def evaluate_model_performance(cv_method):
    # getting the dataset
    X, Y = get_dataset()
    # getting the model
    model = get_model()
    # evaluating the model
    scores = cross_val_score(model, X, Y, scoring='accuracy', cv=cv_method, n_jobs=-1)
    # returning the mean, minimum and maximum scores
    return round(mean(scores), 2), round(scores.min(), 2), round(scores.max(), 2)

# calculating the ideal test condition
ideal_score, _, _ = evaluate_model_performance(LeaveOneOut())
print("Ideal score: ", ideal_score)

# defining the number of folds to test
folds = range(2, 21)

# calculation accuracy for each k value in the defined range
for k in folds:
    # defining the test condition
    cv_method = KFold(n_splits=k, shuffle=True, random_state=10)
    # evaluating the k value
    mean_k, min_k, max_k = evaluate_model_performance(cv_method)
    # printing the performance of each k value
    print(f"Folds={k}, accuracy={mean_k} ({min_k},{max_k})")

输出:

Ideal score:  0.83
Folds=2, accuracy=0.81 (0.81,0.81)
Folds=3, accuracy=0.83 (0.79,0.85)
Folds=4, accuracy=0.84 (0.8,0.86)
Folds=5, accuracy=0.83 (0.78,0.88)
Folds=6, accuracy=0.83 (0.77,0.88)
Folds=7, accuracy=0.83 (0.76,0.89)
Folds=8, accuracy=0.83 (0.77,0.88)
Folds=9, accuracy=0.83 (0.75,0.9)
Folds=10, accuracy=0.82 (0.74,0.9)
Folds=11, accuracy=0.83 (0.77,0.9)
Folds=12, accuracy=0.83 (0.7,0.9)
Folds=13, accuracy=0.82 (0.77,0.91)
Folds=14, accuracy=0.82 (0.66,0.93)
Folds=15, accuracy=0.82 (0.76,0.92)
Folds=16, accuracy=0.83 (0.67,0.92)
Folds=17, accuracy=0.83 (0.73,0.93)
Folds=18, accuracy=0.83 (0.68,0.93)
Folds=19, accuracy=0.82 (0.68,0.92)
Folds=20, accuracy=0.82 (0.66,0.96)

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程