贷款逾期(6)-交叉验证

任务

使用网格搜索对模型进行调优并采用五折交叉验证的方式进行模型评估。

1.网格搜索

网格搜索

1.1 什么是Grid Search 网格搜索?

网格搜索是一种调参手段;在所有候选的参数选择中,通过循环遍历,尝试每一种可能性,表现最好的参数就是最终的结果。其原理就像是在数组里找最大值。(为什么叫网格搜索?以有两个参数的模型为例,参数a有3种可能,参数b有4种可能,把所有可能性列出来,可以表示成一个3*4的表格,其中每个cell就是一个网格,循环过程就像是在每个网格里遍历、搜索,所以叫grid search)

1.2 Simple Grid Search:简单的网格搜索

原始数据集划分成训练集和测试集以后,其中测试集除了用作调整参数,也用来测量模型的好坏
缺点:导致最终的评分结果比实际效果要好。(因为测试集在调参过程中,送到了模型里,而我们的目的是将训练模型应用在unseen data上)
解决方法:对训练集再进行一次划分,分成训练集和验证集,这样划分的结果就是:原始数据划分为3份,分别为:训练集、验证集和测试集;其中训练集用来模型训练,验证集用来调整参数,而测试集用来衡量模型表现好坏。然而,这种简单的grid search方法,其最终的表现好坏与初始数据的划分结果有很大的关系,为了处理这种情况,我们采用交叉验证的方式来减少偶然性。

1.3代码实现

#!/user/bin/env python
#-*- coding:utf-8 -*-
# @Time    : 2018/11/24 10:41
# @Author  : 刘
# @Site    : 
# @File    : wanggesuoshuo.py
# @Software: PyCharm
import  pickle
from sklearn.svm import SVC

"""
读取数据
"""

path = "E:/mypython/moxingxuexi/"
print("0 读取特征")
f = open(path + 'feature/V4.pkl', 'rb')
X_train, X_test, y_train,y_test= pickle.load(f)
f.close()

print("Size of training set:{} size of testing set:{}".format(X_train.shape[0],X_test.shape[0]))

"""
网格搜索
"""
X_train,X_val,y_train,y_val = X_train, X_test, y_train,y_test
print("训练集:{} 验证集:{} 测试集:{}".format(X_train.shape[0],X_val.shape[0],X_test.shape[0]))
best_score = 0
for gamma in [0.001,0.01,0.1,1,10,100]:
    for C in [0.001,0.01,0.1,1,10,100]:
        svm = SVC(gamma=gamma,C=C)#对于每种参数可能的组合,进行一次训练;
        svm.fit(X_train,y_train)
        score = svm.score(X_val,y_val)
        print("当前gamma值:{} ,当前C值:{} ,当前score:{} ".format(gamma,C,score))
        if score > best_score:#找到表现最好的参数
            best_score = score
            best_parameters = {'gamma':gamma,'C':C}
"""【网格搜索结束】"""
svm=SVC(**best_parameters)  #使用最佳参数,构建新的模型
svm.fit(X_train,y_train) #使用训练集和验证集进行训练,more data always results in good performance
test_score = svm.score(X_test,y_test) # evaluation模型评估

print("Best score:{:.2f}".format(best_score))
print("Best parameters:{}".format(best_parameters))
print("Best score on test set:{}".format(test_score))

2.交叉验证

交叉验证的基本思想是把在某种意义下将原始数据(dataset)进行分组,一部分做为训练集(train set),另一部分做为验证集(validation set or test set),首先用训练集对分类器进行训练,再利用验证集来测试训练得到的模型(model),以此来做为评价分类器的性能指标。

一个模型如果性能不好,要么是因为模型过于复杂导致过拟合(高方差),要么是模型过于简单导致导致欠拟合(高偏差)。使用交叉验证评估模型的泛化能力,使用交叉验证可以减少初始数据的划分的偶然性,使得对模型的评估更加准确。

 

在这里插入图片描述


交叉验证(K折、留一、留p、随机)

2.1KFold

将原始数据分成K组(一般是均分),将每个子集数据分别做一次验证集,其余的K-1组子集数据作为训练集,这样会得到K个模型,用这K个模型最终的验证 集的分类准确率的平均数作为此K-CV下分类器的性能指标。

2.2Leave-one-out Cross-validation 留一法

留一法Leave-one-out Cross-validation:是一种特殊的交叉验证方式。顾名思义,如果样本容量为n,则k=n,进行n折交叉验证,每次留下一个样本进行验证。主要针对小样本数据。

优点:
(1)每一回合中几乎所有的样本皆用于训练模型,因此最接近原始样本的分布,这样评估所得的结果比较可靠。
(2)实验过程中没有随机因素会影响实验数据,确保实验过程是可以被复制的。

但LOO-cv的缺点则是计算成本高,因为需要建立的模型数量与原始数据样本数量相同,当原始数据样本数量相当多时,LOO-CV在实作上便有困难几乎就是不显示,除非每次训练分类器得到模型的速度很快,或是可以用并行化计算减少计算所需的时间。

 2.3 LeavePOut 

