Hoja de Trucos de scikit-learn (sklearn)
Última actualización
Cargar y dividir los datos
Aparta un conjunto de test antes que nada y no lo mires hasta el final.
| Tarea | Código |
|---|---|
| Importar el divisor | from sklearn.model_selection import train_test_split |
| Features y target desde un DataFrame | X = df.drop(columns="target")
y = df["target"] |
| Dataset integrado como pandas | from sklearn.datasets import load_iris
X, y = load_iris(return_X_y=True, as_frame=True) |
| Datos sintéticos para experimentar | from sklearn.datasets import make_classification
X, y = make_classification(n_samples=500, n_features=8, random_state=0) |
| División 80/20 en train y test | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) |
| Mantener la proporción de clases en ambas partes | train_test_split(X, y, test_size=0.2, stratify=y, random_state=42) |
| Train, validación y test (60/20/20) | X_tmp, X_test, y_tmp, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
X_train, X_val, y_train, y_val = train_test_split(X_tmp, y_tmp, test_size=0.25, random_state=0) |
Preprocesar las features
Ajusta un transformador solo con los datos de entrenamiento y luego transforma ambos conjuntos. Ajustarlo con los datos de test filtra información.
| Tarea | Código |
|---|---|
| Imports | from sklearn.preprocessing import StandardScaler, MinMaxScaler, OneHotEncoder, OrdinalEncoder |
| Escalar a media 0 y desviación estándar 1 | scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train[["age", "income"]])
X_test_s = scaler.transform(X_test[["age", "income"]]) |
| Escalar al rango de 0 a 1 | MinMaxScaler().fit_transform(X_train[["age", "income"]]) |
| One-hot encoding de categorías | enc = OneHotEncoder(handle_unknown="ignore", sparse_output=False)
enc.fit_transform(X_train[["city"]]) |
| Codificar categorías ordenadas como números | OrdinalEncoder(categories=[["low", "mid", "high"]]).fit_transform([["mid"], ["high"]]) |
| Rellenar valores faltantes | from sklearn.impute import SimpleImputer
SimpleImputer(strategy="median").fit_transform(X_train[["age", "income"]]) |
| Features polinómicas y de interacción | from sklearn.preprocessing import PolynomialFeatures
PolynomialFeatures(degree=2, include_bias=False).fit_transform(X_train[["age", "income"]]) |
| Obtener DataFrames en vez de arrays | scaler.set_output(transform="pandas") |
| Etiquetas de texto a enteros | from sklearn.preprocessing import LabelEncoder
LabelEncoder().fit_transform(["cat", "dog", "cat"]) |
Elegir un modelo
Empieza por lo simple y usa el modelo simple como la puntuación a superar.
| Problema | Empieza con | Después prueba |
|---|---|---|
| Predecir un número (regresión) | LinearRegression(), Ridge(alpha=1.0) | RandomForestRegressor(), HistGradientBoostingRegressor() |
| Predecir una clase (clasificación) | LogisticRegression(max_iter=1000) | RandomForestClassifier(), HistGradientBoostingClassifier() |
| Pocos datos, puntos parecidos comparten etiqueta | KNeighborsClassifier(n_neighbors=5) | SVC(kernel="rbf") |
| Reglas que puedes leer | DecisionTreeClassifier(max_depth=3) | RandomForestClassifier() |
| Agrupar filas sin etiquetas | KMeans(n_clusters=3) | DBSCAN(eps=0.5) |
| Menos features para gráficos o velocidad | PCA(n_components=2) | TSNE(n_components=2) |
| Detectar filas inusuales | IsolationForest(random_state=0) | LocalOutlierFactor() |
Entrenar un modelo
Todos los estimadores siguen el mismo patrón: créalo con su configuración y luego llama a fit.
| Tarea | Código |
|---|---|
| El patrón para cualquier modelo | model = LogisticRegression(max_iter=1000)
model.fit(X_train, y_train) |
| Regresión lineal | from sklearn.linear_model import LinearRegression
LinearRegression() |
| Regresión lineal regularizada | from sklearn.linear_model import Ridge, Lasso
Ridge(alpha=1.0), Lasso(alpha=0.1) |
| Regresión logística (clasificación) | from sklearn.linear_model import LogisticRegression
LogisticRegression(C=1.0, max_iter=1000) |
| k vecinos más cercanos | from sklearn.neighbors import KNeighborsClassifier
KNeighborsClassifier(n_neighbors=5) |
| Árbol de decisión | from sklearn.tree import DecisionTreeClassifier
DecisionTreeClassifier(max_depth=3, random_state=0) |
| Random forest | from sklearn.ensemble import RandomForestClassifier
RandomForestClassifier(n_estimators=200, random_state=0) |
| Gradient boosting, rápido con muchos datos | from sklearn.ensemble import HistGradientBoostingClassifier
HistGradientBoostingClassifier(random_state=0) |
| Máquina de vectores de soporte | from sklearn.svm import SVC
SVC(kernel="rbf", C=1.0) |
| Naive Bayes | from sklearn.naive_bayes import GaussianNB
GaussianNB() |
| Baseline que siempre predice la clase mayoritaria | from sklearn.dummy import DummyClassifier
DummyClassifier(strategy="most_frequent") |
Predecir e inspeccionar
| Tarea | Código |
|---|---|
| Predecir clases o valores | y_pred = model.predict(X_test) |
| Probabilidad de la clase positiva | model.predict_proba(X_test)[:, 1] |
| Puntuación rápida: accuracy o R² | model.score(X_test, y_test) |
| Coeficientes de un modelo lineal | model.coef_, model.intercept_ |
| Importancia de features de un modelo de árbol | pd.Series(forest.feature_importances_, index=X_train.columns).sort_values() |
| Importancia barajando cada feature | from sklearn.inspection import permutation_importance
permutation_importance(model, X_test, y_test, random_state=0).importances_mean |
| Etiquetas de clase que conoce el modelo | model.classes_ |
| Leer y cambiar la configuración | model.get_params(), model.set_params(C=0.5) |
| Dibujar un árbol de decisión | from sklearn.tree import plot_tree
plot_tree(tree, filled=True, feature_names=list(X_train.columns)) |
Métricas de clasificación
La accuracy por sí sola esconde los errores en una clase poco frecuente. Revisa también la precisión, el recall y la matriz de confusión.
| Tarea | Código |
|---|---|
| Imports | from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score |
| Accuracy | accuracy_score(y_test, y_pred) |
| Precisión, recall y F1 | precision_score(y_test, y_pred), recall_score(y_test, y_pred), f1_score(y_test, y_pred) |
| F1 para varias clases | f1_score(y_test, y_pred, average="macro") |
| Todas las métricas por clase | from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred)) |
| Matriz de confusión | from sklearn.metrics import confusion_matrix
confusion_matrix(y_test, y_pred) |
| Graficar la matriz de confusión | from sklearn.metrics import ConfusionMatrixDisplay
ConfusionMatrixDisplay.from_estimator(model, X_test, y_test) |
| ROC AUC a partir de probabilidades | from sklearn.metrics import roc_auc_score
roc_auc_score(y_test, model.predict_proba(X_test)[:, 1]) |
| Graficar la curva ROC | from sklearn.metrics import RocCurveDisplay
RocCurveDisplay.from_estimator(model, X_test, y_test) |
| Accuracy para clases desbalanceadas | from sklearn.metrics import balanced_accuracy_score
balanced_accuracy_score(y_test, y_pred) |
| Tu propio umbral de decisión | y_pred = (model.predict_proba(X_test)[:, 1] >= 0.3).astype(int) |
Métricas de regresión
Las métricas de error están en las unidades del target (cuanto más bajas, mejor). R² es la proporción de varianza explicada (1 es perfecto).
| Tarea | Código |
|---|---|
| Imports | from sklearn.metrics import mean_absolute_error, mean_squared_error, root_mean_squared_error, r2_score |
| Error absoluto medio | mean_absolute_error(y_test, y_pred) |
| Error cuadrático medio y su raíz | mean_squared_error(y_test, y_pred), root_mean_squared_error(y_test, y_pred) |
| Puntuación R² | r2_score(y_test, y_pred) |
| Error porcentual absoluto medio | from sklearn.metrics import mean_absolute_percentage_error
mean_absolute_percentage_error(y_test, y_pred) |
| Graficar predicho frente a real | from sklearn.metrics import PredictionErrorDisplay
PredictionErrorDisplay.from_predictions(y_test, y_pred, kind="actual_vs_predicted") |
Pipelines
Un pipeline encadena el preprocesado y un modelo en un solo estimador, así que la validación cruzada y el grid search ajustan cada paso solo con los folds de entrenamiento.
| Tarea | Código |
|---|---|
| Imports | from sklearn.pipeline import make_pipeline, Pipeline |
| Escalar y luego entrenar un modelo | pipe = make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000))
pipe.fit(X_train, y_train) |
| Pasos con tus propios nombres | pipe = Pipeline([("scale", StandardScaler()), ("model", LogisticRegression(max_iter=1000))]) |
| Acceder a un paso interno | pipe.named_steps["model"], pipe[-1] |
| Pasos distintos para columnas distintas | from sklearn.compose import ColumnTransformer
pre = ColumnTransformer([
("num", StandardScaler(), ["age", "income"]),
("cat", OneHotEncoder(handle_unknown="ignore"), ["city"]),
]) |
| Preprocesado y modelo en un solo objeto | model = make_pipeline(pre, RandomForestClassifier(random_state=0))
model.fit(X_train, y_train)
model.score(X_test, y_test) |
| Elegir columnas por tipo | from sklearn.compose import make_column_selector
make_column_selector(dtype_include="number")(X_train) |
| Imputar y luego escalar | make_pipeline(SimpleImputer(strategy="median"), StandardScaler()) |
| Nombres de las features de salida | pre.get_feature_names_out() |
Validación cruzada
La validación cruzada entrena y evalúa el modelo con varias divisiones, lo que da una estimación más estable que un solo conjunto de test.
| Tarea | Código |
|---|---|
| Imports | from sklearn.model_selection import cross_val_score, cross_validate, KFold, StratifiedKFold |
| Puntuar con 5 folds | scores = cross_val_score(pipe, X, y, cv=5)
scores.mean(), scores.std() |
| Elegir la métrica | cross_val_score(pipe, X, y, cv=5, scoring="f1_macro") |
| Folds barajados | cv = KFold(n_splits=5, shuffle=True, random_state=0) |
| El mismo balance de clases en cada fold | cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=0) |
| Varias métricas y puntuaciones de train | cross_validate(pipe, X, y, cv=cv, scoring=["accuracy", "f1"], return_train_score=True) |
| Una predicción por fila, hecha fuera del fold | from sklearn.model_selection import cross_val_predict
cross_val_predict(pipe, X, y, cv=5) |
| Folds por grupo, folds en orden temporal | from sklearn.model_selection import GroupKFold, TimeSeriesSplit
GroupKFold(n_splits=5), TimeSeriesSplit(n_splits=5) |
| Todos los nombres de scoring válidos | from sklearn.metrics import get_scorer_names
get_scorer_names() |
Grid search y ajuste de hiperparámetros
Una búsqueda entrena el modelo con cada configuración usando validación cruzada, se queda con la mejor y la vuelve a entrenar con todos los datos de entrenamiento.
| Tarea | Código |
|---|---|
| Imports | from sklearn.model_selection import GridSearchCV, RandomizedSearchCV |
| Probar todas las combinaciones | grid = GridSearchCV(RandomForestClassifier(random_state=0), {"n_estimators": [50, 100], "max_depth": [None, 5]}, cv=5)
grid.fit(X_train, y_train) |
| Mejor configuración y su puntuación | grid.best_params_, grid.best_score_ |
| Usar el mejor modelo | grid.best_estimator_.predict(X_test), grid.score(X_test, y_test) |
| Ajustar un paso dentro de un pipeline | GridSearchCV(pipe, {"logisticregression__C": [0.1, 1, 10]}, cv=5).fit(X_train, y_train) |
| Configuraciones aleatorias desde distribuciones | from scipy.stats import randint
search = RandomizedSearchCV(RandomForestClassifier(random_state=0), {"n_estimators": randint(50, 150)}, n_iter=5, cv=3, random_state=0)
search.fit(X_train, y_train) |
| Usar todos los núcleos de la CPU | GridSearchCV(pipe, {"logisticregression__C": [0.1, 1]}, cv=5, n_jobs=-1) |
| Todos los resultados como tabla | pd.DataFrame(grid.cv_results_).sort_values("rank_test_score") |
Clustering y reducción de dimensionalidad
Los modelos no supervisados aprenden solo de X. Escala antes las features, porque ambos usan distancias.
| Tarea | Código |
|---|---|
| Clusters con k-means | from sklearn.cluster import KMeans
km = KMeans(n_clusters=3, random_state=0)
labels = km.fit_predict(X) |
| Centros de los clusters e inercia | km.cluster_centers_, km.inertia_ |
| Qué tan separados están los clusters | from sklearn.metrics import silhouette_score
silhouette_score(X, labels) |
| Clusters por densidad, el ruido es -1 | from sklearn.cluster import DBSCAN
DBSCAN(eps=0.5, min_samples=5).fit_predict(X) |
| Proyectar sobre 2 componentes | from sklearn.decomposition import PCA
pca = PCA(n_components=2)
X_2d = pca.fit_transform(X) |
| Varianza que explica cada componente | pca.explained_variance_ratio_ |
| Conservar el 95% de la varianza | PCA(n_components=0.95).fit_transform(X) |
scikit-learn 1.9: formas antiguas y qué escribir ahora
El código copiado de tutoriales antiguos puede fallar o lanzar avisos en scikit-learn 1.9. Usa en su lugar las formas de la columna scikit-learn 1.9.
| Tarea | scikit-learn 1.9 | Forma antigua |
|---|---|---|
| Raíz del error cuadrático medio | root_mean_squared_error(y_test, y_pred) | mean_squared_error(y_test, y_pred, squared=False) |
| Salida one-hot densa | OneHotEncoder(sparse_output=False) | OneHotEncoder(sparse=False) |
| Regresión logística L1 (lasso) | LogisticRegression(l1_ratio=1, solver="liblinear") | LogisticRegression(penalty="l1", solver="liblinear") |
| Regresión logística sin regularización | LogisticRegression(C=np.inf) | LogisticRegression(penalty=None) |
Guardar, cargar y reproducir
| Tarea | Código |
|---|---|
| Guardar un modelo o pipeline entrenado | import joblib
joblib.dump(model, "model.joblib") |
| Volver a cargarlo | model = joblib.load("model.joblib") |
| El mismo resultado en cada ejecución | random_state=0 |
| Qué versión está instalada | import sklearn
sklearn.__version__ |
El código de scikit-learn detrás de un flujo de trabajo real de machine learning, en el orden en que lo escribes: cargar y dividir los datos, preprocesarlos, elegir un modelo, entrenar y predecir, medir el resultado, encadenar los pasos en un pipeline, hacer validación cruzada y ajustar con grid search. Cada fila es un fragmento corto que puedes pegar, con una línea que explica qué hace.
Todos los modelos de scikit-learn comparten la misma API: fit aprende de los datos de entrenamiento, y predict y transform aplican lo aprendido. Todo está escrito para scikit-learn 1.9, la versión que usa Coddy, con X para las features y y para el target. scikit-learn trabaja con arrays de NumPy y DataFrames de pandas, y la hoja de trucos de Matplotlib cubre los gráficos. ¿Empiezas con Python? Arranca por la hoja de trucos de Python.
Preguntas frecuentes sobre la hoja de trucos de scikit-learn
¿Esta hoja de trucos de scikit-learn es gratis?
¿sklearn es lo mismo que scikit-learn?
pip install scikit-learn), y sklearn es el nombre que importas en el código (from sklearn.linear_model import LinearRegression). Una hoja de trucos de sklearn y una de scikit-learn cubren lo mismo.¿Cuál es la diferencia entre fit, transform y fit_transform?
fit aprende de los datos: un scaler aprende la media de cada columna y un modelo aprende sus pesos. transform aplica lo aprendido, y fit_transform hace las dos cosas en una sola llamada. Usa fit_transform con el conjunto de entrenamiento y solo transform con el de test, o los datos de test se filtran al entrenamiento. Un pipeline lo hace por ti.¿Tengo que escalar mis features?
¿Con qué modelo de scikit-learn empiezo?
LinearRegression para predecir números y LogisticRegression para predecir clases. Después prueba RandomForestClassifier o HistGradientBoostingClassifier (o sus versiones de regresión), compáralos con validación cruzada y ajusta el mejor con GridSearchCV.¿Qué versión de scikit-learn cubre esta hoja de trucos?
squared=False en mean_squared_error, sparse=False en OneHotEncoder y el argumento penalty de LogisticRegression, están en la tabla de formas antiguas junto a lo que debes escribir en su lugar.