Z-Score Normalization

RawGraph

Last edited

Fact-checked

In review queue

Sources

18 citations

Revision

v8 · 6,343 words

Fact-checks are independent of edits: a reviewer re-verifies the article against its sources and stamps the date. How we verify

See also: Machine learning terms

What is z-score normalization?

Z-score normalization, also called standardization, standard score normalization, or z-score scaling, is a data preprocessing technique that transforms a numerical feature so that it has a mean of 0 and a standard deviation of 1, computed as z=(xμ)/σz = (x - \mu) / \sigma. The transformation subtracts the feature mean from each value and then divides the result by the feature standard deviation. The output values are called z-scores, and each z-score represents how many standard deviations a given data point sits above or below the mean of its distribution. The scikit-learn documentation defines the operation succinctly: "Standardize features by removing the mean and scaling to unit variance."[1]

In machine learning, z-score normalization is one of the most widely used feature scaling methods. Many learning algorithms are sensitive to the relative scales of input features. Without scaling, a feature measured in thousands (such as annual income in dollars) can dominate a feature measured in single digits (such as age in decades), leading to poor model performance and slow convergence. Standardization addresses this problem by placing all features on a comparable scale while preserving the shape of each feature's distribution.[1][2]

The technique has roots in classical statistics that predate machine learning by more than a century. Francis Galton's late-19th-century work on hereditary statistics and Karl Pearson's early-20th-century formalization of the product-moment correlation coefficient relied on standardized variables. The textbook Statistical Methods by George W. Snedecor and William G. Cochran, first published in 1937 and revised through eight editions, helped cement standardization as a default operation in applied statistics.[15] The same arithmetic that statisticians used to compare student test scores or crop yields now serves as a routine step in modern training pipelines for deep learning models.

What is the z-score normalization formula?

The z-score for a single observation is computed as:

z=xμσz = \frac{x - \mu}{\sigma}

where:

SymbolMeaning
zThe standardized value (z-score)
xThe original raw value
mu (mean)The arithmetic mean of all values for that feature
sigma (std)The standard deviation of all values for that feature

To standardize an entire feature column, compute the mean and standard deviation across all observations in the training set, then apply the formula to every value, including values in the validation and test sets. The scikit-learn documentation states the same formula directly: "The standard score of a sample x is calculated as: z=(xu)/sz = (x - u) / s," where u is the mean of the training samples and s is their standard deviation.[1]

Should you use population or sample standard deviation?

A subtle but important choice when implementing z-score normalization is whether to use the population standard deviation or the sample standard deviation. The two formulas differ only in their denominator:

FormulaDenominatorCommon name
Population variancenDivides by the number of observations
Sample variancen - 1Bessel's correction; produces an unbiased estimate of the population variance

scikit-learn's StandardScaler and the NumPy function numpy.std default to the population formula (denominator n). The pandas function Series.std defaults to the sample formula (denominator n-1). The SciPy function scipy.stats.zscore defaults to the population formula but accepts a ddof argument that switches to the sample form. For large training sets the difference between the two is small, but the inconsistency between libraries occasionally causes off-by-a-fraction discrepancies that are worth understanding before debugging a pipeline.[1][16]

LibraryFunctionDefault ddofResult
scikit-learnStandardScaler0Population std
NumPynumpy.std0Population std
SciPyscipy.stats.zscore0Population std (configurable)
pandasDataFrame.std1Sample std (Bessel correction)
TensorFlowtf.math.reduce_std0Population std

What are the mathematical properties of z-score normalization?

After z-score normalization is applied to a feature, the transformed values always exhibit two key properties:[3]

  1. Zero mean. The mean of the z-scores equals zero. Subtracting the original mean from every value centers the distribution at the origin.
  2. Unit variance. The standard deviation (and therefore the variance) of the z-scores equals one. Dividing by the original standard deviation rescales the spread to a standard size.

These properties hold regardless of the original distribution's shape. If the raw data is skewed, the z-scored data will still be skewed; standardization changes the location and scale but not the shape of the distribution.

For data that follows a normal distribution, z-scores have an additional useful interpretation. Roughly 68% of values fall between z=1z = -1 and z=+1z = +1, about 95% fall between z=2z = -2 and z=+2z = +2, and approximately 99.7% fall between z=3z = -3 and z=+3z = +3. This is known as the 68-95-99.7 rule (or the empirical rule).[3]

