模型评估
使用metric函数来进行评分
sklearn.metrics里面提供了一些函数来帮助我们进行评分。其中里面以_score结尾的函数的返回值越大,模型的性能越好。而以_error或_loss结尾的函数,返回值越小,表示模型性能越好。从命名上来看,这一点不难理解。
metrics里面的很多函数名不直接传入scoring后面,因为有一些函数需要传入特定的参数才能够使用。比如在使用fbeta_score的时候需要传入bata参数等。 在这个时候,我们的做法是把函数名和参数封装一下,封装成为一个新的函数,然后传入scoring后面。封装的方法是使用metrics的make_scorer方法。
from sklearn.metrics import make_scorer, fbeta_score
#我们用make_scorer封装了fbeta_score,它需要传入一个参数
ftwo_score = make_scorer(fbeta_score, beta=2)
from sklearn.model_selection import GridSearchCV
from sklearn.svm import LinearSVC
grid = GridSearchCV(LinearSVC(), param_grid={‘C‘:[1, 10]}, scoring=ftwo_score)
使用metrics的make_score方法,我们可以制定出我们自己的方法,这个方法需要满足下面一些条件:
- 需要传入一个我们自定义的函数的名称
- 需说明greater_is_better的值是True还是False。 当值为正的时候,返回的是score的值,值越高性能越好。当为False的时候,返回的为score的负值,值越低越好。
- 是否是针对分类问题的。 传入needs_threshold=True来说明是针对分类问题的,默认情况为False。
- 其余的参数。如在f1_score中的bata,labels。
import numpy as np
from sklearn.metrics import make_scorer
def my_custom_loss_func(ground_truth, predictions):
diff = np.abs(ground_truth - predictions).max()
return np.log(1 + diff)
loss = make_scorer(my_custom_loss_func, greater_is_better=False)
score = make_scorer(my_custom_loss_func, greater_is_better=True)
ground_truth = [[1], [1]]
predictions = [0, 1]
from sklearn.dummy import DummyClassifier
clf = DummyClassifier(strategy=‘most_frequent‘, random_state=0)
clf = clf.fit(ground_truth, predictions)
#这段代码的原理是这样的,我们的clf使用ground_truth 和predictions进行训练
#使用clf.predict(ground_truth) 进行预测以后的结果为[0,0],
#my_custom_loss_func(np.array([0,0], np.array[0,1]) 最后得到log(2) = 0.69314
print(score(clf, ground_truth, predictions))
print(loss(clf, ground_truth, predictions))
我们还可以实现我们自己的评分对象.为了实现更高的自由度,我们可以不使用上述的make_scorer方法,完全定制出来我们自己的评分对象,这需要遵循两点
- 能够调用(estimater, X, y)参数,estimater是我们的模型,X为数据集, y为X数据集的真实结果。
- 需要返回一个分数作为评分的结果。该分数能够从某个方面反映出我们模型的好坏。
模型调参
1.贪心调参
采用贪心算法选取局部最优的思想,每次选择一个参数(其他参数为默认或者为已经调至最优的参数)调至最优。代码如下:
## LGB的参数集合:
objective = ['regression', 'regression_l1', 'mape', 'huber', 'fair']
num_leaves = [3,5,10,15,20,40, 55]
max_depth = [3,5,10,15,20,40, 55]
bagging_fraction = []
feature_fraction = []
drop_rate = []
# 贪心调参 每一轮针对某个特征找到最优的值,
# key-参数名字 value为对应的参数值
best_obj = dict()
for obj in objective:
model = LGBMRegressor(objective=obj)
score = np.mean(cross_val_score(model, X=train_X, y=train_y_ln, verbose=0, cv = 5, scoring=make_scorer(mean_absolute_error)))
best_obj[obj] = score
best_leaves = dict()
for leaves in num_leaves:
model = LGBMRegressor(objective=min(best_obj.items(), key=lambda x:x[1])[0], num_leaves=leaves)
score = np.mean(cross_val_score(model, X=train_X, y=train_y_ln, verbose=0, cv = 5, scoring=make_scorer(mean_absolute_error)))
best_leaves[leaves] = score
best_depth = dict()
for depth in max_depth:
model = LGBMRegressor(objective=min(best_obj.items(), key=lambda x:x[1])[0],
num_leaves=min(best_leaves.items(), key=lambda x:x[1])[0],
max_depth=depth)
score = np.mean(cross_val_score(model, X=train_X, y=train_y_ln, verbose=0, cv = 5, scoring=make_scorer(mean_absolute_error)))
best_depth[depth] = score
sns.lineplot(x=['0_initial','1_turning_obj','2_turning_leaves','3_turning_depth'], y=[0.143 ,min(best_obj.values()), min(best_leaves.values()), min(best_depth.values())])
2.网格调参(Grid Search)
Sklearn-GridSearchCV:一种调参的方法,当你算法模型效果不是很好时,可以通过该方法来调整参数,通过循环遍历,尝试每一种参数组合,返回最好的得分值的参数组合。由于遍历的组合较多,在算力条件一般的情况下,适用于小数据集。代码如下:
# grid search 网格搜索调参 遍历所有给定的值进行调参 适用于小数据集
# 原来的数据集分割为训练集和测试集之后,其中测试集起到的作用有两个,一个是用来调整参数,一个是用来评价模型的好坏,这样会导致评分值会比实际效果要好。(因为我们将测试集送到了模型里面去测试模型的好坏,而我们目的是要将训练模型应用在没使用过的数据上。)
from sklearn.model_selection import GridSearchCV
parameters = {'objective': objective , 'num_leaves': num_leaves, 'max_depth': max_depth}
model = LGBMRegressor()
# 交叉验证~
clf = GridSearchCV(model, parameters, cv=5)
clf = clf.fit(train_X, train_y)
clf.best_params_
3.贝叶斯调参:
在搜索空间过大的时候,网格搜索的速度实在不太能让人接受,贝叶斯调参相对于网格搜索的优势如下
- 贝叶斯调参采用高斯过程,会考虑到之前的参数信息,不断地更新先验;网格搜索则不会考虑先验信息。
- 贝叶斯调参迭代次数少,速度快;网格搜索会遍历所有的可能的参数组合,所以速度慢,参数多时易导致维度爆炸
- 贝叶斯调参针对非凸问题依然稳健;网格搜索针对非凸问题易得到局部最优。
# 贝叶斯调参
from bayes_opt import BayesianOptimization
from sklearn.metrics import mean_absolute_error, make_scorer
# 用 make_scorer封装metrics中的评分函数供scoring使用
def rf_cv(num_leaves, max_depth, subsample, min_child_samples):
val = cross_val_score(
LGBMRegressor(objective = 'regression_l1',
num_leaves=int(num_leaves),
max_depth=int(max_depth),
subsample = subsample,
min_child_samples = int(min_child_samples)
),
X=train_X, y=train_y_ln, verbose=0, cv = 5, scoring=make_scorer(mean_absolute_error)
).mean()
return 1 - val
# 核心三个部分 目标函数的设计:rf_cv,域空间的设定(参数范围),最优化search
rf_bo = BayesianOptimization(
rf_cv,
{
'num_leaves': (2, 100),
'max_depth': (2, 100),
'subsample': (0.1, 1),
'min_child_samples' : (2, 100)
}
)
rf_bo.maximize()
# 输出最优参数组合
print(rf_bo.max)
https://github.com/fmfn/BayesianOptimization 有贝叶斯调参代码更加详细的一个介绍
附录:
常用模型的链接一个记录回头整理一下:
来源:https://www.cnblogs.com/z1141000271/p/12644141.html