GridSearchCV 意外行为(始终将第一个参数作为最佳参数返回)



我有一个多类分类问题,我需要找到最好的参数。我无法更改max_itersolvertol(它们已给出),但我想检查哪个penalty更好。但是,GridSearchCV总是将第一个给定的惩罚作为最佳惩罚返回。

例:

from sklearn.model_selection import cross_val_score, GridSearchCV, StratifiedKFold
cv = StratifiedKFold(n_splits=5, random_state=0, shuffle=True)
fixed_params = {
'random_state': 42,
'multi_class': 'multinomial',
'solver': 'saga',
'tol': 1e-3,
'max_iter': 500
}
parameters = [
{'C': [0.001, 0.01, 0.1, 1, 10, 100, 1000], 'penalty': ['l1', 'l2', None]},
{'C': [0.001, 0.01, 0.1, 1, 10, 100, 1000], 'penalty': ['elasticnet'], 'l1_ratio': np.arange(0.0, 1.0, 0.1)}     
]
model = GridSearchCV(LogisticRegression(**fixed_params), parameters, n_jobs=-1, verbose=10, scoring='f1_macro' ,cv=cv)
model.fit(X_train, y_train)
print(model.best_score_)
# 0.6836409100287101
print(model.best_params_)
# {'C': 0.1, 'penalty': 'l2'}

如果我更改parameters行的顺序,结果将完全相反:

from sklearn.model_selection import cross_val_score, GridSearchCV, StratifiedKFold
cv = StratifiedKFold(n_splits=5, random_state=0, shuffle=True)

fixed_params = {
'random_state': 42,
'multi_class': 'multinomial',
'solver': 'saga',
'tol': 1e-3,
'max_iter': 500
}
parameters = [
{'C': [0.001, 0.01, 0.1, 1, 10, 100, 1000], 'penalty': ['elasticnet'], 'l1_ratio': np.arange(0.0, 1.0, 0.1)} 
{'C': [0.001, 0.01, 0.1, 1, 10, 100, 1000], 'penalty': ['l1', 'l2', None]}          
]

model = GridSearchCV(LogisticRegression(**fixed_params), parameters, n_jobs=-1, verbose=10, scoring='f1_macro' ,cv=cv)
model.fit(X_train, y_train)
print(model.best_score_)
# 0.6836409100287101
print(model.best_params_)
# {'C': 0.1, 'l1_ratio': 0.0, 'penalty': 'elasticnet'}

因此,两个选项的best_score_相同,但best_params_不是。

你能告诉我出了什么问题吗?

Edited
GridSearchCV 与使用默认参数的基线相比,给出的结果更差。
基线:

baseline_model = LogisticRegression(multi_class='multinomial', solver='saga', tol=1e-3, max_iter=500)
baseline_model.fit(X_train, y_train)
train_pred_baseline = baseline_model.predict(X_train)
print(f1_score(y_train, train_pred_baseline, average='micro'))

逻辑回归(C=1.0, class_weight=无, 对偶=假, fit_intercept=真, intercept_scaling=1, l1_ratio=无, max_iter=500, multi_class="多项式", n_jobs=无, 惩罚="l2", random_state=无,求解器='saga',tol=0.001,详细=0, warm_start=假)

基线给了我比GridSearchCV好f1_micro

0.7522768670309654

Edited-2
因此,根据最佳f1_score性能,C = 1是我的模型的最佳选择。但是网格搜索CV返回我C = 0.1。 我想,我想念一些东西...
Baselinef1_macro也比GridSearchCV好:

train_pred_baseline = baseline_model.predict(X_train)
print(f1_score(y_train, train_pred_baseline, average='macro'))
# 0.7441968750050458

其实没什么问题。事情是这样的。Elasticnet 同时使用 L1 和 L2 惩罚项。但是,如果您的l1_ratio为 0,那么您基本上是在应用 L2 正则化,因此您只使用 L2 惩罚项。如文档中所述:

设置l1_ratio=0等效于使用penalty='l2',而设置l1_ratio=1等效于使用penalty='l1'。对于0 < l1_ratio <1,惩罚是L1和L2的组合。

由于您的第二个结果必须l1_ratio为 0,因此等效于 使用 L2 惩罚项。

最新更新