Z-Score RangeApproximate Percentage of Data (Normal Distribution)
-1 to +168%
-2 to +295%
-3 to +399.7%
-4 to +499.994%

Is z-score normalization invertible?

Z-score normalization is an affine transformation of the form f(x) = ax + b with a = 1/sigma and b = -mu/sigma. Affine transformations preserve linear relationships, which is why standardization does not change the rank ordering of values, the Pearson correlation coefficient between two features, or the coefficient of determination of a linear fit. They do, however, change unstandardized regression coefficients in interpretable ways, which is the basis for standardized regression coefficients (also called beta coefficients) used in social science research.

The transformation is invertible. Given a fitted scaler with stored mean mu and standard deviation sigma, the original value is recovered as x = z*sigma + mu. Inverse transformation is essential for two practical workflows. First, when a target variable has been standardized before training a regression model, the model's predictions must be inverted before they are reported in original units. Second, when interpreting feature importance scores or explaining model behavior, analysts often want to map z-scored thresholds back to the original measurement scale.

# Inverse transform with scikit-learn
from sklearn.preprocessing import StandardScaler
import numpy as np

X = np.array([[180, 85], [170, 70], [160, 60], [150, 55], [165, 65]])
scaler = StandardScaler().fit(X)
X_scaled = scaler.transform(X)
X_recovered = scaler.inverse_transform(X_scaled)
# X_recovered equals X within floating-point precision

A worked example of z-score normalization

Consider a dataset with two features: height (in cm) and weight (in kg).

PersonHeight (cm)Weight (kg)
A18085
B17070
C16060
D15055
E16565

Step 1: Compute summary statistics.

FeatureMean (mu)Standard Deviation (sigma)
Height (cm)165.010.0
Weight (kg)67.010.84

Step 2: Apply the formula to each value.

PersonHeight Z-ScoreWeight Z-Score
A(180 - 165) / 10 = 1.50(85 - 67) / 10.84 = 1.66
B(170 - 165) / 10 = 0.50(70 - 67) / 10.84 = 0.28
C(160 - 165) / 10 = -0.50(60 - 67) / 10.84 = -0.65
D(150 - 165) / 10 = -1.50(55 - 67) / 10.84 = -1.11
E(165 - 165) / 10 = 0.00(65 - 67) / 10.84 = -0.18

After standardization, both features are centered around zero and expressed in comparable units (standard deviations). A height z-score of 1.50 and a weight z-score of 1.66 tell us that Person A is 1.5 standard deviations above the mean height and 1.66 standard deviations above the mean weight.

Step 3: Verify the output statistics.

After standardization, the mean of each scaled column should be zero (within floating-point precision) and the standard deviation should be one. For the height z-scores: 1.50 + 0.50 + (-0.50) + (-1.50) + 0.00 = 0, so the mean is exactly 0. For the weight z-scores: 1.66 + 0.28 + (-0.65) + (-1.11) + (-0.18) = 0.00, again confirming a zero mean. Computing the standard deviation of each transformed column produces a value of 1.00. These checks are useful as unit tests when implementing a custom standardizer.

Why does standardization help machine learning?

Faster gradient descent convergence

Many machine learning models, including linear regression, logistic regression, and neural networks, are trained using gradient descent. When input features have very different scales, the loss surface becomes elongated (shaped like a narrow valley rather than a symmetric bowl). Gradient descent in such a landscape oscillates back and forth across the narrow dimension and makes slow progress along the long dimension, resulting in slow convergence. Standardizing the features reshapes the loss surface into something closer to a symmetric bowl, allowing gradient descent to take more direct paths toward the minimum and converge significantly faster.[2][4]

This effect can be quantified using the condition number of the Hessian matrix of the loss surface. A condition number near 1 corresponds to a roughly spherical loss surface, while a large condition number corresponds to an elongated valley. Standardization reduces the condition number by removing scale-driven magnitude differences across features. Yann LeCun and colleagues' 1998 paper Efficient BackProp recommended centering and scaling inputs precisely for this reason and noted that the recommendation extended to hidden activations as well, foreshadowing later work on batch normalization.[10]

Equal feature weighting

