Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 9

Train-Test Split: Preventing Data Leakage

Recommended resources

Welcome to the second module of our course, where we shift our focus from cleaning existing data to strategically preparing it for machine learning models. In the previous module, we honed our skills in identifying and resolving issues like missing values, outliers, and duplicates, ensuring our dataset is accurate and consistent. Now, we'll learn how to transform this clean data into a format that is optimal for model training.

This lesson addresses a cornerstone of responsible machine learning practice: splitting your data into training and testing sets. You'll learn not just how to perform this split using Python, but more importantly, why it is an absolutely critical first step in any modeling pipeline. Our goal is to understand how this separation prevents a subtle but serious error known as data leakage, ensuring that we can build models we can trust.

Why We Split Data: The Problem of Data Leakage

The ultimate goal of a supervised machine learning model is to make accurate predictions on new, unseen data. If we train and evaluate our model on the same dataset, we're essentially letting it "see the answers" before the test. The model might simply memorize the training data, a phenomenon called overfitting. It would likely perform exceptionally well on that data, but fail spectacularly when presented with data it hasn't encountered before.

To get an honest assessment of a model's performance, we must evaluate it on data it has never seen during training. This is the fundamental purpose of the train-test split.

However, the risk of "cheating" goes beyond just training and testing on the same data. A more subtle but equally damaging issue is data leakage.

Data Leakage Basics, with Examples in Scikit-Learn

This article from AI Mind provides a crisp definition of data leakage and illustrates the core problem.

Please read the first part of the article to grasp the formal definition and the most basic example of leakage. Start from the beginning and read up to the introduction of the train-test split, focusing on the definition: the core concept. Continue reading the example where the model is trained on the entire dataset. Note the high accuracy score, which is misleading.

As the article highlights, data leakage occurs when information from outside the training dataset is used to create the model. This gives the model access to information it would not have in a real-world prediction scenario, leading to an over-optimistic evaluation of its performance.

The most common and dangerous source of data leakage happens during preprocessing. Imagine you want to scale your features using standardization, which requires calculating the mean and standard deviation. If you calculate these values using the entire dataset and then split it into training and testing sets, the training data has been influenced by the test data. Information about the test set's distribution (its mean and standard deviation) has "leaked" into the training process.

The correct procedure is always:

  1. Split the data into a training set and a test set.
  2. Fit your preprocessing tools (like scalers or imputers) on the training data only.
  3. Transform both the training and test data using the fitted preprocessor.

This ensures the test set remains completely unseen until the final evaluation.

A visual representation of data leakage. Scaling the data before splitting it into training and test sets allows information from the test data to influence the training process, leading to unreliable model evaluation.

The Three Data Subsets: Training, Validation, and Testing

For a robust machine learning workflow, we often partition our data into three distinct subsets:

  1. Training Set: The largest portion of the data, used to fit the parameters of the machine learning model. The model learns the relationships between features and the target variable from this data.
  2. Validation Set: A subset of data used to tune the model's hyperparameters (e.g., the K in K-Nearest Neighbors, or the depth of a decision tree). The model is trained on the training set, and its performance is evaluated on the validation set for different hyperparameter settings. This helps select the best model configuration without touching the test set.
  3. Test Set: A completely held-out set of data that is used only once, at the very end of the project, to provide an unbiased estimate of the final model's performance on unseen data.

In many cases, the validation step is handled more robustly using a technique called k-fold cross-validation, which we will cover in a later lesson. In that approach, the initial split is just into training and testing, and the training data is then intelligently sub-divided to create multiple validation folds.

A standard machine learning workflow. The full dataset is first split into training and test sets. The training data is used for model fitting and hyperparameter tuning (often with cross-validation), and the test set is reserved for the final, unbiased evaluation.

The following article provides a superb overview of these concepts.

Split Your Dataset With scikit-learn's train_test_split() – Real Python

