Skip to content
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

Typo in grid_search_reduction.py causing AttributeError: 'GridSearchReduction' object has no attribute 'moment' #451

Closed
haas-christian opened this issue Mar 31, 2023 · 4 comments · Fixed by #452

Comments

@haas-christian
Copy link
Contributor

In the current version of GridSearchReduction, there's a typo in the predict() function that causes an AttributeError when trying to use a fitted GridSearchReduction model for predicting a new dataset.

Specifically, the typo is in line 140:
if isinstance(self.model.moment, red.ClassificationMoment):

Since the model does not have an attribute moment, it will cause the Attribute Error. Instead, the moment attribute of the model should be self.model.moment_ :
if isinstance(self.model.moment_, red.ClassificationMoment):

Here's an example that shows the described behavior:

# Load all necessary packages
from aif360.algorithms.preprocessing.optim_preproc_helpers.data_preproc_functions import load_preproc_data_adult
from aif360.algorithms.inprocessing.grid_search_reduction import GridSearchReduction
from sklearn.linear_model import LogisticRegression
import numpy as np

# Get the dataset and split into train and test
dataset_orig = load_preproc_data_adult()

privileged_groups = [{'sex': 1}]
unprivileged_groups = [{'sex': 0}]

np.random.seed(0)
dataset_orig_train, dataset_orig_test = dataset_orig.split([0.7], shuffle=True)

estimator = LogisticRegression(solver='lbfgs', max_iter=1000)

np.random.seed(0) #need for reproducibility
grid_red = GridSearchReduction(estimator=estimator,
                               constraints="EqualizedOdds",
                               drop_prot_attr=False)
grid_red.fit(dataset_orig_train)
grid_red_pred = grid_red.predict(dataset_orig_test)
@mnagired
Copy link
Collaborator

mnagired commented Apr 3, 2023

Hi there,

Thanks for flagging this. Interesting, do you know if self.model.moment_ is the only way to fix this?

For example, in the code for GridSearchReduction in the sklearn-compatible version of AIF360, you can see the use of self.model._constraints.

@haas-christian
Copy link
Contributor Author

That's a good question. Based on my understanding, we want to check if the provided moment is one that is implemented as ClassificationMoment in fairlearn. if isinstance(self.model.moment_, red.ClassificationMoment) would check this, since self.moment_ in the sklearn-compatible version of GridSearchReduction refers to the fairlearn ClassificationMoment. In contrast, if we call self.model.constraints, we only get the str representation.

In the above code sample, when I call self.model.moment_, I get the result <fairlearn.reductions._moments.utility_parity.EqualizedOdds at 0x1bb41350130>, indicating it's a FairLearn moment.
However, if I call self.model.constraints, I get 'EqualizedOdds', indicating a simple str representation.

An alternative way to checking if isinstance(self.model.moment, red.ClassificationMoment) could be to check if self.model.constraints is a key in a dict of accepted moments, similar to what the sklearn-compatible version does (lines 116-123):

        moments = {
            "DemographicParity": red.DemographicParity,
            "EqualizedOdds": red.EqualizedOdds,
            "TruePositiveRateParity": red.TruePositiveRateParity,
            "FalsePositiveRateParity": red.FalsePositiveRateParity,
            "ErrorRateParity": red.ErrorRateParity,
            "BoundedGroupLoss": red.BoundedGroupLoss,
        }

However, since this dict is only specified in fit(), it cannot be accessed via self.model at the moment. So, another fix could be to add this dict of accepted moments in the init() function of GridSearchReduction, and then check if the model moment is in this dict, similar to what lines 124-126 do in the sklearn-compatible version:

if isinstance(self.constraints, str):
            if self.constraints not in moments:
                raise ValueError(f"Constraint not recognized: {self.constraints}")

Compared to this, fixing the typo to self.model.moment_ seems the easier choice in my opinion.

@mnagired
Copy link
Collaborator

mnagired commented Apr 5, 2023

Thanks for the exploration!

This makes sense to me, could you please open a PR with your changes to line 140 above and link this issue there?

haas-christian added a commit to haas-christian/AIF360-GridSearchReductionFix that referenced this issue Apr 5, 2023
Linked to issue Trusted-AI#451 of AIF360: Trusted-AI#451 

Signed-off-by: haas-christian <34253996+haas-christian@users.noreply.github.com>
@haas-christian
Copy link
Contributor Author

Done!

@mnagired mnagired linked a pull request Apr 5, 2023 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants