The starting code's model is KNeighborsClassifier(n_neighbors=5): it predicts what the 5 training customers closest to a row did. Closeness is measured on the raw numbers, so a column with big numbers, like money spent, can drown out a column of small counts. A StandardScaler puts every column on the same scale first.
A scaler works in two moves. fit(rows) learns each column's average and spread from the rows you give it. transform(rows) gives back those rows scaled with what it learned: each value becomes (value - average) / spread. fit_transform(rows) does both on the same rows.
visits_scaler = StandardScaler()
visits_scaler.fit([[2], [8], [2], [8]]) # learns average 5, spread 3
print(visits_scaler.transform([[11]])) # [[2.]] because (11 - 5) / 3 = 2
The starting code scales all of X first and splits afterwards. So the 75 test rows helped set the averages the training rows were scaled with: a little of the test set leaked into training, and the test is no longer a fair surprise.
The honest order: split first, fit the scaler on X_train only, then transform both parts with that same scaler, just as you'd scale a new customer tomorrow with the averages you already have. The two scores differ only a little, but only the second one is honest:
Scaled before the split: 0.653 Scaled after the split: 0.64
Your task: below the blank line, split the unscaled X and y (25% for testing, random_state=0), make a StandardScaler in scaler, fit it on X_train, fit model on the scaled training rows, and print "Scaled after the split:" with the model's rounded score on the test rows, scaled by the same scaler.
Assignment
Follow the Coding Tutorial to scale the honest way: split first, fit the scaler on the training rows only, and score the model on test rows transformed by that scaler.
Hint
Call fit on the scaler once, with X_train. After that, only use scaler.transform(...), for both X_train and X_test; never fit a scaler on the test rows.
Free plan: 30 tutor messages. PRO is unlimited.
