Model Evaluation with Train and Test Splits
Linear models can struggle with skewed features that have many small values and a few very large ones, and transforming such features often improves the fit.
Why a Few Huge Values Cause Trouble
Many real datasets contain a feature whose values are mostly small, with a handful of extremely large values sitting far to the right. Counts, prices, and durations often look like this. The feature may carry useful information about the target, yet a linear model can still struggle with it. This article shows why that happens, how a logarithm-based transformation helps, and how to decide which features are worth transforming.
What do you think happens?
Before we transform anything, consider the expression log(x + 1) when x = 0. What is its value?
Reveal answer
0
Adding 1 turns x = 0 into 1, and the logarithm of 1 is 0. This is exactly why the form log(x + 1) is used: a plain logarithm of 0 is undefined, but the +1 keeps every value of zero or more inside the range where the logarithm is defined.
Tracing a Skewed Feature
Picture a feature whose values cluster near zero while a few values sit far above the rest. If you plot it, the points form a long tail stretching to the right. Statisticians call this a skewed distribution. Follow the values through a linear model step by step. A linear model fits a straight-line relationship between each feature and the target. When a few values are enormous, they dominate that fit. The many small values are squeezed into a tiny region of the scale, where the model cannot tell them apart well.
Consider a made-up count feature with five observations: 0, 1, 3, 12, and 950. Four of the values are below 13, but the last one is 950. On a raw scale, the gap between 0 and 12 is almost invisible next to the gap between 12 and 950. A straight line that tries to account for the 950 point is pulled far away from the cluster of small values, so the small values receive almost no distinct treatment. The fastest way to see this in practice is to fit a model on the raw data and look at the held-out test score.
Compressing Values with log(x + 1)
A logarithm compresses large values. Once it is applied, the very large values move much closer to the bulk of the data, while the small values, which were crowded together, occupy a wider stretch of the scale. The feature becomes more evenly spread, and a linear relationship can describe it more effectively. The transformation changes the scale of the feature. It does not discard any of its values.
Read the diagram from top to bottom in each column. Before the transform, the raw gap from 12 to 950 is enormous compared with the gap from 0 to 3. After the transform, the largest value is 6.86, and the small values are spread across a visibly wider range relative to it. The 950 observation is still the largest value, but it no longer dominates the scale.
[0. 0.69 1.39 2.56 6.86]np.log1p(x)computes log(x + 1) for every element of the array in one call- Zero stays a valid input, which is why the +1 form is used instead of a plain logarithm
np.roundis only used here to make the printed output easier to read
Worked Example: Transforming a Count Feature
Applying log(x + 1) to a feature with zeros and a large outlier
A feature records the number of visits per customer: 0, 1, 3, 12, and 950. Apply log(x + 1) and describe what happens to the spread.
- 1Add 1 to each value
The shifted values are 1, 2, 4, 13, and 951. The zero has become 1, so every value is now at least 1.
- 2Take the natural logarithm
The results are approximately 0, 0.69, 1.39, 2.56, and 6.86. The zero maps to exactly 0.
- 3Compare the gaps
On the raw scale, the gap between 12 and 950 is 938, which is far larger than the gap between 0 and 12. On the log scale, the gap between 2.56 and 6.86 is 4.30, while the gap between 0 and 2.56 is 2.56. The large value now sits at a more moderate distance from the rest.
- 4Confirm no value was lost
There are still five observations in the same order. Only the scale changed.
The feature now has the same five ordered observations, with the very large value pulled closer to the bulk of the data, so a linear relationship can describe it more evenly.
Deciding Which Features to Transform
There is no single transformation that always works. Finding the best transformation for each combination of dataset and model is somewhat of an art. In the source's example, every feature happened to share the same properties, which is rarely true in practice. Usually only a subset of the features should be transformed, and sometimes each feature needs its own transformation.
The flowchart captures the main decision. Tree-based models are generally unaffected by these transforms, while linear models often depend on them. The source also notes that binning, polynomials, and interactions can have a large influence on less complex models such as linear models and naive Bayes models. Other models, including SVMs, nearest neighbors, and neural networks, may sometimes benefit, but the effect is usually less predictable. Because the effect is empirical, the practical test is to compare held-out scores with and without the transform.
Reducing Feature Count with Univariate Selection
Transformations change the values of existing features. A second lever is to change how many features the model sees. It is tempting to create many new features, but adding features makes all models more complex and raises the chance of overfitting. When the feature count is high, it can be wise to keep only the most useful features and discard the rest, which can produce simpler models that generalize better.
The source describes three basic strategies: univariate statistics, model-based selection, and iterative selection. All three are supervised, meaning they use the target. Univariate selection scores each feature independently against the target, keeps the top percentile of features, and passes the reduced set to the model. SelectPercentile is the scikit-learn tool for keeping a chosen percentage of the highest-scoring features.
f_regressionis a univariate score function that rates each feature against a numeric target- percentile=50 keeps the top half of the features by score
fit_transformuses the target, so it is called on the training data only- transform applies the already-learned selection to the test data without refitting
Checking Reduced Features on a Held-Out Test Set
Because feature selection uses the target, it is supervised, and it must be fitted only on the training portion of the data. The test set must remain untouched during selection. If the selector saw the test targets, the test score would no longer measure performance on unseen data, and it would look better than the model deserves.
Follow the diagram from the full dataset. The training split is used to fit the selector, which decides which columns survive. The test split then passes through the same learned selection without being used to make any choice. The model is trained on the reduced training data, and the test score reflects how it performs on rows it has never seen. Compare this score against the score from the unreduced features to judge whether the reduction helped.
Mistakes When Transforming and Selecting Features
Common mistake Applying log(x) directly to a feature that contains zeros
What it looks likenp.log(counts) where counts includes 0 produces negative infinity for those rows.
Why it failsThe logarithm of zero is undefined, so the zero values cannot be represented after a plain logarithm.
Do this insteadUse log(x + 1), written in NumPy as np.log1p(counts), which keeps zero valid.
Common mistake Transforming every feature by default
What it looks likeApplying a log transform to every column, including features that are already evenly spread.
Why it failsThe source notes that only a subset of features usually needs transforming, and the best choice is empirical.
Do this insteadInspect each feature's distribution and compare held-out scores with and without the transform.
Common mistake Expecting tree-based models to benefit from the same transforms
What it looks likeAdding a log transform before a tree-based model and expecting a large jump in accuracy.
Why it failsTree-based models are generally unaffected by these transforms, while linear models often depend on them.
Do this insteadSave the transform effort for linear and similar models, and test before assuming any gain.
Common mistake Fitting feature selection on the full dataset
What it looks likeCalling fit_transform on all rows before splitting into train and test.
Why it failsSelection uses the target, so the test targets leak into the choice of features and the test score is no longer a fair check.
Do this insteadFit the selector on the training split only, then call transform on the test split.
Common mistake Keeping every feature because more features seem more informative, even though extra features increase complexity and overfitting risk
Practice: Choosing a Transform and a Selection Rule
A dataset has a feature called daily_downloads with values 0, 2, 5, 9, 40, and 2000, and a linear regression model predicts a score. Describe whether you would apply log(x + 1) to daily_downloads, which function you would call in NumPy, and how you would confirm the choice using a held-out test score.
Hints
- Look for the pattern of many small values with a few very large ones, and check whether the feature contains zeros.
- A linear model is the kind of model that often depends on this transform, while a tree-based model usually does not.
- Compare the test score with and without the transform, fitting any selection on the training split only.
Key Takeaways
- Skewed features, with many small values and a few very large ones, can squeeze most of the data into a small region of the scale, which limits how well a linear model fits.
- The form log(x + 1), written as
np.log1pin NumPy, compresses large values, keeps zeros valid, and preserves the order of the observations. - Transform only the features that benefit, decide empirically, and remember that tree-based models usually do not need these transforms.
- Univariate selection with SelectPercentile reduces the feature count, must be fitted on training data only, and should be checked with a held-out test score.