Capitulo 06
Machine Learning basico: el primer modelo de verdad
5 algoritmos, cuando usar cada uno, y por que el baseline es tu mejor amigo
Los 5 algoritmos fundamentales de ML (Logistic Regression, KNN, Arboles, Random Forest, Gradient Boosting), cuando usar cada uno, las metricas que importan segun el problema, y cross-validation para estimar performance real.
6.1 La verdad que nadie te dice en los tutoriales
En un proyecto de ML, el 80% del trabajo no es entrenar el modelo. Es: entender el problema, limpiar los datos, hacer feature engineering, validar honestamente, comunicar resultados. El modelo es el 20% que el negocio ve. Si los otros 80% estan mal, el modelo es ruido bonito.
Este modulo te da el vocabulario y la caja de herramientas de los 5 modelos que cubren el 95% de los problemas tabulares del mundo real.
6.2 Los 3 problemas canonicos de ML supervisado
| Problema | Target | Metricas | Ejemplo |
|---|---|---|---|
| bin | y ∈ {0, 1} Spam/no-spam, fraude, churn. | ||
| multi | y ∈ {0, 1, ..., K} Reconocer digitos, clasificar imagenes. | ||
| reg | y ∈ ℝ Precio de casa, demanda, temperatura. |
Antes de elegir modelo, responde: ¿Que error es mas caro, FP o FN? Esa respuesta determina la metrica, el threshold, y en ultima instancia el modelo. En medicina, FN (no detectar cancer) >> FP (falsa alarma). En spam, FP (marcar un mail bueno como spam) puede ser >> FN (dejar pasar un spam). En fraude, depende del volumen.
6.3 Los 5 algoritmos que tienes que dominar
Logistic Regression
M6A pesar del nombre, es CLASIFICACION. Estima P(y=1|X) usando la funcion sigmoide. Lineal en los features (despues de transformacion). Pros: rapido, interpretable, da probabilidades bien calibradas. Contras: no captura relaciones no lineales.
Ej: Primer modelo que entrenar en cualquier problema de clasificacion. Si LR anda bien, los datos tienen estructura lineal. Si anda mal, considera features polinomiales o un modelo no lineal.
K-Nearest Neighbors (KNN)
M6Clasifica un punto segun la mayoria de votos de sus K vecinos mas cercanos en el espacio de features. Lazy: no aprende nada en fit, todo el trabajo es en predict. Pros: simple, no asume distribucion. Contras: lento en prediccion con muchos datos, sensible al escalado y a features irrelevantes.
Arbol de Decision
M6Particiona recursivamente el espacio de features usando preguntas binarias. Cada hoja tiene una prediccion. Pros: MUY interpretable (puedes ver el camino de decision), maneja mixto (numerico + categorico), no requiere escalado. Contras: overfittea con facilidad, inestable (pequenos cambios en datos cambian mucho el arbol).
Random Forest
M6Ensemble de muchos arboles de decision entrenados con (a) bootstrap samples de los datos y (b) subconjuntos aleatorios de features. Cada arbol vota. Pros: muy robusto, rara vez overfittea, no requiere escalado, da feature importance gratis. Contras: menos interpretable que un solo arbol, mas lento, modelos grandes.
Gradient Boosting (XGBoost / LightGBM / CatBoost)
M6Ensemble SECUENCIAL: cada arbol corrige los errores del anterior. Pros: estado del arte en datos tabulares, mayor accuracy que RF. Contras: mas hiperparametros, mas riesgo de overfit, mas lento de entrenar.
- ¿Tienes > 10k muestras? Empieza con Logistic Regression. Es el baseline honesto.
- ¿La accuracy es inaceptable? KNN (datasets chicos) o Random Forest (datasets medianos).
- ¿Quieres el maximo de performance? Gradient Boosting con tuning.
- ¿Necesitas explicabilidad al negocio? Un solo Arbol de Decision o un modelo con SHAP sobre cualquier ensemble.
6.4 Comparativa head-to-head con datos reales
import numpy as np
import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split, cross_val_score, StratifiedKFold
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.metrics import classification_report, roc_auc_score, f1_score
# Cargar datos
data = load_breast_cancer()
X = pd.DataFrame(data.data, columns=data.feature_names)
y = data.target # 0=maligno, 1=benigno
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
# Modelos con la misma estructura de Pipeline
# - StandardScaler solo donde tiene sentido (LR y KNN)
# - Random_state fijo para reproducibilidad
modelos = {
'Logistic Regression': Pipeline([
('scaler', StandardScaler()),
('model', LogisticRegression(max_iter=1000, random_state=42))
]),
'KNN (k=5)': Pipeline([
('scaler', StandardScaler()),
('model', KNeighborsClassifier(n_neighbors=5))
]),
'Decision Tree': Pipeline([
('model', DecisionTreeClassifier(max_depth=5, random_state=42))
]),
'Random Forest': Pipeline([
('model', RandomForestClassifier(n_estimators=100, max_depth=10, random_state=42, n_jobs=-1))
]),
'Gradient Boosting': Pipeline([
('model', GradientBoostingClassifier(n_estimators=100, max_depth=3, random_state=42))
]),
}
# Validacion cruzada ESTRATIFICADA (mantiene proporcion de clases)
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
print(f"{'Modelo':<22} {'Accuracy':<12} {'F1':<10} {'ROC-AUC':<10}")
print("=" * 60)
for nombre, modelo in modelos.items():
acc = cross_val_score(modelo, X_train, y_train, cv=cv, scoring='accuracy').mean()
f1 = cross_val_score(modelo, X_train, y_train, cv=cv, scoring='f1').mean()
auc = cross_val_score(modelo, X_train, y_train, cv=cv, scoring='roc_auc').mean()
print(f"{nombre:<22} {acc:.3f} {f1:.3f} {auc:.3f}")
# NOTA: se entrena 5 modelos * 3 metricas * 5 folds = 75 fits por ejecucion
# En datasets grandes, considera usar n_jobs=-1 6.5 Cross-Validation: la verdad sobre tu modelo
K-Fold Cross-Validation
M6Divide los datos en K partes. Entrena K veces, cada vez usando K-1 partes para entrenar y 1 para validar. La metrica final es la MEDIA de las K metricas. Ventaja: usa todos los datos para train y test, da estimacion de varianza (std entre folds).
Todo el preprocessing (imputacion, escalado, encoding, feature selection) va ADENTRO del loop de CV. Si lo haces ANTES del CV, la informacion del fold de validacion se filtra al train via las estadisticas globales. Ejemplo clasico: imputar con la media de TODO el dataset antes del CV = leakage.
from sklearn.model_selection import cross_val_score, KFold
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
# FORMA INCORRECTA (leakage)
# imp = SimpleImputer()
# X_imp = imp.fit_transform(X) # usa la media de TODO el dataset
# cross_val_score(model, X_imp, y) # cada fold usa stats de test
# FORMA CORRECTA (sin leakage)
model = Pipeline([
('imputer', SimpleImputer()), # aprende la media SOLO en train de cada fold
('scaler', StandardScaler()),
('clf', LogisticRegression())
])
cv = KFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X, y, cv=cv, scoring='roc_auc')
print(f"AUC: {scores.mean():.3f} ± {scores.std():.3f}") - Stratified K-Fold: mantiene la proporcion de clases en cada fold. Es el default para clasificacion desbalanceada.
- TimeSeriesSplit: para series temporales. Train en [0:t], val en [t:t+k], desplazandose. Nunca mira el futuro.
- Group K-Fold: cuando hay grupos (ej: mismo paciente en multiples filas). No separa filas del mismo grupo entre train y val.
- Leave-One-Out: K=N. Cada fold es 1 muestra. Solo util con datasets muy pequenos (< 100).
6.6 Bias-Variance tradeoff (el diagnostico fundamental)
- Bias alto (underfitting): el modelo es demasiado simple, no captura la estructura real de los datos. Error alto en train Y en test. Solucion: modelo mas complejo, mejores features, menos regularizacion.
- Variance alta (overfitting): el modelo es demasiado complejo, memoriza ruido del train. Error bajo en train, alto en test. Solucion: mas datos, regularizacion (max_depth menor, alpha mayor, dropout), ensemble.
El objetivo: encontrar el punto de equilibrio, generalmente via learning curves.
import matplotlib.pyplot as plt
import numpy as np
from sklearn.model_selection import learning_curve
from sklearn.ensemble import RandomForestClassifier
train_sizes, train_scores, val_scores = learning_curve(
RandomForestClassifier(n_estimators=100, max_depth=10, random_state=42),
X_train, y_train,
cv=5,
train_sizes=np.linspace(0.1, 1.0, 10),
scoring='roc_auc',
n_jobs=-1,
)
train_mean = train_scores.mean(axis=1)
val_mean = val_scores.mean(axis=1)
plt.figure(figsize=(8, 5))
plt.plot(train_sizes, train_mean, 'o-', label='Train AUC', color='#06B6D4')
plt.plot(train_sizes, val_mean, 'o-', label='Validation AUC', color='#8B5CF6')
plt.fill_between(train_sizes, val_mean - val_scores.std(axis=1), val_mean + val_scores.std(axis=1), alpha=0.2, color='#8B5CF6')
plt.xlabel('Tamanio del training set')
plt.ylabel('ROC-AUC')
plt.title('Learning Curves: diagnostico de bias-variance')
plt.legend()
plt.grid(alpha=0.3)
import seaborn as sns; sns.despine()
plt.tight_layout()
plt.show()
# Diagnostico:
# - Train alto, val bajo, curvas NO convergen → overfitting. Mas datos o regularizacion.
# - Train bajo, val bajo, curvas convergen → underfitting. Modelo mas complejo.
# - Train alto, val alto, curvas convergen → punto optimo. 6.7 Errores comunes
- Cargá un dataset publico de clasificacion (Titanic, Breast Cancer, Iris, Wine). Documenta el problema en 3 lineas.
- Establece UNA metrica principal segun el tipo de problema (F1, ROC-AUC, etc). Justifica tu eleccion.
- Entrena los 5 modelos (LR, KNN, DT, RF, GBM) usando Pipeline + StandardScaler + Cross-Validation con Stratified K-Fold (k=5). Reporta media y std de la metrica en CV.
- Para el modelo ganador, hace un reporte completo en el test set: classification report + ROC-AUC + matriz de confusion. Comenta que clase es mas dificil de predecir y por que.
- Calcula el baseline con
DummyClassifier(strategy=‘most_frequent’). Si tu modelo no lo supera por un margen significativo, el problema no justifica ML. - Bonus: ajusta hiperparametros del mejor modelo con
GridSearchCV. Reporta los mejores hiperparametros y cuanto mejoro el CV.