关于交叉验证与数据集划分,及其实现
- 交叉验证,主要就是当数据集较小的时候,为了更好的利用数据集,以kfold为例,将其等分为k份,进行k次训练,每次训练以第i份为test,其他的k-1份为train,然后对得到的结果的取平均,得到最终的模型评估数据
- 一般的在k-1份上训练时,还需要兼具调参的过程,即选超参数
- 首先要知道如何得到最终的模型,分为两步
- 模型选择
- 模型评估
- 模型选择model selection:
- 作用是选出在val上表现最好的超参数,是纵向的比较(主要是比较超参数的选择)
- 模型评估model assessment:
- 作用是无偏的对选出的模型进行评估,是横向的比较(和其他模型比较)
- 一个数据集分为train_val_test三个部分
- 下面以常用的一种交叉验证方式进行说明:
- model_selection和test部分,用k-fold交叉验证,比如5折,10折
- model_selection内部的train_val的划分,可以交叉验证(cross validation,cv),也可以直接holdout(留一,也就是直接split)
- 实现部分:
- 首先明确,我们划分的应该是index!,而不是直接对data划分,对index的划分会更加灵活一点
- model_selection / test的划分:
- 常见的是使用sklearn的 StratifiedKFold,Stratify是分层的意思,这有助于保证label的比例在每个部分都是一定的,避免出现正类负类比例在train/test中的不平衡所引起的误差,更甚者,如果test全是一个label,是无法使用roc_auc_score()的!
- 首先是初始化:
class sklearn.model_selection.StratifiedKFold(n_splits=5, shuffle=False, random_state=None)
- 通过方法
split(self, X, y[, groups])
Generate indices to split data into training and test set 划分 - 我们可以看到返回的index,所以这里的X可以用data,但是更好的是用np.arange(len(targets)),何乐而不为呢?
- 在model_selection的划分一般就直接用train_test_split()
- 一般的我们将split好的indices存到json文件
self.splits = []
for train_idxs , test_idxs in outer_kfold.split(X=np.arange(len(targets)) , y =targets)
split = {"test":test_idxs , "model_selection":[]}
train_inner_idx , val_inner_idx = train_test_split(train_idxs , stratify = targets[train_idxs] , test_size = self.holdout_test_size)
split["model_selection"].append({"train":train_idxs[train_inner_idx] , "val":train_idxs[val_inner_idx]})
self.splits.append(split)
json.dump(self.splits , fp )
所用的函数: 1. sklearn : StratifiedKFold , train_test_split
REF:
A Fair Comparison of Graph Neural Networks for Graph Classificationarxiv.org( 知乎不会在提交之后再渲染一下markdown我是没想到的,属实xx