在建模时一般要将数据集划分为训练集、验证集、测试集
一、为什么要划分?
构建模型的目标是通过在训练集上训练模型,然后在验证集上验证模型的参数效果,最后在测试集上测试模型的泛化能力。
最终的目标是使模型的泛化能力最大化,也就是泛化误差最小化,然而怎样去度量或者近似度量泛化误差呢?
1.训练误差=经验误差(×)
原因:很可能出现过拟合,也有可能出现欠拟合
- 过拟合:学习器把训练样本学的太好了,以至于把训练样本自身的一些性质作为潜在样本会具有的一般性质,这样会导致泛化性能下降。
- 欠拟合:训练样本的一般性质尚未学好
2.泛化误差(×)
不可能泛化到所有的可能性
3.测试误差作为泛化误差的近似(✔)
二、怎样划分?
1.留出法(hold-out cross-validation)
- 要尽可能保持数据分布的一致性,也就是训练集和测试集中样本类别比例是一致的。
- 一般取2/3~4/5作为训练集。
- 适用:数据量足够
- 缺点:只做一次分割且比例是自己确定的、分割后数据分布与原始分布的差异等敏感问题
- 改进:在验证模型效果的时候,可以随机分割训练集和测试集,一般随机生成10000次,然后生成模型准确率的分布。这样评估模型效果更加客观。通过分布,可以看到模型表现最差的时候是什么水平,如果最差的情况都可以接受,那模型效果就合格了。
# 选择变量
y=churn['flag']
x=churn[['contract_month','internet_other','streamingtv']]
# 切分训练集与测试集
from sklearn.cross_validation import train_test_split
for i in range(1000):
X_train, X_test, y_train, y_test = train_test_split(x,y, test_size=0.3) # 不要设置随机种子random_state保证每次划分的随机性
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
2.k折交叉验证(K-fold)
- 一般取10
- 适用:数据量足够
- 缺点:k越大越好,但是计算负担大。对数据集的大小有很高的要求。如果数据量不是很足够的话,比如把k设成20,可能测试集里面就没有几个数据了。
(1)sklearn.model_selection
from sklearn.model_selection import StratifiedKFold
sk=StratifiedKFold(n_splits=5,shuffle=True,random_state=0)
# shuffle=True:先打乱顺序再做划分
# random_state=0(固定值就可以),保证每次的拆分结果是相同的
X_data = Train_data[feature_cols]
Y_data = Train_data['price']
# 将训练集拆分成训练集和验证集validation
for train_ind,val_ind in sk.split(X_data,Y_data):
train_x=X_data.iloc[train_ind].values
train_y=Y_data.iloc[train_ind]
val_x=X_data.iloc[val_ind].values
val_y=Y_data.iloc[val_ind]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
(2)sklearn.cross_validation
from sklearn.cross_validation import KFold
kf = KFold(25, n_folds=5, shuffle=False)
# 其他同上
- 1
- 2
- 3
(3)sklearn.cross_validation
from sklearn.cross_validation import cross_val_score
scores = cross_val_score(knn, X, y, cv=10, scoring='accuracy')
print(scores.mean())
- 1
- 2
- 3
3.自助法bootstrap
- 问题:改变了初始数据的分布,引入了估计偏差,也就是用改变数据分布带来的误差来弥补数据量少带来的误差。
- 适用:数据集较小,难以有效划分训练和测试集