-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add functionality for early stopping rounds. #193
Conversation
Thanks for this. I have a few concerns with this implementation. The first is that, we had thus far carefully avoided parsing the output messages for obvious reasons. There is apparently no way around the fact that having this kind of functionality requires it, so I don't think we could disallow it, however, I think that if we are going to do this we should (at the very least) have dedicated log message parsing functions, and expose that useful functionality in the API rather than cramming it into |
modifications pending PR to dmlc/XGBoost
Hi @ExpandingMan , thanks for the feedback.
For the tolerance on score comparison -that it is extra functionality beyond what is currently available. Early stopping criteria within the R & Python implementations are both based on number of rounds where no improvement has been made and this is how convergence is tested for. This is generally fine so long as you have an evaluation set which would stop overfitting. In the event that we may be checking early stopping against a training set only, it would take much longer to reach a point where there is no improvement. I think what you mentioned is a good suggestion which would be valuable where the only other alternative would be to define the number of rounds upfront. I suggest we tackle that particular enhancement in a separate PR. |
Thanks. I have to take a more careful look at this later, right now I'm mostly concerned about making sure we can add a tolerance without breaking changes, though hopefully a keyword argument will suffice. One quick comment I wanted to make is that we can't have |
`early_stopping_rounds` if 0, the early stopping function is not triggered. If set to a positive integer, | ||
training with a validation set will stop if the performance doesn't improve for k rounds. | ||
|
||
`maximize` If early_stopping_rounds is set, then this parameter must be set as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to imply that the user must input the value whenever they input early_stopping_rounds
. Maybe better to say something like "only used if early_stopping_rounds > 0
".
Ok, comments in line. I think the gist is that, in order not to return a message string from |
…used by early stopping round logic.
…. Included additional test case coverage.
Early stopping rounds - incorporated fixes, documentation examples, comment updates and new test cases
@ExpandingMan I've updated the early stopping rounds branch to incorporate some fixes. Predominantly, as the watchlist was previously defaulting to a Dict, this is an unordered data structure which meant relying on the ordering of elements in this data structure could cause unintentional behaviour. Modifications have been made to account for this to ensure order is preserved based on user input (if an OrderedDict is provided). To ensure backwards compatibility, I've maintained the same xgboost interface but placed a warning if a user inputs a Dict watchlist with more than 1 element and has decided to use the early stopping rounds functionality. To support early stopping rounds, I've also extended the Booster class to have additional attributes which capture the best round (iteration) and best score as per other XGBoost language implementations. This can then be directly used with the already defined ntree_limit parameter in the predict() method. I've made additional test cases to also give test coverage to these enhancements. |
Thanks, especially for all the testing. The way I see it the major issue here is the return of the message string, as commented above. Even if it were not breaking it's a bizarre interface. There are lots of other ways of handling this. (See inline comments above, they are still there.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry guys, I just realized after doing the same thing on another PR that nobody could see the comments I wrote. I hate this entire github feature.
… early stopping rounds and watchlist.
… parsing XGBoost logs.
Moved log message parsing to update! instead of updateone and converted various warnings to exceptions
This looks good to me, thanks! Let me give it a more thorough look when I get a chance, and hopefully I can merge. |
I haven't forgotten this but I haven't gone through it yet... feel free to ping me if I don't get back to it this week. |
Looks good to me, thanks for this. |
Had a need for early stopping rounds and followed the discussion found here #158 to implement this version of it.