GridSearchCV 意外行为(始终 returns 第一个参数为最佳)
GridSearchCV unexpected behaviour (always returns the first parameter as the best)
我遇到了多类分类问题,我需要找到最佳参数。我无法更改 max_iter
、solver
和 tol
(已提供),但我想检查哪个 penalty
更好。然而,GridSearchCV
总是returns第一个给出的惩罚是最好的。
示例:
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_
不同。
你能告诉我哪里出了问题吗?
已编辑
与使用默认参数的基线相比,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)
Baseline 给我 f1_micro 比 GridSearchCV 更好:
0.7522768670309654
已编辑-2
因此,根据最佳 f1_score
性能,C = 1
是我模型的最佳选择。但是 GridSearchCV returns 我 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 惩罚项。
我遇到了多类分类问题,我需要找到最佳参数。我无法更改 max_iter
、solver
和 tol
(已提供),但我想检查哪个 penalty
更好。然而,GridSearchCV
总是returns第一个给出的惩罚是最好的。
示例:
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_
不同。
你能告诉我哪里出了问题吗?
已编辑
与使用默认参数的基线相比,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)
Baseline 给我 f1_micro 比 GridSearchCV 更好:
0.7522768670309654
已编辑-2
因此,根据最佳 f1_score
性能,C = 1
是我模型的最佳选择。但是 GridSearchCV returns 我 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 usingpenalty='l2'
, while settingl1_ratio=1
is equivalent to usingpenalty='l1'
. For0 < l1_ratio <1
, the penalty is a combination of L1 and L2.
由于您的第二个结果 l1_ratio
为 0,因此相当于使用 L2 惩罚项。