Scaling

StandardScaler — fit on train, transform train and test.

Many models care about feature scale. Units in the tens and prices in the tens of thousands would let the large column dominate. StandardScaler subtracts the mean and divides by the standard deviation. Fit it on train only.

Goal

Scale train and test without leaking test statistics, then compare coefficients.

Fit on train, transform both

from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

X, y = make_classification(n_samples=200, n_features=4, random_state=0)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=0
)
scaler = StandardScaler()
scaler.fit(X_train)
X_train_s = scaler.transform(X_train)
X_test_s = scaler.transform(X_test)
print("train mean", X_train_s.mean(axis=0).round(3))
print("train std ", X_train_s.std(axis=0).round(3))
print("test mean ", X_test_s.mean(axis=0).round(3))

Train means sit near 0. Test means are close, not exact — that is expected.

fit_transform

from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

X, y = make_classification(n_samples=200, n_features=4, random_state=0)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=0
)
scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train)
X_test_s = scaler.transform(X_test)
clf = LogisticRegression(max_iter=200)
clf.fit(X_train_s, y_train)
print("accuracy:", round(accuracy_score(y_test, clf.predict(X_test_s)), 3))
print("coef", clf.coef_.round(3))

fit_transform on train is fit then transform. On test, only transform.

Pitfall

scaler.fit(X) on all rows, including test, leaks information. The test set must look like future data the scaler has never seen.