-
Notifications
You must be signed in to change notification settings - Fork 401
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
Q ExponentiatedGradient results vary using the same model and data #1261
Comments
Yes, you're missing the Please reopen if this doesn't fully address your question. |
Hello @romanlutz, indeed by setting the random_state parameter I can obtain consistent predictions using the same fitted instance of ExponentiatedGradient. However, if I refit the ExponentiatedGradient I lose reproducibility again. I can partly solve it by setting a numpy seed before fitting, and that way the results are reproducible in a single system, even restarting my jupyter kernel, but not if I move for example from my windows to linux PCs. I was especially interested in this kind of reproducibility because I'm writing a technical post and I would have liked the readers to be able to reexecute the notebook and obtain exactly the same results. But I guess it's just due to the nature of the algorithm that it's not possible. Thanks anyways! |
@MiroDudik this sounds like a question for you. |
@CarlaFernandez -- there shouldn't be any randomness in the exponentiated gradient during fitting. we tried hard to only use deterministic optimizers. my guess is that what you see is somehow coming from CatBoostClassifier and/or possibly from how we clone the classifiers internally here:
So, one idea would be to compare whether the following three classifiers are returning the same model: from sklearn import clone
# your code setting up CatBoostClassifierAdapter and params
model1 = CatBoostClassifierAdapter(cat_features=categorical_features, **params)
model2 = CatBoostClassifierAdapter(cat_features=categorical_features, **params)
model3 = clone(estimator=model1, safe=False)
model1.fit(...)
model2.fit(...)
model3.fit(...) |
Hello @MiroDudik , how would I go about checking that model1, model2 and model3 are the same model? I can see that all of them return the same predictions, is that enough to ensure they are the same model? (I would think so) |
Hi @CarlaFernandez, I am not super familiar with the |
It seems that import copy
model4 = copy.deepcopy(model1) # do this before model1 is fitted!!! Thanks so much for helping us chase this bug! |
We have a bugfix. We'll just need to come up with a small regression test that would not create a dependence on catboost... |
I suspect that there is some kind of bug in the For some reason i have some issues with installing catboost, @CarlaFernandez could you let me know what you get when you do: model1.get_params() You get a very similar result if you delete the import copy
from sklearn import clone
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
data=load_iris()
X = data.data
y = data.target
class RandomForestClassifierTest(RandomForestClassifier):
def get_params(self,**kwargs):
params = super().get_params(**kwargs)
del params['random_state']
return params
model1 = RandomForestClassifierTest(random_state=0)
model2 = RandomForestClassifierTest(random_state=0)
model3 = clone(estimator=model1, safe=False)
model4 = copy.deepcopy(model1)
print(model1.fit(X,y).feature_importances_)
print(model2.fit(X,y).feature_importances_)
print(model3.fit(X,y).feature_importances_)
print(model4.fit(X,y).feature_importances_) which outputs:
|
Hi @hildeweerts , this is the output I obtain from
I guess what you wanted to see are the hyperparameters for the actual catboost model, not the adapter, so here they are (
I'm attaching my requirements.txt file in case it helps you with the catboost installation or debugging the problem: Thank you :) |
The fact that What does this line return: model1.get_params(deep=False) # similarly from model2,3,4 BTW, even if the implementation of |
@CarlaFernandez -- together with @romanlutz and @hildeweerts , we played a bit with your implementation, and the issue is in how
That said, I still think that we should still replace |
I agree with @MiroDudik on replacing clone with deepcopy, but curious what @adrinjalali thinks as well. Adding a bit to what @MiroDudik wrote regarding the code. Perhaps we can resolve this for your particular problem @CarlaFernandez, too, so that you don't have to wait for a release. Can you elaborate on the purpose of the adapter class?
and if I look into the wrapper's BTW I ran the same with the unchanged wrapper class and the @CarlaFernandez I hope that makes sense. Feel free to respond if you have thoughts, comments, or questions. I'd love to hear if that unblocks you 🙂 |
Hello @romanlutz and all, thanks for the support on this issue. I originally created the Adapter class simply because I thought I needed my model to inherit from sklearn's BaseEstimator to make it work with fairlearn. Reading the docs more carefully, I now see it just needed to implement I now think my issue was more due to a lack of attention to detail while reading than anything else! But, I still think it is a really useful thing to document, since people might be using custom models and need to pass extra parameters to the constructor. And of course the fix substituting copy for deepcopy is a nice find! Thanks again and regards |
It's great feedback, thanks for being so responsive and providing a sample that is easy to reproduce. @fairlearn/fairlearn-maintainers this is a good reminder to make our requirements of estimators more visible in the docs. |
I really wouldn't replace
So I'd suggest document well what we expect, how the estimator works, and how people could potentially fix this issue. |
Thanks @adrinjalali! i'm not sure whether this was already discussed during one of the calls during my vacation, but @MiroDudik what do you think given adrin's points? |
Problem
Hello,
I'm using the ExponentiatedGradient to perform mitigations on a Catboost classifier. Each time I run the
fit
and obtain the MetricsFrame for my sensitive features, I get different results. I would like to know if this is normal, or if I may be missing someseed
parameter somewhere.Reproducible example
I'm working with the census data, and this is my code:
The text was updated successfully, but these errors were encountered: