赞
踩
GridSearchCV
参数 | 解释 |
---|---|
penalty | 正则化项 |
dual | 是否求解对偶问题* |
tol | 迭代停止条件:两轮迭代损失值差值小于tol时,停止迭代 |
C | 经验风险和结构风险在损失函数中的权重 |
fit_intercept | 线性方程中是否包含截距项 |
intercept_scaling | 相当于此前讨论的特征最后一列全为1的列,当使用liblinear求解参数时用于捕获截距 |
class_weight | 各类样本权重* |
random_state | 随机数种子 |
solver | 损失函数求解方法* |
max_iter | 求解参数时最大迭代次数,迭代过程满足 max_iter 或 tol 其一即停止迭代 |
multi_class | 多分类问题时求解方法* |
verbose | 是否输出任务进程 |
warm_start | 是否使用上次训练结果作为本次运行初始参数 |
l1_ratio | 当采用弹性网正则化时, l 1 l1 l1正则项权重,就是损失函数中的 ρ \rho ρ |
penalty
参数和 C
来进行搜索调参,则这两个参数就是两个不同维度,而这两个参数的不同取值就是这个参数空间中的一系列点,例如 (penalty=‘l1’, C=1)、(penalty=‘l1’, C=0.9)、(penalty=‘l2’, C=0.8) 等等,我们需要挑选出最优组合GridSearchCV
的原因model_selection
模块查找相关内容GridSearchCV
会尝试参数空间内的所有组合,而 RandomizedSearchCV
则会先进行采样再来进行搜索,即对某个参数空间的某个随机子集进行搜索
from sklearn.model_selection import GridSearchCV GridSearchCV? # 建议好好看看官方注释 GridSearchCV( estimator, param_grid, *, scoring=None, n_jobs=None, refit=True, cv=None, # to use the default 5-fold cross validation verbose=0, pre_dispatch='2*n_jobs', error_score=nan, return_train_score=False, )
estimator
和 param_grid
,指定对象,最重要的参数scoring
、refit
和 cv
三个参数。当然这三个参数都不是必要参数(有默认值),但这三个参数却是直接决定模型结果评估过程、并且对最终模型参数选择和模型泛化能力提升至关重要的三个参数n_jobs
和 pre_dispatch
,用于规定调用的核心数和一个任务按照何种方式进行并行运算;在网格搜索中,由于无需根据此前结果来确定后续计算方法,所以可以并行计算。在默认情况下并行任务的划分数量和n_jobs相同。当然,这组参数的合理设置能够一定程度提高模型网格搜索效率,但如果需要大幅提高执行速度,建议使用RandomizedSearchCV、或者使用Halving方法来进行加速# 数据导入
from sklearn.datasets import load_iris
X, y = load_iris(return_X_y=True)
# 预留测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=24)
saga
求解,逻辑回归中不同的损失函数、多分类策略,它都可以解决,避免后续还要调整clf = LogisticRegression(max_iter=int(1e6), solver='saga')
clf.get_params()
penalty
和 C
这两个参数来进行参数空间的构造param_grid_simple = {'penalty': ['l1', 'l2'],
'C': [1, 0.5, 0.1, 0.05, 0.01]}
param_grid_ra = [
{'penalty': ['l1', 'l2'], 'C': [1, 0.5, 0.1, 0.05, 0.01]},
{'penalty': ['elasticnet'], 'C': [1, 0.5, 0.1, 0.05, 0.01], 'l1_ratio': [0.3, 0.6, 0.9]}
]
search = GridSearchCV(estimator=clf,
param_grid=param_grid_simple)
search.fit(X_train, y_train)
Name | Description |
---|---|
cv_results_ | 交叉验证过程中的重要结果 |
best_estimator_ | 最终挑选出的最优 |
best_score_ | 在最优参数情况下,训练集的交叉验证的平均得分 |
best_params_ | 最优参数组合 |
best_index_ | CV过程会对所有参数组合标号,该参数表示最优参数组合的标号 |
scorer | 在最优参数下,计算模型得分的方法 |
n_splits_ | 交叉验证的折数 |
search.best_estimator_ # LogisticRegression(C=1, max_iter=1000000, penalty='l1', solver='saga') search.best_estimator_.coef_ # array([[ 0. , 0. , -3.47349066, 0. ], # [ 0. , 0. , 0. , 0. ], # [-0.55506614, -0.34227663, 3.03238721, 4.12147362]]) # 这就是逻辑回归自己的事了 search.best_estimator_.score(X_train,y_train), search.best_estimator_.score(X_test,y_test) # (0.9732142857142857, 0.9736842105263158) search.best_score_ # 验证集准确率的平均值 # 0.9644268774703558 # 包含了各组超参数交叉验证的结果 search.cv_results_ # 选评估指标也是用于CV的 search.best_params_ # {'C': 1, 'penalty': 'l1'}
导入和 F1-Score 相关的评估指标计算函数
from sklearn.metrics import precision_score,recall_score,f1_score
小试牛刀
y_true = np.array([1, 0, 0, 1, 0, 1])
y_pred = np.array([1, 1, 0, 1, 0, 1])
precision_score(y_true, y_pred), recall_score(y_true, y_pred), f1_score(y_true, y_pred)
# (0.75, 1.0, 0.8571428571428571)
具体参数含义
precision_score?
Name | Description |
---|---|
y_true | 数据集真实标签 |
y_pred | 标签预测结果 |
labels | 允许以列表形式输入其他形态的标签,一般不进行修改 |
pos_label | positive类别标签 |
average | 多分类时指标计算方法 |
sample_weight | 不同类别的样本权重 |
zero_division | 当分母为0时返回结果 |
重点介绍多分类问题时 average
参数不同取值时的计算方法
此处以 recall
为例进行计算,重点介绍当average取值为 macro
、micro
和 weighted
的情况,其他指标也类似,有简单多分类问题如下(已按某种多分类问题求解策略得到如下预测结果,F1-Score作为指标时不需要指明)
y_true = np.array([0, 1, 2, 2, 0, 1, 1, 2, 0, 2])
y_pred = np.array([0, 1, 0, 2, 2, 1, 2, 2, 0, 2])
# 注:预测结果为类别标签,概率结果是进一步算出来的
tp1 = 2
tp2 = 2
tp3 = 3
fn1 = 1
fn2 = 1
fn3 = 1
re1 = 2/3
re2 = 2/3
re3 = 3/4
np.mean([re1, re2, re3])
# 0.6944444444444443
macro
时的计算结果recall_score(y_true, y_pred, average='macro') # 0.6944444444444443
weighted
时的结果re1 * 3/10 + re2 * 3/10 + re3 * 4/10 # 0.7
recall_score(y_true, y_pred, average='weighted') # 0.7
micro
时的计算结果tp = tp1 + tp2 + tp3
fn = fn1 + fn2 + fn3
tp / (tp+fn) # 0.7
recall_score(y_true, y_pred, average='micro') # 0.7
对于上述三个不同参数的选取
小结
from sklearn.metrics import roc_auc_score
y_true = np.array([1, 0, 0, 1, 0, 1])
y_pred = np.array([0.9, 0.7, 0.2, 0.7, 0.4, 0.8]) # 概率预测结果
roc_auc_score(y_true, y_pred) # 0.9444444444444444
y_true = np.array([1, 0, 0, 1, 0, 1])
y_pred = np.array([1, 1, 0, 1, 0, 1])
roc_auc_score(y_true, y_pred) # 0.8333333333333334
y_true = np.array([1, 0, 0, 1, 0, 1])
y_pred = np.array([0.6, 0.6, 0.4, 0.6, 0.4, 0.6])
roc_auc_score(y_true, y_pred) # 0.8333333333333334
Name | Description |
---|---|
max_fpr | fpr最大值,fpr是roc曲线的横坐标 |
multi_class | 分类器在进行多分类时进行的多分类问题处理策略 |
multi_class
,一般是二分类器中用于解决多元分类问题时的参数(如逻辑回归)
ovr
macro
和 weighted
的计算过程
# 预测概率的第一列
y_true_1 = np.array([1, 0, 0, 0, 1, 0, 0, 0, 1, 0])
y_pred_1 = np.array([0.8, 0.2, 0.5, 0.2, 0.3, 0.1, 0.3, 0.3, 0.9, 0.3])
r1 = roc_auc_score(y_true_1, y_pred_1)
r1 # 0.8809523809523809
y_true_2 = np.array([0, 1, 0, 0, 0, 1, 1, 0, 0, 0])
y_pred_2 = np.array([0.2, 0.6, 0.3, 0, 0.2, 0.8, 0.2, 0.3, 0, 0.1])
r2 = roc_auc_score(y_true_2, y_pred_2)
r2 # 0.8571428571428571
y_true_3 = np.array([0, 0, 1, 1, 0, 0, 0, 1, 0, 1])
y_pred_3 = np.array([0, 0.2, 0.2, 0.8, 0.5, 0.1, 0.5, 0.4, 0.1, 0.6])
r3 = roc_auc_score(y_true_3, y_pred_3)
r3 # 0.8125
np.mean([r1, r2, r3])
# 0.8501984126984127
y_pred = np.concatenate([y_pred_1.reshape(-1, 1), y_pred_2.reshape(-1, 1), y_pred_3.reshape(-1, 1)], 1)
y_pred
y_true = np.array([0, 1, 2, 2, 0, 1, 1, 2, 0, 2])
roc_auc_score(y_true, y_pred, average='macro', multi_class='ovr')
# 0.8501984126984127
r1 * 3/10 + r2 * 3/10 + r3 * 4/10
# 0.8464285714285713
roc_auc_score(y_true, y_pred, average='weighted', multi_class='ovr')
np.random.seed(24)
X = np.random.normal(0, 1, size=(1000, 2))
y = np.array(X[:,0]+X[:, 1]**2 < 1.5, int)
np.random.seed(24)
for i in range(200):
y[np.random.randint(1000)] = 1
y[np.random.randint(1000)] = 0
plt.scatter(X[:, 0], X[:, 1], c=y)
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.7, random_state = 42)
pipe = make_pipeline(PolynomialFeatures(),
StandardScaler(),
LogisticRegression(max_iter=int(1e6)))
pipe.get_params()
param_grid = [
{'polynomialfeatures__degree': np.arange(2, 10).tolist(), 'logisticregression__penalty': ['l1'], 'logisticregression__C': np.arange(0.1, 2, 0.1).tolist(), 'logisticregression__solver': ['saga']},
{'polynomialfeatures__degree': np.arange(2, 10).tolist(), 'logisticregression__penalty': ['l2'], 'logisticregression__C': np.arange(0.1, 2, 0.1).tolist(), 'logisticregression__solver': ['lbfgs', 'newton-cg', 'sag', 'saga']},
{'polynomialfeatures__degree': np.arange(2, 10).tolist(), 'logisticregression__penalty': ['elasticnet'], 'logisticregression__C': np.arange(0.1, 2, 0.1).tolist(), 'logisticregression__l1_ratio': np.arange(0.1, 1, 0.1).tolist(), 'logisticregression__solver': ['saga']}
]
GridSearchCV?
GridSearchCV(
estimator,
param_grid,
*,
scoring=None,
n_jobs=None,
refit=True,
cv=None,
verbose=0,
pre_dispatch='2*n_jobs',
error_score=nan,
return_train_score=False,
)
scoring
参数最基础的情况下可以选择输入str(字符串)或者callable(可调用)对象,也就是可以输入指代某个评估函数的字符串,或者直接输入某评估指标函数(通过make_score函数创建的函数),来进行模型结果的评估
import sklearn
sorted(sklearn.metrics.SCORERS.keys())
roc_auc
参数只能指代metrics.roc_auc_score函数的二分类功能,如果需要进行多分类,则需要在scoring参数中输入 roc_auc_ovr
、roc_auc_ovo
或者 roc_auc_ovr_weighted
、roc_auc_ovo_weighted
,即需要指明求解多分类问时的划分策略from sklearn.metrics import roc_auc_score
roc_auc_score?
GridSearchCV(estimator=pipe,
param_grid=param_grid,
scoring='roc_auc_ovr') # 字符串
# 或者
from sklearn.metrics import make_scorer
acc = make_scorer(roc_auc_score) # 可调用对象
GridSearchCV(estimator=pipe,
param_grid=param_grid,
scoring=acc)
# 评估指标函数
accuracy_score([1, 1, 0], [1, 1, 1])
# 评估器结果评估函数
acc = make_scorer(accuracy_score)
acc(search.best_estimator_, X_train, y_train)
search.score(X_train, y_train)
scoring = {'AUC': 'roc_auc', 'Accuracy': make_scorer(accuracy_score)} # 需要转化
# {'AUC': make_scorer(roc_auc_score), 'Accuracy': 'accuracy'} 这样也可,那到底需要手动转化吗?
# 需要注意的是,尽管此时网格搜索评估器将同时计算一组参数下的多个评估指标结果并输出,但我们只能选取其中一个评估指标作为挑选超参数的依据,由 refit 决定
# 而其他指标尽管仍然会计算,但结果只作参考
search = GridSearchCV(estimator=clf,
param_grid=param_grid_simple,
scoring=scoring,
refit='Accuracy') # refit参数中输入的评估指标,就是最终决定参数/超参数选择的评估指标
# 构造机器学习流 pipe = make_pipeline(PolynomialFeatures(), StandardScaler(), LogisticRegression(max_iter=int(1e6))) # 构造参数空间 param_grid = [ {'polynomialfeatures__degree': np.arange(2, 10).tolist(), 'logisticregression__penalty': ['l1'], 'logisticregression__C': np.arange(0.1, 2, 0.1).tolist(), 'logisticregression__solver': ['saga']}, {'polynomialfeatures__degree': np.arange(2, 10).tolist(), 'logisticregression__penalty': ['l2'], 'logisticregression__C': np.arange(0.1, 2, 0.1).tolist(), 'logisticregression__solver': ['lbfgs', 'newton-cg', 'sag', 'saga']}, {'polynomialfeatures__degree': np.arange(2, 10).tolist(), 'logisticregression__penalty': ['elasticnet'], 'logisticregression__C': np.arange(0.1, 2, 0.1).tolist(), 'logisticregression__l1_ratio': np.arange(0.1, 1, 0.1).tolist(), 'logisticregression__solver': ['saga']} ] # 实例化搜索评估器 search = GridSearchCV(estimator=pipe, param_grid=param_grid, scoring='roc_auc', n_jobs=5) # 训练 search.fit(X_train, y_train) # 查看结果 search.best_score_ # 0.7879905483853072 search.best_params_ # {'logisticregression__C': 0.2, # 'logisticregression__penalty': 'l1', # 'logisticregression__solver': 'saga', # 'polynomialfeatures__degree': 3}
search.best_estimator_.score(X_train,y_train)
# 0.7857142857142857
search.best_estimator_.score(X_test,y_test)
# 0.7866666666666666
# 可以验证
accuracy_score(search.best_estimator_.predict(X_train), y_train)
accuracy_score(search.best_estimator_.predict(X_test), y_test)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。