达观杯文本智能处理(六)——模型调优与融合
一、任务描述
- 进一步通过网格搜索法对3个模型进行调优(用5000条数据,调参时采用五折交叉验证的方式),并进行模型评估,展示代码的运行结果。(可以尝试使用其他模型)
- 模型融合,模型融合方式任意,并结合之前的任务给出你的最优结果。
例如Stacking融合,用你目前评分最高的模型作为基准模型,和其他模型进行stacking融合,得到最终模型及评分结果。
二、 K折交叉验证回顾
交叉验证的过程
- 选择K的值(一般是10),将数据集分成K等份
- 使用其中的K-1份数据作为训练数据,另外一份数据作为测试数据,进行模型的训练
- 使用一种度量测度来衡量模型的预测性能
交叉验证的优点
- 交叉验证通过降低模型在一次数据分割中性能表现上的方差来保证模型性能的稳定性
- 交叉验证可以用于选择调节参数、比较模型性能差别、选择特征
交叉验证的缺点
- 交叉验证带来一定的计算代价,尤其是当数据集很大的时候,导致计算过程会变得很慢
三、网格搜索法
1.简介
GridSearchCV的sklearn官方网址:
GridSearchCV,它存在的意义就是自动调参,只要把参数输进去,就能给出最优化的结果和参数。但是这个方法适合于小数据集,一旦数据的量级上去了,很难得出结果。这个时候就是需要动脑筋了。数据量比较大的时候可以使用一个快速调优的方法——坐标下降。它其实是一种贪心算法:拿当前对模型影响最大的参数调优,直到最优化;再拿下一个影响最大的参数调优,如此下去,直到所有的参数调整完毕。这个方法的缺点就是可能会调到局部最优而不是全局最优,但是省时间省力,巨大的优势面前,还是试一试吧,后续可以再拿bagging再优化。
通常算法不够好,需要调试参数时必不可少。比如SVM的惩罚因子C,核函数kernel,gamma参数等,对于不同的数据使用不同的参数,结果效果可能差1-5个点,sklearn为我们提供专门调试参数的函数grid_search。
2.参数说明
class sklearn.model_selection.GridSearchCV(estimator, param_grid, scoring=None, fit_params=None, n_jobs=1, iid=True, refit=True, cv=None, verbose=0, pre_dispatch=‘2*n_jobs’, error_score=’raise’, return_train_score=’warn’)
(1) estimator
选择使用的分类器,并且传入除需要确定最佳的参数之外的其他参数。每一个分类器都需要一个scoring参数,或者score方法:如estimator=RandomForestClassifier(min_samples_split=100,min_samples_leaf=20,max_depth=8,max_features=‘sqrt’,random_state=10),
(2) param_grid
需要最优化的参数的取值,值为字典或者列表,例如:param_grid =param_test1,param_test1 = {‘n_estimators’:range(10,71,10)}。
(3) scoring=None
模型评价标准,默认None,这时需要使用score函数;或者如scoring=‘roc_auc’,根据所选模型不同,评价准则不同。字符串(函数名),或是可调用对象,需要其函数签名形如:scorer(estimator, X, y);如果是None,则使用estimator的误差估计函数。具体值的选取看本篇第三节内容。
(4) fit_params=None
(5) n_jobs=1
n_jobs: 并行数,int:个数,-1:跟CPU核数一致, 1:默认值
(6) iid=True
iid:默认True,为True时,默认为各个样本fold概率分布一致,误差估计为所有样本之和,而非各个fold的平均。
(7) refit=True
默认为True,程序将会以交叉验证训练集得到的最佳参数,重新对所有可用的训练集与开发集进行,作为最终用于性能评估的最佳模型参数。即在搜索参数结束后,用最佳参数结果再次fit一遍全部数据集。
(8) cv=None
交叉验证参数,默认None,使用三折交叉验证。指定fold数量,默认为3,也可以是yield训练/测试数据的生成器。
(9) verbose=0, scoring=None
verbose:日志冗长度,int:冗长度,0:不输出训练过程,1:偶尔输出,>1:对每个子模型都输出。
(10) pre_dispatch=‘2*n_jobs’
指定总共分发的并行任务数。当n_jobs大于1时,数据将在每个运行点进行复制,这可能导致OOM,而设置pre_dispatch参数,则可以预先划分总共的job数量,使数据最多被复制pre_dispatch次
(11) error_score=’raise’
(12) return_train_score=’warn’
如果“False”,cv_results_属性将不包括训练分数。
三、实现与比较
数据预处理
##读取数据
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
train_data=pd.read_csv('datalab/14936/train_set.csv',nrows=5000)
##删除‘article’
train_data.drop(columns='article', inplace=True)
##TF-IDF文本处理
tfidf=TfidfVectorizer()
x_train=tfidf.fit_transform(train_data['word_seg'])
##将训练集拆分成训练集和测试集
#x:要划分的样本集 y:要划分的样本结果
#test_size:测试集占比 random_state:随机数的种子
y=train_data['class']
x_train,x_test,y_train,y_test=train_test_split(x_train,y,test_size=0.3,random_state=123)
网格搜索法
#网格搜索 5折交叉验证。
def gride_search(model,para):
grid = GridSearchCV(model,para,cv = 5,scoring = 'accuracy',n_jobs = 4)
grid = grid.fit(x_train,y_train)
if hasattr(model,'decision_function'):
y_predict_pro = grid.decision_function(x_test)
y_default_predict_pro = model.decision_function(x_test)
else:
y_predict_pro = grid.predict_proba(x_test)[:,1]
y_default_predict_pro = model.predict_proba(x_test)[:,1]
print ('参数调整前后对比:')
print ('best score:',grid.best_score_)
print ('默认参数:', model.get_params)
print ('最优参数:',grid.best_params_)
print ('默认参数 训练误差:', model.score(x_train,y_train))
print ('最优参数 训练误差:', grid.score(x_train,y_train))
print ('默认参数 测试误差:', model.score(x_test,y_test))
print ('最优参数 测试误差:', grid.score(x_test,y_test))
LR模型优化
实现
#加载包
from sklearn.linear_model import LogisticRegression
from sklearn import svm
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
import lightgbm as lgb
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import make_classification
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
from sklearn.metrics import accuracy_score
from sklearn.metrics import roc_auc_score
#LR
clf_lr = LogisticRegression(random_state=2018)
clf_lr.fit(x_train,y_train)
#调整参数penalty ,C
para = {'penalty':['l1','l2'],'C':[1e-2, 1e-1, 1, 10]}
gride_search(clf_lr,para)
f1_score
#LR模型的f1-score
# 用最优参数训练模型
lg = LogisticRegression(C=10, penalty='l2')
lg.fit(x_train, y_train)
lg_y_prediction = lg.predict(x_test)
label = []
for i in range(1, 20):
label.append(i)
f1 = f1_score(y_test, lg_y_prediction, labels=label, average='micro')
print('lg/The F1 Score: ' + str("%.2f" % f1))
结果:
f1_score:
SVM模型优化
实现
##SVM模型优化
clf_svm = svm.SVC(random_state = 2018)
clf_svm.fit(x_train,y_train)
#调整参数:C, kernel, gamma
para = {'C':[1e-2, 1e-1, 1, 10],'kernel':['linear','poly','rbf','sigmoid']}
gride_search(clf_svm,para)
f1_score
##svm模型的f1-score
# 用最优参数训练模型
svm= svm.LinearSVC(C=10)
svm.fit(x_train, y_train)
svm_y_prediction = svm.predict(x_test)
label = []
for i in range(1, 20):
label.append(i)
f1 = f1_score(y_test, svm_y_prediction, labels=label, average='micro')
print('SVM/The F1 Score: ' + str("%.2f" % f1))
结果:
f1-score
lightGBM模型优化
实现
#lightGBM
clf_lgb = lgb.LGBMClassifier(random_state=2018)
clf_lgb.fit(x_train,y_train)
#调整参数 learning_rate,max_depth,n_estimators
para = {'learning_rate': [0.2,0.5,0.7], 'max_depth': range(1,10,2), 'n_estimators':range(20,100,10)}
gride_search(clf_lgb,para)
f1-score
'C': 10, 'kernel': 'linear'
结果:
f1-score**
三种模型比较
模型 | 最优参数 | F1评分 |
---|---|---|
LR | C=10, penalty=‘l2’ | F1=0.67 |
SVM | ‘C’: 10, ‘kernel’: ‘linear’ | F1=0.68 |
LightGBM |
程序在跑,结果后续补