Разные значения на выходе при одинаковых параметрах при классификации данных

Подбираю параметры для наилучшего обучения модели классификации.

Делаю это так:

print('Исходная обученность:         ', lgb_m_REZ) 
g = 775
max_score = 0
g_best = 0
i_best = 0
while g < 779:
    i = 25
    X_train2, X_test2, y_train2, y_test2 = train_test_split(X, y, test_size=0.33, random_state=g)
    while i < 28:
        param_grid = {
        'max_features' : ['auto','sqrt', 'log2'],
        'learning_rate' : [ 0.05 , 0.1 , 0.2 , 0.3 ],
        'random_state' : [i],
        }
        svc = GradientBoostingClassifier()
        clf = GridSearchCV(svc, param_grid)
        clf.fit(X_train2, y_train2)
        print('random_state sample:       ', g)
        print('random_state model:        ', i)
        print('При подборе параметров:       ', clf.best_score_)
        print('При подборе параметров:       ', clf.best_params_)
        if clf.best_score_>lgb_m_REZ and clf.best_score_> max_score:
            max_score = clf.best_score_
            g_best = g
            i_best = i
        print('Лучшее значение при подборе параметров: ', max_score, 'i ', i_best,'g ', g_best)
        i+=1
    g+=1 

Получаю к примеру значения, которые дают лучший вариант, чем при первом прогоне модели:

{'learning_rate': 0.3, 'max_features': 'sqrt', 'random_state': 25}
g = 775
i = 25

Подставляю их вот так:

X_train3, X_test3, y_train3, y_test3 = train_test_split(X, y, test_size=0.33, random_state=775)
lgb_m1 = GradientBoostingClassifier(max_features='sqrt', learning_rate= 0.3, random_state=25)
lgb_m1.fit( X_train3, y_train3) 
print(lgb_m_REZ)
res3 = lgb_m1.predict(X_test3)
print('Доля правильно угаданных значений: ', accuracy_score(res3, y_test3))

В итоге, результаты разные.

Где я ошибся? Что я делаю не так?


Ответы (1 шт):

Автор решения: MaxU

Похоже вы не совсем понимаете для чего и как используется параметр random_state в Scikit-Learn.

Этот параметр используется исключительно для того, чтобы при нескольких запусках команды с одинаковыми входными параметрами получать одинаковые результаты. Т.е. использование этого параметра позволяет получать детерминированные результаты для функций и методов классов, которые используют генератор случайных чисел.

Подбирать random_state для того чтобы получить чуть лучший результат при разбиении выборки или при обучении модели - не имеет смысла. Ведь модель обучается для того, чтобы предсказывать значения для неизвестных выборок.

Подобранный для обучающей и тестовой выборок random_state никак не гарантирует лучший результат для неизвестной выборки данных.


Поэтому нет смысла тратить ресурсы впустую и подбирать random_state - он используется только для воспроизведения результатов.

Лучше подбирать настоящие гиперпараметры модели, например n_estimators, criterion, min_samples_split, min_samples_leaf, max_depth, etc.

Иногда для воспроизводимости результата приходится явно задавать задавать значение np.random.seed().

Я бы переписал ваш код следующим образом:

random_state = 123

np.random.seed(random_state)
X_train2, X_test2, y_train2, y_test2 = \
    train_test_split(X, y, test_size=0.33, random_state=random_state)

param_grid = {
    'max_features' : ['auto','sqrt', 'log2'],
    'learning_rate' : [ 0.05 , 0.1 , 0.2 , 0.3 ],
    'n_estimators': [50, 100, 250, 500],
    'criterion': ['friedman_mse','mse','mae']
}
svc = GradientBoostingClassifier(random_state=random_state)
np.random.seed(random_state)
clf = GridSearchCV(svc, param_grid, random_state=random_state)
clf.fit(X_train2, y_train2)

после этого используйте лучшие подобранные параметры или же можно воспользоваться уже обученной с лучшими параметрами моделью: clf.best_estimator_

clf.best_estimator_.score(X_test2, y_test2)
→ Ссылка