模型选择
当假设空间含有不同的复杂度的模型时,会面临模型选择(Model Selection)问题。我们希望所选择的模型要与真模型的参数个数相同,所选择的模型的参数向量与真模型的参数向量相近。然而,一味追求提高分类器的预测能力,所选择的模型的复杂度会比真模型要高,这种现象被称为过拟合(Over-fitting)
过拟合指学习时选择的模型所含的参数过多,导致该模型对已知数据预测的很好,但对未知数据预测很差的现象。因此,模型选择旨在避免过拟合并提高模型的预测能力
在模型选择时,不仅要考虑对已知数据的预测能力,还要考虑对未知数据的预测能力
奥卡姆剃刀定律是机器学习选择算法时可参照的标准之一。其含义是:在其他条件一样的情况下,选择简单的那个
该定律的意义在于数据的拟合和低复杂性之间实际上存在着折衷
理论上假设的解决方案越复杂,就越能拟合数据,训练数据误差就会越低(左下图)
泛化数据误差实际是训练数据误差与另一个名为过拟合误差的函数之和
在泛化误差最小得情况下,可获得最佳复杂性
在现实生活中,通常只会获得训练数据误差。但实践表明,如果你不去选择能够使训练数据误差最小化的模型,而是选择复杂性低一点的模型,算法的表现往往会更好
过拟合是机器学习算法性能不佳得主要缘由。这也是在机器学习中应用奥卡姆剃刀定律的原因
模型选择方法主要有正则化和交叉验证方法
(1)正则化
模型选择的典型方法是正则化(Regularization)。正则化是结构风险最小化策略的实现,是在经验风险上加一个正则化项(Regularizer)或惩罚项(Penalty)。正则化项一般是模型复杂度的单调递增函数,模型越复杂,正则化值就越大,比如,正则化项可以是模型参数向量的范数
正则化符合奥卡姆剃刀(Occam’s razor)原理。奥卡姆剃刀原理应用于模型选择时认为,在所有可能选择的模型中,能够很好地解释已知数据并且尽可能简单才是最好的模型,也就是应该选择的模型。从贝叶斯估计的角度来看,正则化项对应于模型的先验概率。可以假设复杂的模型有较大的先验概率,简单的模型有较小的先验概率
(2)交叉验证
另一种常用的模型选择方法是交叉验证(Cross Validation)。如果给定的样本数据充足,进行模型选择的一种简单方法是随机地将数据集划分为训练集(Training set)、验证集(Validation Set)和测试集(Test Set)三部分。
训练集用来训练模型,验证集用于模型的选择,测试机则用于最终对学习方法进行评估,在学习到的不同复杂度的模型中,选择对验证集有最小预测误差的模型,由于验证集有足够多的数据,用它对模型进行选择是有效的
然而在许多实际应用中,数据是不充足的,为了选择好的模型,可以采用交叉验证方法,交叉验证的基本思路是重复的使用数据,把给定数据划分为训练集和测试集,在此基础上进行反复训练,测试和模型选择
1.简单交叉验证
简单交叉验证方法是随机地将已给数据分为训练集和测试集(如70%的数据作为训练集,30%的数据作为测试集),然后用训练集在各种条件下(如不同的参数个数)训练模型在测试集上评价各个模型的测试误差,选出测试误差最小的模型
示例如下
代码如下
from sklearn.model_selection import train_test_split import numpy as np X = np.array([[1, 2], [3, 4],[5,6],[7, 8]]) y = np.array([1, 2, 2, 1]) X_train,X_test,y_train,y_test = train_test_split(X,y, test_size=0.50, random_state = 5) print("X_train:\n",X_train) print("y_train:\n",y_train) print("X_test:\n",X_test) print("y_test:\n",y_test)
2. k-折交叉验证
在k-折交叉验证(k-fold Cross-Validation)中,首先随机地将已给数据划分为k个互不相交的大小相同的子集,然后利用k-1个子集的数据训练模型,利用余下的子集测试模型。将这一过程对可能的k种选择重复进行,最后选出k次评测中平均测试误差最小的模型
示例如下
from sklearn.model_selection import KFold import numpy as np X = np.array([[1, 2], [3, 4],[5,6],[7, 8]]) y = np.array([1, 2, 2, 1]) kf = KFold(n_splits=2) for train_index, test_index in kf.split(X): print("Train:", train_index,"Validation:",test_index) X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index]
3.留一交叉验证
k折交叉验证的特殊情形是k=N,即k设置为元组的个数,称为留一交叉验证(Leave-one-out Cross Validation),往往在数据缺乏的情况下使用
示例如下
from sklearn.model_selection import LeaveOneOut import numpy as np X = np.array([[1, 2], [3, 4],[5,6],[7, 8]]) y = np.array([1, 2, 2, 1]) loo = LeaveOneOut() loo.get_n_splits(X) for train_index, test_index in loo.split(X): print("train:", train_index, "validation:", test_index)
scikit-learn还提供了RepeatedKFold和StratifiedKFold验证方法 前者是针对非平衡数据的分层采样,分层采样就是每一个子集中都保持原始数据集的类别比例
创作不易 觉得有帮助请点赞关注收藏~~~