社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  机器学习算法

机器学习必须了解的7种交叉验证方法

生态遥感前沿 • 1 年前 • 324 次点击  

Part17种机器学习交叉验证方法

交叉验证在机器学习模型中的主要目的是为了防止过拟合,并提高模型的泛化能力

过拟合是指模型在训练数据上训练得过于完善,但在新的未见数据上表现不佳。

什么是“训练-测试-验证”?

我们通常根据训练-测试拆分,会将同一个数据集分为训练和测试

训练集用于训练模型。模型参数从训练集中学习它们的值。最终评估是在测试集上进行的,该测试集在训练期间模型是不知道的。

除了训练-测试集外,还有另一个被称为验证集的数据集。

验证集用于通过不同组合的超参数多次训练模型。因此,它用于超参数调整。

一个非常简单的划分方法:我们可以通过两次调用 Scikit-learntrain_test_split() 函数,将整个数据集分为训练集、测试集和验证集。

X_train, X_rem, y_train, y_rem = train_test_split(X, y,
                                                  train_size=0.70)

X_valid, X_test, y_valid, y_test = train_test_split(X_rem,y_rem,
                                                    test_size=0.15)

当以这种方式进行拆分时,训练集(X_train 和 y_train 部分)占70% ,测试集和验证集(X_test 和 y_test 部分)占 15%

在大多数情况下,我们不会以这种方式创建单独的验证集,而是用交叉验证。可惜大部分的机器学习学者仅仅将数据集简单划分,而不考虑交叉验证。

引用一个段落来说明交叉验证的精髓:

将训练集(有时是整个数据集)分成多个Folder(子集),并使用一个Folder作为验证集,其余Folder作为训练集。我们在不同的迭代中更换验证Folder。每次迭代的评估分数会被平均,以获得模型更稳健的评估分数。

让我们开始吧~

1训练数据和模型

本文的数据是python自带的iris鸢尾花数据集,模型用随机森林简单展示。代码如下,数据和代码可以文末下载:

from sklearn.model_selection import train_test_split
import pandas as pd
dataset = pd.read_csv('/home/mw/project/iris.csv')

数据属性

我们用四个花的属性预测类别(即这是一个分类问题):

X = dataset[['Sepal.Length''Sepal.Width''Petal.Length''Petal.Width']]
y = dataset['Species']

2训练-测试拆分

训练-测试划分

代码如下:

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y,
                                                    train_size=0.80)

当数据集较小时,应为训练集分配大约 70-80% 的实例。

当数据集非常大时,应为训练集分配大约 95-98% 的实例。

一个经验是,分配给训练模型的数据越多,模型就越好!

训练-测试拆分不适用于不平衡的数据集。分类数据集可能遭受类别不平衡的问题。因此,训练集可能包含同一类的所有实例,模型将无法在新的未见数据上实现泛化

留出验证可能产生高方差和不一致的结果。这是因为拆分是在数据点的不同组合上进行的,训练集可能无法完全代表原始数据集。

顺便再训练出我们的随机森林模型:

from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier(random_state=0)
model = model.fit(X_train,y_train)
score_c = model.score(X_test, y_test)

3k折交叉验证

k折交叉验证是最常用(也是最推荐)的交叉验证技术。使用k折交叉验证,你会得到一致的结果,且能选择优秀的超参数

在k折交叉验证中,原始数据集或训练数据集被拆分为k个折叠(子集)。然后,我们训练模型k次(迭代),并获得k个性能估计。在每次迭代中,我们使用一个折叠(验证折叠)评估模型,剩余的k-1个折叠用于训练模型。我们在每次迭代中也更换验证折叠,以更好地代表数据集。每次迭代记录的k个性能估计被平均,以获得模型的更稳健评估分数。

k折交叉验证可以通过多种方式执行。

最简单的方式是使用 Scikit-learnKFold() 函数。折叠数在 n_splits 超参数中指定。代码如下:

from sklearn.model_selection import KFold

kf = KFold(n_splits=5, shuffle=True)


for train_index, val_index in kf.split(X, y):
    X_train, X_val = X.iloc[train_index], X.iloc[val_index]
    y_train, y_val = y.iloc[train_index], y.iloc[val_index]
    
    # 在训练集上训练模型,然后在验证集上进行评估
    model.fit(X_train, y_train)
    score = model.score(X_val, y_val)
    
    # 打印模型评估结果
    print("Validation score:", score)

# X represents the entire dataset
k折交叉验证结果

结果表明模型的泛化能力比较好。

我们可以使用 Scikit-learnGridSearchCV()RandomizedSearchCV() 函数进行带有交叉验证的超参数调整。

from sklearn.model_selection import GridSearchCV
hyperparameter_space ={'n_estimators':range(1,101,10)}  

gs = GridSearchCV(model, param_grid=hyperparameter_space, 
                  scoring="accuracy", cv=5)

gs.fit(X_train, y_train)

打印gs.best_params_变量

选择最优超参数

最好的子树数量是71

4分层k折交叉验证

分层k折交叉验证概念图

