-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Encapsulated the selector training within a function and called it inside _init_ #1473
Encapsulated the selector training within a function and called it inside _init_ #1473
Conversation
autosklearn/experimental/askl2.py
Outdated
global metrics | ||
global selector_files | ||
global strategies | ||
global this_directory |
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's the reason to make these global
?
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.
Those variables were being used inside the fit()
function of askl2. A better solution would be to declare them as class variables instead, I guess.
autosklearn/experimental/askl2.py
Outdated
@@ -339,6 +335,7 @@ def __init__( | |||
"classifier": include_estimators, | |||
"feature_preprocessor": include_preprocessors, | |||
} | |||
train_selectors() |
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.
Perhaps we can improve the startup time further by only training the selector for the metric
that is given. In the case of no metric given, I guess we can just default to using all of them.
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 do see the metric
parameter that is accepted by askl2. Should this be a list of metrics? And if nothing is passed, we could use the default ones.
Codecov Report
@@ Coverage Diff @@
## development #1473 +/- ##
===============================================
- Coverage 84.31% 84.15% -0.17%
===============================================
Files 147 151 +4
Lines 11284 11496 +212
Branches 1934 1995 +61
===============================================
+ Hits 9514 9674 +160
- Misses 1256 1288 +32
- Partials 514 534 +20 |
So the report you see at the bottom are our automated checks which run a benchmark of tests against autosklearn. As you can see they have currently failed. You can click on any one of them and look at the log to see which tests failed.
You can run this locally using The Let me know if something isn't clear, I can't guarantee any feedback over the weekend so don't hesitate to reach out. |
After encapsulating the selector training, |
Hi @aseemk98, So for the As for the tests, feel free to modify as needed so things work as intended, we can review it and make sure it's still correct. Since the scope of variables is changing, it makes sense that the tests should be changed too. |
@eddiebergman , |
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.
So I would still ask that the global
keywords are removed, either they should be properties of the ASKL2Classifer
or just moved explicitly into the global state if that doesn't make sense to do.
The tests on the automated tests also seem to pass fine, the doc tests are failing due to a known issue so I wouldn't worry about that one. |
682c119
to
7cd763d
Compare
There was an issue with the previous commit with the test-case 2. That has now been fixed in the latest one. There are no global variables either, an instance of |
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.
Hey, looks a lot cleaner now :) Thanks!
So one more thing I would block merging on and it's a minor thing about renaming metrics
to selector_metrics
. It's our fault as we are using metrics
to mean multiple metrics for training and ensemble soon and so it would conflict with what metrics
means here which is just for training the selector.
With that changed, I would merge as is
autosklearn/experimental/askl2.py
Outdated
@@ -367,6 +307,81 @@ def __init__( | |||
allow_string_features=allow_string_features, | |||
) | |||
|
|||
def train_selectors(self, selected_metric=None): | |||
self.metrics = (balanced_accuracy, roc_auc, log_loss) |
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.
Could we call this self.selector_metrics
? We have a version of multi-objective autosklearn coming soon and we use metrics
to indicate a list of metrics used for training.
metric_list = [selected_metric] | ||
else: | ||
metric_list = self.metrics | ||
for metric in metric_list: |
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.
Minor comment, adding some spacing between different constructs like if/else
and for
is nice. I imagine it was clumped like this before but there's no reason not to improve it now :) Non-blocking though, it's mergable without it.
If you're up for the task, you could also test that this functionality works as intended, i.e. the selector is only trained for the |
Hi @eddiebergman, |
Sure seems good as it is now. For the tests we need to consider what we actually want to test, I can think of a few points but if you have more, please feel free to add them!
For 1., it would be good to do this for all metrics but you can use @pytest.mark.parametrize("name", ["Anna", "assemk98", "apple"])
def test_something_something(name: str):
assert name.lower().startswith("a") For 2., it can be done along with the first test. For 3., I think at the moment it will then train a selector for every metric, similar to the old behavior. You might be able to squeeze it these checks with 1. and 2. but perhaps it's better to make it seperate For 4., the test might require you to look at these examples on how to create a custom metric. I guess it's behaviour should be the same as it was before in that all selectors are trained? You might consider some tests like: @pytest.mark.parametrize("metric", [...])
def test_askl2_fits_selector_for_given_metric_at_init(metric):
# Create askl2 with metric
# Make sure when it's created, the selector file exists
# Make sure there's no other unneeded selector trained
# ... we might need to clean up selector files so it won't interfere with other tests
def test_askl2_when_no_metric_specified():
# Create Askl2 with no metric
# Make sure when its created, all the selector files for the default metrics are created
# ... we might need to clean up selector files so it won't interfere with other tests
def test_askl2_fit_with_custom_metric():
# Create a custom metric
# Create askl2 with metric
# Make sure the behaviour is .... (same as before)
# ... we might need to clean up selector files so it won't interfere with other tests |
Hi @eddiebergman, Sure! I can write tests for the code, I was thinking along the same lines too. I'll create a new PR for the same! Also, if there are any other issues apart from the one I just addressed, would love to work to work on that as well! |
It would be good to have the tests in the same PR but for sure, if your willing to help out some more, we can find some good issues! Happy to have the extra hands :) |
Hi @eddiebergman , |
Yup, what you say makes sense to pass an explicit path :) You have a good instinct so in general, you can go with what you think makes sense and if it seems off during the code review, we can discuss it then! |
Hi @eddiebergman , |
Hi @eddiebergman, |
Hi @aseemk98, Very sorry for the delay, we got swamped with some other work and this slipped under the radar, thanks for bumping this! So the way you handled case 2 makes sense and in general the tests seem all good to me :) Two points however. When I ran the online tests and they seem to fail when calling the There's also the option to use def test_something(tmp_path):
# Gives you a clean directory specifically for this test
assert tmp_path.is_dir()
assert len(list(tmp_path.iterdir())) == 0
# It's deleted once the test ends We could use it like so: @pytest.mark.parametrize(
"metric",
[metric for _, metric in autosklearn.metrics.CLASSIFICATION_METRICS.items()],
)
def test_askl2_fits_selector_for_given_metrics_at_init(tmp_path, metric):
# Not that it was added as a parameter
# No need to clean it up
# Might be good to leave a comment why this was done, doesn't seem obvious from looking
# only at the test
with unittest.mock.patch("os.environ.get") as mock_foo:
mock_foo.return_value = str(tmp_path) # Unfortunatly autoklearn isn't great with Pathlib
...
# No need to clean it up There's nothing wrong with the Once that issue is fixed in which ever way you prefer, I'm happy to merge! Apologies for the delay once again. Best, |
Hi @eddiebergman, |
Hi @eddiebergman , |
So it makes sense it should fail for other metrics other than the three predefined ones, take a look at the folder I took at look at the old implementation and it seems like that if a user passed in a custom metric and it wasn't one of those three predefined ones, it would use the selector for auto-sklearn/autosklearn/experimental/askl2.py Lines 385 to 390 in b2ac331
I'll see how to get the automated tests to run on every push for you so that you get faster feedback on it :) |
So it appears there's not much I can do about not having to manually approve workflows, it's a safety thing that github has no real opt-out for. In general though, the local tests should be a good indicator of the tests here, the bigger thing to figure out wuld be why it passes for you locally, as it really shouldn't given there's a selector for only these 3 metrics. |
After making changes in the test script, do I have to make changes elsewhere from them to be actually applied? Or is there a different way to run tests? I use this command: |
That command should work, you should make sure you have autosklearn install in editable mode, i.e. |
Yeah, that's exactly how I had installed dependencies. Anyway, pushed a new commit that tests only on the default metrics we have listed in experimental. Hopefully, now it works. |
@eddiebergman
Is there a reason for this? Or it is running all required tests? |
So the filter Secondly I see that you removed the test for a custom metric, we could keep it in and make sure it does the old behaviour which was to use the one for balanced accuracy. However since this has been going on for a while, I'll also just be happy as soon as the tests pass :) |
One test is still failing. Everything else passed. |
And it's failing for a part of the code that doesn't call askl2. |
The other one is unrelated to this PR and it's a known issue we have. Everything looks good, I'll merge this in once we're good ready to with other changes we have coming :) Thanks for the PR and sorry for the week delay that happened! |
@eddiebergman thank you as well. You were super patient and helpful! This was my first contribution and was really fun for me :) |
Glad to hear! The test part of contributions is always difficult for the first time, every project will have it's own test setup and I still struggle with this for every new project, no worries :) If you'd like to give any feedback on what we could improve for future contributors, finding an issue, things missing from the contribution guide or just general feedback of any kind that might encourage people to contribute, we would love to hear! Feel free to do so here or else you can find my email on my profile page and drop me an email there if you would prefer :) Also if you ever would like to contribute again, please let us know, as a benefit, we can enable workflows to automatically run for non-first-time contributers which means there's less stalling and waiting for direct feedback! Best, |
Hi @eddiebergman , I would love to take on more issues with auto sklearn, maybe something more challenging this time :) |
Hello again, Closing this will probably be towards the end of the month, we have some other PR's and things that are currently being used for research and we don't want to make benchmarking harder with new changes being put in. I'll take a look today and try find an issue that seems manageable :) Best, |
…side _init_ (#1473) * Encapsulated the selector training within a function and called it inside __init__ * Made changes in the test script that trains selectors before testing * Moved global variables inside the askl2 class, changes in the test script supporting that * Committing after running pre-commit * Fixed issue resulting into failure of case 2 * Changed metrics to selector_metrics * Added additional tests for askl2 * Added a boolean to the class to check for re-training of selectors * Using tmp_path instead of tmpdir * Removed tests for all metrics * Removed test for custom metric
No description provided.