W3docs

Scaling delle feature in Python

Impara lo scaling delle feature in Python con scikit-learn: StandardScaler, MinMaxScaler, RobustScaler e MaxAbsScaler — con esempi e output.

I modelli di machine learning vengono addestrati su dataset in cui ogni feature può coprire un intervallo numerico molto diverso. La luminosità dei pixel può variare da 0 a 255, mentre il reddito va da 0 a 1.000.000. Quando le grandezze delle feature differiscono di ordini di grandezza, gli algoritmi che si basano sulle distanze (k-NN, SVM, k-means) o sulla discesa del gradiente (regressione logistica, reti neurali) possono attribuire un peso sproporzionato alle feature con valori più grandi. Lo scaling delle feature porta tutte le feature in un intervallo comparabile, in modo che il modello possa imparare da tutte loro in ugual misura.

Questo capitolo spiega perché lo scaling è importante, illustra i quattro scaler disponibili in scikit-learn, ne mostra l'output su dati reali e dimostra il modo corretto di integrare lo scaling in una pipeline di machine learning senza far trapelare informazioni sui dati di test.

Perché lo Scaling delle Feature è Importante

Considera un semplice dataset con due feature — age (20–60) e income (20.000–100.000). La colonna income ha valori circa 1.000 volte più grandi rispetto ad age. Per gli algoritmi che misurano la distanza euclidea, una variazione di un'unità in income domina completamente una variazione di un'unità in age.

Situazioni specifiche in cui lo scaling è essenziale:

  • Algoritmi basati sulle distanzeK-Nearest Neighbors e K-Means Clustering calcolano le distanze tra i punti dati. Feature non scalate rendono la metrica di distanza priva di significato.
  • Ottimizzatori con discesa del gradienteLogistic Regression e Linear Regression convergono molto più rapidamente quando tutte le feature si trovano in intervalli simili.
  • Modelli con regolarizzazione — Ridge, Lasso ed ElasticNet penalizzano i coefficienti grandi in ugual misura. Una feature con scala elevata attrae artificialmente un coefficiente piccolo, nascondendone la vera importanza.

Quando NON è necessario lo scaling: i modelli basati su alberi (Decision Tree, Random Forest, Gradient Boosting) operano sulle soglie delle singole feature. La scala assoluta di una feature non influisce sul punto in cui cade la migliore suddivisione, quindi lo scaling non ha effetto sulla loro accuratezza.

I Quattro Scaler di scikit-learn

StandardScaler

StandardScaler (detto anche normalizzazione z-score) trasforma ogni feature in modo che abbia media 0 e deviazione standard 1.

Formula per feature:

z = (x − mean) / std

Questa è la scelta predefinita quando non si hanno motivi validi per preferirne un'altra. Funziona bene con dati distribuiti normalmente ed è quella attesa dalla maggior parte dei modelli lineari con regolarizzazione.

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))

Output:

Training set — mean per feature (should be ~0):
[ 0. -0. -0. -0.]

Training set — std per feature (should be ~1):
[1. 1. 1. 1.]

Si noti che fit_transform viene chiamato solo sul set di addestramento. Chiamarlo anche sul set di test farebbe trapelare le statistiche del test set nei parametri dello scaler — vedi la sezione Data Leakage qui sotto.

MinMaxScaler

MinMaxScaler riscala ogni feature in un intervallo fisso, per impostazione predefinita [0, 1].

Formula per feature:

x_scaled = (x − min) / (max − min)

Usa MinMaxScaler quando hai bisogno di valori in un intervallo limitato — ad esempio, per alimentare dati in una rete neurale con unità di output sigmoid, oppure quando l'algoritmo downstream si aspetta input non negativi.

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))

Output:

Min per feature (should be 0): [0. 0. 0. 0.]
Max per feature (should be 1): [1. 1. 1. 1.]

Attenzione: MinMaxScaler è molto sensibile agli outlier. Un singolo valore estremo comprime tutti gli altri valori in una banda stretta a un'estremità dell'intervallo. Se i dati contengono outlier, considera RobustScaler come alternativa.

RobustScaler

RobustScaler utilizza la mediana e l'intervallo interquartile (IQR) invece della media e della deviazione standard, rendendolo resistente agli outlier.

Formula per feature:

x_scaled = (x − median) / IQR

dove IQR = Q3 − Q1 (75° percentile meno 25° percentile).

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))

Output:

Median per feature (should be ~0):
[0. 0. 0. 0.]

RobustScaler è la scelta giusta quando il dataset contiene outlier che non puoi o non vuoi rimuovere.

MaxAbsScaler

MaxAbsScaler divide ogni valore per il massimo valore assoluto nel set di addestramento, collocando ogni feature nell'intervallo [−1, 1] senza spostare i dati.

Formula per feature:

x_scaled = x / max(|x|)

Questo è l'unico scaler che lascia i dati centrati sullo zero. È specificamente progettato per le matrici sparse (es. vettori TF-IDF da testo) dove spostare la media distruggerebbe la sparsità.

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))

Output:

Max absolute value per feature (should be 1):
[1. 1. 1. 1.]

Confronto tra i Quattro Scaler

La tabella seguente riassume quando usare ciascuno scaler:

ScalerIntervallo di outputSensibile agli outlierIdeale per
StandardScalerillimitato (mean=0, std=1)Dati distribuiti normalmente, modelli lineari con regolarizzazione
MinMaxScaler[0, 1] (configurabile)Reti neurali, dati pixel di immagini
RobustScalerillimitato (median=0)NoDati con outlier significativi
MaxAbsScaler[−1, 1]Matrici sparse (feature testuali)

Evitare il Data Leakage

Il data leakage si verifica quando le informazioni del set di test influenzano la fase di preprocessing. L'errore tipico è addestrare lo scaler sull'intero dataset prima di suddividerlo:

# 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
)

L'ordine corretto è sempre suddividere prima, poi addestrare lo scaler solo sui dati di addestramento:

# 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 transformation

Per maggiori informazioni sulla suddivisione train/test, vedi Train/Test Split.

Usare una Pipeline per Mantenere lo Scaling Sicuro

Una Pipeline di scikit-learn è il metodo più robusto per combinare lo scaling con un modello. La pipeline garantisce che fit_transform venga chiamato sui dati di addestramento e solo transform su qualsiasi fold di validazione — anche durante la cross-validation.

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))

Output:

CV accuracy scores: [0.967 1.    0.933 0.9   1.   ]
Mean accuracy:       0.96

La pipeline elimina automaticamente il rischio di data leakage in tutti e cinque i fold di cross-validation.

Ottimizzazione degli Iperparametri dello Scaler

Puoi ottimizzare la scelta dello scaler insieme agli iperparametri del modello 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))

Output:

Best scaler: StandardScaler
Best C:      10.0
Best score:  0.973

Questo permette ai dati di indicare quale scaler funziona meglio per un dato modello e dataset.

Capitoli Correlati

  • Train/Test Split — suddividi i dati prima di addestrare qualsiasi scaler
  • Categorical Data — codifica le feature non numeriche prima dello scaling
  • K-Nearest Neighbors — modello basato sulle distanze che richiede feature scalate
  • K-Means Clustering — algoritmo di clustering sensibile alla scala delle feature
  • Linear Regression — modello con discesa del gradiente che converge più rapidamente con lo scaling
  • Logistic Regression — classificatore con regolarizzazione che beneficia di StandardScaler
  • Cross Validation — usa una Pipeline per garantire che lo scaling sia privo di leakage durante la CV
  • Grid Search — ottimizza la scelta dello scaler insieme agli iperparametri del modello
Was this page helpful?