El Machine Learning (Aprendizaje Automático) es una rama de la Inteligencia Artificial que proporciona a los sistemas la capacidad de aprender automáticamente y mejorar a partir de la experiencia sin ser programados explícitamente para cada tarea.
En palabras de Arthur Samuel, quien acuñó el término en 1959, el Machine Learning es "el campo de estudio que da a las computadoras la capacidad de aprender sin ser programadas explícitamente".
El Machine Learning se ha convertido en una herramienta indispensable en la ciencia de datos, permitiendo:
El aprendizaje automático se divide generalmente en tres categorías principales:
En el aprendizaje supervisado, el algoritmo aprende de datos etiquetados (ejemplos de entrada-salida). El objetivo es aprender una función que, dada una entrada, predice correctamente la salida.
Principales tareas:
En el aprendizaje no supervisado, el algoritmo aprende patrones a partir de datos no etiquetados, sin tener una "respuesta correcta" predefinida.
Principales tareas:
En el aprendizaje por refuerzo, un agente aprende a tomar decisiones mediante la interacción con un entorno, recibiendo recompensas o penalizaciones según sus acciones.
Esta sección está basada en el Apéndice B (Machine Learning Project Checklist) del libro Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow: Concepts, Tools, and Techniques to Build Intelligent Systems 2nd Edition de Aurélien Géron, con algunas adaptaciones y adiciones personales basadas en mi experiencia y en otros materiales didácticos.
El libro está acompañado por un repositorio con Jupyter Notebooks: https://github.com/ageron/handson-ml2
Un proyecto de Machine Learning sigue un proceso estructurado que permite desarrollar modelos efectivos y confiables. A continuación, presento una guía paso a paso que puede servir como lista de verificación para tus proyectos.
El primer paso es entender claramente qué problema estamos tratando de resolver:
Una vez definido el problema, debemos obtener los datos necesarios:
El análisis exploratorio de datos nos permite entender mejor la información con la que contamos:
Existen varias librerías en Python que facilitan el EDA:
# Ejemplos de librerías para EDA
import pandas as pd
import pandas_profiling # Generación automática de reportes EDA
import sweetviz # Visualizaciones automáticas
import dtale # Interfaz interactiva para exploración
import matplotlib.pyplot as plt
import seaborn as sns
# Ejemplo básico
# Cargar datos
df = pd.read_csv('datos.csv')
# Resumen estadístico
print(df.describe())
# Verificar valores nulos
print(df.isnull().sum())
# Crear un informe completo con pandas_profiling
from pandas_profiling import ProfileReport
profile = ProfileReport(df, title="Informe de Datos")
profile.to_file("informe_eda.html")
Esta fase es crucial para exponer mejor los patrones en los datos y prepararlos para los algoritmos de ML:
# Ejemplo de preparación de datos en Python
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
# Definir transformadores para variables numéricas
num_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())
])
# Definir transformadores para variables categóricas
cat_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')),
('onehot', OneHotEncoder(handle_unknown='ignore'))
])
# Combinar transformadores
preprocessor = ColumnTransformer(
transformers=[
('num', num_transformer, numerical_cols),
('cat', cat_transformer, categorical_cols)
])
# Crear un pipeline para la preparación de datos
data_pipeline = Pipeline(steps=[('preprocessor', preprocessor)])
# Aplicar las transformaciones
X_processed = data_pipeline.fit_transform(X)
En esta fase, evaluamos diferentes algoritmos para identificar los más prometedores:
Al evaluar diferentes modelos, es fundamental utilizar validación cruzada para obtener una estimación confiable de su rendimiento. Esta técnica divide los datos en varios subconjuntos o "pliegues" (folds) y realiza múltiples iteraciones de entrenamiento y evaluación.
En la validación cruzada de k-pliegues (k-fold cross-validation), el proceso es el siguiente:
# Ejemplo de evaluación de modelos en Python
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
# Definir modelos a evaluar
models = {
'LogisticRegression': LogisticRegression(),
'RandomForest': RandomForestClassifier(),
'SVC': SVC(),
'KNeighbors': KNeighborsClassifier(),
'DecisionTree': DecisionTreeClassifier()
}
# Evaluar cada modelo con validación cruzada
results = {}
for name, model in models.items():
cv_scores = cross_val_score(model, X_train, y_train, cv=5, scoring='accuracy')
results[name] = {
'mean_score': cv_scores.mean(),
'std_score': cv_scores.std()
}
print(f"{name}: {cv_scores.mean():.4f} (±{cv_scores.std():.4f})")
Una vez identificados los modelos prometedores, optimizamos sus hiperparámetros:
Un paso crucial en el afinamiento de modelos es la optimización de hiperparámetros, que consiste en encontrar la configuración óptima de parámetros externos al modelo que afectan su rendimiento y capacidad de generalización.
Los hiperparámetros son configuraciones que no se aprenden durante el entrenamiento, sino que deben especificarse previamente. Ejemplos comunes incluyen:
Existen principalmente dos enfoques para la búsqueda de hiperparámetros:
| Grid Search | Evalúa exhaustivamente todas las combinaciones posibles de valores de hiperparámetros especificados. Es completa pero computacionalmente costosa cuando hay muchos parámetros. |
| Random Search | Muestrea aleatoriamente combinaciones del espacio de hiperparámetros. Suele ser más eficiente que Grid Search, especialmente cuando no todos los hiperparámetros son igualmente importantes. |
# Ejemplo de afinamiento de hiperparámetros
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import randint, uniform
# Definir espacio de búsqueda para Random Forest
param_dist = {
'n_estimators': randint(100, 500),
'max_depth': randint(5, 30),
'min_samples_split': randint(2, 20),
'min_samples_leaf': randint(1, 10),
'max_features': ['auto', 'sqrt', 'log2', None]
}
# Crear el modelo base
rf = RandomForestClassifier()
# Configurar la búsqueda aleatoria
random_search = RandomizedSearchCV(
rf,
param_distributions=param_dist,
n_iter=100,
cv=5,
scoring='accuracy',
n_jobs=-1,
verbose=1
)
# Ejecutar la búsqueda
random_search.fit(X_train, y_train)
# Obtener y mostrar los mejores parámetros
print("Mejores parámetros:", random_search.best_params_)
print("Mejor puntuación:", random_search.best_score_)
# Evaluar en el conjunto de prueba
best_model = random_search.best_estimator_
test_score = best_model.score(X_test, y_test)
print(f"Puntuación en el conjunto de prueba: {test_score:.4f}")
Entender por qué y cómo funciona el modelo es esencial para generar confianza y detectar posibles problemas:
# Ejemplo de análisis de interpretabilidad
import shap
import matplotlib.pyplot as plt
from sklearn.inspection import permutation_importance
# Para modelos basados en árboles, podemos ver directamente la importancia de características
feature_importances = best_model.feature_importances_
feature_names = X_train.columns
# Visualizar importancia de características
plt.figure(figsize=(10, 6))
sorted_idx = np.argsort(feature_importances)
plt.barh(range(len(sorted_idx)), feature_importances[sorted_idx])
plt.yticks(range(len(sorted_idx)), np.array(feature_names)[sorted_idx])
plt.xlabel('Importancia de Característica')
plt.title('Importancia de Características del Modelo')
plt.tight_layout()
plt.show()
# Para análisis más avanzados, podemos usar SHAP
explainer = shap.TreeExplainer(best_model)
shap_values = explainer.shap_values(X_test)
# Resumen de valores SHAP
shap.summary_plot(shap_values, X_test, feature_names=feature_names)
# Gráfico de dependencia para ver relaciones específicas
shap.dependence_plot("feature_name", shap_values, X_test)
Comunicar efectivamente los resultados es clave para el éxito del proyecto:
La implementación en producción y el mantenimiento continuo son esenciales para el éxito a largo plazo:
# Ejemplo de cómo guardar un modelo para producción
import joblib
from sklearn.pipeline import Pipeline
# Crear un pipeline completo que incluya preprocesamiento y modelo
full_pipeline = Pipeline([
('preprocessor', preprocessor), # El preprocesador definido anteriormente
('model', best_model) # El mejor modelo encontrado
])
# Entrenar el pipeline completo
full_pipeline.fit(X_train_raw, y_train) # Datos sin preprocesar
# Guardar el pipeline para uso en producción
joblib.dump(full_pipeline, 'modelo_produccion.pkl')
# Ejemplo de carga y uso del modelo en producción
loaded_model = joblib.load('modelo_produccion.pkl')
predictions = loaded_model.predict(new_data) # Se puede usar directamente con datos sin procesar
Para implementar este flujo de trabajo, scikit-learn es la herramienta más utilizada en Python. Ofrece una API consistente para diferentes algoritmos y utilidades de preprocesamiento, evaluación y selección de modelos.
En los próximos capítulos exploraremos en detalle cómo utilizar scikit-learn y otras librerías para implementar cada paso de este flujo de trabajo, centrándonos en regresión, clasificación y clustering.
Para trabajar efectivamente con Machine Learning en Python, es fundamental comprender dos conceptos centrales en scikit-learn: la diferencia entre transformadores y estimadores, y cómo utilizar pipelines para crear flujos de trabajo eficientes y reproducibles.
En el ecosistema de scikit-learn, todos los objetos son estimadores, pero existen diferentes tipos especializados que cumplen funciones específicas en el flujo de trabajo de Machine Learning.
Los transformadores son un tipo especial de estimador que se usa para transformar datos. Implementan métodos adicionales para modificar los datos de entrada.
Características principales de los transformadores:
fit(X): Aprende parámetros para la transformación a partir de los datostransform(X): Aplica la transformación aprendida a nuevos datosfit_transform(X): Combina fit() y transform() en una sola operaciónLos predictores son estimadores que implementan el método predict() para hacer predicciones sobre nuevos datos. A diferencia de los transformadores que modifican los datos, los predictores aprenden patrones y relaciones para generar predicciones.
Características principales de los predictores:
fit(X, y): Aprende patrones de los datos de entrenamiento y sus etiquetaspredict(X): Genera predicciones para nuevos datos basándose en el conocimiento aprendidoscore(X, y): Evalúa la calidad de las predicciones comparándolas con las etiquetas verdaderasUn Pipeline en scikit-learn es una herramienta que permite encadenar múltiples pasos de procesamiento y modelado en un flujo secuencial. Esta es una de las características más poderosas de scikit-learn para crear workflows reproducibles y eficientes.
Los pipelines resuelven varios problemas comunes en Machine Learning:
Un pipeline está compuesto por:
fit() y transform())Para consolidar los conceptos aprendidos en este capítulo, te invito a realizar el siguiente ejercicio:
Para profundizar en Machine Learning con Python, recomendamos consultar estos valiosos recursos: