Skip to content

Create TargetMeanPredictor class to enhance SelectByTargetMeanPerformance - #358

Closed
Morgan-Sell wants to merge 157 commits into
feature-engine:mainfrom
Morgan-Sell:issue_296
Closed

Create TargetMeanPredictor class to enhance SelectByTargetMeanPerformance #358
Morgan-Sell wants to merge 157 commits into
feature-engine:mainfrom
Morgan-Sell:issue_296

Conversation

@Morgan-Sell

@Morgan-Sell Morgan-Sell commented Jan 5, 2022

Copy link
Copy Markdown
Collaborator

SelectByTargetMeanPerformance class will call TargetMeanPredictor allowing the use of cross-validation to return the important features.

Important links:
https://scikit-learn.org/stable/glossary.html#term-predictors
https://scikit-learn.org/stable/glossary.html#term-classifier

Important: in a classifier predict() should output the real label, not 1, 0:
https://scikit-learn.org/stable/glossary.html#term-predict

check example classifier here:
https://scikit-learn.org/stable/developers/develop.html#rolling-your-own-estimator

@Morgan-Sell

Copy link
Copy Markdown
Collaborator Author

Need to link issues #296 and #334.

@Morgan-Sell

Morgan-Sell commented Jan 10, 2022

Copy link
Copy Markdown
Collaborator Author

Hi @solegalli,

I've made some progress on the TargetMeanPredictor class. In PR #334, we discussed creating the codebase so the predict() method accepts a pandas series. This causes some problems given the use of the encoders and discretisers. I've documented the problems below and suggested one potential solution.

Issues:

  • X for the predict() method must be a dataframe to be compatible w/ the BaseEncoder class which is the parent class to the MeanEncoder class.
  • If we switch input X to a dataframe w/ one column, then _check_input_matches_training_df in the BaseEncoder class returns a ValueError b/c the shape of dataframe X does not coincide with the shape of the dataframe that is used to fit the MeanEncoder().

I suspect it is cumbersome to revise all the inheritance rules/checks from the parent classes, e.g., BaseEncoder, and the encoders/discretisers that are instantiated w/in the TargetMeanPredictor class.

One solution could be to require that the user inputs a dataframe w/ the same dimensions and variable names as the dataframe that is used to fit the TargetMeanPredictor. The predict() method could have another parameter - variable_name - that instructs the predictor which pandas series to return.

Do you have any thoughts? If so, please share!

Also, the codebase is a WIP, so it's not in the best shape ;)

@solegalli solegalli left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Morgan-Sell

Thank you for the code start. I made a few comments. Could you take a look?

Thank you!

Comment thread feature_engine/prediction/target_mean_prediction.py Outdated
Comment thread feature_engine/prediction/target_mean_prediction.py Outdated
Comment thread feature_engine/prediction/target_mean_prediction.py Outdated
Comment thread feature_engine/prediction/target_mean_prediction.py Outdated
Comment thread feature_engine/prediction/target_mean_prediction.py Outdated
@solegalli

Copy link
Copy Markdown
Collaborator

Need to link issues #296 and #334.

this normally goes in the first comment you make in the PR and it takes the form:
closes #296
closes #334

conventions :p ...

@solegalli solegalli left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Morgan-Sell

Thank you so much for the quick turnaround with the code.

I made some suggestions on how to re-write the transform() method that should answer the issues you raised in your last comment.

If you still encounter errors, I would say, write a couple of tests, it doesn't matter that they are failing, because tests normally helps us (or at least me :p) understand where the problem is coming from.

transform(X) should take in the same dataframe that was used in fit(). Fit can take a df with multiple columns or a df with 1 column. sklearn classes do not take in pandas series, so if we have a series, we need to add .to_frame() for it to work. Please add a test using a series.to_frame() to test the functionality as well.

If something does not work or you feel stuck, don't worry, just draft some tests and we take it from there.

Thank you!

Comment thread feature_engine/prediction/target_mean_prediction.py Outdated
Comment thread feature_engine/prediction/target_mean_prediction.py Outdated
Comment thread feature_engine/prediction/target_mean_prediction.py Outdated
Comment thread feature_engine/prediction/target_mean_prediction.py Outdated
the values will be sorted.

strategy: str, default='equal_width'
Whether to create the bins for discretization of numerical variables using

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace

Whether the bins should be of equal width ('equal_width') or equal frequency ('equal_frequency').

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use an underscore or hyphen, e.g., equal_width vs equal-width? I feel like I've seen both uses or I may be confusing feature-engine and sklearn semantics. I'm adopting your pedantic tendencies ;)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trailing underscores are only added to attributes that learn parameters during the fit() method as per sklearn conventions.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm referring to the potential values for the self.strategy parameter. The parameter can either be equal-width or equal-distance.

Should I use (1) equal_distance and equal_width or (2) equal-distance and equal-width?

Option 1 uses an underscore. Option 2 uses a hyphen.

I suspect we want to be consistent w/ sklearn and within the feature-engine library.

Comment thread feature_engine/prediction/target_mean_prediction.py Outdated
Comment thread feature_engine/prediction/target_mean_prediction.py Outdated
Comment thread feature_engine/prediction/target_mean_prediction.py Outdated
Comment thread feature_engine/prediction/target_mean_prediction.py Outdated
Comment thread tests/conftest.py Outdated


