Feature scaling and preprocessing

intro 8 minfundamentalspreprocessing

The idea

Many models silently assume all features live on a comparable scale. When they do not, the large-scale feature wins by accident of units, not by signal. The mechanism differs by family:

Who is exempt: trees. A split xj>tx_j > t only ever compares a feature to its own threshold, so any monotone transform of xjx_j produces an equivalent tree. This is a real practical advantage of tree ensembles on raw tabular data.

The standard transforms:

z=x−μσ(standardize),x′=x−xmin⁡xmax⁡−xmin⁡(min-max),x′=x−median⁡(x)IQR⁡(x)(robust).\begin{aligned} z &= \frac{x - \mu}{\sigma} && \text{(standardize)}, \\ x' &= \frac{x - x_{\min}}{x_{\max} - x_{\min}} && \text{(min-max)}, \\ x' &= \frac{x - \operatorname{median}(x)}{\operatorname{IQR}(x)} && \text{(robust)}. \end{aligned}

plus log⁡(1+x)\log(1+x) for right-skewed positive features, and one-hot encoding for unordered categories (ordinal codes would fabricate an order that distances and linear models take literally).

The iron rule: fit every transform on the training data only, then apply the frozen parameters everywhere else. The test set must simulate production, and production cannot see the future.

Worked example

k-NN on two features — income (dollars) and age (years). Three people:

PersonIncomeAge
A50,00025
B52,00060
C60,00026

Raw Euclidean distances from A:

d(A,B)=20002+352≈2000.3d(A,C)=100002+12≈10000.0d(A, B) = \sqrt{2000^2 + 35^2} \approx 2000.3 \qquad d(A, C) = \sqrt{10000^2 + 1^2} \approx 10000.0

B is "closest" — a 60-year-old with nearly the same income beats a 26-year-old peer — because a 35-year age gap contributes 352=122535^2 = 1225 while a modest $10,000 income gap contributes 10810^8. Age is decorative.

Now standardize with training statistics μinc=54,000\mu_{\text{inc}} = 54{,}000, σinc=5,000\sigma_{\text{inc}} = 5{,}000, μage=37\mu_{\text{age}} = 37, σage=12\sigma_{\text{age}} = 12:

Personzincz_{\text{inc}}zagez_{\text{age}}
A−0.80-0.80−1.00-1.00
B−0.40-0.401.921.92
C1.201.20−0.92-0.92

d(A,B)=0.402+2.922≈2.95d(A,C)=2.002+0.082≈2.00d(A, B) = \sqrt{0.40^2 + 2.92^2} \approx 2.95 \qquad d(A, C) = \sqrt{2.00^2 + 0.08^2} \approx 2.00

The neighborhood flips: C is now A's neighbor. Same data, same algorithm — the only thing that changed is that both features finally speak the same units.

Cheat sheet

TransformFormulaUse when
Standardize(x−μ)/σ(x-\mu)/\sigmadefault for linear/SVM/k-NN/PCA/NN
Min-max(x−xmin⁡)/(xmax⁡−xmin⁡)(x - x_{\min})/(x_{\max}-x_{\min})bounded input needed; no big outliers
Robust(x−median)/IQR(x-\text{median})/\text{IQR}outlier-heavy features
log⁡(1+x)\log(1+x)—right-skewed positive features (income, counts)
One-hotindicator per categoryunordered categoricals for linear/distance models
ModelNeeds scaling?Mechanism
k-NN, k-means, SVM (RBF)yesdistances dominated by large-scale features
Linear/logistic via gradient descent, neural netsyesill-conditioned loss surface slows convergence
Ridge / lasso / elastic netyespenalty is unit-blind
PCAyesvariance is unit-dependent
Trees, random forest, gradient boostingnosplits invariant to monotone transforms
OLS via normal equationnot for predictionsbut scaling helps conditioning and coefficient comparability