Article · 2024-01-01

Feature Normalization: A Complete Guide from Concept to Code

In scikit-learn, a single line of Pipeline code elegantly chains feature scaling with model training, delivering efficient, leak-free preprocessing:

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression

# 创建一个流水线,先进行 Z-Score 标准化,再训练逻辑回归模型
pipe = make_pipeline(StandardScaler(), LogisticRegression())

# 传入原始训练数据,流水线会自动处理
pipe.fit(X_train, y_train)

This guide walks you through feature normalization from foundational concepts to code practice to advanced topics, so you can master this essential data science skill with confidence.


1. Foundational Concepts

1.1 Dimension

Dimension originated in physics to denote the unit composition of a physical quantity. In data science, we repurpose the term to describe a feature's unit and scale. As mentioned above, height_m (unit: meters, scale: ~1) and income_cny (unit: Chinese yuan, scale: ~10,000) are two features with different dimensions.

1.2 Normalization vs. Standardization

Though "normalization" often serves as a catch-all term, it properly splits into two distinct types: Normalization and Standardization, each with different targets and methods.

Term Typical Implementation Target Distribution Use Case
Normalization Min-Max Scaling [0, 1] or [-1, 1] Preserve original data proportion or apply distance-based algorithms (image processing, KNN).
Standardization Z-Score Scaling Mean μ = 0, std σ = 1 Most gradient descent algorithms (linear regression, SVM, neural networks) for numerical stability.

In short: Normalization cares about "range," Standardization cares about "distribution."


2. Why Normalize?

Four core reasons justify scaling your data:


3. Common Normalization Methods

Here are the most widely used normalization methods with formulas and scikit-learn implementations.

Method Formula scikit-learn Example
Min-Max $x' = \frac{x - x_{\min}}{x_{\max} - x_{\min}}$ python\nfrom sklearn.preprocessing import MinMaxScaler\nX_mm = MinMaxScaler().fit_transform(X)\n
Z-Score $z = \frac{x - \mu}{\sigma}$ python\nfrom sklearn.preprocessing import StandardScaler\nX_z = StandardScaler().fit_transform(X)\n
Max-Abs $x' = \frac{x}{ x_{\max}
Robust (IQR) $x' = \frac{x - \text{median}}{\text{IQR}}$ python\nfrom sklearn.preprocessing import RobustScaler\nX_r = RobustScaler().fit_transform(X)\n

For lightweight manual Min-Max scaling in environments without external libraries:

import numpy as np

def minmax_scale(X):
    """手动实现 Min-Max 缩放"""
    X = np.asarray(X, dtype=float)
    # 加上一个极小值 1e-12 防止分母为零
    return (X - X.min(0)) / (X.max(0) - X.min(0) + 1e-12)

4. End-to-End Example: Mixed Dimensions and Two Scaling Methods

Let's see how Min-Max and Z-Score scaling transform actual data.

Environment: Python 3.9+, scikit-learn 1.2+, np.random.seed(42)

Data: Five records with height_m (meters) and income_cny (yuan) features.

import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler, StandardScaler

# 设置随机种子以保证结果可复现
np.random.seed(42)

# 创建原始数据
df = pd.DataFrame({
    "height_m": np.round(np.random.uniform(1.55, 1.85, 5), 2),
    "income_cny": np.random.randint(5_000, 50_000, 5)
})

# 应用 Min-Max 缩放
df[["height_mm", "income_mm"]] = MinMaxScaler().fit_transform(df[["height_m", "income_cny"]])

# 应用 Z-Score 缩放
df[["height_z",  "income_z" ]] = StandardScaler().fit_transform(df[["height_m", "income_cny"]])

# 打印结果
print(df.round(2))

Output comparison:

   height_m  income_cny  height_mm  income_mm  height_z  income_z
0      1.66       21850       0.25       0.03     -0.72     -0.91
1      1.84       42194       1.00       0.75      1.43      0.88
2      1.77       26962       0.71       0.21      0.60     -0.46
3      1.73       49131       0.54       1.00      0.12      1.49
4      1.60       21023       0.00       0.00     -1.43     -0.99

Result interpretation:

Through scaling, the two originally mismatched features—height and income—are brought into comparable numeric ranges. They can now be compared intuitively and used directly for model training.


5. Normalization and Model Fit

Not every model needs normalization. Knowing which ones are sensitive is critical.

Strong Dependence / Strongly Recommended Insensitive / Optional
Linear/Logistic Regression Decision Trees
Support Vector Machines (SVM) Random Forests
K-Nearest Neighbors (KNN) Gradient Boosting (GBDT, XGBoost, LightGBM)
K-Means Clustering Naive Bayes
Neural Networks
Principal Component Analysis (PCA)
Linear Discriminant Analysis (LDA)

Core reason: Tree models (decision trees, random forests) split on feature thresholds; they care about rank order, not magnitude. They are insensitive to monotonic scaling.

Special note: In regression, if your target y spans a wide range (e.g., house price prediction), log transformation (np.log1p) or standardization of y itself is common optimization. After prediction, apply the inverse transform (np.expm1) to recover the original scale.


6. Best Practices in Practice

  1. Prevent data leakage: This is critical. Fit the scaler only on the training set, then apply that fitted scaler to training, validation, and test sets. Fitting on the entire dataset leaks test information into training, inflating evaluation metrics.

  2. Use Pipeline: Strongly prefer sklearn.pipeline.Pipeline or make_pipeline. It bundles preprocessing and model training so that cross-validation and deployment strictly enforce "fit on training, transform all data." This eliminates leakage at the source.

  3. Handle streaming data: If data arrives continuously and cannot load into memory at once, StandardScaler provides partial_fit(). Feed it batches incrementally; it dynamically updates global mean and variance.

  4. Handle outliers first: Min-Max is extremely sensitive to outliers. A single extreme value compresses all other points into a narrow band. Best practice: address outliers (via RobustScaler, clipping, or removal) before deciding on Min-Max.


7. Common Pitfalls


8. Advanced Topics

Feature normalization extends far beyond the basics. Here are deeper topics worth exploring:


9. Java Quick Start

For developers implementing normalization in Java, here is a quick start using apache.commons.math3 for manual Min-Max scaling.

import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;

public class MinMaxScaler {
    /**
     * 对二维数组的每一列(特征)进行 Min-Max 缩放
     * @param X 输入数据,shape: [n_samples, n_features]
     * @return 缩放后的数据
     */
    public static double[][] transform(double[][] X) {
        if (X == null || X.length == 0) {
            return new double[0][0];
        }
        int nFeatures = X[0].length;
        double[][] Y = new double[X.length][nFeatures];

        for (int j = 0; j < nFeatures; j++) {
            double min = Double.MAX_VALUE;
            double max = -Double.MAX_VALUE;
            // 第一次遍历,找到当前特征的最大值和最小值
            for (double[] row : X) {
                min = Math.min(min, row[j]);
                max = Math.max(max, row[j]);
            }
            
            double range = max - min;
            // 防止分母为零
            if (range == 0) range = 1e-12;

            // 第二次遍历,应用 Min-Max 公式
            for (int i = 0; i < X.length; i++) {
                Y[i][j] = (X[i][j] - min) / range;
            }
        }
        return Y;
    }
}

10. Closing

Feature normalization is an indispensable tool in your data preprocessing kit. When it's essential and when it's optional depends entirely on your algorithm and task. It is not a one-size-fits-all step, but a choice informed by data distribution and model characteristics.

This guide provides a clear map. You now have the foundation to confidently select and apply the right scaling strategy for your next project.

Further reading:

© 2026 Yuxu Ge ·