Distance-based algorithms such as k-nearest neighbors (KNN), k-means clustering, and support vector machines (SVM) calculate distances between data points. Without standardization, features with larger numeric ranges contribute disproportionately to the distance calculation. For example, if one feature ranges from 0 to 1,000 and another from 0 to 1, the first feature would overwhelm the second in any Euclidean distance computation. Standardization ensures that every feature contributes equally.[1][5]

The Euclidean distance between two standardized observations equals the unweighted Mahalanobis distance under the assumption that the features are uncorrelated. When the features are correlated, the full Mahalanobis distance further multiplies by the inverse covariance matrix, but z-score standardization is still a useful first step before computing distances.

Improved regularization

Regularization techniques such as L1 regularization (Lasso) and L2 regularization (Ridge) penalize large weight values. When features are on different scales, the associated weights must differ in magnitude just to compensate for the scale differences, not because of genuine differences in feature importance. Standardization removes scale-driven magnitude differences, allowing the regularization penalty to treat all features fairly.[5]

In the original 1996 Lasso paper, Robert Tibshirani assumed that the predictors were standardized to have mean zero and unit variance before applying the penalty. Most modern implementations, including scikit-learn's Lasso, Ridge, and ElasticNet classes, expect the user to standardize the inputs explicitly via StandardScaler. Failing to standardize before fitting a regularized linear model is one of the more common silent bugs in applied machine learning.

Better performance in PCA

Principal Component Analysis (PCA) identifies the directions of maximum variance in the data. If features are not standardized, PCA tends to identify the features with the largest numeric ranges as the most important, even if those features are not truly the most informative. In Sebastian Raschka's empirical study on a wine classification dataset, test-set prediction accuracy rose from 64.81% (without standardization) to 98.15% (with standardization applied before PCA), a difference of more than 33 percentage points.[4][5]

A related operation is whitening, which goes beyond z-score normalization by also decorrelating the features. Whitening transforms a feature vector x with mean mu and covariance Sigma into W*(x - mu) where W is chosen so that the resulting covariance matrix is the identity. PCA whitening is a common preprocessing step for autoencoders, independent component analysis, and certain generative models.

Which models require standardization?

Not all algorithms benefit equally from standardization. The table below summarizes which model families typically need it and which do not.[5][6]

Model TypeNeeds Standardization?Reason
Linear regression, logistic regressionYesUses gradient descent; convergence depends on feature scale
Support vector machines (SVM)YesDistance-based kernel computations are scale-sensitive
K-nearest neighbors (KNN)YesEuclidean distance dominated by large-scale features
K-means clusteringYesCluster assignment uses distance metrics
Neural networksYesGradient-based optimization; large-scale inputs cause unstable gradients
Principal Component Analysis (PCA)YesVariance-based; scale differences distort principal components
Lasso, Ridge, Elastic NetYesRegularization penalty depends on weight magnitude
Naive Bayes (Gaussian)SometimesClass-conditional Gaussians are estimated independently per feature, but standardization can stabilize numerical computation
Decision treesNoSplits are based on thresholds; scale-invariant
Random forestsNoEnsemble of decision trees; inherits scale invariance
Gradient boosted trees (XGBoost, LightGBM)NoTree-based; not affected by feature scale
Rule-based modelsNoDecision rules use thresholds, not magnitudes

How does z-score normalization compare to other scalers?

Z-score normalization is one of several feature scaling techniques. The other common ones are min-max scaling, robust scaler, max-abs scaling, and the quantile transformer.[7]

ScalerOutput CenterOutput SpreadOutput RangeOutlier RobustnessWhen to Use
StandardScaler (z-score)Mean = 0Std = 1UnboundedModerateDefault for gradient-based models, distance-based methods, PCA
MinMaxScalerDepends on dataDepends on data[0, 1] or customLowBounded inputs needed (image pixels), neural networks with sigmoid outputs
RobustScalerMedian = 0IQR = 1UnboundedHighDatasets with outliers or heavy-tailed distributions
MaxAbsScalerPreservedScaled by max absolute value[-1, 1]LowSparse data; preserves zero entries
Normalizer (L2)Per rowUnit norm per rowUnit sphereLowText classification with TF-IDF, cosine similarity
QuantileTransformerMedian = 0Uniform or normalBoundedHighHeavily skewed features
PowerTransformer (Yeo-Johnson, Box-Cox)Approx. mean 0Approx. std 1UnboundedHighFeatures that should be made more Gaussian-like