与 LeaveOneOut 非常相似,因为它通过从整个集合中删除 p 个样本来创建所有可能的 训练/测试集。

2.4 ShuffleSplit 

迭代器将会生成一个用户给定数量的独立的训练/测试数据划分。样例首先被打散然后划分为一对训练测试集合

2.5TimeSeriesSplit

TimeSeriesSplit 是 k-fold 的一个变体,它首先返回 k 折作为训练数据集,并且 (k+1) 折作为测试数据集。 请注意,与标准的交叉验证方法不同,连续的训练集是超越前者的超集。 另外,它将所有的剩余数据添加到第一个训练分区,它总是用来训练模型。

# 交叉验证方式

## 对交叉验证方式进行指定,如验证次数,训练集测试集划分比例等
kf = KFold(n_splits=5, random_state=1)
loo = LeaveOneOut()#将数据集分成训练集和测试集,测试集包含一个样本,训练集包含n-1个样本
lpo = LeavePOut(p=2000)## #将数据集分成训练集和测试集,测试集包含p个样本,训练集包含n-p个样本
ss= ShuffleSplit(n_splits=5, test_size=.25, random_state=0)
## ShuffleSplit 咋一看用法跟LeavePOut 很像,其实两者完全不一样,LeavePOut 是使得数据集经过数次分割后,所有的测试集出现的
##元素的集合即是完整的数据集,即无放回的抽样,而ShuffleSplit 则是有放回的抽样,只能说经过一个足够大的抽样次数后,保证测试集出
##现了完成的数据集的倍数。
tss = TimeSeriesSplit(n_splits=5)# 针对时间序列的处理,防止未来数据的使用,分割时是将数据进行从前到后切割(这个说法其实不太恰当,因为切割是延续性的。。)

2.6代码实现

#!/user/bin/env python
#-*- coding:utf-8 -*-
# @Time    : 2018/11/24 11:50
# @Author  : 刘
# @Site    : 
# @File    : CV.py
# @Software: PyCharm
from pandas import Series, DataFrame
import pickle
from sklearn import svm
from sklearn.model_selection import *	#划分数据 交叉验证
from sklearn.metrics import accuracy_score, recall_score, f1_score, roc_auc_score, roc_curve
import warnings
warnings.filterwarnings("ignore")
path = "E:/mypython/moxingxuexi/"
"""
1 读取数据
"""
print("0 读取特征")
f = open(path + 'feature/V4.pkl', 'rb')
train, test, y_train,y_test = pickle.load(f)
f.close()
"""
2进行k次训练;用k个模型分别对测试集进行预测,并得到k个结果,再进行结果的融合
"""
preds= []
i = 0
"""
3交叉验证方式
"""
kf= KFold(n_splits=5,random_state=1)
loo =LeaveOneOut()
lpo= LeavePOut(p=2000)
ss= ShuffleSplit(n_splits=5,test_size=.25,random_state=0)
tss=TimeSeriesSplit(n_splits=5)

logo = LeaveOneGroupOut()
lpgo = LeavePGroupsOut(n_groups=3)
gss = GroupShuffleSplit(n_splits=4, test_size=.5, random_state=0)
gkf = GroupKFold(n_splits=2)

"""
【配置交叉验证方式】
"""
cv=ss


clf = svm.SVC(kernel='linear',C=1)
score_sum = 0
# 原始数据的索引不是从0开始的,因此重置索引
y_train = y_train.reset_index(drop=True)
y_test = y_test.reset_index(drop=True)
for train_idx,vali_idx in cv.split(train,y_train):
    i+=1
    """获取训练集和验证集"""
    f_train_x=DataFrame(train[train_idx])
    f_train_y = DataFrame(y_train[train_idx])
    f_vali_x = DataFrame(train[vali_idx])
    f_vali_y = DataFrame(y_train[vali_idx])
    """训练分类器"""
    classifier=svm.LinearSVC()
    classifier.fit(f_train_x,f_train_y)
    """对测试集进行训练"""
    y_test = classifier.predict(test)
    preds.append(y_test)
    """对验证集进行预测,并计算f1分数"""
    pre_vali = classifier.predict(f_vali_x)
    score_vali = f1_score(y_true=f_vali_y,y_pred=pre_vali,average='macro')
    print("第{}折,验证集分数:{}".format(i,score_vali))
    score_sum +=score_vali
    score_mean = score_sum/i
    print("第{}折后,验证集平均分数:{}".format(i,score_mean))

3网格搜索与交叉验证

#!/user/bin/env python
#-*- coding:utf-8 -*-
# @Time    : 2018/11/24 15:14
# @Author  : 刘
# @Site    : 
# @File    : GridsearchCV2.py
# @Software: Py
import numpy as np
import pickle
from sklearn.tree import DecisionTreeClassifier
from xgboost.sklearn import  XGBClassifier
from sklearn import svm
import lightgbm as lgb
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import *

path= "E:/mypython/moxingxuexi/"

