Fit Before Split

scaler = StandardScaler().fit(X)                              # line 1
X_scaled = scaler.transform(X)                                # line 2
X_tr, X_te, y_tr, y_te = train_test_split(X_scaled, y)        # line 3
model = Ridge().fit(X_tr, y_tr)                               # line 4
print(model.score(X_te, y_te))                                # line 5

The score printed at line 5 is optimistic. Which line is the defect, and what exactly crossed the boundary?

A

No line is defective: StandardScaler never looks at y, so an unsupervised transform cannot leak.

B

Line 1: the per-column mean and standard deviation are computed over the test rows as well, so information about the test set is baked into every training feature.

C

Line 3: splitting after transforming is fine, but train_test_split shuffles by default, which mixes test rows into the training set.

D

Line 4: Ridge should have been fit inside a cross-validation loop, and a single fit on one split is what makes the score optimistic.