Z-score normalization vs min-max normalization: what is the difference?

Z-score normalization and min-max normalization are the two most common feature scaling techniques. They serve different purposes and behave differently in the presence of outliers. The core distinction is that z-score normalization is unbounded and centered on the mean (mean 0, std 1), whereas min-max normalization squashes every value into a fixed range such as 0 to 1.[7]

PropertyZ-Score Normalization (Standardization)Min-Max Normalization
Formulaz=(xμ)/σz = (x - \mu) / \sigmax=(xxmin)/(xmaxxmin)x' = (x - x_{\min}) / (x_{\max} - x_{\min})
Output rangeUnbounded (typically -3 to +3 for normal data)Fixed [0, 1] (or custom range)
Center and spreadMean = 0, Std = 1Depends on data range
Outlier sensitivityModerate (mean and std are affected, but output is not bounded)High (a single extreme value compresses all other values into a narrow band)
Distribution shapePreservedPreserved
Best forAlgorithms using gradient descent or distance metrics; data with outliersAlgorithms requiring bounded inputs (e.g., pixel values for image models); data with no significant outliers

When to choose standardization: Use z-score normalization when the data may contain outliers, when no fixed output range is required, or when training algorithms that assume normally distributed features (such as many linear models and SVMs).

When to choose min-max scaling: Use min-max normalization when a bounded output range is needed (for example, pixel intensity values in image processing) and when the data contains no significant outliers.

In practice, it is often worth trying both approaches and comparing model performance through cross-validation.[7]

What is robust standardization?

Standard z-score normalization uses the mean and standard deviation, both of which are sensitive to extreme values. When a dataset contains significant outliers, a single extreme observation can shift the mean and inflate the standard deviation, distorting the standardized values for all other points.

Robust standardization addresses this limitation by replacing the mean with the median and the standard deviation with the interquartile range (IQR, the range between the 25th and 75th percentiles):[8]

xrobust=xmedianIQRx_{\text{robust}} = \frac{x - \text{median}}{\text{IQR}}

Because the median and IQR are less sensitive to outliers than the mean and standard deviation, robust standardization produces more stable scaling in the presence of extreme values.

In scikit-learn, robust standardization is available through the RobustScaler class:

from sklearn.preprocessing import RobustScaler

scaler = RobustScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
ScalerCenter StatisticScale StatisticOutlier Robustness
StandardScalerMeanStandard deviationLow
RobustScalerMedianInterquartile range (IQR)High

What is the modified z-score (MAD-based)?

A closely related variant is the modified z-score introduced by Boris Iglewicz and David Hoaglin in their 1993 American Statistical Association volume How to Detect and Handle Outliers. The modified z-score uses the median absolute deviation (MAD) instead of the standard deviation:[11]

Mi=0.6745ximedianMADM_i = 0.6745 \cdot \frac{x_i - \text{median}}{\text{MAD}}

where MAD = median(|x_i - median|) and the constant 0.6745 is the inverse of the 75th percentile of the standard normal distribution. This constant rescales the MAD so that, for normally distributed data, the modified z-score is approximately equal to the ordinary z-score.

Iglewicz and Hoaglin recommended treating any observation with |M_i| > 3.5 as a potential outlier. The modified z-score is widely used in anomaly detection systems where the underlying distribution is heavy-tailed or contaminated, and a small number of outliers should not influence the threshold for the rest of the data.

StatisticStandard z-scoreModified z-score
CenterMeanMedian
ScaleStandard deviation1.4826MAD1.4826 \cdot \text{MAD} (or equivalently divides by MAD/0.6745)
Outlier flag rule of thumbz>3\lvert z \rvert > 3M>3.5\lvert M \rvert > 3.5
Breakdown point0% (a single extreme value distorts both stats)50% (median and MAD remain stable until half the data is corrupted)

How do you apply z-score normalization with StandardScaler in scikit-learn?

The most common way to apply z-score normalization in Python is through the StandardScaler class in scikit-learn, whose documentation describes its job as: "Standardize features by removing the mean and scaling to unit variance."[1] Below is a typical workflow:

from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

# Split the data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

# Create and fit the scaler on TRAINING data only
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)

# Transform the test data using the SAME scaler
X_test_scaled = scaler.transform(X_test)

