Proyecto de Machine Learning enfocado en el análisis de segmentación y clustering utilizando el algoritmo K-Means, con capacidades adicionales de predicción mediante XGBoost para clasificación de clusters.
Este proyecto implementa técnicas de aprendizaje no supervisado mediante el algoritmo K-Means para descubrir patrones y agrupar datos similares. Adicionalmente, utiliza modelos supervisados (XGBoost) para predecir a qué cluster pertenecen nuevos datos, creando un pipeline completo de segmentación y clasificación.
- Segmentar datos en grupos homogéneos mediante K-Means
- Identificar patrones y características de cada cluster
- Determinar el número óptimo de clusters
- Crear modelos predictivos para asignar nuevos datos a clusters
- Visualizar y analizar los resultados del clustering
- Proporcionar insights accionables basados en la segmentación
- Clustering K-Means: Implementación optimizada del algoritmo
- Determinación de K: Método del codo y Silhouette Score
- Preprocesamiento: Escalado y normalización de datos
- Modelo Predictivo: XGBoost para clasificación de clusters
- Visualizaciones: Gráficos 2D y 3D de clusters
- Análisis de Perfiles: Caracterización de cada cluster
- Modelos Guardados:
modelo_xgboost.pklyscaler.pkllistos para usar
K-MEDIAS-DANNY/
│
├── src/
│ ├── app.py # Script principal del proyecto
│ ├── explore.ipynb # Notebook de exploración y análisis
│ └── utils.py # Funciones auxiliares
│
├── data/
│ ├── raw/ # Datos originales sin procesar
│ ├── interim/ # Datos en transformación
│ └── processed/ # Datos procesados con clusters asignados
│
├── models/ # Directorio para modelos adicionales
│
├── modelo_xgboost.pkl # Modelo XGBoost entrenado para clasificar clusters
├── scaler.pkl # Scaler para normalización de datos
│
├── .devcontainer/ # Configuración de desarrollo
├── .vscode/ # Configuración de VS Code
├── requirements.txt # Dependencias del proyecto
└── README.md # Este archivo
- Abre el repositorio en GitHub Codespaces
- El entorno se configurará automáticamente
- Todas las dependencias se instalarán automáticamente
- ¡Listo para comenzar!
Requisitos Previos
- Python 3.11 o superior
- pip (gestor de paquetes)
- Git
Pasos de Instalación
- Clona el repositorio:
git clone https://github.com/DannyAIX/K-MEDIAS-DANNY.git
cd K-MEDIAS-DANNY- Crea un entorno virtual (recomendado):
python -m venv venv
source venv/bin/activate # En Windows: venv\Scripts\activate- Instala las dependencias:
pip install -r requirements.txt- Configura variables de entorno (si es necesario):
cp .env.example .envpython src/app.pyjupyter notebook src/explore.ipynb-
Preparación de Datos
- Cargar datos en
data/raw/ - Explorar y limpiar datos
- Manejar valores faltantes y outliers
- Cargar datos en
-
Preprocesamiento
- Normalizar/Estandarizar features
- Selección de variables relevantes
- Reducción de dimensionalidad (opcional)
-
Determinación de K
- Método del codo (Elbow Method)
- Silhouette Score
- Davies-Bouldin Index
-
Clustering
- Entrenar modelo K-Means
- Asignar clusters a los datos
- Evaluar calidad del clustering
-
Análisis de Clusters
- Caracterizar cada cluster
- Visualizar distribuciones
- Extraer insights
-
Modelo Predictivo
- Entrenar XGBoost para predecir clusters
- Evaluar modelo
- Guardar para producción
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
# Cargar datos
df = pd.read_csv('data/raw/datos.csv')
# Seleccionar features para clustering
features = ['feature1', 'feature2', 'feature3', 'feature4']
X = df[features]
# Normalizar datos
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# Entrenar K-Means
kmeans = KMeans(
n_clusters=4, # Número de clusters
init='k-means++', # Método de inicialización
n_init=10, # Número de ejecuciones
max_iter=300, # Iteraciones máximas
random_state=42
)
# Ajustar y predecir
clusters = kmeans.fit_predict(X_scaled)
# Añadir clusters al dataframe
df['cluster'] = clusters
print(f'Inercia: {kmeans.inertia_}')
print(f'Número de iteraciones: {kmeans.n_iter_}')from sklearn.metrics import silhouette_score
# Método del codo
inertias = []
silhouette_scores = []
K_range = range(2, 11)
for k in K_range:
kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
kmeans.fit(X_scaled)
inertias.append(kmeans.inertia_)
silhouette_scores.append(silhouette_score(X_scaled, kmeans.labels_))
# Visualizar método del codo
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))
ax1.plot(K_range, inertias, 'bo-')
ax1.set_xlabel('Número de Clusters (k)')
ax1.set_ylabel('Inercia')
ax1.set_title('Método del Codo')
ax1.grid(True)
ax2.plot(K_range, silhouette_scores, 'ro-')
ax2.set_xlabel('Número de Clusters (k)')
ax2.set_ylabel('Silhouette Score')
ax2.set_title('Silhouette Score por K')
ax2.grid(True)
plt.tight_layout()
plt.show()
# Determinar K óptimo
optimal_k = K_range[np.argmax(silhouette_scores)]
print(f'K óptimo según Silhouette Score: {optimal_k}')import seaborn as sns
from sklearn.decomposition import PCA
# Reducir a 2D con PCA
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
# Crear dataframe para visualización
df_plot = pd.DataFrame({
'PC1': X_pca[:, 0],
'PC2': X_pca[:, 1],
'Cluster': clusters
})
# Gráfico
plt.figure(figsize=(12, 8))
sns.scatterplot(
data=df_plot,
x='PC1',
y='PC2',
hue='Cluster',
palette='viridis',
s=100,
alpha=0.7
)
# Centroides
centroids_pca = pca.transform(kmeans.cluster_centers_)
plt.scatter(
centroids_pca[:, 0],
centroids_pca[:, 1],
c='red',
marker='X',
s=300,
edgecolors='black',
label='Centroides'
)
plt.title('Visualización de Clusters (PCA)', fontsize=14)
plt.xlabel(f'PC1 ({pca.explained_variance_ratio_[0]:.2%} varianza)')
plt.ylabel(f'PC2 ({pca.explained_variance_ratio_[1]:.2%} varianza)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()from mpl_toolkits.mplot3d import Axes3D
# PCA a 3 componentes
pca_3d = PCA(n_components=3)
X_pca_3d = pca_3d.fit_transform(X_scaled)
# Gráfico 3D
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111, projection='3d')
scatter = ax.scatter(
X_pca_3d[:, 0],
X_pca_3d[:, 1],
X_pca_3d[:, 2],
c=clusters,
cmap='viridis',
s=50,
alpha=0.6
)
# Centroides
centroids_3d = pca_3d.transform(kmeans.cluster_centers_)
ax.scatter(
centroids_3d[:, 0],
centroids_3d[:, 1],
centroids_3d[:, 2],
c='red',
marker='X',
s=300,
edgecolors='black'
)
ax.set_xlabel('PC1')
ax.set_ylabel('PC2')
ax.set_zlabel('PC3')
plt.title('Clusters en 3D')
plt.colorbar(scatter)
plt.show()# Estadísticas descriptivas por cluster
cluster_profiles = df.groupby('cluster').agg({
'feature1': ['mean', 'std', 'min', 'max'],
'feature2': ['mean', 'std', 'min', 'max'],
'feature3': ['mean', 'std', 'min', 'max'],
'feature4': ['mean', 'std', 'min', 'max']
})
print("Perfiles de Clusters:")
print(cluster_profiles)
# Tamaño de cada cluster
cluster_sizes = df['cluster'].value_counts().sort_index()
print("\nTamaño de clusters:")
print(cluster_sizes)
# Visualización de perfiles
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
features_to_plot = ['feature1', 'feature2', 'feature3', 'feature4']
for idx, feature in enumerate(features_to_plot):
ax = axes[idx // 2, idx % 2]
df.boxplot(column=feature, by='cluster', ax=ax)
ax.set_title(f'Distribución de {feature} por Cluster')
ax.set_xlabel('Cluster')
ax.set_ylabel(feature)
plt.tight_layout()
plt.show()import pickle
from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report
# Preparar datos para modelo supervisado
X_train, X_test, y_train, y_test = train_test_split(
X_scaled, clusters, test_size=0.2, random_state=42, stratify=clusters
)
# Entrenar XGBoost para predecir clusters
xgb_model = XGBClassifier(
max_depth=5,
learning_rate=0.1,
n_estimators=100,
random_state=42
)
xgb_model.fit(X_train, y_train)
# Evaluar
y_pred = xgb_model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy del modelo predictivo: {accuracy:.4f}')
print('\nReporte de clasificación:')
print(classification_report(y_test, y_pred))
# Guardar modelo y scaler
with open('modelo_xgboost.pkl', 'wb') as f:
pickle.dump(xgb_model, f)
with open('scaler.pkl', 'wb') as f:
pickle.dump(scaler, f)
print('\n¡Modelos guardados exitosamente!')import pickle
import pandas as pd
# Cargar modelos
with open('modelo_xgboost.pkl', 'rb') as f:
model = pickle.load(f)
with open('scaler.pkl', 'rb') as f:
scaler = pickle.load(f)
# Nuevos datos
new_data = pd.DataFrame({
'feature1': [2.5],
'feature2': [3.1],
'feature3': [1.8],
'feature4': [4.2]
})
# Preprocesar
new_data_scaled = scaler.transform(new_data)
# Predecir cluster
predicted_cluster = model.predict(new_data_scaled)
predicted_proba = model.predict_proba(new_data_scaled)
print(f'Cluster asignado: {predicted_cluster[0]}')
print(f'Probabilidades por cluster:')
for i, prob in enumerate(predicted_proba[0]):
print(f' Cluster {i}: {prob:.4f}')El proyecto utiliza las siguientes métricas para evaluar el clustering:
- Inercia: Suma de distancias al cuadrado al centroide más cercano
- Silhouette Score: Medida de qué tan similar es un punto a su cluster (-1 a 1)
- Davies-Bouldin Index: Ratio de dispersión intra-cluster vs inter-cluster
- Calinski-Harabasz Score: Ratio de varianza entre clusters vs dentro de clusters
from sklearn.metrics import (
silhouette_score,
davies_bouldin_score,
calinski_harabasz_score
)
# Calcular métricas
silhouette = silhouette_score(X_scaled, clusters)
davies_bouldin = davies_bouldin_score(X_scaled, clusters)
calinski = calinski_harabasz_score(X_scaled, clusters)
print(f'Silhouette Score: {silhouette:.4f}')
print(f'Davies-Bouldin Index: {davies_bouldin:.4f}')
print(f'Calinski-Harabasz Score: {calinski:.4f}')- Python 3.11+
- scikit-learn: Implementación de K-Means
- pandas: Manipulación de datos
- numpy: Operaciones numéricas
- XGBoost: Modelo predictivo de clusters
- scikit-learn: Preprocesamiento y métricas
- matplotlib: Gráficos básicos
- seaborn: Visualizaciones estadísticas
- plotly: Gráficos interactivos (opcional)
- pickle: Serialización de modelos
- jupyter: Notebooks interactivos
- Segmentación de Clientes: Agrupar clientes por comportamiento de compra
- Marketing: Identificar audiencias objetivo
- E-commerce: Personalización de recomendaciones
- Detección de Anomalías: Identificar puntos atípicos
- Compresión de Imágenes: Reducir colores en imágenes
- Análisis de Redes Sociales: Identificar comunidades
- Bioinformática: Clasificación de genes o proteínas
✅ Simple y fácil de implementar ✅ Rápido y eficiente con grandes datasets ✅ Escala bien con el número de muestras ✅ Garantiza convergencia
❌ Requiere especificar K de antemano ❌ Sensible a inicialización (solucionado con k-means++) ❌ Asume clusters esféricos y de tamaño similar ❌ Sensible a outliers ❌ No funciona bien con clusters no convexos
- Implementar otros algoritmos de clustering (DBSCAN, Hierarchical)
- Agregar validación cruzada para el modelo predictivo
- Crear dashboard interactivo con Streamlit
- Implementar clustering incremental para datos streaming
- Agregar análisis de sensibilidad
- Exportar resultados a formatos empresariales
- API REST para asignación de clusters en tiempo real
Las contribuciones son bienvenidas. Para cambios importantes:
- Fork del proyecto
- Crea una rama feature (
git checkout -b feature/MejorAlgoritmo) - Commit tus cambios (
git commit -m 'Add: nuevo algoritmo de clustering') - Push a la rama (
git push origin feature/MejorAlgoritmo) - Abre un Pull Request
- Scikit-learn K-Means
- K-Means Clustering: Algorithm, Applications
- Choosing the Right Number of Clusters
- XGBoost Documentation
Este proyecto está basado en el template de 4Geeks Academy para el bootcamp de Data Science y Machine Learning.
DannyAIX
- GitHub: @DannyAIX
- Proyecto: K-MEDIAS-DANNY
- 4Geeks Academy por el template base
- Comunidad de scikit-learn
- Desarrolladores del ecosistema de ML en Python
⭐️ Si este proyecto te resultó útil, considera darle una estrella en GitHub
🎯 ¿Necesitas segmentar datos? Este proyecto combina lo mejor del clustering no supervisado con la predicción supervisada.