特征缩放:StandardScaler 与 MinMaxScaler
您将对训练数据拟合 StandardScaler 和 MinMaxScaler,分别转换测试数据,并理解在测试数据上拟合为何会造成数据泄漏
特征缩放:StandardScaler 与 MinMaxScaler 是 CoddyKit 上的免费 Machine Learning Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Machine Learning Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Machine Learning Academy 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
Why Feature Scaling Matters
Many machine learning algorithms are sensitive to the scale of input features. If one feature spans 0–1000 and another spans 0–1, distance-based models like KNN and SVM will be dominated by the larger-scale feature. Gradient descent algorithms also converge much faster when features share a similar scale. Tree-based models like Random Forests and XGBoost are scale-invariant and do not require scaling, but almost every other algorithm benefits from it.
import numpy as np
# Without scaling: 'income' dominates 'age'
X = np.array([
[25, 50000],
[35, 80000],
[45, 120000]
])
# Distance between row 0 and row 1 (Euclidean)
dist = np.sqrt((25-35)**2 + (50000-80000)**2)
print('Distance dominated by income:', dist)
# age contributes 100, income contributes 900,000,000 to squared distanceStandardScaler: Z-Score Normalisation
StandardScaler transforms each feature to have zero mean and unit variance by applying the formula: z = (x - mean) / std. This is called standardisation or z-score normalisation. The resulting values are centred around 0 with no fixed range. StandardScaler is the default choice for most algorithms including logistic regression, SVMs, and neural networks, especially when the feature distribution is approximately Gaussian.
from sklearn.preprocessing import StandardScaler
import numpy as np
X = np.array([[25, 50000], [35, 80000], [45, 120000]], dtype=float)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
print('Scaled data:\n', X_scaled)
print('Mean per feature:', X_scaled.mean(axis=0)) # ~[0, 0]
print('Std per feature:', X_scaled.std(axis=0)) # ~[1, 1]How StandardScaler Stores Statistics
After calling fit(), StandardScaler stores the training-set statistics in scaler.mean_ and scaler.scale_ (standard deviation). These same statistics are used when you call transform() on new data — meaning the test set is scaled using training set parameters, not its own. This is the correct behaviour: in production, you receive individual samples one at a time and must scale them using the statistics computed during training.
from sklearn.preprocessing import StandardScaler
import numpy as np
X_train = np.array([[1, 200], [2, 400], [3, 600]], dtype=float)
X_test = np.array([[4, 800]], dtype=float)
scaler = StandardScaler()
scaler.fit(X_train) # Learn mean and std from training data ONLY
print('Learned mean:', scaler.mean_)
print('Learned scale:', scaler.scale_)
X_train_s = scaler.transform(X_train)
X_test_s = scaler.transform(X_test) # Uses SAME training statistics
print('Test scaled:', X_test_s)MinMaxScaler: Rescaling to a Fixed Range
MinMaxScaler compresses each feature to a specified range, typically [0, 1], using the formula: x_scaled = (x - x_min) / (x_max - x_min). Unlike StandardScaler, it preserves the relative shape of the distribution and handles non-Gaussian data well. It is sensitive to outliers: a single extreme value can squish all other values near zero or one. MinMaxScaler is popular for neural networks and image pixel values (scaled to [0, 1]).
from sklearn.preprocessing import MinMaxScaler
import numpy as np
X = np.array([[10], [20], [30], [40], [50]], dtype=float)
scaler = MinMaxScaler(feature_range=(0, 1))
X_scaled = scaler.fit_transform(X)
print('MinMax scaled:', X_scaled.flatten())
# [0.0, 0.25, 0.5, 0.75, 1.0]
# Custom range: scale to [-1, 1]
scaler2 = MinMaxScaler(feature_range=(-1, 1))
print('[-1,1] scaled:', scaler2.fit_transform(X).flatten())RobustScaler: Handling Outliers
RobustScaler scales using the median and interquartile range (IQR) instead of mean and standard deviation. Because median and IQR are not influenced by extreme values, RobustScaler is a better choice when your data contains significant outliers. The formula is: x_scaled = (x - median) / IQR. Use RobustScaler when you cannot remove outliers and want them to have minimal influence on the scaled values passed to your model.
from sklearn.preprocessing import RobustScaler
import numpy as np
# Data with outlier at 1000
X = np.array([[1], [2], [3], [4], [1000]], dtype=float)
from sklearn.preprocessing import StandardScaler, RobustScaler
std_s = StandardScaler().fit_transform(X)
rob_s = RobustScaler().fit_transform(X)
print('StandardScaler (outlier squishes others):')
print(std_s.flatten())
print('RobustScaler (outlier isolated):')
print(rob_s.flatten())Choosing the Right Scaler
Here is a quick decision guide: use StandardScaler when your data is roughly Gaussian and you have no extreme outliers — it is the safest default. Use MinMaxScaler when you need values in a fixed range, such as for image data or algorithms that require [0, 1] inputs. Use RobustScaler when outliers are present and meaningful (e.g., financial data with fraud spikes). For tree-based models (Random Forest, XGBoost, LightGBM), skip scaling entirely — it offers no benefit and adds unnecessary complexity.
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
# Decision helper
def pick_scaler(has_outliers, needs_fixed_range, is_tree_model):
if is_tree_model:
return 'No scaling needed'
elif has_outliers:
return 'RobustScaler'
elif needs_fixed_range:
return 'MinMaxScaler'
else:
return 'StandardScaler'
print(pick_scaler(False, False, False)) # StandardScaler
print(pick_scaler(True, False, False)) # RobustScaler
print(pick_scaler(False, True, False)) # MinMaxScaler
print(pick_scaler(False, False, True)) # No scaling neededFitting on Test Data: The Leakage Trap
A common mistake is calling fit_transform() on the test set, which computes a new mean and standard deviation from test data. This is a form of data leakage because the scaler is influenced by test-set values. The correct pattern is: fit(X_train) → transform(X_train) → transform(X_test). Even a small accuracy improvement from this leak can lead to overconfident production deployments that fail on truly unseen data.
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
import numpy as np
X = np.random.randn(100, 3)
y = (X[:, 0] > 0).astype(int)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
scaler = StandardScaler()
# CORRECT: fit on train, transform both
scaler.fit(X_train)
X_train_s = scaler.transform(X_train)
X_test_s = scaler.transform(X_test)
# WRONG (leakage):
# scaler.fit_transform(X_test) <- never do thisScaling Inside a Pipeline
The cleanest way to avoid scaling leakage is to embed the scaler inside a scikit-learn Pipeline. When the pipeline is fitted with cross_val_score or GridSearchCV, each fold fits the scaler only on the training portion of that fold. The test fold is never touched during fitting. This is the production-ready pattern: preprocessing and modelling steps are bundled together, making deployment as simple as calling pipeline.predict(X_new).
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_iris
X, y = load_iris(return_X_y=True)
pipe = Pipeline([
('scaler', StandardScaler()),
('clf', LogisticRegression(max_iter=200))
])
# Scaler fitted only on train fold in each CV iteration
scores = cross_val_score(pipe, X, y, cv=5)
print('CV accuracy:', scores.mean().round(3))Inverse Transform: Back to Original Scale
After making predictions, you may need to convert predictions back to the original scale — for example, a house-price model trained on log-scaled prices must output prices in dollars. Both StandardScaler and MinMaxScaler provide inverse_transform() to reverse the scaling. Only inverse-transform the target variable when it was scaled before training. Features do not typically need to be inverse-transformed because they are consumed internally by the model.
from sklearn.preprocessing import StandardScaler
import numpy as np
y_train = np.array([100000, 200000, 300000, 400000], dtype=float).reshape(-1, 1)
target_scaler = StandardScaler()
y_scaled = target_scaler.fit_transform(y_train)
print('Scaled target:', y_scaled.flatten())
# After predicting in scaled space:
y_pred_scaled = np.array([[0.5]])
y_pred_original = target_scaler.inverse_transform(y_pred_scaled)
print('Prediction in original scale:', y_pred_original)Scaling Sparse Data with MaxAbsScaler
Sparse matrices — common in text classification with TF-IDF vectors — should not be scaled with StandardScaler or MinMaxScaler because centering destroys sparsity by making most zeros non-zero, which defeats the purpose of sparse storage. MaxAbsScaler scales each feature by its maximum absolute value, mapping values to the range [-1, 1] without centering, and preserves the sparsity structure. Always use MaxAbsScaler when working with sparse feature matrices from vectorisers like TfidfVectorizer.
from sklearn.preprocessing import MaxAbsScaler
from scipy.sparse import csr_matrix
import numpy as np
# Simulated sparse TF-IDF matrix
X_sparse = csr_matrix(np.array([
[0, 0.5, 0.3, 0],
[0.8, 0, 0, 0.4],
[0, 0.2, 0, 0.6]
]))
scaler = MaxAbsScaler()
X_scaled = scaler.fit_transform(X_sparse)
print('Scaled sparse matrix:\n', X_scaled.toarray())
# All values in [-1, 1], sparsity preservedComparing Scalers on Real Data
To see the practical effect of each scaler, compare their output distributions side by side. After scaling, StandardScaler output should be approximately N(0,1), MinMaxScaler output should span [0,1], and RobustScaler output should have median at 0 with IQR of 1. Plotting histograms before and after scaling confirms the transformation worked correctly. Good feature scaling is a prerequisite for reliable model training, not an optional add-on.
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
import numpy as np
X = np.random.exponential(scale=100, size=(200, 1)) # Skewed data
scalers = {
'StandardScaler': StandardScaler(),
'MinMaxScaler': MinMaxScaler(),
'RobustScaler': RobustScaler()
}
fig, axes = plt.subplots(1, 4, figsize=(16, 4))
axes[0].hist(X, bins=30); axes[0].set_title('Original')
for ax, (name, sc) in zip(axes[1:], scalers.items()):
ax.hist(sc.fit_transform(X), bins=30)
ax.set_title(name)
plt.tight_layout()
plt.show()Quick Check
Test your understanding of Machine Learning with Python concepts from this lesson.
Lesson Recap
In this lesson you learned: why feature scaling is essential for distance-based and gradient-descent algorithms, how StandardScaler standardises to N(0,1) while MinMaxScaler compresses to [0,1], and the critical rule of fitting scalers only on training data to prevent leakage. Next up we explore encoding categorical variables with OrdinalEncoder and OneHotEncoder.
常见问题解答
「特征缩放:StandardScaler 与 MinMaxScaler」课时是免费的吗?
是的 — 「特征缩放:StandardScaler 与 MinMaxScaler」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Machine Learning Academy 课程的其余内容,请升级到 CoddyKit PRO。 Machine Learning Academy 课程共包含 4 节课。
「特征缩放:StandardScaler 与 MinMaxScaler」这节课中我会学到什么?
您将对训练数据拟合 StandardScaler 和 MinMaxScaler,分别转换测试数据,并理解在测试数据上拟合为何会造成数据泄漏 你通过在浏览器中直接运行的动手代码来练习 Machine Learning Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Machine Learning Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Machine Learning Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「特征缩放:StandardScaler 与 MinMaxScaler」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Machine Learning Academy 课中编写并运行代码吗?
能。每节 Machine Learning Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 处理缺失值:删除、填补与标记
- 特征缩放:StandardScaler 与 MinMaxScaler
- 编码分类变量:OrdinalEncoder 与 OneHotEncoder
- 使用 ColumnTransformer 组合步骤