
🔬 Día Mundial de la Investigación en Cáncer: Clasificación de Cáncer de Piel (HAM10000) con Teachable Machine y Python (1º Bachillerato)
Cada 24 de septiembre conmemoramos el Día Mundial de la Investigación en Cáncer. Frente a las campañas simbólicas que no aportan soluciones, en el aula respondemos con Ciencia Ciudadana e Inteligencia Artificial aplicada: enseñamos a nuestro alumnado a manipular conjuntos de datos clínicos reales, entrenar modelos de visión artificial y cuestionar con pensamiento crítico la fiabilidad y ética de estas herramientas.
En esta actividad práctica para 1º de Bachillerato (Cultura Digital y Pensamiento Computacional), nos enfrentamos a uno de los repositorios de dermatología más importantes del mundo: el dataset HAM10000 (Skin Cancer MNIST) de Kaggle. Aprendemos a extraer una muestra optimizada sin saturar el disco duro de los equipos del instituto y entrenamos un clasificador de lesiones cutáneas (melanomas vs. lunares benignos) en Google Teachable Machine.
Plaintext
┌─────────────────────────────────────────────────────────────────────────────┐
│ FLUJO DE TRABAJO: DETECCIÓN DE CÁNCER DE PIEL CON IA │
│ │
│ ┌──────────────────┐ Extracción Eficiente ┌───────────────────────────┐ │
│ │ Dataset HAM10000 ├─────────────────────────>│ Script Python + PowerShell│ │
│ │ (Kaggle ~5 GB) │ (Muestra de 18 MB) │ (Filtra 'mel' y 'nv') │ │
│ └──────────────────┘ └─────────────┬─────────────┘ │
│ │ │
│ ┌──────────────────┐ Evaluación a Ciegas ┌─────────────▼─────────────┐ │
│ │ Debate Ético │<─────────────────────────┤ Teachable Machine │ │
│ │ (Falsos Pos/Neg) │ Test con 20 fotos │ (50 Sanas / 50 Enfermas) │ │
│ └──────────────────┘ └───────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
🔗 Recursos y Fuentes de Datos
- Dataset de Kaggle:Skin Cancer MNIST: HAM10000 (~5 GB).
- Entorno de IA:Google Teachable Machine (Proyecto de Imagen).
- Claves de Diagnóstico del Dataset (
HAM10000_metadata.csv):mel= Melanoma (Cáncer / Enferma).nv= Nevus melanocítico / Lunar común benigno (Sano).
🛠️ Paso 1: Gestión Eficiente de Datos en el Aula (Script Python)
El dataset completo ocupa más de 5 Gigabytes, lo que colapsaría el almacenamiento de los ordenadores del aula. Además, las 10.000 imágenes están mezcladas sin categorizar en carpetas.
Para resolverlo, ejecutamos este script en Python desde PowerShell (abriendo la consola directamente en la carpeta con la tecla Alt + D y escribiendo powershell). El script lee los metadatos en memoria y extrae únicamente 120 imágenes (~18 MB) directamente desde el archivo archive.zip sin descomprimirlo todo.
Python
import os
import zipfile
import pandas as pd
archivo_zip = 'archive.zip'
print('⏳ Leyendo los metadatos de HAM10000 sin descomprimir todo el ZIP...')
with zipfile.ZipFile(archivo_zip, 'r') as z:
# 1. Leer el CSV de diagnósticos directamente desde la memoria
with z.open('HAM10000_metadata.csv') as f:
df = pd.read_csv(f)
# 2. Seleccionar 60 lunares sanos ('nv') y 60 melanomas ('mel')
sanas_ids = df[df['dx'] == 'nv']['image_id'].unique()[:60]
enfermas_ids = df[df['dx'] == 'mel']['image_id'].unique()[:60]
sanas_train, sanas_test = set(sanas_ids[:50]), set(sanas_ids[50:60])
enfermas_train, enfermas_test = set(enfermas_ids[:50]), set(enfermas_ids[50:60])
mapa_destinos = {}
for img_id in sanas_train:
mapa_destinos[f'{img_id}.jpg'] = os.path.join(
'entrenamiento', 'sanas', f'{img_id}.jpg'
)
for img_id in sanas_test:
mapa_destinos[f'{img_id}.jpg'] = os.path.join(
'test', 'sanas', f'{img_id}.jpg'
)
for img_id in enfermas_train:
mapa_destinos[f'{img_id}.jpg'] = os.path.join(
'entrenamiento', 'enfermas', f'{img_id}.jpg'
)
for img_id in enfermas_test:
mapa_destinos[f'{img_id}.jpg'] = os.path.join(
'test', 'enfermas', f'{img_id}.jpg'
)
# 3. Crear carpetas de destino en el disco
for c in [
os.path.join('entrenamiento', 'sanas'),
os.path.join('entrenamiento', 'enfermas'),
os.path.join('test', 'sanas'),
os.path.join('test', 'enfermas'),
]:
os.makedirs(c, exist_ok=True)
# 4. Extraer únicamente los 120 archivos seleccionados
extraidas = 0
for ruta_interna in z.namelist():
nombre = os.path.basename(ruta_interna)
if nombre in mapa_destinos:
with open(mapa_destinos[nombre], 'wb') as out:
out.write(z.read(ruta_interna))
extraidas += 1
print(
f'✅ ¡Listo! Se han extraído {extraidas} imágenes distribuidas en'
" 'entrenamiento' y 'test'."
)
💻 Paso 2: Entrenamiento del Modelo en Google Teachable Machine
Una vez ejecutado el script, dispondremos de la siguiente estructura en el equipo:
Plaintext
📁 entrenamiento/
├── 📁 sanas/ (50 imágenes de lunares benignos)
└── 📁 enfermas/ (50 imágenes de melanomas)
📁 test/
├── 📁 sanas/ (10 imágenes ciegas)
└── 📁 enfermas/ (10 imágenes ciegas)
Guía para el Alumnado en la Plataforma:
- Accede a Teachable Machine y selecciona “Proyecto de imagen” > “Modelo de imagen estándar”.
- Configura las dos clases de entrenamiento:
- Clase 1: Renómbrala como
Sana / Nevus Benignoy arrastra las 50 fotos de la carpetaentrenamiento/sanas. - Clase 2: Renómbrala como
Enferma / Melanomay arrastra las 50 fotos de la carpetaentrenamiento/enfermas.
- Clase 1: Renómbrala como
- Haz clic en “Preparar modelo” (Train Model) y espera a que el navegador procese los patrones visuales (bordes, asimetría, pigmentación).
- Fase de Test: Desactiva la webcam en el panel de vista previa, cambia a opción “Archivo” y prueba una a una las imágenes guardadas en las carpetas de
test. Comprueba si el modelo identifica correctamente las lesiones que nunca ha visto antes.
⚕️ Debate Ético y Científico: La Regla ABCDE vs. Visión Artificial
Tras evaluar la precisión del modelo en la fase de test, abrimos el debate en el aula sobre los riesgos de la automatización en dermatología:
1. Falsos Negativos vs. Falsos Positivos en Oncología
- Falso Negativo (Riesgo Vital): La IA diagnostica como “Sana” una lesión que en realidad es un melanoma. El paciente se confía, no acude al especialista y el tumor hace metástasis.
- Falso Positivo: La IA alerta de un melanoma ante un lunar completamente inofensivo. Provoca angustia psicológica en el paciente y saturación de las listas de espera en sanidad pública por biopsias innecesarias.
2. La Regla Clínica ABCDE del Melanoma
Enseñar al alumnado qué analiza la medicina tradicional frente a los patrones de píxeles de la red neuronal:
- Asimetría (la mitad de la lesión no coincide con la otra).
- Bordes irregulares o deshilachados.
- Color no uniforme (sombras marrones, negras, rojas o azuladas).
- Diámetro superior a 6 mm.
- Evolución (cambios en forma, tamaño o sangrado con el tiempo).
3. Sesgos de Datos y Fototipos Cutáneos
Discutimos la importancia de la representatividad en los datasets de IA: la mayoría de imágenes de repositorios públicos corresponden a pieles claras (fototipos I y II de Fitzpatrick). Un modelo entrenado únicamente con estas muestras puede perder eficacia drásticamente al evaluar lesiones en pieles más pigmentadas.
🎓 Vinculación Curricular (1º de Bachillerato)
- Materia: Cultura Digital y Pensamiento Computacional / Programación y Computación / Biología.
- Saberes Básicos (LOMLOE):
- Tratamiento de Datos y Scripting: Automatización mediante código en Python para el filtrado eficiente de grandes conjuntos de datos.
- Principios de Inteligencia Artificial: Extracción de características visuales, matriz de confusión, sesgo muestral y sobreajuste.
- Ciudadanía Digital y Ética Tecnológica: Evaluación de los límites del diagnóstico automatizado y responsabilidad social de la tecnología.


