.Start:
特征选择,归一化是数据处理中必备的两个步骤,交叉验证是模型评估以及超参数搜索中经常用到的方法。然而在实际操作中,初学者往往会有这样的疑问:
(1)是先做特征选择还是先划分 训练集-验证集-测试集?
(2)是先做归一化还是先划分 训练集-验证集-测试集?
(3)交叉验证以及带有超参数寻优的交叉验证的细节?
在实际做研究/项目的过程中,初学者常常会有上述疑问,以笔者多年的文献阅读以及code review的经历来看,很多人并没有搞清楚这些问题,即使文章已经在会议/期刊上面正式发表,有的人似乎根本没有注意到这个问题。鉴于此笔者尝试回答上述问题,以加强对机器学习中 追求模型泛化能力 这一终极目标的理解。
通俗地讲,我们的目的是利用已知数据训练模型,期望它在未知数据上有良好的测试性能。 已知数据指的就是训练集, 未知数据指的就是测试集, 测试性能指的就是泛化能力。因此,专业的讲,我们的目的是 利用训练集来训练模型使得它具有良好的泛化能力。
模型在训练集上的表现,即训练误差,只能度量模对训练集的拟合程度。为了度量模型的泛化能力,需要另外一份独立的数据集,即测试集,该数据集应该与训练集独立/没有交集并且服从相同的分布(即独立同分布, I.I.D)。模型在该测试集上的表现,即测试误差,能够反映模型的泛化能力。
几个小问题:
(1)如何评估模型好坏?
根据“奥卡姆剃刀”准则, 一个好的模型既不能太简单也不能太复杂(简单和复杂指的是模型的复杂度),太简单易出现欠拟合,太复杂易出现过拟合。通过对比模型的训练误差和测试误差的差异可以评估模型的好坏:1)训练误差<<测试误差:出现过拟合,此时应当尝试降低模型复杂度或者扩充训练集;2)训练误差和测试误差都很小:出现欠拟合,此时应当尝试增加模型复杂度。3)测试误差接近训练误差:模型较好。
(2)验证集发挥什么作用?
在没有超参数寻优时,只需要划分训练集-测试集即可。当模型有超参数需要确定时,就需要另外一份独立的数据集,即验证集,用于确定最优超参数。
训练集不能作为验证集:原因与划分训练集-测试集类似,给超参数指定一个值,用训练集训练模型然后在训练集上评估超参数不同取值的优劣,会导致选出的最有超参数是有偏的。
测试集不能作为验证集:在模型训练/超参数调优的过程中,测试集是未知的,将测试集作为验证机等同于“作弊”。
总的来说,训练集,验证机,测试集三者应该是I.I.D.,。
应该先划分 训练集-验证集-测试集,否则会存在数据泄露的问题,因为特征选择过程中利用了验证集,测试集的信息。
具体流程:首先划分 训练集-验证集-测试集,然后在训练集上进行特征选择,筛选出有效特征(特征子集)后,把训练集,验证集和测试集往特征子集上分别进行投影,得到最终的 训练集-验证集-测试集。
应该先划分 训练集-验证集-测试集,否则会存在数据泄露的问题,因为归一化过程中(具体来说就是确定归一化参数normalizer)利用了验证集,测试集的信息。
具体流程:首先划分 训练集-验证集-测试集,然后在训练集上拟合用于归一化的normalizer, 然后将normalizer分别应用于训练集,验证集,测试集,得到最终的 训练集-验证集-测试集。
说明:normalizer的具体参数形式取决于归一化的方式:
(1) min-max normalization: normalizer指的是训练集中每个特征的最小值和最大值对组成的集和 { ( m i n k , m a x k ) } k = 1 k = K \{(min_k, max_k)\}_{k=1}^{k=K} {(mink,maxk)}k=1k=K , K为特征的数量,min_k, max_k分别表示第k个特征的最小值和最大值。
归一化的具体过程如下:
x k x_{k} xk=( x k x_{k} xk - m i n k min_{k} mink) / ( m a x k max_{k} maxk - m i n k min_{k} mink), k ∈ \in ∈ {1,2, …, K}
(2) Z-Score normalizer: normalizer指的是训练集中每个特征取值的均值和标准差对组成的集和: { ( m e a n k , s t d k ) } k = 1 k = K \{(mean_k, std_k)\}_{k=1}^{k=K} {(meank,stdk)}k=1k=K,
归一化的具体过程如下:
x k x_{k} xk=( x k x_{k} xk - m e a n k mean_k meank) / s t d k std_k stdk, k ∈ \in ∈ {1,2, …, K}
交叉验证的目的:消除因数据划分对模型测试性能的影响,从而得到更加客观、可靠的结果。
过程: 将数据集K等分,用第k份数据作为测试集用来测试在其余K-1份数据集上训练的模型,得到测试结果,然后遍历k的取值,最终的结果即为K次结果的平均值。论文中呈现的结果(测试集上的结果)一般为 mean(std)的形式。K一般取10,称为10折交叉验证,需要跑10次实验。
带有超参数寻优的交叉验证: 除了外层的交叉验证用于消除因数据划分对模型测试性能的影响,内层还有一次交叉验证用于消除因数据划分对超参数选择的影响。
过程: 每确定一组超参数组合, 将数据集 K 2 K_2 K2等分, 第k (k ∈ \in ∈ {1,2,…, K 2 K_2 K2})次时(外层),将第k份数据作为测试集,将其余K-1份数据再 K 1 K_1 K1等分(内层),将其中第m(m ∈ \in ∈ {1,2,…, K 1 K_1 K1})份数据作为验证集,其余 K 1 K_1 K1 -1份数据作为训练集,遍历m, 将 K 1 K_1 K1次运行结果的平均值做为选择当前超参数组合且第k份数据作为测试集时模型的性能,再遍历k,将 K 2 K_2 K2 次运行结果的平均值作为选择当前超参数组合时模型的性能。 可以看到,每选择一组超参数组合,需要运行实验 K 1 K_1 K1 ⋅ \cdot ⋅ K 2 K_2 K2 次, 假设超参数组合数量为P, 则需要运行 K 1 K_1 K1 ⋅ \cdot ⋅ K 2 K_2 K2 ⋅ \cdot ⋅ P P P次实验,而 P与超参数的数量以及每个超参数的取值范围大小成指数关系, 因此运行的试验次数是非常大的 。
高级的超参数寻优技术:为了克服上述问题,提出了启发式的超参数寻优方法, 例如 Bayesian optimization , random srearch etc 链接 , 本质上都是在确定性和不确定性之间权衡以找寻下一个潜在的最优超参数组合。
关于Bayesianoptimization 有几篇博客写的非常好,推荐:
关于 Random search:
3. https://zhuanlan.zhihu.com/p/26964683
此外,还有遗传算法,粒子群算法用于超参数的确定,不再赘述。
本博客为笔者日常思考的总结,如有帮到大家,不胜欣慰。