在数据分析的过程中,有时我们的标签数据分布不平衡,比如要对是否对客户授信放贷进行建模,如果我们手上的原始数据中,获得贷款的样本数量比没有获得贷款的样本数量要多得多的话,那么这个数据是极其不平衡的,再进行建模将数据汇给模型的时候,非常容易导致过拟合的现象,因为这个模型更加偏向于对客户授信。这个时候需要进行交叉验证,通过对数据进行随机化而分组。
KFold与StratifiedKFold
在机器学习中经常会用到交叉验证,常用的就是KFold和StratifiedKFold,那么这两个函数有什么区别,应该怎么使用呢?
首先这两个函数都是sklearn模块中的,在应用之前应该导入:
from sklearn.model_selection import StratifiedKFold,KFold
KFold划分数据集:根据n_split直接进行顺序划分,不考虑数据label分布
StratifiedKFold划分数据集:划分后的训练集和验证集中类别分布尽量和原数据集一样
KFold函数
KFold函数共有三个参数:
- n_splits:默认为3,表示将数据划分为多少份,即k折交叉验证中的k;
shuffle:默认为False,表示是否需要打乱顺序,这个参数在很多的函数中都会涉及,如果设置为True,则会先打乱顺序再做划分,如果为False,会直接按照顺序做划分;
在每次划分时,是否进行洗牌,若为False,其效果相当于random_state为整数(含零),每次划分的结果相同,若为True,每次划分的结果不一样,表示经过洗牌,随机取样的
random_state:默认为None,表示随机数的种子,只有当shuffle设置为True的时候才会生效。
将训练/测试数据集划分n_splits个互斥子集,每次只用其中一个子集当做测试集,剩下的(n_splits-1)作为训练集,进行n_splits次实验并得到n_splits个结果。
对于不能均等分的数据集,前n_samples%n_spllits子集拥有n_samples//n_spllits+1个样本,其余子集都只有n_samples//n_spllits个样本。(例10行数据分3份,只有一份可分4行,其他均为3行)
from sklearn.model_selection import KFold
import numpy as np
X = np.array([[10, 1], [20, 2], [30, 3], [40, 4], [50, 5], [60, 6], [70, 7], [80, 8], [90, 9], [100, 10], [90, 9], [100, 10]])
# 两个类别:1:1
Y = np.array([1,1,1,1,1,1,2,2,2,2,2,2])
print("Start Testing KFold...")
# KFold划分数据集的原理:根据n_split直接进行顺序划分
kfolds = KFold(n_splits=3, shuffle=False)
for (trn_idx, val_idx) in kfolds.split(X, Y):
print((trn_idx, val_idx))
print((len(trn_idx), len(val_idx)))
StratifiedKFold
StratifiedKFold函数的参数与KFold相同。
from sklearn.model_selection import StratifiedKFold
import numpy as np
X = np.array([[10, 1], [20, 2], [30, 3], [40, 4], [50, 5], [60, 6], [70, 7], [80, 8], [90, 9], [100, 10], [90, 9], [100, 10]])
# 两个类别:1:1
Y = np.array([1,1,1,1,1,1,2,2,2,2,2,2])
print('\n' + "Start Testing StratifiedKFold...")
# StratifiedKFold: 抽样后的训练集和验证集的样本分类比例和原有的数据集尽量是一样的
stratifiedKFolds = StratifiedKFold(n_splits=3, shuffle=False)
for (trn_idx, val_idx) in stratifiedKFolds.split(X, Y):
print((trn_idx, val_idx))
print((len(trn_idx), len(val_idx)))