我不确定我是否了解该过程的每个部分,但它有一个明显的问题:因为 CV 应用于内部循环,因此存在严重的模型过度拟合其他参数(特征子集)的风险,模型类型,采样技术)。根据目标,这不一定是错误的,但相应地解释结果很重要。例如,在这种情况下,结果将显示不同的特征子集在数据上的表现如何,但子集之间的这种性能差异不应该被认为是可靠的:一个特定的子集可能碰巧比另一个子集更好。
这是一个相当复杂的设置,我假设需要考虑效率限制。如果可能的话,最可靠的结果将通过使用不同的数据子集进行几个阶段的 CV(或其他技术,例如bagging )来获得。例如,您可以运行整个过程几次,每次使用不同的随机实例子集:通过这种方式,您可以平均性能并查看特定的功能子集是否始终优于另一个(例如,对于其他功能的相同想法)参数)。
[已编辑] 免责声明:我不知道是否有任何标准方法可以进行这样的复杂多级设置,我的建议仅基于我对一些大致相似的案例的经验。
通常的想法是,每一个选择都可以被视为一个超参数,包括特征子集、模型类型、架构、采样技术。因此,我认为理想情况下应该在每个级别进行交叉验证,即将每个循环级别放在一个函数中,并使用不同的数据子集调用这个函数 k 次。它看起来像这样:
train1, val1 = splitDataset()
iterate each featureSubset:
train2, val2 = splitData(train1)
resultTrain2 = kfoldCV(processLevel2, train2)
resultLevel2 = apply(resultTrain2, val2)
resultLevel1 = apply(resultLevel2, val1)
processLevel2:
iterate each modelType:
train3, val3 = splitData(train2)
resultTrain3 = kfoldCV(processLevel3, train3)
...
备注:我不是 100% 确定算法,也许我过于复杂了。我认为它给出了一般的想法。
但是当然按照这个逻辑计算复杂度变得太高了,所以你可能不得不走一些捷径。我过去成功尝试过的一件事是使用遗传学习来同时优化不同的参数:这意味着拥有代表不同参数(特征子集、模型类型等)的不同“基因”,每个都有它的一组值,然后运行应该收敛到所有参数的一组最佳值的遗传过程(每次评估特定的参数组合时我都使用 CV)。但是我不知道这是否是一种非常正统的方法:)
[编辑2]
经过更多思考,我想我会尝试做这样的事情:
innerData, valOuter = splitDataset() // keep large amount for validation set, say between 20-40%
train, valInner = splitDataset(innerData)
iterate each featureSubset:
iterate each modelType:
model = manuallySearchGoodArchitecture(featureSubset, modelType, train, val)
iterate each samplingTechnique:
train_temporary = applySampling(samplingTechnique)
HPs = HPOptimization(model, train_temporary, valInner)
result = k-FOldCV(model, HPs, samplingTechnique, train)
end
end
end
bestHPCombinations = select top N HPCombinations from first stage
for each HPCombination in bestHPCombinations
model = train(innerData)
result = apply(model, valOuter)
end
它更简单:这个想法只是对一些新数据重新评估第一阶段的结果,以避免过度拟合(这里 HPCombination 包括 featuresSubset、modelType 等)。第二阶段还可以包括 CV 或 bagging,以获得更可靠的结果。但总的来说,我认为这个选项是相当可靠的,因为第一阶段的最佳模型不太可能只是偶然地成为第二阶段的最佳模型。