K折交叉验证|K Fold

机器学习 · 2023-04-01 · 219 人浏览
K折交叉验证|K Fold

背景

一般来说在训练时会将数据分为两部分,一部分用于训练,另一部分用于验证。这会引起以下几点问题:

  • 首先数据的切割是人为/随机的,不同切割可能会导致模型的不同精度。或者说人为切割的验证集有可能偏离了真实分布
  • 其次训练数据被分为两部分,验证集不参与训练,网络的数据来源缩水了,影响训练效果。虽然最后会将所有训练数据都丢入模型中来评估测试集,但是在这之前评估模型或者说模型调参还是只能使用一部分的训练数据

基本概念

K是一个指定的数字。执行K折交叉验证时,首先会将数据划分成(大致)相等的K个部分,每部分叫做一个。每次选取其中一个折作为验证集,由其他K-1个折作为训练集训练模型,训练好的模型用验证集评估正确性。

换句话说,K折交叉验证将会产生K个模型,最后得到的精度将是这K个模型精度的均值

交叉验证一般用于评估模型的泛化性能,也可以使用带交叉验证的网格搜索确定超参数

image-20230328104210900

优缺点

  • K折交叉验证的精度结果反映了模型对数据集中的所有样本都有较好的泛化性
  • 通过对数据的多次划分,提供了模型对于训练集选择的敏感性信息。即反映了数据在最好/最坏情况下模型的表现情况。
  • 交叉验证使数据使用更高效,K越大时,训练集的占比可以更大。更多的数据自然可以得到更精确的模型。

sklearn

from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression

iris = load_iris()
logreg = LogisticRegression(max_iter=1000)

scores = cross_val_score(logreg, iris.data, iris.target)
print("Cross-validation scores: {}".format(scores))

分层K折交叉验证 .etc

分层K折交叉验证

分层K折交叉验证保证了每个折中类别的比例和整个数据集中的相同。比如该数据集中90%的样本是A类,10%的样本是B类。那么K折中的每一折都是符合A占90%,B占10%。

分层K折避免这种情况发生:某一折里只包含A类的样本,导致验证精度很差,无法给出分类器的整体性能

随机K折交叉验证

为了避免标准K折交叉验证中折内类别比例异常的情况,还可以使用随机K折交叉验证。

kfold = KFold(n_splits=3, shuffle=True, random_state=0)
print("Cross-validation scores:\n{}".format(
    cross_val_score(logreg, iris.data, iris.target, cv=kfold))

留一法交叉验证

留一法可以看作是每折只有单个样本的K折交叉验证.

from sklearn.model_selection import LeaveOneOut
loo = LeaveOneOut()
scores = cross_val_score(logreg, iris.data, iris.target, cv=loo)
print("Number of cv iterations: ", len(scores))
print("Mean accuracy: {:.2f}".format(scores.mean()))

打乱划分交叉验证

每次划分为训练集采样train_size个点,为测试集(或者说验证集)采样test_size个点.将这种方法重复n_iter次.

image-20230328110830120

from sklearn.model_selection import ShuffleSplit
shuffle_split = ShuffleSplit(test_size=.5, train_size=.5, n_splits=10)
scores = cross_val_score(logreg, iris.data, iris.target, cv=shuffle_split)
print("Cross-validation scores:\n{}".format(scores))

打乱划分交叉验证允许在训练集和测试集大小之外指定迭代次数.也可以允许每次迭代仅使用部分数据.对于二次采样大型数据的试验比较有效.

分组交叉验证

有时候数据是分组的,比如每个人有多个数据.那么测试集中的数据最好是整组出现的,不应该出现测试集中某个人的数据出现在训练集中,这会影响对模型的泛化能力的评估.

image-20230328111504785

from sklearn.model_selection import GroupKFold
# create synthetic dataset
X, y = make_blobs(n_samples=12, random_state=0)
# assume the first three samples belong to the same group,
# then the next four, etc.
groups = [0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3]
scores = cross_val_score(logreg, X, y, groups=groups, cv=GroupKFold(n_splits=3))
print("Cross-validation scores:\n{}".format(scores))
机器学习 K Fold
Theme Jasmine by Kent Liao