Skip to content

前言

  • 训练集:用于模型拟合的数据样本。
  • 验证集:是模型训练过程中单独留出的样本集,它可以用于调整模型的超参数和用于对模型的能力进行初步评估。常采用交叉验证的方法将训练数据集再细分成不同的验证数据集去训练模型。
  • 测试集:用来评估最终模型的泛化能力。但不能作为调参、选择特征等操作的依据。

机器学习过程中,我们常常将数据分为训练集和测试集。测试集完全不参与模型的训练,而用于最终模型的评估。在训练过程中,常常会出现过拟合问题,即训练误差小,测试误差大。如果此时就使用测试数据来调整模型参数,就相当于在训练时已知部分测试数据的信息,会影响最终评估结果的准确性。通常的做法是在训练数据再中分出一部分做为验证(Validation)数据,用来评估模型的训练效果。

验证数据取自训练数据,但不参与训练,这样可以相对客观的评估模型对于训练集之外数据的匹配程度。

KFold交叉验证

模型在验证数据中的评估常用的是交叉验证,又称循环验证。它将原始数据分成K组(K-Fold),将每个子集数据分别做一次验证集,其余的K-1组子集数据作为训练集,这样会得到K个模型。这K个模型分别在验证集中评估结果,最后的误差MSE(Mean Squared Error)加和平均就得到交叉验证误差。交叉验证有效利用了有限的数据,并且评估结果能够尽可能接近模型在测试集上的表现,可以做为模型优化的指标使用。

1、如果训练数据集相对较小,则增大k值。
增大k值,在每次迭代过程中将会有更多的数据用于模型训练,能够得到最小偏差,同时算法时间延长。且训练块间高度相似,导致评价结果方差较高。
2、如果训练集相对较大,则减小k值。
减小k值,降低模型在不同的数据块上进行重复拟合的性能评估的计算成本,在平均性能的基础上获得模型的准确评估。

代码实例

判断模型在新数据上的拟合质量(或预期值)可以采用score方法,越大越好。

from sklearn import datasets, svm
digits = datasets.load_digits()
X_digits = digits.data
y_digits = digits.target
svc = svm.SVC(C=1, kernel='linear')
svc.fit(X_digits[:-100], y_digits[:-100]).score(X_digits[-100:], y_digits[-100:])
0.98

kfold交叉验证

from sklearn import datasets
import numpy as np
from sklearn import svm

digits = datasets.load_digits()
X = digits.data
y = digits.target
svc = svm.SVC(C=1,kernel='linear')
#svc.fit(X[:-100],y[:-100])
#print(svc.score(X[-100:],y[-100:]))  #用最后100个测试
X_folds = np.array_split(X,3)  #将数组三个一组分割
y_folds = np.array_split(y,3)
scores = []
for k in range(3):
    X_train = list(X_folds)
    X_test = X_train.pop(k)      #pop会改变原数组,X_train也删除了索引为k的元素
    X_train = np.concatenate(X_train)
    y_train = list(y_folds)
    y_test = y_train.pop(k)
    y_train = np.concatenate(y_train)
    scores.append(svc.fit(X_train,y_train).score(X_test,y_test))
print(scores)
[0.9348914858096828, 0.9565943238731218, 0.9398998330550918]

交叉验证生成器

sklearn有直接生成训练/测试索引列表的类,更简洁、方便的实现交叉验证。类提供了 split 方法,方法允许输入能被分解的数据集,并为每次选择的交叉验证策略迭代生成训练/测试集索引

from unicodedata import digit
from sklearn.model_selection import KFold,cross_val_score
from sklearn import datasets,svm

digits = datasets.load_digits()
X_digits = digits.data
y_digits = digits.target
svc = svm.SVC(C=1,kernel='linear')

X = ['a','a','b','c','c','c']
k_fold = KFold(n_splits=3)
for train_indices,test_indices in k_fold.split(X):
    print(f'Train:{train_indices} | test:{test_indices}')

Train:[2 3 4 5] | test:[0 1]
Train:[0 1 4 5] | test:[2 3]
Train:[0 1 2 3] | test:[4 5]

根据选取的索引进行交叉验证

socres = [svc.fit(X_digits[train],y_digits[train]).score(X_digits[test],y_digits[test])
for train,test in k_fold.split(X_digits)]:
    print(socres)
[0.9348914858096828, 0.9565943238731218, 0.9398998330550918]

也可以直接用cross_val_score算出交叉验证分数

print(cross_val_score(svc,X_digits,y_digits,cv=k_fold,n_jobs=-1)) #n_jobs=-1运算调度到全部cpu上进行
[0.93489149 0.95659432 0.93989983]

通过改变scoring参数来指定替换的评分方法

print(cross_val_score(svc,X_digits,y_digits,cv=k_fold,scoring='precision_macro'))
[0.93969761 0.95911415 0.94041254]

https://blog.csdn.net/xiaohutong1991/article/details/107924703