# Train a model on the scaled data
model = LogisticRegression()
model.fit(X_train_scaled, y_train)
accuracy = model.score(X_test_scaled, y_test)

Key parameters

ParameterDefaultDescription
with_meanTrueIf True, center data by subtracting the mean
with_stdTrueIf True, scale data to unit variance
copyTrueIf False, attempt to modify arrays in place instead of copying

Key attributes (after fitting)

AttributeDescription
mean_Per-feature mean computed from the training data
var_Per-feature variance computed from the training data
scale_Per-feature scaling factor, generally computed as the square root of var_
n_features_in_Number of features seen during fit
n_samples_seen_Number of samples processed (relevant for partial_fit)

Why fit the scaler on training data only?

A critical best practice is to fit the scaler on the training set only and then use the same fitted scaler to transform the validation and test sets. This prevents data leakage, a situation where information from the test set influences the training process. If the scaler were fit on the entire dataset (including test data), the computed mean and standard deviation would contain information from the test set, giving the model an unfair advantage during evaluation and producing overly optimistic performance estimates.[9]

To reduce the risk of data leakage, scikit-learn recommends using Pipelines, which chain preprocessing steps and the estimator together and automatically ensure that fit is called only on the training fold during cross-validation:

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('svm', SVC())
])

pipeline.fit(X_train, y_train)
score = pipeline.score(X_test, y_test)

Sparse data

Setting with_mean=False is required when standardizing sparse matrices because subtracting a non-zero mean from every element would densify the matrix and consume large amounts of memory. The scikit-learn API supports partial_fit, which updates mean_ and var_ incrementally over multiple chunks of data using the Welford online algorithm described below. This pattern is useful for datasets larger than memory and for streaming preprocessing.

Implementing standardization from scratch

import numpy as np

class MyStandardScaler:
    def fit(self, X):
        self.mean_ = X.mean(axis=0)
        self.scale_ = X.std(axis=0, ddof=0)
        # Avoid division by zero for constant features
        self.scale_[self.scale_ == 0.0] = 1.0
        return self

    def transform(self, X):
        return (X - self.mean_) / self.scale_

    def fit_transform(self, X):
        return self.fit(X).transform(X)

    def inverse_transform(self, X_scaled):
        return X_scaled * self.scale_ + self.mean_

The scikit-learn implementation is more elaborate (sparse-matrix support, numerical stability checks, partial fit, validation of input shapes), but the arithmetic core is the same.

