-
Notifications
You must be signed in to change notification settings - Fork 83
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
Simplify logging behavior #2645
Conversation
Codecov Report
@@ Coverage Diff @@
## main #2645 +/- ##
=======================================
- Coverage 99.9% 99.9% -0.0%
=======================================
Files 301 301
Lines 27851 27751 -100
=======================================
- Hits 27802 27702 -100
Misses 49 49
Continue to review full report at Codecov.
|
evalml/automl/automl_search.py
Outdated
logger.info("Exiting AutoMLSearch.") | ||
self._activate_logger | ||
self.logger.info("Exiting AutoMLSearch.") | ||
self._deactivate_logger |
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.
Warning: missing parentheses to invoke the methods here
I'm surprised our lint didn't catch this! I wonder if there's a way / file an issue to have lint fail if we try to invoke a non-property as a property. Tagging @angela97lin since she's been messing with linting / style recently
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.
That's a really good question @dsherry! I'm not sure I've run into anything that would have caught this--probably tricky to do since calling this without the paraentheses still returns the method and is "valid" 🤔 . Will keep an eye out though!
evalml/automl/automl_search.py
Outdated
"AutoMLSearch.search() has already been run and will not run again on the same instance. Re-initialize AutoMLSearch to search again." | ||
) | ||
self._deactivate_logger() |
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.
What would happen if we deleted _deactivate_logger
entirely from this PR?
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.
Deleting _deactivate_logger
would mean we can no longer run AutoML search with verbose=False
after running with verbose=True
, since our get_logger
function (run when verbose is True) modifies the same logger that's grabbed by logging.getLogger
when verbose is False.
Just now in reading your comments I had a thought - it doesn't have to be the case that the logger obtained when verbose is True vs when verbose is False have the same name. Instead, we could create another sub-logger for when verbose is True (like I did with pipeline.describe()
and others) so that it would maintain any user-configured logging behavior without needing to be reset with _deactivate_logger
at the end of each method that uses it. This would also resolve your question above about setting the logging level back to logging.WARNING
in _deactivate_logger
, as that would no longer be necessary. Thoughts?
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.
Left a question and a few nits, but this was great work!
@@ -1358,7 +1369,7 @@ def _check_for_high_variance(self, pipeline, cv_scores, threshold=0.5): | |||
return high_variance_cv | |||
cv_range = max(cv_scores) - min(cv_scores) | |||
if cv_range >= threshold * allowed_range: | |||
logger.warning( | |||
self.logger.warning( |
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.
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.
The warning is still there in both cases, it just appears in different ways! When verbose=False
, the default logging is used, so warnings and higher are printed in the default format of red highlighting. When verbose=True
, we override the default formatting settings, so while warnings are still printed to stdout (along with all the info level information), they are no longer highlighted in red.
You can see the same warning in the verbose=True
case where the report of the Decision Tree cv scores are.
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 is a great PR. I like what's going on here and the simplicity of it.
I think the one thing we should address before merge is the testing strategy. Does it make sense to test this feature by running a variety of tests with verbose on and off? I think this is OK for tests that don't drastically increase the test runtime by much (don't run automl.search). What are your thoughts on keeping the tests as written before this PR, but adding verbose=True to all of them, then have just a single test that verifies that nothing is logged when verbose=False. It seems that if verbose=False, a single test should capture that entirely.
Let me know your thoughts. If you don't want to do that, I think it would be sufficient to show the runtime of the tests isn't drastically affected!
Another nice to have would be if you could silence the dask/cfengine stuff in the docs. Out of scope, so feel free to tell me to pound sand.
@@ -337,10 +360,17 @@ def test_pipeline_fit_raises(AutoMLTestEnv, X_y_binary, caplog): | |||
assert np.isnan(score) | |||
|
|||
|
|||
def test_pipeline_score_raises(AutoMLTestEnv, X_y_binary, caplog): | |||
@pytest.mark.parametrize("verbose", [True, False]) |
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.
Ok, do we need to run this test for both verbosities if we're not checking for anything different?
@@ -362,7 +392,9 @@ def test_pipeline_score_raises(AutoMLTestEnv, X_y_binary, caplog): | |||
|
|||
|
|||
@patch("evalml.objectives.AUC.score") | |||
def test_objective_score_raises(mock_score, X_y_binary, caplog): | |||
@pytest.mark.parametrize("verbose", [True, False]) |
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.
Same question here, except I think now we're also going to pay a penalty of running search. I worry that all the parametrization of verbosity doesn't really provide much testing benefit while increasing the runtime of tests.
@@ -2564,7 +2607,9 @@ def test_early_stopping(caplog, logistic_regression_binary_pipeline_class, X_y_b | |||
|
|||
assert not automl._should_continue() | |||
out = caplog.text | |||
assert "2 iterations without improvement. Stopping search early." in out | |||
assert ( |
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.
I think this test makes sense and can test both verbosities without much penalty in runtime.
@chukarsten thanks for the testing suggestions! I took another look at the tests with parameterizations of verbose values, and I agree, a lot of them weren't necessary. I've filtered through them, according to a few criteria:
At this point, every test that includes |
Closes #1174 - design doc here