Escalonamento de Recursos em Python
Aprenda escalonamento de recursos em Python com scikit-learn: StandardScaler, MinMaxScaler, RobustScaler e MaxAbsScaler — com exemplos e saída.
Os modelos de aprendizado de máquina são treinados em conjuntos de dados onde cada recurso pode abranger intervalos numéricos muito diferentes. O brilho de pixels pode variar de 0 a 255, enquanto a renda varia de 0 a 1.000.000. Quando as magnitudes dos recursos diferem por ordens de grandeza, algoritmos que dependem de distâncias (k-NN, SVM, k-means) ou descida de gradiente (regressão logística, redes neurais) podem dar peso desproporcional aos maiores recursos. O escalonamento de recursos traz todos os recursos para um intervalo comparável, para que o modelo possa aprender com todos eles de forma igualitária.
Este capítulo explica por que o escalonamento importa, cobre os quatro escaladores disponíveis no scikit-learn, mostra suas saídas em dados reais e demonstra a maneira correta de integrar o escalonamento em um pipeline de aprendizado de máquina sem vazar dados de teste.
Por Que o Escalonamento de Recursos Importa
Considere um conjunto de dados simples com dois recursos — age (20–60) e income (20.000–100.000). A coluna income tem valores aproximadamente 1.000 vezes maiores que age. Para algoritmos que medem distância euclidiana, uma mudança de uma unidade em income domina completamente uma mudança de uma unidade em age.
Situações específicas em que o escalonamento é essencial:
- Algoritmos baseados em distância — K-Nearest Neighbors e K-Means Clustering calculam distâncias entre pontos de dados. Recursos não escalonados tornam a métrica de distância sem sentido.
- Otimizadores por descida de gradiente — Regressão Logística e Regressão Linear convergem muito mais rápido quando todos os recursos estão em intervalos similares.
- Modelos regularizados — Ridge, Lasso e ElasticNet penalizam coeficientes grandes de forma igual. Um recurso de grande escala atrai artificialmente um coeficiente pequeno, ocultando sua verdadeira importância.
Quando você NÃO precisa de escalonamento: modelos baseados em árvore (Árvores de Decisão, Florestas Aleatórias, Gradient Boosting) dividem com base em limiares individuais de recursos. A escala absoluta de um recurso não afeta onde ocorre a melhor divisão, portanto o escalonamento não tem efeito na precisão deles.
Os Quatro Escaladores do scikit-learn
StandardScaler
O StandardScaler (também chamado de normalização z-score) transforma cada recurso para ter média 0 e desvio padrão 1.
Fórmula por recurso:
z = (x − mean) / stdEsta é a escolha padrão quando não há motivo forte para preferir outro. Funciona bem para dados normalmente distribuídos e é esperado pela maioria dos modelos lineares regularizados.
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import numpy as np
data = load_iris()
X = data.data # shape (150, 4)
y = data.target
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # fit + transform on training data
X_test_scaled = scaler.transform(X_test) # transform only (no re-fit)
# Inspect the result
print("Training set — mean per feature (should be ~0):")
print(np.round(X_train_scaled.mean(axis=0), 4))
print("\nTraining set — std per feature (should be ~1):")
print(np.round(X_train_scaled.std(axis=0), 4))Saída:
Training set — mean per feature (should be ~0):
[ 0. -0. -0. -0.]
Training set — std per feature (should be ~1):
[1. 1. 1. 1.]Observe que fit_transform é chamado somente no conjunto de treinamento. Chamá-lo também no conjunto de teste vazaria as estatísticas do conjunto de teste para os parâmetros do escalador — veja a seção Vazamento de Dados abaixo.
MinMaxScaler
O MinMaxScaler redimensiona cada recurso para um intervalo fixo, por padrão [0, 1].
Fórmula por recurso:
x_scaled = (x − min) / (max − min)Use o MinMaxScaler quando precisar de valores em um intervalo delimitado — por exemplo, alimentar dados em uma rede neural com unidades de saída sigmoid, ou quando o algoritmo downstream espera entradas não negativas.
from sklearn.preprocessing import MinMaxScaler
mm_scaler = MinMaxScaler() # default feature_range=(0, 1)
X_train_mm = mm_scaler.fit_transform(X_train)
X_test_mm = mm_scaler.transform(X_test)
print("Min per feature (should be 0):", np.round(X_train_mm.min(axis=0), 4))
print("Max per feature (should be 1):", np.round(X_train_mm.max(axis=0), 4))Saída:
Min per feature (should be 0): [0. 0. 0. 0.]
Max per feature (should be 1): [1. 1. 1. 1.]Atenção: o MinMaxScaler é muito sensível a outliers. Um único valor extremo comprime todos os outros valores em uma faixa estreita em uma extremidade do intervalo. Se seus dados contêm outliers, considere usar o RobustScaler.
RobustScaler
O RobustScaler usa a mediana e o intervalo interquartil (IQR) em vez da média e do desvio padrão, tornando-o resistente a outliers.
Fórmula por recurso:
x_scaled = (x − median) / IQRonde IQR = Q3 − Q1 (percentil 75 menos o percentil 25).
from sklearn.preprocessing import RobustScaler
rb_scaler = RobustScaler()
X_train_rb = rb_scaler.fit_transform(X_train)
X_test_rb = rb_scaler.transform(X_test)
print("Median per feature (should be ~0):")
print(np.round(np.median(X_train_rb, axis=0), 4))Saída:
Median per feature (should be ~0):
[0. 0. 0. 0.]O RobustScaler é a escolha certa quando seu conjunto de dados contém outliers que você não pode ou não deseja remover.
MaxAbsScaler
O MaxAbsScaler divide cada valor pelo valor absoluto máximo no conjunto de treinamento, colocando cada recurso no intervalo [−1, 1] sem deslocar os dados.
Fórmula por recurso:
x_scaled = x / max(|x|)Este é o único escalador que mantém dados centrados em zero centrados. Ele é especificamente projetado para matrizes esparsas (por exemplo, vetores TF-IDF de texto) onde deslocar a média destruiria a esparsidade.
from sklearn.preprocessing import MaxAbsScaler
ma_scaler = MaxAbsScaler()
X_train_ma = ma_scaler.fit_transform(X_train)
X_test_ma = ma_scaler.transform(X_test)
print("Max absolute value per feature (should be 1):")
print(np.round(np.abs(X_train_ma).max(axis=0), 4))Saída:
Max absolute value per feature (should be 1):
[1. 1. 1. 1.]Comparando os Quatro Escaladores
A tabela abaixo resume quando usar cada escalador:
| Escalador | Intervalo de saída | Sensível a outliers | Melhor para |
|---|---|---|---|
StandardScaler | ilimitado (mean=0, std=1) | Sim | Dados normalmente distribuídos, modelos lineares regularizados |
MinMaxScaler | [0, 1] (configurável) | Sim | Redes neurais, dados de pixels de imagens |
RobustScaler | ilimitado (median=0) | Não | Dados com outliers significativos |
MaxAbsScaler | [−1, 1] | Sim | Matrizes esparsas (recursos de texto) |
Evitando Vazamento de Dados
O vazamento de dados ocorre quando informações do conjunto de teste influenciam a etapa de pré-processamento. O erro típico é ajustar o escalador em todo o conjunto de dados antes de dividi-lo:
# WRONG — leaks test-set statistics into the scaler
scaler = StandardScaler()
X_all_scaled = scaler.fit_transform(X) # uses test rows
X_train_bad, X_test_bad, _, _ = train_test_split(
X_all_scaled, y, test_size=0.2, random_state=42
)A ordem correta é sempre dividir primeiro, depois ajustar o escalador apenas nos dados de treinamento:
# CORRECT
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # fit on train only
X_test_scaled = scaler.transform(X_test) # apply the same transformationPara mais informações sobre a divisão treino/teste em si, consulte Train/Test Split.
Usando um Pipeline para Manter o Escalonamento Seguro
Um Pipeline do scikit-learn é a maneira mais robusta de combinar escalonamento com um modelo. O pipeline garante que fit_transform seja chamado nos dados de treinamento e apenas transform em qualquer fold de validação — mesmo durante a validação cruzada.
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
import numpy as np
X, y = load_iris(return_X_y=True)
pipe = Pipeline(steps=[
("scaler", StandardScaler()),
("model", LogisticRegression(max_iter=200)),
])
scores = cross_val_score(pipe, X, y, cv=5, scoring="accuracy")
print("CV accuracy scores:", np.round(scores, 3))
print("Mean accuracy: ", round(scores.mean(), 3))Saída:
CV accuracy scores: [0.967 1. 0.933 0.9 1. ]
Mean accuracy: 0.96O pipeline elimina o risco de vazamento de dados em todos os cinco folds de validação cruzada automaticamente.
Ajuste de Hiperparâmetros do Escalador
Você pode ajustar a escolha do escalador junto com os hiperparâmetros do modelo usando Grid Search:
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import load_iris
import numpy as np
X, y = load_iris(return_X_y=True)
pipe = Pipeline(steps=[
("scaler", StandardScaler()),
("model", LogisticRegression(max_iter=300)),
])
param_grid = {
"scaler": [StandardScaler(), MinMaxScaler(), RobustScaler()],
"model__C": [0.1, 1.0, 10.0],
}
grid = GridSearchCV(pipe, param_grid, cv=5, scoring="accuracy")
grid.fit(X, y)
print("Best scaler:", grid.best_params_["scaler"].__class__.__name__)
print("Best C: ", grid.best_params_["model__C"])
print("Best score: ", round(grid.best_score_, 3))Saída:
Best scaler: StandardScaler
Best C: 10.0
Best score: 0.973Isso permite que os dados digam qual escalador funciona melhor para um determinado modelo e conjunto de dados.
Capítulos Relacionados
- Train/Test Split — divida seus dados antes de ajustar qualquer escalador
- Categorical Data — codifique recursos não numéricos antes de escalonar
- K-Nearest Neighbors — modelo baseado em distância que requer recursos escalonados
- K-Means Clustering — algoritmo de agrupamento sensível à escala dos recursos
- Linear Regression — modelo por descida de gradiente que converge mais rápido com escalonamento
- Logistic Regression — classificador regularizado que se beneficia do StandardScaler
- Cross Validation — use um Pipeline para garantir que o escalonamento seja livre de vazamentos durante a CV
- Grid Search — ajuste a escolha do escalador junto com os hiperparâmetros do modelo