web-dev-qa-db-fra.com

La documentation de xgboost est-elle incorrecte? (rondes d'arrêt et meilleure et dernière itération)

vous trouverez ci-dessous une question sur le paramètre xgboost early stopping rounds et sur la manière dont il donne ou non la meilleure itération lorsque c’est la raison pour laquelle l’ajustement prend fin.

Dans la documentation de xgboost, on peut voir dans la section scikit learn api ( link ) que lorsque l'ajustement s'arrête en raison du paramètre d'arrêts précoces:

Active l'arrêt précoce. L'erreur de validation doit diminuer au moins tous les tours "early_stopping_rounds" pour continuer l'entraînement. Nécessite au moins un élément dans les évaluations. S'il y en a plus d'un, utilisera le dernier. Renvoie le modèle de la dernière itération (pas la meilleure).

Quand on réédite cela, il semble que le modèle retourné, dans ce cas, n’est pas le meilleur, mais le dernier. Il est possible d’appeler le prévision avec le paramètre ntree_limit avec le paramètre bst.best_ntree_limit indiqué à la fin de l’ajustement.

En ce sens, il devrait fonctionner de la même manière que le train de xgboost puisque l’ajustement de l’application scikitlearn ne semble être qu’une intégration du train et d’autres éléments.

Il est discuté avec soin ici discussion de débordement de pile ou ici une autre discussion

Mais quand j'ai essayé de résoudre ce problème et de vérifier comment cela fonctionnait avec mes données, je n'ai pas trouvé le comportement que je pensais devoir avoir. En fait, le comportement que j'ai rencontré n'était pas du tout celui décrit dans ces discussions et cette documentation.

J'appelle un ajustement de cette façon:

reg = xgb.XGBRegressor (n_jobs = 6, n_estimators = 100, max_depth = 5)

reg.fit(
   X_train, 
   y_train, 
   eval_metric='rmse',    
   eval_set=[(X_train, y_train), (X_valid, y_valid)],
   verbose=True,
   early_stopping_rounds = 6)

et voici ce que j'obtiens à la fin:

[71]    validation_0-rmse:1.70071   validation_1-rmse:1.9382
[72]    validation_0-rmse:1.69806   validation_1-rmse:1.93825
[73]    validation_0-rmse:1.69732   validation_1-rmse:1.93803
Stopping. Best iteration:
[67]    validation_0-rmse:1.70768   validation_1-rmse:1.93734

et quand je vérifie les valeurs de validation que j'ai utilisées:

y_pred_valid = reg.predict(X_valid)
y_pred_valid_df = pd.DataFrame(y_pred_valid)
sqrt(mse(y_valid, y_pred_valid_df[0]))

Je reçois

1.9373418403889535

Si l’aiguille avait renvoyé la dernière itération au lieu de la meilleure, elle aurait dû donner une moyenne autour de 1,93803, mais elle a donné une moyenne à 1,93734, exactement le meilleur score.

J'ai vérifié à nouveau de deux manières: [Edit] J'ai modifié le code ci-dessous en fonction de @Eran Moshe answer

y_pred_valid = reg.predict(X_valid, ntree_limit=reg.best_ntree_limit)
y_pred_valid_df = pd.DataFrame(y_pred_valid)
sqrt(mse(y_valid, y_pred_valid_df[0]))

1.9373418403889535

et même si j'appelle l'ajustement (sachant que le meilleur itérateur est le 67e) avec seulement 68 estimateurs, je suis sûr que le dernier est le meilleur:

reg = xgb.XGBRegressor(n_jobs=6, n_estimators = 68, max_depth= 5)

reg.fit(
   X_train, 
   y_train, 
   eval_metric='rmse',    
   eval_set=[(X_train, y_train), (X_valid, y_valid)],
   verbose=True,
   early_stopping_rounds = 6)

le résultat est le même:

1.9373418403889535

Cela semble donc donner à penser que contrairement à la documentation et aux nombreuses discussions à ce sujet, l’ajustement de xgboost, lorsque stoppé par le paramètre d’arrêt précoce, donne le meilleur iter, pas le dernier.

Est-ce que je me trompe, si oui, où et comment expliquez-vous le comportement que j'ai rencontré?

Merci pour l'attention

6
Lyxthe Lyxos

Je pense que ce n’est pas faux, mais incohérent

La documentation de la méthode predict est correcte (par exemple, voir ici ). Pour être sûr à 100%, il vaut mieux consulter le code: xgb github , donc predict se comporte comme indiqué dans sa documentation, mais la documentation fit est obsolète. S'il vous plaît, postez-le sous forme de problème sur github XGB et soit ils corrigeront la documentation, soit vous deviendrez contributeur XGB :)

1
Mykhailo Lisovyi

Vous avez une erreur de code ici.

Remarquez comment

reg.predict(X_valid, ntree_limit=reg.best_ntree_limit)

Devrait être

y_pred_valid = reg.predict(X_valid, ntree_limit=reg.best_ntree_limit)

Donc, en fait, vous faites la même comparaison, lors du calcul

sqrt(mse(y_valid, y_pred_valid_df[0]))

Xgboost fonctionne exactement comme vous l'avez lu. early_stopping_round = x s'entraînera jusqu'à ce qu'il ne s'améliore pas pour x tours consécutifs. 

Et lors de la prédiction avec ntree_limit=y, il utilisera UNIQUEMENT les premiers __ Boosters y.

0
Eran Moshe

Pour être plus précis, et selon @Mykhailo Lisovyi, la documentation est assez incohérente dans la section api de scikit-learn puisque le paragraphe approprié indique que, lorsqu’une étape d’arrêt précoce se produit, la dernière itération est renvoyée non pas la meilleure, mais le paragraphe indique que lorsque la prédiction est appelée sans spécifier ntree_limit, ntree_limit est égal à best_ntree_limit.

Ainsi, lors de la lecture de la partie fit, on pourrait penser qu’il est nécessaire de spécifier quel est le meilleur itérateur lorsqu’on appelle le prédict, mais lors de la lecture de la partie prédite, le meilleur iter est donné par défaut, c’est le dernier iter avoir à spécifier si nécessaire.

J'ai posté un problème sur le github de xgboost .... wait & see

[UPDATE]: la demande d'extraction a été acceptée: link

0
Lyxthe Lyxos