How is z-score normalization computed online (Welford's algorithm)?

When training data does not fit in memory or arrives as a continuous stream, the mean and variance must be computed incrementally rather than from a single batch. The naive approach of accumulating the running sum and the running sum of squares (sum, sum_sq) and then computing the variance as sum_sq/n - (sum/n)^2 is numerically unstable: subtracting two large, similar quantities loses precision.

B. P. Welford published a numerically stable online algorithm in 1962 that updates the mean and a running quantity M2 (the sum of squared deviations from the running mean) one observation at a time:[12]

def welford_update(state, x):
    n, mean, M2 = state
    n += 1
    delta = x - mean
    mean += delta / n
    delta2 = x - mean
    M2 += delta * delta2
    return n, mean, M2

def welford_finalize(state):
    n, mean, M2 = state
    if n < 2:
        return mean, float('nan')
    variance_pop = M2 / n           # population variance
    variance_samp = M2 / (n - 1)    # sample variance with Bessel correction
    return mean, variance_pop ** 0.5

Welford's recursion preserves accuracy across many updates and is the basis of partial_fit in scikit-learn's StandardScaler, tf.keras.layers.Normalization.adapt in TensorFlow, and equivalent functions in PyTorch. A parallel version of the same recursion (Chan, Golub, and LeVeque 1979) merges the statistics from two partitions and is used in distributed feature-statistics jobs on systems such as Apache Spark.

What are the framework APIs for z-score normalization?

FrameworkAPINotes
scikit-learnsklearn.preprocessing.StandardScalerfit, transform, partial_fit, inverse_transform; integrates with Pipeline and ColumnTransformer
SciPyscipy.stats.zscorePure function; supports axis and ddof arguments
NumPyManual: (x - x.mean(axis=0)) / x.std(axis=0)No built-in scaler; commonly used in custom code
pandas(df - df.mean()) / df.std()Default std uses Bessel correction (ddof=1)
TensorFlowtf.keras.layers.NormalizationPreprocessing layer; call adapt(dataset) to compute statistics
PyTorchManual or torchvision.transforms.NormalizeThe Normalize transform expects pre-computed mean and std; for images these are typically the channel-wise statistics of the training set (e.g., the ImageNet mean [0.485, 0.456, 0.406] and std [0.229, 0.224, 0.225])
Spark MLlibpyspark.ml.feature.StandardScalerDistributed; configurable withMean and withStd
PolarsManual via (col - col.mean()) / col.std()Lazy evaluation supported
Rscale(x, center=TRUE, scale=TRUE)Built-in; uses sample standard deviation

How does z-score normalization relate to batch and layer normalization?

Batch normalization extends the core idea behind z-score normalization into the hidden layers of deep neural networks. Proposed by Sergey Ioffe and Christian Szegedy in 2015, batch normalization applies standardization to the activations of each layer during training.[13]

For each mini-batch, the algorithm computes the mean and variance of the activations and then normalizes them:

x^=xμbatchσbatch2+ϵ\hat{x} = \frac{x - \mu_{\text{batch}}}{\sqrt{\sigma_{\text{batch}}^2 + \epsilon}}

where epsilon is a small constant added for numerical stability. After normalization, the values are scaled and shifted using two learnable parameters, gamma and beta:

y=γx^+βy = \gamma \hat{x} + \beta

These learnable parameters allow each layer to recover the optimal activation distribution, while still benefiting from the stability that normalization provides.

Layer normalization, introduced by Jimmy Lei Ba, Jamie Ryan Kiros, and Geoffrey Hinton in 2016, applies the same arithmetic but computes the statistics across the feature dimension of a single example rather than across the batch dimension.[14] Layer normalization is the standard choice in transformer architectures because it does not depend on the batch size and is well-suited to variable-length sequences. Other variants include instance normalization (used in style transfer), group normalization (used in computer vision when batch sizes are small), and RMSNorm (used in modern large language models such as the LLaMA family).

AspectZ-Score NormalizationBatch NormalizationLayer Normalization
Applied toInput features (before training)Hidden layer activationsHidden layer activations
Statistics computed acrossEntire training setMini-batch (per channel)Feature dimension (per example)
Statistics source at inferenceStored from trainingRunning averages collected during trainingComputed from each input on the fly
Learnable parametersNonegamma (scale) and beta (shift) per channelgamma and beta per feature
Common useAll ML modelsCNNsTransformers, RNNs

Batch normalization allows the use of higher learning rates, reduces sensitivity to weight initialization, and provides a mild regularization effect. It has become a standard component in modern convolutional neural networks and other deep architectures.[13]

How is z-score normalization used in anomaly detection?

The absolute z-score is a popular heuristic for outlier and anomaly detection. Under the assumption that a feature is approximately normally distributed, observations with |z| > 3 are sometimes flagged as suspicious because they correspond to the tails of the empirical 68-95-99.7 rule and account for only about 0.3% of the distribution.

The three-sigma rule is convenient but blunt. It assumes a unimodal, approximately Gaussian distribution; on heavy-tailed or skewed data, the threshold either flags too many points (Cauchy-like distributions, financial returns) or too few (long-tailed user behavior data). For these reasons, modified z-scores based on the median and MAD (Iglewicz and Hoaglin 1993) and quantile-based methods such as isolation forest are often preferred for production anomaly detection pipelines.[11]

MethodSensitivity ThresholdRobust to skew?
Standard z-scorez>2\lvert z \rvert > 2 (loose), z>3\lvert z \rvert > 3 (strict)No
Modified z-score (MAD)M>3.5\lvert M \rvert > 3.5Yes
IQR rule (Tukey)x outside [Q11.5IQR,Q3+1.5IQR][Q_1 - 1.5 \cdot \text{IQR}, Q_3 + 1.5 \cdot \text{IQR}]Yes
Mahalanobis distanceChi-squared threshold on multivariate distancePartial
Isolation forestScore-basedYes

A practical financial example is the z-score of returns, used to flag market days where an asset's daily return is more than three standard deviations from its rolling average. Risk-management systems use such rules to trigger model recalibration or reporting events.

Where is z-score normalization used outside machine learning?

Z-score normalization predates machine learning by more than a century and remains heavily used across the quantitative sciences and finance:

  • Education and psychometrics. Standardized tests such as the SAT, GRE, and IQ tests report scores derived from z-scores that have been linearly rescaled to a target mean and standard deviation. The classical SAT scaled score has historically targeted a mean of 500 and a standard deviation of 100 per section, while the Wechsler Adult Intelligence Scale (WAIS) IQ scale targets a mean of 100 and a standard deviation of 15.
  • Pediatric medicine. The World Health Organization Child Growth Standards report z-scores for weight-for-age, height-for-age, and BMI-for-age. A child below z=2z = -2 on weight-for-age is classified as underweight, and below z=3z = -3 as severely underweight.[18]
  • Finance. Edward Altman's 1968 Altman Z-Score is a weighted combination of standardized accounting ratios used to predict corporate bankruptcy. Modern risk-management systems also compute rolling z-scores of asset returns to flag tail events.
  • Quality control. Six Sigma uses standardized deviations from a target value to characterize manufacturing defects per million opportunities.
  • Sports analytics. Player and team metrics are often expressed as z-scores relative to a league average for cross-position comparisons (often called plus-minus metrics in basketball or WAR in baseball when adjusted for league context).
  • Climate science. Temperature and precipitation anomalies are routinely reported as departures from a reference period mean expressed in standard deviations, allowing comparisons across stations with different baselines.
  • Genomics and bioinformatics. Gene-expression z-scores are computed within microarray and RNA-seq experiments to highlight genes that are over- or under-expressed relative to the average across samples.

What are common pitfalls of z-score normalization?

A number of mistakes show up repeatedly when applying z-score normalization in practice. Avoiding them tends to be more valuable than choosing between scaler variants.

PitfallWhy it is wrongCorrect approach
Fitting the scaler on the full datasetTest-set statistics leak into trainingFit on X_train only; transform X_train, X_val, X_test
Standardizing across rows instead of across columnsRows mix incommensurable features (height, weight, age); the per-row mean has no statistical meaningStandardize per column (axis=0); per-row normalization is for vector-norm scaling, not z-score
Standardizing one-hot or binary indicatorsDestroys interpretability and sparsity, and the resulting values may be larger than the original signalSkip standardization for binary or categorical encodings; use ColumnTransformer to apply scaling only to numeric features
Forgetting to standardize new inference dataProduction input distribution differs from training; model receives unscaled inputsSave the fitted scaler with the model and apply transform at inference
Standardizing the target variable without invertingPredictions reported in the wrong unitsApply inverse_transform to predictions before reporting
Standardizing each fold separately and aggregatingEach fold has slightly different statistics; not comparableUse scikit-learn Pipeline so the scaler is refit per fold automatically
Standardizing time-series data with the full seriesFuture statistics leak into past predictionsUse rolling or expanding statistics that respect temporal ordering
Using the same scaler for training and inference, then retraining the scaler laterModel expects the original mean and std; new statistics shift the distributionVersion the scaler alongside the model; retrain both together
Constant feature with zero varianceDivision by zero in the denominatorDetect and handle via with_std=False, removal, or replacing zero std with 1
Mixing population and sample standard deviationsTiny numeric differences cause confusion across librariesPick one convention (usually population, ddof=0) and stick with it across the pipeline

How do you standardize time-series data?

For time series and forecasting problems, z-score normalization must be performed in a way that respects temporal ordering. Computing the global mean and standard deviation across the entire series, then transforming all observations, leaks future information into the past. A safer approach is to use a rolling window or expanding window of past values to standardize each time step relative to its history. Libraries such as statsmodels and Prophet include rolling normalization helpers, and PyTorch and TensorFlow data-loaders support precomputed per-window statistics.

# Expanding-window z-score for a pandas Series
import pandas as pd

series = pd.Series(values)
rolling_mean = series.expanding(min_periods=30).mean().shift(1)
rolling_std = series.expanding(min_periods=30).std().shift(1)
z_series = (series - rolling_mean) / rolling_std

The .shift(1) step is essential. It ensures that the statistics at time t are computed only from observations strictly before t.

Practical tips for z-score normalization

  • Always standardize after splitting. Compute the mean and standard deviation from the training set only. Apply the same transformation to validation and test data.
  • Store scaler parameters for production. When deploying a model, save the fitted scaler alongside the model so that incoming data can be transformed with the exact same mean and standard deviation used during training.
  • Consider robust scaling for dirty data. If your dataset has significant outliers or measurement errors, try RobustScaler before defaulting to StandardScaler.
  • Tree-based models do not need it. Decision trees, random forests, and gradient boosted trees are invariant to monotonic transformations of features, so standardization neither helps nor hurts.
  • Match the scaler to inference. As Google's Machine Learning Crash Course warns, "If you normalize a feature during training, you must also normalize that feature when making predictions."[2]
  • Use ColumnTransformer for mixed types. Apply standardization only to numeric columns; leave categorical and binary indicators untouched.
  • Combine with imputation. Fit imputation and standardization in one Pipeline so that train and inference apply the same operations in the same order.
  • Watch for constant features. Features with zero variance break the formula; remove them or set with_std=False.
  • Do not standardize tree-model targets. Tree-based regressors are scale-equivariant for the target; standardizing the target is unnecessary and complicates inverse-transform bookkeeping.
  • Experiment. There is no universal best scaler. Try both StandardScaler and MinMaxScaler, evaluate using cross-validation, and pick whichever produces better results for your specific problem.

History and terminology

The term standard score appears throughout the early-20th-century statistical literature, and Karl Pearson's correlation work in the 1890s explicitly used standardized variables. Ronald A. Fisher's 1925 Statistical Methods for Research Workers further popularized the use of standardized residuals and tabulated values of the standard normal distribution. The letter z for the standardized variable became conventional through textbooks such as Snedecor and Cochran's Statistical Methods and through the widespread reproduction of standard-normal tables in undergraduate courses.[15]

In machine learning, the equivalent operation has been called z-score normalization, standardization, autoscaling (in chemometrics), and mean-centering and unit-variance scaling. The scikit-learn project chose the name StandardScaler to emphasize the unit-variance result, while TensorFlow calls the equivalent layer Normalization and exposes the mean and variance via the adapt method.[17] Despite the variety of names, the underlying arithmetic has been unchanged for more than a century.

Explain like I'm 5 (ELI5)

Imagine you and your friends are comparing how good you are at two different games: one where scores go up to 1,000, and another where scores only go up to 10. If you just look at the raw numbers, the first game's scores always seem "bigger" and more important, even though a score of 8 out of 10 might be just as impressive as 800 out of 1,000.

Z-score normalization is like a magic translator. It takes every score and asks: "How far above or below average is this?" Then it writes the answer in a simple language where "0" means perfectly average, "+1" means one step above average, and "-1" means one step below average. Now you can compare your performance across both games fairly, because the numbers all speak the same language.

See also

References

  1. StandardScaler - scikit-learn documentation
  2. Numerical Data: Normalization - Google Machine Learning Crash Course
  3. Z-Scores and the Standard Normal Distribution - Statistics LibreTexts/01:_Fundamentals_of_Statistics/1.04:_Chapter_4-_z_Scores_and_the_Standard_Normal_Distribution)
  4. About Feature Scaling and Normalization - Sebastian Raschka
  5. Importance of Feature Scaling - scikit-learn documentation
  6. Which Machine Learning Algorithms Require Feature Scaling - The Professionals Point
  7. Normalization vs. Standardization - DataCamp
  8. RobustScaler - scikit-learn documentation
  9. Common Pitfalls and Recommended Practices - scikit-learn documentation
  10. Efficient BackProp - LeCun, Bottou, Orr, and Muller, 1998
  11. How to Detect and Handle Outliers - Iglewicz and Hoaglin, 1993, ASQC Quality Press
  12. Note on a Method for Calculating Corrected Sums of Squares and Products - B. P. Welford, Technometrics 1962
  13. Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift - Ioffe and Szegedy, 2015
  14. Layer Normalization - Ba, Kiros, and Hinton, 2016
  15. Statistical Methods - Snedecor and Cochran, 8th ed., Iowa State University Press, 1989
  16. scipy.stats.zscore - SciPy documentation
  17. Normalization layer - TensorFlow documentation
  18. WHO Child Growth Standards - World Health Organization

Improve this article

Add missing citations, update stale details, or suggest a clearer explanation. Every suggestion is reviewed for sourcing before it goes live.

7 revisions by 1 contributors · full history

Suggest edit