train_test_split
在分类问题中,我们通常通过对训练集进行train_test_split,划分成train 和test 两部分,其中train用来训练模型,test用来评估模型,模型通过fit方法从train数据集中学习,然后调用score方法在test集上进行评估,打分;从分数上我们可以知道 模型当前的训练水平如何。
然而,这种方式存:只进行了一次划分,数据结果具有偶然性,如果在某次划分中,训练集里全是容易学习的数据,测试集里全是复杂的数据,这样就会导致最终的结果不尽如意;反之,亦是如此。
因为没有测试集,所以先把训练集抽出来一些做测试集,一些做训练集,这是一次性的行为,接着,对我们的训练接进行cv折的交叉验证,得到分数, 选择分数最高的参数,然后最后在在测试集上看分数
from sklearn import datasets #自带数据集
from sklearn.model_selection import train_test_split,cross_val_score #划分数据 交叉验证
from sklearn.neighbors import KNeighborsClassifier #一个简单的模型,只有K一个参数,类似K-means
import matplotlib.pyplot as plt
iris = datasets.load_iris() #加载sklearn自带的数据集
X = iris.data #这是数据
y = iris.target #这是每个数据所对应的标签
train_X,test_X,train_y,test_y = train_test_split(X,y,test_size=1/3,random_state=3)
#这里划分数据以1/3的来划分 训练集训练结果 测试集测试结果
k_range = range(1,31)
cv_scores = [] #用来放每个模型的结果值
for n in k_range:
knn = KNeighborsClassifier(n) #knn模型,这里一个超参数可以做预测,当多个超参数时需要使用另一种方法GridSearchCV
scores = cross_val_score(knn,train_X,train_y,cv=10,scoring='accuracy')
#cv:选择每次测试折数 accuracy:评价指标是准确度,可以省略使用默认值,具体使用参考下面。
cv_scores.append(scores.mean())
plt.plot(k_range,cv_scores)
plt.xlabel('K')
plt.ylabel('Accuracy') #通过图像选择最好的参数
plt.show()
best_knn = KNeighborsClassifier(n_neighbors=3) # 选择最优的K=3传入模型
best_knn.fit(train_X,train_y) #训练模型
print(best_knn.score(test_X,test_y)) #看看评分
cross_val_score用来做交叉验证,里面的一个参数cv的选择比较悬疑,有时会用cv=n,有时又用cv=KFold(n_splits=n)。
查来查去,在《machine learning》终于找到了一个说法:
When an integer is passed to the cv parameter of cross_val_score():
StratifiedKFold is used if the estimator is a classifier and y is either binary or multiclass.
In all other cases, KFold is used.
啥意思?还是翻译一下:如果估计器是一个分类器,并且y是二进制或多类,则使用StratifiedKFold,如果是其他情况,就用KFold
这里的StratifiedKFold是啥?cv=StratifiedKFold(n_splits=5)其实就等价于cv=5
http://blog.sina.com.cn/s/blog_7103b28a0102w70h.html几种CV方法的生成策略
2 几种不同的CV策略生成器
前面提到,cross_val_score中的参数cv可以接受不同的CV策略生成器作为参数,以此使用不同的CV算法。这里介绍几种sklearn中的CV策略生成器函数
2.1 K-fold
最基础的CV算法,也是默认采用的CV策略。主要的参数包括两个,一个是样本数目,一个是k-fold要划分的份数。
2.2 Stratified k-fold
与k-fold类似,将数据集划分成k份,不同点在于,划分的k份中,每一份内各个类别数据的比例和原始数据集中各个类别的比例相同。
2.3 Leave-one-out
参数只有一个,即样本数目。
2.4 Leave-P-out
每次从整体样本中去除p条样本作为测试集,如果共有n条样本数据,那么会生成
个训练集/测试集对。和LOO,KFold不同,这种策略中p个样本中会有重叠。
2.5 Leave-one-label-out
这种策略划分样本时,会根据第三方提供的整数型样本类标号进行划分。每次划分数据集时,取出某个属于某个类标号的样本作为测试集,剩余的作为训练集。
2.6 Leave-P-Label-Out
与Leave-One-Label-Out类似,但这种策略每次取p种类标号的数据作为测试集,其余作为训练集。
[cross_val_score中cv=5与cv=KFold(n_splits=5)的区别]
果如上图,仔细看看会发现第一个和第三个的结果一模一样,这也证明了“cv=StratifiedKFold(n_splits=5)其实就等价于cv=5”
上面都是纸上谈兵,直接实操一下看看结果。
我在泰坦尼克预测案例中,用了随机森林来玩,估计器是分类器,并且Y是二进制值,按照上面的结论,这里应该用cv=3(或者cv=StratifiedKFold(n_splits=3))最合适。跑完结果发现,cv=3的结果确实优于cv=kf的结果
https://blog.csdn.net/qq_22592457/article/details/103584053(https://blog.csdn.net/qq_22592457/article/details/103584053)
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import KFold,cross_val_score,StratifiedKFold
alg=RandomForestClassifier(random_state=1,n_estimators=10,min_samples_leaf=1,min_samples_split=2)
kf=KFold(n_splits=3,random_state=1)
score1=cross_val_score(alg,X,y,cv=3)
score2=cross_val_score(alg,X,y,cv=kf)
score3=cross_val_score(alg,X,y,cv=StratifiedKFold(n_splits=3))
print("score1=",score1,"score2=",score2,"score3=",score3)
score1= [0.78114478 0.82491582 0.79461279] score2= [0.78114478 0.8013468 0.79461279] score3= [0.78114478 0.82491582 0.79461279]
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import KFold,cross_val_score,StratifiedKFold
alg=RandomForestClassifier(random_state=1,n_estimators=10,min_samples_leaf=1,min_samples_split=2)
kf=KFold(n_splits=3,random_state=1)
score1=cross_val_score(alg,X,y,cv=3)#能够给出这个参数构造的模型的分数,根据评价函数得出的分数,根据分数高低来选择最优的参数
score2=cross_val_score(alg,X,y,cv=kf)#因为默认是准确率为scoring参数,所以得到的分数就是准确率
score3=cross_val_score(alg,X,y,cv=StratifiedKFold(n_splits=3))
print("score1=",score1,"score2=",score2,"score3=",score3)