NelworksNelworks

ML & AI / Season 1 / EP09

Cross-Validation Data Leakage (Group Leakage)

Shez

Kurumi, meet our new star. "Model X."

Kurumi

Another one? What happened to Model Y?

Shez

Model X is a genius! Look at that CV score! I ran a 5-Fold Cross-Validation. He predicted the customer behavior perfectly, 5 times in a row!

Kurumi

98.5%. Suspicious... Did you test him on *new* customers?

Shez

I tested him on the Validation Folds! That *is* unseen data!

Kurumi

`KFold(n_splits=5, shuffle=True)`.

Kurumi

Ah. I see. You didn't test him. You let him cheat.

Shez

Cheat? I shuffled the data! It's random! Randomness is the essence of fairness!

Kurumi

Randomness is the essence of leakage when your data has **Groups**.

Kurumi

How many rows of data do you have for User 42?

Shez

He's a power user. He has about 50 transactions in the dataset.

Kurumi

That is where the problem lies. When you shuffle randomly, where do those 50 transactions go?

Kurumi

Statistically, 40 of them go into the Training Set. And 10 of them go into the Test Set.

Shez

Yeah. So?

Kurumi

Imagine User 42 is a specific topic. Let's say "History of Rome."

Shez

Here are 40 questions about Rome to study.

Shez

(Reading) "Caesar died in 44 BC." "Nero played the fiddle." Got it.

Shez

Now, answer these 10 *new* questions about Rome.

Shez

Easy. "Who died in 44 BC?" It's Caesar. "Who played the fiddle?" It's Nero.

Shez

See? He learned History!

Kurumi

No. He memorized the **Subject**.

Kurumi

Now, send Model X into production. A new user signs up. User 99.

Shez

(Sweating) Uh...

Shez

I... I don't know who Caesar is in Quantum Physics.

Kurumi

He fails. Because he never learned *how to learn*. He just memorized that "User 42 likes Roman History."

Kurumi

This is **Identity Leakage**.

Kurumi

By putting pieces of User 42 in both Train and Test, the model learns to identify *User 42*, not the *purchase pattern*.

Shez

So my model is just... recognizing faces?

Kurumi

It's a "Who's Who" directory, not a predictive engine.

Kurumi

You validated the same customer five times. LinkedIn would clap. But in engineering, we call this **Overfitting**.

Shez

But I need to use all the data! How do I stop him from memorizing faces?

Kurumi

You need to respect the **Group Boundaries**.

Kurumi

If User 42 is in the Training Set, *every single transaction* he ever made must be in the Training Set.

Kurumi

The user must be invisible to the model during training if you want to test on them.

Shez

Oh! So when it sees the Test set, it's seeing a total stranger.

Kurumi

Exactly. Just like in Production.

Shez

`from sklearn.model_selection import GroupKFold`.

Shez

`cv = GroupKFold(n_splits=5)`.

Shez

`cv.split(X, y, groups=user_ids)`.

Kurumi

Make sure you pass the `groups` parameter. Otherwise, it just defaults to index splitting.

Shez

Got it. Passing `user_id`.

Shez

"Hold on, User 42. Your friends are already inside the 'Train' club. You have to go there too. You can't enter the 'Test' club."

Shez

But I want to be tested!

Shez

Not in this fold, buddy.

Shez

Okay... calculating...

Shez

NOOO! It ruined my model! It's garbage now!

Kurumi

(Sipping coffee) It didn't ruin your model. It revealed the truth.

Kurumi

That 64% is what you were *actually* going to get in production.

Kurumi

I just saved you from deploying a dud and getting fired next month.

Shez

Okay. 64% is bad. How do I improve the *truth*?

Kurumi

You do real engineering.

Kurumi

1. Feature Engineering that is **User-Agnostic**.

Kurumi

Don't use "User ID" as a feature. Use "Frequency of Purchase" or "Time Since Last Login."

Kurumi

Teach the model to look at the *behavior*, not the *identity*.

Kurumi

2. Aggregated Features. "Average spend of *similar* users."

Kurumi

Generalize. Don't memorize.

Shez

Removing `user_id` from features. Adding `rolling_mean_7d`. Adding `category_preference_ratio`.

Shez

Running `GroupKFold` again.

Shez

78%. It's... better.

Kurumi

And one more thing. Is your data **Time-Dependent**?

Shez

Uh... yeah. Transaction logs.

Kurumi

Then `GroupKFold` isn't enough. You need **Time Series Split**.

Shez

Why?

Kurumi

If you randomly split users, you might train on User B (who bought in 2024) and test on User A (who bought in 2023).

Kurumi

The model learns the future trends (e.g., "Macroeconomic Inflation") from User B and uses it to predict the past for User A.

Shez

Why is it so hard to stop the model from cheating?

Kurumi

You need to design smarter tests.

Kurumi

For now, `GroupKFold` is enough. Next time, we'll handle `TimeSeriesSplit`.