This section from the Real Python guide on train_test_split() explains the rationale behind splitting data.

Read the section titled "The Importance of Data Splitting". Pay close attention to the descriptions of the three subsets and how splitting helps identify underfitting and overfitting.


Implementing the Train-Test Split in Python

Now that we understand the "why," let's focus on the "how." Scikit-learn, the primary Python library for machine learning, provides a simple and powerful function for this task: train_test_split.

The following video from Ryan & Matt Data Science provides a clear, practical walkthrough of how to use this function. It covers everything from loading data with pandas to performing the split and verifying the results.

Train Test Split with Python Machine Learning (Scikit-Learn)

This video is a hands-on tutorial for using scikit-learn's train_test_split function.

Please watch the entire video. As you have a strong background in Python and pandas, the initial data loading will be familiar. Focus on the train_test_split specific parts: Preparing X and Y: Understanding the convention of separating the feature matrix (X) from the target vector (y). The train_test_split call: Pay close attention to the syntax and the key parameters being explained: test_size and random_state. Verifying the split: See how to use the .shape attribute to confirm that the data has been split into the correct proportions.

To solidify what you've seen in the video, let's review the function and its most important parameters.

The function train_test_split is located in sklearn.model_selection. At its most basic, you pass it your features X and your target y.

from sklearn.model_selection import train_test_split




# X represents your features, y represents your target variable
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

Here's a breakdown of the key parameters:

  • test_size: This determines the proportion of the dataset to allocate to the test set. It's typically a float between 0.0 and 1.0. A common split is 80% for training and 20% for testing (test_size=0.2), or 70/30. You can also use train_size to specify the proportion for the training set instead.
  • random_state: This is a crucial parameter for reproducibility. The split is random, so if you run the function again, you'll get a different split. By setting random_state to any integer (e.g., 42), you ensure that you get the exact same split every time you run the code. This is essential for debugging, consistent results, and sharing your work.
  • shuffle: This is True by default, meaning the data is shuffled before being split. This is almost always what you want, to ensure the training and test sets are representative samples. The main exception is for time-series data, where you might want to preserve the temporal order.
  • stratify: This parameter is incredibly useful for classification problems, especially with imbalanced classes. By setting stratify=y, you ensure that the proportion of each class in the target variable y is the same in both the training and testing sets as it is in the original dataset. For example, if your original dataset is 10% class A and 90% class B, stratify=y guarantees that both your training and test sets will also have a ~10/90 split.

The Real Python article has an excellent section detailing these parameters with code examples.

Split Your Dataset With scikit-learn's train_test_split() – Real Python

This section provides a detailed guide on using the train_test_split function with clear code snippets.

Read the section "Application of train_test_split()". This will reinforce what you saw in the video and provide more detail. Focus specifically on the explanations for: The random_state parameter, to solidify your understanding of reproducibility. The stratify parameter. Work through the code example to see how it preserves the class distribution.


Conclusion

In this lesson, we established the first and most important rule of feature preprocessing and model building: split your data first. This practice is your primary defense against data leakage and overfitting, ensuring that your model's performance metrics are a true reflection of its ability to generalize to new data.

Here are the key takeaways:

  • Data Leakage occurs when information from the test set contaminates the training process, leading to falsely optimistic performance metrics.
  • Train-Test Split is the fundamental technique to prevent leakage and get an unbiased evaluation of your model.
  • The Correct Workflow is to split the data into training and test sets before applying any preprocessing steps like scaling, encoding, or imputation.
  • Scikit-Learn's train_test_split is the standard tool for this task in Python. Using random_state ensures reproducibility, and stratify is crucial for maintaining class proportions in classification tasks.

Now that we have a robust framework for evaluating our models, we are ready to proceed with feature engineering. In our next lesson, we will explore feature scaling. We will apply normalization and standardization techniques correctly—that is, after performing a train-test split—to prepare our data for algorithms that are sensitive to the scale of input features.