@pytest.fixture(scope="module")
def df_pred():

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets more this df into a conftest inside the test_prediction module.

@Morgan-Sell Morgan-Sell Jan 13, 2022

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Will these dataframes only be used for predictor classes? Therefore we create a separate conftest file.

@Morgan-Sell

Copy link
Copy Markdown
Collaborator Author

Muchas gracias por el feedback, @solegalli! I'm still refactoring the codebase. It's a long list ;)

In the meantime, please poke and prod where you see fit!

@Morgan-Sell

Morgan-Sell commented Jan 13, 2022

Copy link
Copy Markdown
Collaborator Author

Hi @solegalli,

A few questions:

  1. Given that the TargetMeanPredictor class has a mean_accuracy_score method, should the class object be able to return classification labels, e.g. binary? If so, should we build a predict_proba method?

  2. Should we make edits to the SelectByTargetMeanPerformance class in this issue or do we create a new issue?

  3. Other than creating a test for mean_accuracy_score, are there any other tests that we should implement?

@solegalli

Copy link
Copy Markdown
Collaborator

Hi @Morgan-Sell

Before I review, could you please try and review the files committed to this PR? I think something went wrong with rebase.

Check out main, pull upstream main to your main branch, then check out your feature branch, rebase main onto it, and then force push.

thank you!

@Morgan-Sell

Morgan-Sell commented Jan 30, 2022

Copy link
Copy Markdown
Collaborator Author

Hola @solegalli,

I implemented all the variable-manipulation unit tests except for test_error_find_cat_and_num_vars_datetime_var(). _find_categorical_and_numerical_variables() is returning datetime_range as a categorical variable.

I'm stuck! _find_categorical_and_numerical_variables() is working on a notebook; however, I cannot translate it to the code base.

What am I missing? :(

Also, like PR #360, the code is returning tests/test_selection/test_check_estimator_selectors.py ........Fatal Python error: Segmentation fault. Do you have any idea as to what is causing the error?

@solegalli solegalli mentioned this pull request Jan 31, 2022

@solegalli solegalli left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Morgan-Sell

Well done with the code changes and the tests. This is looking really good.

I wonder if you could experiment with a few functions from sklearn that are used for classifiers and predictors and expand the tests a bit more.

See my comments below.

Thank you!

Comment thread tests/test_variable_manipulation.py Outdated
assert _find_all_variables(df_vartypes, non_existing_vars)


def test_find_categorical_and_numeric_variables_one_categorical_variables(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we put all these tests together (into 1) and use parametrize?

also, can we use a df that already exists? like df_vartypes?

@Morgan-Sell Morgan-Sell Feb 3, 2022

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that the conftest dataframes are either (1) not recognized if they are not imported or (2) stay as a function object.

Is there an example of passing a conftest dataframe to @pytest.mark.parametrize?

Comment thread feature_engine/prediction/base_predictor.py Outdated
Comment thread feature_engine/prediction/base_predictor.py Outdated
"""
# check if 'X' is a dataframe
_is_dataframe(X)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Morgan-Sell

would you be so kind to experiment with adding this check and see if the tests still pass:

# Check that X and y have correct shape
X, y = check_X_y(X, y, dtype=None)

check_X_y is from sklearn and supposedly checks that X and y fulfill some criteria.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I played w/ check_X_y. The function returns numpy arrays which lack a dtype and cause errors downstream.

I tried transforming X and y into pandas dataframe and series after check_X_y was executed. This caused ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all(). to occur for various unit tests.

I think the root of both errors exists when the MeanEncoder is applied.


# check inf
_check_contains_inf(X, self.variables_numerical_)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we use Check_X-y we do not need to check for na and inf ourselves. In theory. But I have not tried.

I was wondering if you could try commenting this out and see if the tests still pass?

@Morgan-Sell Morgan-Sell Feb 5, 2022

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See prior comment.

Comment thread tests/conftest.py Outdated
Comment thread tests/test_prediction/test_target_mean_classifier.py
Comment thread tests/test_prediction/test_target_mean_classifier.py
Comment thread tests/test_prediction/test_target_mean_regressor.py Outdated
Comment thread tests/test_prediction/test_target_mean_regressor.py
@Morgan-Sell

Copy link
Copy Markdown
Collaborator Author

Hola @solegalli,

Shoudl we delete the tests test_target_mean_predictor_transformation() and test_regression_score_calculation_with_equal_frequency() for both the classifier and regressor? They seem redundant now that we are testing predict, predict_proba, predict_log_proba, and score for one, two and >=3 variables.

@Morgan-Sell

Copy link
Copy Markdown
Collaborator Author

Hola @solegalli,

I haven't heard from you in a while. I hope you're busy having fun!

Do you have any thoughts on my above questions or the classes in general? Abrazo!

@solegalli

Copy link
Copy Markdown
Collaborator

Hola @solegalli,

I haven't heard from you in a while. I hope you're busy having fun!

Do you have any thoughts on my above questions or the classes in general? Abrazo!

Yep. Sorry. Actually I was working on a different PR.

This one is a bit out of my comfort zone so I need to do some research to get more familiar with sklearn classifiers and regressors mixins. It'll take me a little longer.

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 this pull request may close these issues.

2 participants