Tuesday Tip #46: How to prevent data leakage in pandas & scikit-learn ☔


Hi Reader,

I'm really proud of this week's tip because it covers a topic (data leakage) that took me years to fully understand. 🧠

It's one of those times when I feel like I'm truly contributing to the collective wisdom by distilling complex ideas into an approachable format. 💡

You can read the tip below 👇 or on my blog.


🔗 Link of the week

Building an AI Coach to Help Tame My Monkey Mind (Eugene Yan)

In this short post, Eugene describes his experiences calling an LLM on the phone for coaching:

As I walk to work, I share my anxieties, use it as a sounding board for ideas, and clarify new concepts I come across in papers and podcasts. My AI coach helps me prep for difficult scenarios, such as giving tough feedback, so the actual conversation goes better. It also acts as a mirror by clarifying and reflecting my emotions back at me, and provides an external perspective.

I love this idea. I called up his AI coach for a few minutes (for free; see the post for details), and while I definitely felt awkward, I could see how it would be useful once you've tuned the coach to your own needs (and gotten used to having a conversation with a bot!)


👉 Tip #46: How to prevent data leakage in pandas & scikit-learn

Let's pretend you're working on a supervised Machine Learning problem using Python's scikit-learn library. Your training data is in a pandas DataFrame, and you discover missing values in a column that you were planning to use as a feature.

After considering your options, you decide to impute the missing values, which means that you're going to fill in the missing values with reasonable values.

How should you perform the imputation?

  • Option 1 is to fill in the missing values in pandas, and then pass the transformed data to scikit-learn.
  • Option 2 is to pass the original data to scikit-learn, and then perform all data transformations (including missing value imputation) within scikit-learn.

Option 1 will cause data leakage, whereas option 2 will prevent data leakage.

Here are questions you might be asking:

  • What is data leakage?
  • Why is data leakage problematic?
  • Why would data leakage result from missing value imputation in pandas?
  • How can I prevent data leakage when using pandas and scikit-learn?

Answers below! 👇


What is data leakage?

Data leakage occurs when you inadvertently include knowledge from testing data when training a Machine Learning model.

Why is data leakage problematic?

Data leakage is problematic because it will cause your model evaluation scores to be less reliable. This may lead you to make bad decisions when tuning hyperparameters, and it will lead you to overestimate how well your model will perform on new data.

It's hard to know whether data leakage will skew your evaluation scores by a negligible amount or a huge amount, so it's best to just avoid data leakage entirely.

Why would data leakage result from missing value imputation in pandas?

Your model evaluation procedure (such as cross-validation) is supposed to simulate the future, so that you can accurately estimate right now how well your model will perform on new data.

But if you impute missing values on your whole dataset in pandas and then pass your dataset to scikit-learn, your model evaluation procedure will no longer be an accurate simulation of reality. That's because the imputation values will be based on your entire dataset (meaning both the training portion and the testing portion), whereas the imputation values should just be based on the training portion.

In other words, imputation based on the entire dataset is like peeking into the future and then using what you learned from the future during model training, which is definitely not allowed.

How can we avoid this in pandas?

You might think that one way around this problem would be to split your dataset into training and testing sets and then impute missing values using pandas. (Specifically, you would need to learn the imputation value from the training set and then use it to fill in both the training and testing sets.)

That would work if you're only ever planning to use train/test split for model evaluation, but it would not work if you're planning to use cross-validation. That's because during 5-fold cross-validation (for example), the rows contained in the training set will change 5 times, and thus it's quite impractical to avoid data leakage if you use pandas for imputation while using cross-validation!

How else can data leakage arise?

So far, I've only mentioned data leakage in the context of missing value imputation. But there are other transformations that if done in pandas on the full dataset will also cause data leakage.

For example, feature scaling in pandas would lead to data leakage, and even one-hot encoding (or "dummy encoding") in pandas would lead to data leakage unless there's a known, fixed set of categories.

More generally, any transformation which incorporates information about other rows when transforming a row will lead to data leakage if done in pandas.

How does scikit-learn prevent data leakage?

Now that you've learned how data transformations in pandas can cause data leakage, I'll briefly mention three ways in which scikit-learn prevents data leakage:

  • First, scikit-learn transformers have separate fit and transform steps, which allow you to base your data transformations on the training set only, and then apply those transformations to both the training set and the testing set.
  • Second, the fit and predict methods of a Pipeline encapsulate all calls to fit_transform and transform so that they're called at the appropriate times.
  • Third, cross_val_score splits the data prior to performing data transformations, which ensures that the transformers only learn from the temporary training sets that are created during cross-validation.

Conclusion

When working on a Machine Learning problem in Python, I recommend performing all of your data transformations in scikit-learn, rather than performing some of them in pandas and then passing the transformed data to scikit-learn.

Besides helping you to prevent data leakage, this enables you to tune the transformer and model hyperparameters simultaneously, which can lead to a better performing model!


👋 See you next Tuesday!

Did you like this week’s tip? Please forward it to a friend or share this tip with your favorite Machine Learning community. It really helps me out!

- Kevin

P.S. Bits of wisdom from 73 years of living

Did someone AWESOME forward you this email? Sign up here to receive Data Science tips every week!

Learn Artificial Intelligence from Data School 🤖

Join 25,000+ intelligent readers and receive AI tips every Tuesday!

Read more from Learn Artificial Intelligence from Data School 🤖

Hi Reader, Last week, I encouraged you to experiment with different LLMs, since there’s no one model that is superior across all use cases. Specifically, I suggested you try using Chatbot Arena, which allows you to chat with multiple models at once. It’s completely free, but has two significant disadvantages: Your chats are not private and may be used for research. It lacks the feature-rich interface provided by other LLMs. Today, I want to offer you a better method for experimenting with...

Hi Reader, Over the past 50 tips, I’ve touched on many different topics: Python, Jupyter, pandas, ML, data visualization, and so on. Going forward, I’m planning to focus mostly on Artificial Intelligence. I’m announcing this so you know what to expect, and I know what to deliver! 💌 I’ll also try to make the tips shorter, so that they're easier to digest on-the-go. Finally, I plan to include an “action item” each week, so that you can practice what you’re learning. I hope you like these...

Hi Reader, Next week, I’ll be offering a Black Friday sale on ALL of my courses. I’ll send you the details this Thursday! 🚨 👉 Tip #50: What is a "method" in Python? In Python, a method is a function that can be used on an object because of the object's type. For example, if you create a Python list, the "append" method can be used on that list. All lists have an "append" method simply because they are lists: If you create a Python string, the "upper" method can be used on that string simply...