分层K-Fold是K-Fold交叉验证法的一个增强版,主要用于不平衡数据集。就像K-fold一样,整个数据集被分为大小相同的K-fold。

不同之处在于,每个Fold保留了整个数据集中类标签实例的百分比。因此,分层k折交叉验证适用于类别不平衡的数据集。

我们可以使用 Scikit-learnStratifiedKFold() 函数来执行分层k折交叉验证。折叠数在 n_splits 超参数中指定。

from sklearn.model_selection import StratifiedKFold

skf = StratifiedKFold(n_splits=5, shuffle=True)

for train_index, val_index in skf.split(X, y):
    X_train, X_val = X.iloc[train_index], X.iloc[val_index]
    y_train, y_val = y.iloc[train_index], y.iloc[val_index]
    
    # 在训练集上训练模型,然后在验证集上进行评估
    model.fit(X_train, y_train)
    score = model.score(X_val, y_val)
    
    # 打印模型评估结果
    print("Validation score:", score)
分层k折交叉验证结果

5留一交叉验证

留一交叉验证

留一交叉验证(LOOCV)是k折交叉验证的一个特殊情况,其中k等于n(数据点的总数)。在LOOCV中,一个数据点被用作验证折叠,其余的n-1个折叠用作训练集。迭代的总次数也等于n。

可以使用 Scikit-learnLeaveOneOut() 函数执行留一交叉验证。

from sklearn.model_selection import LeaveOneOut

loo = LeaveOneOut()

for train_index, val_index in loo.split(X, y):
    X_train, X_val = X.iloc[train_index], X.iloc[val_index]
    y_train, y_val = y.iloc[train_index], y.iloc[val_index]
    
    # 在训练集上训练模型,然后在验证集上进行评估
    model.fit(X_train, y_train)
    score = model.score(X_val, y_val)
    
    # 打印模型评估结果
    print("Validation score:", score)

6留出交叉验证

留出交叉验证

留出交叉验证的工作原理与k折交叉验证完全相同,但每个折叠包含p个数据点,而不是将数据集分成k个折叠。在每次迭代中,p个数据点被用作验证集,其余的n-p个数据点用于训练模型。

我们举一个例子来区分k折交叉验证、留一交叉验证和留出交叉验证。假设我们的数据集中有100个数据点。

在k折交叉验证中,如果k=5,则每个折叠有20(100/5)个数据点。在留一出交叉验证中,每个折叠只有一个数据点。在留p出交叉验证中,如果p=5,则每个折叠有5个数据点。可以使用 Scikit-learnLeavePOut() 函数执行留p出交叉验证。

from sklearn.model_selection import LeavePOut

lpo = LeavePOut(5)

7蒙特卡罗交叉验证

蒙特卡洛交叉验证

蒙特卡洛交叉验证(Monte Carlo CV)将数据集分为训练集和验证集,类似于留出验证,但这个过程会重复多次(迭代)。就像在留出验证中一样,我们需要指定用作训练集或验证集的原始数据集的百分比。

  • 拆分迭代的次数也可以作为一个超参数来定义。更多的迭代次数会导致更好的性能,但也增加了计算成本。

  • 蒙特卡洛交叉验证的每次迭代中拆分是随机进行的,同一个数据点可以多次出现在测试折叠中。但在k折交叉验证中,这种情况不会发生!

  • 在蒙特卡洛交叉验证中,有些数据点永远不会被选为验证折叠!

from sklearn.model_selection import ShuffleSplit

MC = ShuffleSplit(n_splits=10, test_size=0.15)

for train_index, val_index in MC.split(X, y):
    X_train, X_val = X.iloc[train_index], X.iloc[val_index]
    y_train, y_val = y.iloc[train_index], y.iloc[val_index]
    
    # 在训练集上训练模型,然后在验证集上进行评估
    model.fit(X_train, y_train)
    score = model.score(X_val, y_val)
    
    # 打印模型评估结果
    print("Validation score:", score)

8时间序列交叉验证

上述交叉验证方法可能不适合评估时间序列模型,因为在时间序列数据中,数据的顺序非常重要。

在时间序列交叉验证中,折叠以前向链接的方式创建。我们从作为训练折叠的一小部分数据开始,并使用更小的数据子集作为验证折叠。验证折叠随时间向前移动,而前一个验证折叠在下一次迭代中被添加到训练折叠中。

我们可以使用 Scikit-learnTimeSeriesSplit() 函数来执行时间序列交叉验证。拆分的次数在 n_splits 超参数中指定。

from sklearn.model_selection import TimeSeriesSplit

tscv = TimeSeriesSplit(n_splits=5)

# X represents the entire dataset
for train_index, val_index in tscv.split(X, y):
    X_train, X_val = X.iloc[train_index], X.iloc[val_index]
    y_train, y_val = y.iloc[train_index], y.iloc[val_index]
    
    # 在训练集上训练模型,然后在验证集上进行评估
    model.fit(X_train, y_train)
    score = model.score(X_val, y_val)
    
    # 打印模型评估结果
    print("Validation score:", score)

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/166155
 
324 次点击