A Complete Guide to Feature Transformation and Scaling Techniques in Machine Learning
Feature engineering is one of the most important steps in building effective machine learning models. Within feature engineering, two key techniques are feature transformation and feature scaling. Properly transforming and scaling your input features can significantly boost the performance and stability of many machine learning algorithms.
In this guide, we‘ll take an in-depth look at various feature transformation and scaling techniques, including how they work, when to use them, and how to implement them in Python using the scikit-learn library. By the end, you‘ll have a solid understanding of these important concepts and a toolbox of techniques to improve your own machine learning pipelines.
Why Feature Transformation and Scaling Matters
Many machine learning algorithms make certain assumptions about the distribution and scale of input features. For example, algorithms like linear regression, logistic regression, and many neural networks converge faster and perform better when features are on a similar scale and close to normally distributed.
There are a few main reasons to transform and scale features:
Normalization: Many algorithms expect input features to be centered around 0 with a standard deviation of 1. Scaling techniques like standardization can achieve this.
Similar scales: Algorithms like gradient descent converge much faster when features are on similar scales. For example, if one feature ranges from 0 to 1 and another ranges from 0 to 1,000,000, the algorithm will take a long time to adjust the weights appropriately. Scaling techniques like min-max scaling can put features on more similar ranges.
More normal distributions: Some algorithms, like linear regression, assume features are normally distributed. Transformations like log transforms can make feature distributions more Gaussian when they are highly skewed.
Let‘s now look at some of the most common techniques and when to use them.
Min-Max Scaling
Min-max scaling, also known as normalization, rescales features to a fixed range, usually between 0 and 1. The transformation is given by:
X_scaled = (X – X_min) / (X_max – X_min)
Where X is an original value, X_min is the minimum value of the feature, and X_max is the maximum value.
This puts all features on a similar scale and can be especially helpful for algorithms that rely on distance measurements like support vector machines and k-nearest neighbors. Here‘s how to do min-max scaling with scikit-learn:
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X_scaled = scaler.fit_transform(X)
A downside of min-max scaling is that it is sensitive to outliers. A single outlier can dramatically compress the range of the transformed data.
Standardization (Z-score Normalization)
Standardization rescales features such that they have a mean of 0 and a standard deviation of 1. The transformation is given by:
X_scaled = (X – X_mean) / X_std
Where X_mean is the mean of the feature and X_std is the standard deviation.
Like min-max scaling, standardization puts features on similar scales. However, it is less sensitive to outliers. Standardization is a go-to scaling technique for many machine learning algorithms and is often a safe default choice.
In scikit-learn, you can standardize features using the StandardScaler:
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
Maximum Absolute Scaling
Maximum absolute scaling scales features by dividing by the maximum absolute value such that the transformed data ranges between -1 and 1. It‘s defined as:
X_scaled = X / max(|X|)
This technique is less common but can be useful when data is already centered around zero, sparse, or when outliers are already removed. It ensures data is between -1 and 1 while preserving sparsity and keeping zero values at zero. Here‘s how to implement it:
from sklearn.preprocessing import MaxAbsScaler
scaler = MaxAbsScaler()
X_scaled = scaler.fit_transform(X)
Robust Scaling
Robust scaling uses more robust measures of central tendency and dispersion, like medians and quartiles. The scaled data is given by:
X_scaled = (X – X_median) / (X_75 – X_25)
Where X_median is the median, X_25 and X_75 are the 25th and 75th percentiles.
Robust scaling is ideal for data with many outliers since medians and quartiles are less influenced by extreme values compared to means and standard deviations. Use robust scaling if you have outliers you want to keep.
from sklearn.preprocessing import RobustScaler
scaler = RobustScaler()
X_scaled = scaler.fit_transform(X)
Quantile Transformation
Quantile transformation aims to map the distribution of each feature to a normal or uniform distribution. It‘s a non-linear transformation that‘s useful when you want features to be more Gaussian for algorithms that assume normality.
Quantile transformation in scikit-learn has a parameter output_distribution which can be set to ‘normal‘ to map to a normal distribution or ‘uniform‘ to map to a uniform distribution. Here‘s how to use it:
from sklearn.preprocessing import QuantileTransformer
transformer = QuantileTransformer(output_distribution=‘normal‘)
X_scaled = transformer.fit_transform(X)
A downside is that quantile transformation can distort linear relationships between features, so use it with caution if you‘re using linear models.
Power Transformation
Power transformations aim to stabilize variance and make data more normal distribution-like. The two most common are:
-
Box-Cox transformation: Only works with strictly positive data. Finds the optimal power transformation to make data as close to normal as possible.
-
Yeo-Johnson transformation: Extension of Box-Cox that works with negative values.
Power transformations are most useful for highly skewed data when you want to use algorithms that assume normality. In scikit-learn, you can use the PowerTransformer:
from sklearn.preprocessing import PowerTransformer
transformer = PowerTransformer(method=‘yeo-johnson‘)
X_scaled = transformer.fit_transform(X)
Log Transformation
Log transformation involves taking the logarithm of each value. It‘s a specific type of power transformation that‘s useful for features that have a wide range of values and/or are highly skewed. Log transforms can make highly skewed distributions more normal and reduce the impact of outliers.
There are different bases you can use for the logarithm, but the natural logarithm (base e) is most common. Add a small constant to zero or negative values before applying log to avoid math errors.
In Python, you can apply a log transform using NumPy:
import numpy as np
X_log = np.log(X + 1)
Unit Vector Scaling
Unit vector scaling, also known as normalization (confusingly, since min-max scaling is also sometimes called normalization), rescales each sample (row) to have a unit norm. The most common are the L1 norm (sum of absolute values equals 1) and L2 norm (Euclidean norm – sum of squares equals 1).
Normalizing samples to unit norms can be helpful for sparse data and for algorithms that expect data to be close to zero. Here‘s how to use the scikit-learn Normalizer:
from sklearn.preprocessing import Normalizer
normalizer = Normalizer(norm=‘l2‘)
X_normalized = normalizer.fit_transform(X)
Custom Transformers
Scikit-learn also allows you to define your own custom transformers using the FunctionTransformer. This is useful if you want to apply a specific math function or a more complex transformation to your features.
For example, let‘s say we want to apply a square root transformation:
from sklearn.preprocessing import FunctionTransformer
import numpy as np
transformer = FunctionTransformer(func=np.sqrt)
X_transformed = transformer.transform(X)
Choosing the Right Technique
With all these options, how do you choose the right feature transformation and scaling technique for your problem? Here are a few guidelines:
-
If your algorithm assumes normality, consider quantile transformation or power transformations like Box-Cox or Yeo-Johnson.
-
If your features have very different scales, consider standardization, min-max scaling, or scaling to unit norm.
-
If you have a lot of outliers, consider robust scaling.
-
If your data is sparse, consider max absolute scaling or normalizing to unit norm.
-
For highly skewed positive data, consider log transforms.
-
Always visualize your data before and after transformation to understand the effect.
Ultimately, the best approach is often to experiment with different techniques and see which results in the best performing model. You can use a pipeline to try different transformers and scalers:
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler, PowerTransformer
pipeline = Pipeline([
(‘scaler‘, StandardScaler()),
(‘classifier‘, LogisticRegression())
])
pipeline2 = Pipeline([
(‘transformer‘, PowerTransformer()),
(‘classifier‘, LogisticRegression())
])
# compare performance of the two pipelines
Conclusion
We‘ve covered a lot in this guide to feature transformation and scaling! To recap, the main techniques we discussed were:
- Min-max scaling
- Standardization
- Max absolute scaling
- Robust scaling
- Quantile transformation
- Power transformation (Box-Cox and Yeo-Johnson)
- Log transform
- Unit vector scaling/normalization
- Custom transformers
The key takeaways are:
-
Feature transformation and scaling are important steps in feature engineering that can greatly improve model performance.
-
Different techniques are appropriate for different types of data and different machine learning algorithms.
-
Experiment with different techniques and compare performance to find the best approach for your problem.
-
Always visualize your data before and after transformation to understand the effects.
With these techniques in your toolkit, you‘re well-equipped to preprocess features for machine learning. The scikit-learn library makes all these techniques easy to implement in Python. I hope this guide has been helpful, and happy feature engineering!