En esta tarea clasificaremos muestras de roca de un levantamiento regional de geoquímica de roca total. El levantamiento contiene 10 000 muestras. Para cada muestra, un laboratorio midió las concentraciones de los óxidos de elementos mayores (en porcentaje en peso), la densidad aparente y la susceptibilidad magnética. Los geólogos de campo cartografiaron cada sitio de muestreo y asignaron una etiqueta de litología: granito, basalto o andesita. Las clases están desbalanceadas.
La tabla se genera con el paquete del curso mlgeo_synth con una semilla fija; el instructor guarda una variante de semilla oculta que usa para verificar por muestreo los resultados entregados.
En esta tarea entrenaremos varios clasificadores para predecir la clase de una muestra de roca a partir de las mediciones (características). Practicaremos la preparación de datos, la reducción de dimensionalidad, el diseño y entrenamiento de modelos, la comparación de modelos y la selección por importancia de características.
Importación de bibliotecas¶
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
1. Preparación de los datos (20 puntos)¶
Seguimos los pasos siguientes:
- lectura (1 punto)
- limpieza (3 puntos)
- correlaciones (4 puntos)
- exploración, dispersión de los valores (3 puntos)
- reducción de dimensionalidad (9 puntos)
import mlgeo_synth
geo = mlgeo_synth.geochem_table(n=10000, seed=2026)
geo.insert(0, "sample_id", [f"S{i:05d}" for i in range(len(geo))])
geo.to_csv("rock_survey.csv", index=False)1.1 Lectura de los datos¶
Lea el data frame de pandas desde el archivo csv “rock_survey.csv”.
Tarea: leer el data frame de pandas (1 punto)
Guarde una copia del data frame, por si acaso.
Descripción de los campos de datos
- sample_id = identificador de la muestra; se explica solo.
Los óxidos de elementos mayores, reportados en porcentaje en peso (wt%) de la roca total:
- SIO2 = sílice (SiO2), el óxido principal en la mayoría de las rocas corticales; alto en rocas félsicas como el granito, bajo en rocas máficas como el basalto.
- AL2O3 = alúmina (Al2O3), alojada principalmente en los feldespatos.
- FEO = hierro total reportado como FeO; alto en rocas máficas.
- MGO = magnesia (MgO), alojada en el olivino y el piroxeno; alta en rocas máficas.
- CAO = cal (CaO), alojada en la plagioclasa cálcica y el piroxeno.
- NA2O = soda (Na2O), alojada en la plagioclasa sódica.
- K2O = potasa (K2O), alojada en el feldespato alcalino y la mica; alta en el granito.
Los óxidos están sujetos al cierre composicional: suman aproximadamente 100 wt%, así que cuando uno sube los demás deben bajar.
Las propiedades físicas:
density_g_cm3 = densidad aparente de la muestra en g/cm3.
mag_susc_si = susceptibilidad magnética, en unidades SI de volumen; sensible al contenido de magnetita de la roca.
label = litología cartografiada por los geólogos de campo (granito, basalto o andesita). Esta será la variable de respuesta que intentaremos predecir.
1.2 Limpieza de los datos¶
Estadísticas básicas de nuestro conjunto de datos.
Tarea: muestre la información básica del encabezado del data frame de pandas (0.5 punto)
Tarea: encuentre los tipos de datos de la base (flotantes, cadenas, etc.) usando la función info() (0.5 punto).
¿Hay alguna característica (o elemento del data frame) que evidentemente no debería influir en nuestra predicción?
sample_id es solo un identificador para volver a acceder a las filas cuando estaban almacenadas en la base de datos original del levantamiento. Por lo tanto no lo necesitaremos para la clasificación, pues no guarda relación con el resultado.
Tarea: elimine esta columna del data frame de pandas. (1 punto)
Averigüemos cuántos ejemplos hay, cuántos atributos o características, y el tipo de clase.
Tarea: ¿cuántos objetos hay en cada clase? (1 punto)
Las clases son “granite”, “basalt” y “andesite”. Están definidas como cadenas, pero las convertiremos a enteros para poder aplicar una función de pérdida sobre las etiquetas de clase durante el entrenamiento. Para esto usamos la función sklearn.preprocessing.LabelEncoder(). Lo haremos y modificaremos las clases en el data frame. Conviene conservar una copia del data frame original, por seguridad.
1.3 Correlaciones de los datos¶
Busquemos ahora las correlaciones más básicas entre las características. Esto puede hacerse con la función corr() aplicada al data frame de pandas. Evalúe esta función y comente qué característica está correlacionada con las demás. Conviene usar la función matshow() de matplotlib para mayor claridad. seaborn es un módulo de python que produce gráficos estadísticos realmente bonitos https://
Tarea: grafique la matriz de correlación que puede llamarse desde el data frame de pandas. (2 puntos)
Pistas:
Use las funciones de heatmap y añada las etiquetas en los ejes. El mapa de color coolwarm es agradable para escalas divergentes como las correlaciones, que varían entre -1 y 1. El argumento center=0 asegura que el mapa de color diverja desde cero. Asegúrese de ignorar la columna de etiquetas “label”. Recuerde que una columna puede eliminarse sobre la marcha con rock_df.drop('label', axis=1).
Tarea: reproduzca el mismo gráfico para cada una de las tres clases. (1 punto) Puede seleccionar los valores del data frame de pandas filtrando sobre la columna ‘label’.
Tarea: ¿puede comentar sobre grupos de características que están correlacionadas entre sí o que parecen independientes unas de otras a la luz de estas correlaciones? (1 punto) Debería esperar correlaciones fuertes entre los óxidos: el cierre composicional los obliga a intercambiarse unos por otros, y la diferenciación magmática los arrastra juntos. ¿La densidad y la susceptibilidad magnética se correlacionan con los óxidos? ¿Los patrones difieren entre las tres litologías?
1.5 Exploración de los datos¶
Dada la estructura de las correlaciones, exploraremos los valores de los datos.
1.5.a. Distribuciones de SiO2¶
El contenido de sílice es el primer número que mira un petrólogo: aumenta con la diferenciación magmática y separa las rocas félsicas de las máficas.
Tarea: grafique histogramas de la columna de características ‘SIO2’ para cada clase (1 punto).
Tarea: describa brevemente la diferencia entre los tres histogramas. (0.5 punto)
Granito:
Basalto:
Andesita:
1.5.b. Densidad y susceptibilidad magnética¶
Ahora graficaremos la densidad aparente (density_g_cm3) contra la susceptibilidad magnética (mag_susc_si), coloreadas por clase. Puede usar la función scatterplot o lmplot de seaborn (https://
Tarea: ¿ve diferencias evidentes tales que uno pudiera discriminar fácilmente entre las clases? (0.5 punto)
1.5.c Los óxidos mayores¶
Recuerde: la matriz de correlación muestra que los óxidos de elementos mayores están correlacionados entre sí para las tres clases.
Tarea: grafique histogramas de los demás óxidos (AL2O3, FEO, MGO, CAO) y discuta por qué espera que estas características estén correlacionadas (1 punto)
1.6 Reducción de dimensionalidad de los datos¶
A esta altura nos quedan 9 características: los siete óxidos (SIO2, AL2O3, FEO, MGO, CAO, NA2O, K2O), density_g_cm3 y mag_susc_si. Entre ellas, los óxidos están correlacionados entre sí. Hay por lo tanto potencial para reducir la dimensión de las características usando PCA sobre esas 7 características.
Usaremos la función de sklearn sklearn.decomposition.PCA() para ajustar y transformar los datos a las coordenadas de las PC. Exploremos primero cuántas PC necesitamos. Ajuste la función de PCA sobre el número total de óxidos. Ajustará la función de PCA sobre un arreglo con las columnas seleccionadas del data frame.
Tarea: realice la PCA sobre un número máximo de PC, muestre los valores de la razón de varianza explicada y decida un número máximo apropiado de PC a usar (6 puntos)
Respuesta sobre cuántas PC usar
Ahora volveremos a realizar la PCA con el número de PC que usted encontró más apropiado. Vuelva a aplicar la función de ajuste y transformación. Actualice el data frame añadiendo el o los valores de PCA y eliminando las columnas de las 7 características de óxidos.
Tarea: PCA de nuevo, ajuste y transforme, actualice el data frame con la o las características nuevas (3 puntos)
2. Agrupamiento no supervisado con KMeans (20 puntos)¶
En esta sección exploraremos si las características de los datos serán suficientes para la clasificación. Como primera exploración, realizaremos una clasificación no supervisada con el agrupamiento KMeans.
2.1 Realice un KMeans preliminar (10 puntos)¶
Implemente aquí KMeans para un número dado de conglomerados y sobre las características de interés. Elija 3 características (por ejemplo PC1, density_g_cm3 y mag_susc_si; recuerde escalarlas).
- Use
sklearnpara realizar el KMeans. - Repita el KMeans y discuta (en una celda de markdown) la estabilidad del agrupamiento (p. ej., use visualizaciones para evaluar la estabilidad de forma cualitativa).
2.2 Encuentre el número óptimo de conglomerados (5 puntos)¶
Use un método para establecer el número óptimo de conglomerados.
2.3 Discuta el desempeño del agrupamiento (5 puntos)¶
- Realice un análisis de silueta (visualización de la silueta y score)
- Calcule (en una celda de python) y discuta (en la celda de markdown siguiente) la homogeneidad respecto de las etiquetas verdaderas (ground truth) usando 3 métricas apropiadas.
Pregunta: Después de realizar el agrupamiento con KMeans y calcular los scores de completitud, homogeneidad y Fowlkes-Mallows, ¿cómo puede determinar si esos scores son buenos? Compare los scores obtenidos con los valores ideales y explique qué indica cada score sobre la calidad del agrupamiento. ¿Qué encuentra en sus resultados?
3 Modelos de aprendizaje automático (30 puntos)¶
Ahora entrenaremos distintos modelos sobre este conjunto de datos. Tenemos las características que quedan tras la reducción de dimensionalidad, 3 clases y 10 000 muestras. Usaremos k vecinos más cercanos, Bayes ingenuo, bosque aleatorio, máquina de vectores de soporte y gradient boosting (potenciación de gradiente) por histogramas.
Seguimos ahora un flujo de trabajo normal de aprendizaje automático:
- Escalado de características (3 puntos)
- División en conjuntos de entrenamiento/prueba (2 puntos)
- Diseño, entrenamiento y prueba de los modelos (15 puntos)
- Comparación de modelos, elija a su ganador, discuta la importancia de características usando el bosque aleatorio. (10 puntos)
3.1 Escalado de características¶
Escalar todos los valores al intervalo (0, 1) reducirá la distorsión debida a valores excepcionalmente altos y hará que algunos algoritmos converjan más rápido. Puede escalar solo las características eliminando la columna “label” sin modificar el data frame en el lugar, usando la función drop() de pandas.
Tarea: escale solo las características (3 puntos)
3.2 Conjuntos de datos de prueba, entrenamiento y validación.¶
Tarea: divida los datos en una parte de entrenamiento y una de prueba. (2 puntos)
Los modelos se entrenarán sobre el conjunto de entrenamiento y se probarán sobre el conjunto de prueba. Use una división estratificada (stratify=y) — las clases están desbalanceadas.
El tiempo de cómputo es importante de considerar cuando se escalan el conjunto de datos y el tamaño del modelo. Puede evaluar el tiempo de cómputo relativo usando la función time.perf_counter() para medir el tiempo absoluto. Luego compare el tiempo de cómputo haciendo la diferencia entre dos marcas de tiempo:
t1=time.perf_counter()
t2=time.perf_counter()
tcomp = t2 - t1
También evaluaremos el desempeño de estos clasificadores multiclase. Evaluaremos el promedio de los scores sobre las 3 etiquetas de clase.
En lo que sigue probaremos varios clasificadores. Siga los pasos:
- definición/diseño del modelo
- entrenamiento
- predicción sobre la prueba
- evaluación: a) imprima el classification_report; b) guarde la precisión, la exhaustividad (recall), el score F y la exactitud en variables
3.3.a K vecinos más cercanos (3 puntos)¶
Consulte los argumentos y la definición de la función aquí: https://
3.3.b Bayes ingenuo (3 puntos)¶
Consulte las páginas del tutorial de sklearn aquí: https://
El Bayes ingenuo supone que los datos siguen una distribución normal, lo que puede lograrse escalando con el MaxAbsScaler. Para este ejemplo usaremos entonces los datos sin escalar, y luego los reescalaremos.
3.3.c Clasificador de bosque aleatorio (3 puntos)¶
Consulte la página del tutorial aquí: https://
3.3.d Clasificador de máquina de vectores de soporte (3 puntos)¶
Consulte la página de información de sklearn aquí: https://
3.3.e Gradient boosting por histogramas (3 puntos)¶
Consulte la página de información aquí: https://
3.4 Desempeño y comparación de los modelos¶
3.4.a Matriz de confusión e interpretación¶
Tarea: grafique la matriz de confusión (2 puntos)
Use ConfusionMatrixDisplay de sklearn para visualizar la matriz de confusión
Tarea: comente cuál parece ser el mejor clasificador (1 punto). También puede comentar las tasas de clasificación errónea y de confusión.
3.4.b Validación cruzada de K pliegues¶
Ahora realizaremos la validación cruzada de k pliegues para los clasificadores. Usamos la función cross_val_score sobre cada estimador, sobre el conjunto de entrenamiento, con 10 pliegues estratificados (StratifiedKFold(n_splits=10)), y usamos el F1 macro como métrica de score (scoring="f1_macro") — las clases están desbalanceadas, así que la exactitud premiaría ignorar la clase rara.
Tarea: realice la validación cruzada sobre los K pliegues y muestre la media y la desviación estándar del score F1 macro (3 puntos)
Tarea: ¿qué método ganó la prueba de validación cruzada (1 punto)?
vea la celda de abajo
3.4.c Y el ganador es...¶
Comparemos los resultados. Tarea: cree un data frame de pandas con todas las métricas de desempeño, incluidos los resultados de la validación cruzada de K pliegues. (2 puntos)
Tarea: comente los scores F1 macro y el desempeño, y elija un ganador. (1 punto)
vea la celda de abajo
4 Resumen (4 puntos)¶
4.1 Importancia de características usando el clasificador de bosque aleatorio¶
Los árboles de decisión tienen la propiedad única de poder ordenar las características por su capacidad de separar las clases. Si algunas características dominan a otras en el poder predictivo sobre las clases, puede reducirse aún más la dimensión de las características para análisis adicionales. El vector de importancia de características está en rfc.feature_importances_, ordenado con importancia ascendente. Guarde el vector de importancias.
Recuerde la advertencia de la lección 3.7: importancia no es causalidad. El ordenamiento reporta lo que el modelo usa para predecir, no lo que hace que una roca sea un granito — y las importancias por impureza reparten el crédito entre características correlacionadas, incluidas las PC que usted construyó a partir de los óxidos.
Tarea: haga un gráfico de barras con la función matplotlib.pyplot.bar. (2 puntos)
Tarea: ¿cuáles son las tres características principales (1 punto)?
escriba en la celda de abajo
En este cuaderno probablemente encontró que las características ligadas a la diferenciación (la primera PC de los óxidos, la densidad, la susceptibilidad magnética) separan las litologías. Un petrólogo le habría dicho que el contenido de sílice separa el granito del basalto — pero ahora usted puede cuantificar qué tan bien, y cuánto cuesta automatizarlo.
Tarea: comente brevemente lo que aprendió (1 punto)
vea la celda de abajo