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

标签 python scikit-learn logistic-regression 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'}

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

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_ 则不同。

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

已编辑
与使用默认参数的基线相比,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'))

LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True, intercept_scaling=1, l1_ratio=None, max_iter=500, multi_class='multinomial', n_jobs=None, penalty='l2', random_state=None, solver='saga', tol=0.001, verbose=0, warm_start=False)

基线给我的 f1_micro 比 GridSearchCV 更好:

0.7522768670309654
 

已编辑-2
因此,根据最佳 f1_score 性能,C = 1 是我的模型的最佳选择。但 GridSearchCV 返回我C = 0.1。 我想,我错过了一些东西......
Baseline 的 f1_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 惩罚项。如文档中所述:

Setting l1_ratio=0 is equivalent to using penalty='l2', while setting l1_ratio=1 is equivalent to using penalty='l1'. For 0 < l1_ratio <1, the penalty is a combination of L1 and L2.

因为您的第二个结果是 l1_ratio为0,相当于使用L2惩罚项。

关于python - GridSearchCV 意外行为(始终返回第一个参数为最佳参数),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69838341/

相关文章:

python - 移动矩阵行以使最大值位于中间

r - 在 stargazer 中格式化多个模型

python - Scikit Learn 中的交叉验证

scikit-learn - sklearn MultiLabelBinarizer() 的问题

r - 概率序数逻辑回归 `MASS::polr` : How to make prediction on new data

python - 如何在不使用文件的情况下以编程方式将模板文本传递到 View ?

Python Win32GUI 查找窗口

python - 注册 OpenAI Gym 畸形环境失败

python - 支持向量回归 (SVR) 在 Ubuntu 18.04 LTS 中未绘制任何图形

python - 为什么 numpy 形状是空的?