"""
读取数据
"""
print("读取特征")
f=open(path + 'feature/V4.pkl','rb')
X_train,X_test,y_train,y_test = pickle.load(f)
f.close()
"""
交叉验证方式
"""
kf = KFold(n_splits=5,random_state=1)
loo = LeaveOneOut()#将数据集分成训练集和测试集,测试集包含一个样本,训练集包含n-1个样本
lpo = LeavePOut(p=2000)## #将数据集分成训练集和测试集,测试集包含p个样本,训练集包含n-p个样本
ss= ShuffleSplit(n_splits=5, test_size=.25, random_state=0)
tss = TimeSeriesSplit(n_splits=5)

"""
模型参数设置
"""
SVM_linear= svm.SVC(kernel='linear',probability=True)
SVM_poly = svm.SVC(kernel = 'poly', probability=True)
SVM_rbf = svm.SVC(kernel = 'rbf',probability=True)
SVM_sigmoid = svm.SVC(kernel = 'sigmoid',probability=True)

SVM_param_grid = {"C":[0.001,0.01,0.1,1,10,100]}
"""【LG】"""
LG = LogisticRegression()
LG_param_grid = {"C":[0.001,0.01,0.1,1,10,100]}

"""【DT】"""

DT = DecisionTreeClassifier()
DT_param_grid = {'max_depth':range(1,5)}
params = {'max_depth':range(1,21),'criterion':np.array(['entropy','gini'])}
"""【XGB-sklearn】"""
# XGB_sklearn = XGBClassifier(learning_rate=0.1,

#               n_estimators=1000,         # 树的个数--1000棵树建立xgboost
#               max_depth=6,               # 树的深度
#               min_child_weight = 1,      # 叶子节点最小权重
#               gamma=0.,                  # 惩罚项中叶子结点个数前的参数
#               subsample=0.8,             # 随机选择80%样本建立决策树
#               colsample_btree=0.8,       # 随机选择80%特征建立决策树
#               objective='multi:softmax', # 指定损失函数
#               nthread=12,                #使用12个CPU计算
#               reg_lambda=1,              #L2正则化
#               scale_pos_weight=1,        # 解决样本个数不平衡的问题
#               random_state=27            # 随机数
#                        )
XGB_sklearn = XGBClassifier()
XGB_sklearn_param_grid = {"max_depth":[1,10,100]}

"""【LGB_sklearn】"""
LGB_sklearn = lgb.LGBMClassifier()
LGB_sklearn_param_grid = {"max_depth":[1,10,100]}

def GridSearch(clf,param_grid,cv,name):
    grid_search = GridSearchCV(clf,param_grid,cv=cv)#实例化一个GridSearchCV类
    grid_search.fit(X_train,y_train) #训练,找到最优的参数,同时使用最优的参数实例化一个新的SVC estimator
    print(name+"_Test set score:{}".format(grid_search.score(X_test,y_test)))
    print(name + "_Best parameters:{}".format(grid_search.best_params_))
    print(name + "_Best score on train set:{}".format(grid_search.best_score_))

GridSearch(LGB_sklearn,LGB_sklearn_param_grid,ss,"LGB_sklearn")
GridSearch(LG,LG_param_grid,ss,"LG")
GridSearch(SVM_linear,SVM_param_grid,ss,"SVM_linear")
GridSearch(DT,DT_param_grid,ss,"DT")
GridSearch(XGB_sklearn,XGB_sklearn_param_grid,ss,"XGB_sklearn")
GridSearch(SVM_rbf,SVM_param_grid,ss,"SVM_rbf")
GridSearch(SVM_sigmoid,SVM_param_grid,ss,"SVM_sigmoid")
GridSearch(SVM_poly,SVM_param_grid,ss,"SVM_poly")

结果

模型 交叉验证方式 网格搜索 最优参数 训练集最优评分 测试集最优评分
LG kf LG_param_grid = {“C”:[0.001,0.01,0.1,1,10,100]} {‘C’: 1} 0.7929873772791024 0.7973086627417998
DT kf DT_param_grid = {‘max_depth’:range(1,5)} {‘max_depth’: 4} 0.7685834502103787 0.7729184188393609
LGB_sklearn kf LGB_sklearn_param_grid = {“max_depth”:[1,10,100]} {‘max_depth’: 1} 0.7915848527349229 0.7863751051303617
XGB_sklearn kf XGB_sklearn_param_grid = {“max_depth”:[1,10,100]} {‘max_depth’: 100} 0.7921458625525947 0.7914213624894869
SVM_linear kf SVM_param_grid = {“C”:[0.001,0.01,0.1,1,10,100]} {‘C’: 10} 0.7870967741935484 0.7922624053826746
SVM_rbf kf SVM_param_grid = {“C”:[0.001,0.01,0.1,1,10,100]} {‘C’: 100} 0.7876577840112202 0.785534062237174
SVM_sigmoid kf SVM_param_grid = {“C”:[0.001,0.01,0.1,1,10,100]} {‘C’: 100} 0.7856942496493688 0.7729184188393609
SVM_ploy kf SVM_param_grid = {“C”:[0.001,0.01,0.1,1,10,100]} {‘C’: 100} 0.7573632538569425 0.7485281749369218

 

参考

交叉验证

黑桃的交叉验证

猜你喜欢

转载自blog.csdn.net/lgy54321/article/details/84434726