Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

355 changes: 355 additions & 0 deletions educational_content/PROYECTO FINAL/EDA_INICIAL_NANOTOXICIDAD_U6.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,355 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "00380316",
"metadata": {},
"source": [
"# EDA inicial para el proyecto de nanotoxicidad\n",
"\n",
"Esta notebook prepara la exploración inicial del dataset disponible en el repositorio para construir el proyecto integrador de la Unidad 6.\n",
"\n",
"Objetivos de esta notebook:\n",
"- identificar el dataset más útil para arrancar\n",
"- entender qué representa cada variable\n",
"- decidir el tipo de problema de Machine Learning\n",
"- evaluar si el dataset es suficiente para un proyecto universitario de 3 semanas\n",
"- dejar una base lista para conectar con `U6_03_IMPLEMENTACION_PROYECTO.ipynb`"
]
},
{
"cell_type": "markdown",
"id": "cb934ea9",
"metadata": {},
"source": [
"## 1. Dataset recomendado para comenzar\n",
"\n",
"El archivo más útil dentro del repositorio para iniciar el trabajo es `educational_content/unit_03_ml_nanomaterials/nanomaterials_full_dataset.csv`.\n",
"\n",
"**Por qué conviene para empezar**\n",
"- Ya existe dentro del repositorio.\n",
"- Tiene variables numéricas y categóricas útiles para un pipeline real.\n",
"- Es pequeño y manejable para un proyecto universitario de 3 semanas.\n",
"- Permite construir EDA, limpieza, pipeline y modelo sin depender de una descarga externa inmediata.\n",
"\n",
"**Limitación importante**\n",
"- Este dataset describe propiedades de nanomateriales, pero no tiene una etiqueta explícita de toxicidad.\n",
"- Por eso, para el modelo final de nanotoxicidad se debe complementar con una fuente de labels de toxicidad o construir una etiqueta derivada y justificable.\n",
"\n",
"**Conclusión práctica**\n",
"- Sirve como base estructural y de pipeline.\n",
"- No es suficiente por sí solo para un clasificador final de toxicidad sin una variable objetivo adecuada."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "26f604ab",
"metadata": {},
"outputs": [],
"source": [
"from pathlib import Path\n",
"import pandas as pd\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"\n",
"sns.set_theme(style=\"whitegrid\")\n",
"\n",
"dataset_path = Path(\"..\") / \"unit_03_ml_nanomaterials\" / \"nanomaterials_full_dataset.csv\"\n",
"if not dataset_path.exists():\n",
" dataset_path = Path(\"c:/Users/natal/OneDrive/Documentos/PROYECTO IA/Antigravity-Nano-Research-Multiagentic-Core/educational_content/unit_03_ml_nanomaterials/nanomaterials_full_dataset.csv\")\n",
"\n",
"df = pd.read_csv(dataset_path)\n",
"print(f'Archivo cargado: {dataset_path}')\n",
"print(f'Forma del dataset: {df.shape[0]} filas x {df.shape[1]} columnas')\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"id": "0ca0c85b",
"metadata": {},
"source": [
"## 2. ¿Qué representa cada variable?\n",
"\n",
"**Variables categóricas principales**\n",
"- `element`: elemento químico base de la nanopartícula.\n",
"- `geometry`: geometría o forma estructural del nanoclúster.\n",
"- `element_group`: grupo químico del elemento.\n",
"\n",
"**Variables estructurales / geométricas**\n",
"- `n_atoms`: número de átomos.\n",
"- `noshells`: número de capas o shells.\n",
"- `radius_mean`, `radius_std`, `radius_max`: resumen estadístico del radio estructural.\n",
"- `asphericity`: qué tan alejada está la partícula de una forma esférica.\n",
"- `compactness`: compacidad geométrica.\n",
"- `surface_fraction`: fracción superficial estimada.\n",
"- `coordination_mean`, `coordination_std`, `coordination_min`, `coordination_max`: estadística de coordinación atómica.\n",
"\n",
"**Variables energéticas / físicas**\n",
"- `energy_per_atom`: energía por átomo.\n",
"- `energy_total`: energía total.\n",
"- `energy_stability`: indicador de estabilidad energética.\n",
"- `melting_point`: punto de fusión estimado.\n",
"- `log_n_atoms`: logaritmo del número de átomos.\n",
"\n",
"**Interpretación para nanotoxicidad**\n",
"Estas variables no describen toxicidad directamente, pero sí capturan rasgos que luego pueden relacionarse con toxicidad: tamaño, forma, estabilidad, coordinación y superficie."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e656fb4c",
"metadata": {},
"outputs": [],
"source": [
"# Inspección rápida del esquema del dataset\n",
"print('Columnas:')\n",
"for col in df.columns:\n",
" print('-', col)\n",
"\n",
"print('\\nTipos de dato:')\n",
"print(df.dtypes)\n",
"\n",
"print('\\nValores faltantes por columna:')\n",
"print(df.isna().sum().sort_values(ascending=False))\n",
"\n",
"print('\\nFilas duplicadas:', df.duplicated().sum())"
]
},
{
"cell_type": "markdown",
"id": "5d6ded3f",
"metadata": {},
"source": [
"## 3. Variable objetivo (target)\n",
"\n",
"Para el proyecto final de nanotoxicidad, la variable objetivo ideal debería ser una de estas dos opciones:\n",
"\n",
"1. **Clasificación binaria**: `toxico` / `no_toxico`.\n",
"2. **Regresión**: un `toxicity_score` continuo entre 0 y 1, o una escala experimental equivalente.\n",
"\n",
"**Decisión recomendada para comenzar**\n",
"- Si el dataset de toxicidad aún no está consolidado, conviene diseñar el proyecto como **clasificación binaria**.\n",
"- Razón: es más defendible con datos limitados, más fácil de explicar y más compatible con un MVP universitario de 3 semanas.\n",
"\n",
"**Importante**\n",
"- El archivo actual no trae una etiqueta de toxicidad directa.\n",
"- Por eso, esta notebook se usa para preparar la estructura y el pipeline, no para entrenar todavía el clasificador final."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c6992461",
"metadata": {},
"outputs": [],
"source": [
"# Perfil básico del dataset\n",
"numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()\n",
"categorical_cols = df.select_dtypes(exclude=[np.number]).columns.tolist()\n",
"\n",
"print('Columnas numéricas:', numeric_cols)\n",
"print('Columnas categóricas:', categorical_cols)\n",
"\n",
"display(df[numeric_cols].describe().T)\n",
"\n",
"for col in categorical_cols:\n",
" \n",
" print(f'\\nFrecuencias de {col}:')\n",
" print(df[col].value_counts(dropna=False).head(10))"
]
},
{
"cell_type": "markdown",
"id": "421882bb",
"metadata": {},
"source": [
"## 4. ¿Conviene clasificación binaria o regresión?\n",
"\n",
"**Recomendación**: comenzar con **clasificación binaria**.\n",
"\n",
"**Motivos**\n",
"- La toxicidad suele presentarse como una decisión de riesgo: pasa / no pasa.\n",
"- Es más fácil conseguir o derivar etiquetas binarias confiables.\n",
"- Las métricas son claras: accuracy, precision, recall, F1 y ROC-AUC.\n",
"- El resultado es fácil de explicar en presentación y reporte.\n",
"\n",
"**Cuándo usar regresión**\n",
"- Solo si consigues un índice de toxicidad continuo bien definido.\n",
"- Si las etiquetas son débiles o poco consistentes, la regresión puede introducir más ruido que valor."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "dd424e39",
"metadata": {},
"outputs": [],
"source": [
"# Matriz de correlación para variables numéricas\n",
"plt.figure(figsize=(12, 8))\n",
"corr = df[numeric_cols].corr(numeric_only=True)\n",
"sns.heatmap(corr, cmap='coolwarm', center=0, linewidths=0.3)\n",
"plt.title('Correlación entre variables numéricas')\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "1eb5b9bc",
"metadata": {},
"source": [
"## 5. ¿El dataset es suficiente para un proyecto universitario de 3 semanas?\n",
"\n",
"**Sí, como base de trabajo y prototipo.**\n",
"\n",
"**Pero con una condición importante**\n",
"- Este dataset por sí solo no alcanza para un modelo final de nanotoxicidad si no incluye la etiqueta objetivo.\n",
"- Lo suficiente aquí es la **estructura**, no el target.\n",
"\n",
"**Evaluación práctica**\n",
"- Tamaño: pequeño, manejable y rápido de iterar.\n",
"- Complejidad: adecuada para el tiempo disponible.\n",
"- Viabilidad académica: alta, si se complementa con una fuente de labels de toxicidad o una estrategia de etiquetado justificable.\n",
"\n",
"**Veredicto**\n",
"- Adecuado para arrancar.\n",
"- No suficiente como única fuente final de entrenamiento para toxicidad."
]
},
{
"cell_type": "markdown",
"id": "b9bd2c1f",
"metadata": {},
"source": [
"## 6. Preparación del dataset para el pipeline de U6\n",
"\n",
"El siguiente paso para U6_03 será: \n",
"\n",
"1. Definir columnas de entrada.\n",
"2. Separar variables numéricas y categóricas.\n",
"3. Crear un preprocesamiento con `ColumnTransformer`.\n",
"4. Construir un `Pipeline` con imputación, escalado y modelo.\n",
"5. Sustituir este dataset estructural por uno con target de toxicidad cuando esté listo.\n",
"\n",
"La idea es que esta notebook deje lista la capa de exploración y preparación antes de entrenar."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "16ad588e",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.model_selection import train_test_split\n",
"from sklearn.compose import ColumnTransformer\n",
"from sklearn.pipeline import Pipeline\n",
"from sklearn.impute import SimpleImputer\n",
"from sklearn.preprocessing import OneHotEncoder, StandardScaler\n",
"\n",
"# Ejemplo de preparación de pipeline, listo para U6_03\n",
"feature_cols = [c for c in df.columns if c not in []]\n",
"X = df.copy()\n",
"\n",
"numeric_features = df.select_dtypes(include=[np.number]).columns.tolist()\n",
"categorical_features = df.select_dtypes(exclude=[np.number]).columns.tolist()\n",
"\n",
"numeric_transformer = Pipeline(steps=[\n",
" ('imputer', SimpleImputer(strategy='median')),\n",
" ('scaler', StandardScaler())\n",
"])\n",
"\n",
"categorical_transformer = Pipeline(steps=[\n",
" ('imputer', SimpleImputer(strategy='most_frequent')),\n",
" ('onehot', OneHotEncoder(handle_unknown='ignore'))\n",
"])\n",
"\n",
"preprocessor = ColumnTransformer(\n",
" transformers=[\n",
" ('num', numeric_transformer, numeric_features),\n",
" ('cat', categorical_transformer, categorical_features),\n",
" ]\n",
")\n",
"\n",
"print('Preprocesador listo para integrarse a U6_03.')"
]
},
{
"cell_type": "markdown",
"id": "89a40b6d",
"metadata": {},
"source": [
"## 7. Visualizaciones iniciales\n",
"\n",
"Estas figuras sirven como evidencia para el reporte y como primer acercamiento al dataset.\n",
"\n",
"Sugerencias de lectura:\n",
"- distribuciones de tamaño y energía\n",
"- relaciones entre estabilidad y coordinación\n",
"- comparación por elemento o geometría"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0a1f323e",
"metadata": {},
"outputs": [],
"source": [
"fig, axes = plt.subplots(2, 2, figsize=(12, 10))\n",
"axes = axes.ravel()\n",
"\n",
"if 'n_atoms' in df.columns:\n",
" sns.histplot(df['n_atoms'], kde=True, ax=axes[0], color='steelblue')\n",
" axes[0].set_title('Distribución de n_atoms')\n",
"\n",
"if 'energy_per_atom' in df.columns:\n",
" sns.histplot(df['energy_per_atom'], kde=True, ax=axes[1], color='darkorange')\n",
" axes[1].set_title('Distribución de energy_per_atom')\n",
"\n",
"if 'coordination_mean' in df.columns and 'energy_stability' in df.columns:\n",
" sns.scatterplot(data=df, x='coordination_mean', y='energy_stability', ax=axes[2], color='forestgreen')\n",
" axes[2].set_title('Coordinación media vs estabilidad energética')\n",
"\n",
"if 'geometry' in df.columns:\n",
" order = df['geometry'].value_counts().index\n",
" sns.countplot(data=df, y='geometry', order=order, ax=axes[3], color='slateblue')\n",
" axes[3].set_title('Frecuencia por geometría')\n",
"\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "eb488202",
"metadata": {},
"source": [
"## 8. Recomendación final para continuar\n",
"\n",
"Para seguir con el proyecto de nanotoxicidad de forma simple y defendible:\n",
"\n",
"1. Conserva este dataset como base estructural.\n",
"2. Agrega una fuente de etiqueta de toxicidad.\n",
"3. Define el problema como clasificación binaria.\n",
"4. Lleva el preprocesamiento a `U6_03_IMPLEMENTACION_PROYECTO.ipynb`.\n",
"5. Integra el safety gate con `external_skills.ai_mining.toxicity_predictor`.\n",
"6. Despliega el mejor modelo con la API de `mi_proyecto_api/`.\n",
"\n",
"Con esto ya tienes una base compatible con la arquitectura de la Unidad 6."
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading
Loading