Es difícil interpretar números

Es conocida la frase (como chiste) que dice que hay tres tipos de engaños: las mentiras, las grandes mentiras, y las estadísticas.

La Estadística, como tal (así con mayúscula al principio), es una rama de la matemática, y como tal uno supondría que es exacta y precisa, y que no da para ambigüedades.

No sólo no es tan así, sino que muchas veces los resultados de usar estadística es una colección de números que hay que saber interpretar.

Este post es sobre un caso conocido como la Paradoja de Simpson (porque Edward H. Simpson la describió en 1951, aunque ya la habían mostrado Karl Pearson en 1899 y Udny Yule en 1903), que muestra un caso sencillo y particular sobre la (mala) interpretación de resultados estadísticos.

La idea acá es que más allá que se enteren de este caso en sí, empecemos a acostumbrarnos y tomar como normal criticar los números que nos muestran como "resultados" en cualquier noticia o publicación, que empecemos a tratar de entender de dónde vienen esos números, cómo fueron calculados, y de ahí validar (o no) las conclusiones que nos muestran.

Entonces, se las cuento.

No, no son estos Simpson.

En los ochenta se hizo un estudio sobre tratamientos para curar piedras en los riñones. Fue un estudio real, con la idea de comparar qué exito tenían en la curación de dicho problema dos tratamientos médicos distintos (involucrando procedimientos quirúrgicos abiertos y cerrados).

Para el estudio se consiguieron 700 personas con este inconveniente, y a la mitad se le hizo un tratamiento (llamaremos A) y a la otra mitad otro (el B). De esos 700, 357 tenían piedras pequeñas en los riñones, y 343 tenían piedras grandes.

La siguiente tabla muestra los cuatro grupos que quedaron (con Gn nombramos cada uno), incluyendo la cantidad de personas a las que se le hizo el tratamiento y la cantidad que se curaron. Por ejemplo el Grupo 1 fue de 87 personas, que tenían piedras chicas y se les realizó el tratamiento A; de ese total se curaron 81 individuos.

Hasta acá tenemos la información pura y dura. No está sometida a ninguna interpretación.

Pasemos ahora a leer los números :)

Poniendo el ojo en los números

Analizando la información

Miremos qué pasó con los pacientes con piedras chicas. Los que recibieron el tratamiento A (grupo 1) se curaron en un 93% (81/87), mientras que los del tratamiento B (grupo 2) se curaron en un 86% (234/270). ¡Es mejor el tratamiento A!

Ahora, los pacientes con piedras grandes. Los que recibieron el tratamiento A (grupo 3) se curaron en un 73% (192/263), mientras que los del tratamiento B (grupo 4) se curaron en un 69% (55/80). ¡Es mejor el tratamiento A!

Conclusión, es mejor el tratamiento A. ¿Cierto?

Bueno. Supongamos que en vez de mirar de forma discriminada por tipo de piedra en los riñones, miramos en su conjunto qué pasó con los distintos tratamientos. Para ambos tratamientos tuvimos 350 pacientes en total. Con el tratamiento A se curaron 273 pacientes (81+192, un 78%), mientras que con el tratamiento B se curaron 289 (234+55, un 83%).

¡Es mejor el tratamiento B! ¿Ciert... pero qué carajo?

¿Es mejor un tratamiento u otro sólo con saber qué tipo de piedras tiene en los riñones? ¿Es mejor no medir el tamaño de las piedras y hacer el tratamiento B, o si ya sabemos el tamaño de las piedras de un paciente, hacer el tratamiento A (más allá de cual sea ese tamaño)?

No puede ser.

La paradoja

En el estudio hay una variable escondida, que es el tamaño de las piedras. Si consideramos esa variable, vemos que influencia fuertemente los tamaños de los grupos. Los grupos 2 y 3 dominan el estudio, mientras que los 1 y 4 son pequeños en comparación.

Esta variable escondida también tiene un efecto en los porcentajes de éxito, incluso es más influyente esta variable escondida que la elección del tratamiento.

En realidad el tratamiento A es mejor que el B, pero al considerar los totales parece lo contrario porque justo tuvimos un montón de piedras grandes (que son más difíciles de curar) con el tratamiento A, mientras que el tratamiento B justo se aplicó en su mayoría con las piedras pequeñas (más fáciles de curar).

En otras palabras, el factor "tamaño de las piedras" supera totalmente al factor "tipo de tratamiento". Sí, el tratamiento A es mejor que el B, pero en realidad la mayor probabilidad de curarse es teniendo piedras pequeñas y no grandes.

Comentarios Imprimir

Fotos, el scanner, y Hewlett Packard siendo tontos

Como les comenté en el post que hablo de que todo el mundo debería aprender programación, estuve escaneando fotos viejas.

En la reunión del 1° de Enero le comenté eso a mi viejo, y él me dijo que también estaba escaneando (otras) fotos, y que con una resolución de 600 dpi estaba logrando verlas bárbaro luego en digital. Seguimos charlando de otras cosas, pero me quedó ese número en la cabeza... ¿qué resolución estaba usando yo?

Un par de días después, en casa, me acordé de esto, y revisé: ¡estaba usando 300 dpi!

¿Por qué? Porque cuando levantaba xsane para escanear algo, las resoluciones que me ofrecía eran 100, 200 y 300. Qué raro, pensé. Por otro lado, yo estaba escaneando con scanimage y especificando la resolución, así que en vez de pasarle 300, le pasé 600, para probar. En ambos casos el resultado fue el mismo, en realidad el escaneo se estaba haciendo a 300 dpi. ¿Podría ser que mi escáner sólo soportara hasta ahí?

Me fijé en las especificaciones que declara Hewlett Packard y vi que (teóricamente) ofrecía mucho más. ¿Entonces? ¿Un bug de software? ¿Dónde?

Para empezar, me puse a buscar donde podía empezar a preguntar o abrir un bug al respecto, y encontré el proyecto mismo de SANE. Entonces abrí un bug ahí, indicando todo lo que me pasaba. Me pidieron más info, me guiaron a actualizar la versión de las bibliotecas usadas, etc.

Terminamos viendo lo que ofrece la impresora misma cuando SANE le pide sus características: dice que es capaz de más, pero que sólo se puede usar hasta 300 dpi :(.

Oh no, ¿y ahora?

No había nada más que hacer a nivel de software en el Linux, pero me dijeron que pruebe con actualizar el firmware de la impresora/escáner mismo, así que fui al sitio de Hewlett Packard, a la parte de soporte, drivers, etc., y no había ningún firmware para descargar :(

Estaba un toque resignado. Pero para probar por probar, pensé que estaría bueno saber cómo se comportaba el escáner desde Windows. Instalé una máquina virtual de Windows en el VirtualBox (todo legal, se pueden bajar de acá para desarrollo, vienen listas para cargar y todo), y me propuse ver que pasaba.

Lo primero que hice (luego de instalar Firefox, realmente), es ir al sitio de Hewlett Packard para bajar los drivers de la impresora/escáner para Windows, y mayúscula fue mi sorpresa al ver que en la lista de cosas para bajar había un nuevo firmware.

Estúpido Hewlett Packard. El firmware figura como que es para una computadora con Windows (¡y no! ¡es para la impresora!) entonces no me lo muestra si voy desde Linux. Encima para cargar el firmware en la impresora/escáner ni hace falta tener Windows (al menos en una de las dos maneras, que es apuntar el navegador a la impresora, loguearse como admin, subir el nuevo archivo de firmware, y listo).

Entonces procedí a actualizar el firmware... no sin cierto cagazo, porque si eso sale mal, SALE MAL. Pero salió todo bien. El primer efecto que vi es que si le pido a SANE que me liste los dispositivos, ahora aparece "uno nuevo", que obviamente es el mismo hardware mostrándose de esta forma.

Si lo elijo, y veo qué resoluciones ofrece, tengo las anteriores más 600 y 1200 dpi. ¡¡Fantástico!!

Y efectivamente, si uso ese dispositivo (tanto desde xsane como con scanimage), las resoluciones altas me dan imágenes más grandes :). Quizás demasiado grandes, sin embargo.

Ejemplos en 100, 300, 600 y 1200 dpi

¿Hasta cuando conviene escalar ahí? Estuve haciendo unas pruebas, y me terminé quedando con 600 dpi: la impresión misma de la foto analógica hace que no tenga ganancia con 1200.

Esto lo vemos en los ejemplos mostrados arriba, que muestran siempre un área del mismo tamaño, 220x500 píxeles: cortes de la misma foto escaneada a esas cuatro resoluciones. A mayor resolución se ve mejor el detalle. Pero al mismo tiempo en la de 600 ya se empieza a ver borroso, y no se gana casi nada al ir a 1200, estamos amplificando el ruido mismo de la foto.

Comentarios Imprimir

Por qué todo el mundo debería saber programar, razón número 1209487.

Yo siempre digo que todo el mundo debería saber programar. No para "vivir de la programación", sino porque es una herramienta más que te puede servir en muchas ocasiones y ahorrarte laburo. Es como saber usar un martillo, o un serrucho. Todo el mundo debería saber.

Esta es una razón más por la que vuelvo a afirmar lo mismo.

En verdad es un ejemplo de cómo, por saber programar, me ahorré muchas (muchas) horas de trabajo manual.

Hace algunos meses, en una visita a mi viejo, volví a ver (en lo que había sido mi habitación) una caja con álbumes de foto en papel. Fotos sacadas con la "cámara de la familia" que tenían mis viejes, una Olympus de medio cuadro (no recuerdo el modelo) que todavía debe andar por ahí pero entró en desuso con el advenimiento de las cámaras digitales.

Tobi y el mar

Decidí llevarme la caja, aprovechando que el año pasado renové la impresora de casa y ahora tiene scanner, con la idea de digitalizarlas.

La caja durmió varias semanas ahí al lado de la computadora hasta que le llegó el turno entre mis tareas/proyectos.

El paso para digitalizarlas era sencillo. Poner una foto-papel en el scanner, usar xsane para bajar la imagen escaneada, abrirla con gimp, recortar la foto, grabar la foto recortada a disco con un número en el nombre del archivo para tener la secuencia.

Sencillo, pero UN EMBOLE.

Algunas optimizaciones eran obvias: poner de a dos fotos en el scanner, o escanear directemente desde gimp. Pero lo que más llevaba tiempo es que a veces el scanner "falla" (no sé si es el hardware, el driver, o qué, pero simplemente se equivoca de medio de entrada y dice que no tiene para escanear), y obviamente el recortar foto por foto no iba a escalar.

Entonces, como siempre que me enfrento a una ardua tarea manual en la computadora, pensé que se podía automatizar.

Lobos marinos en la Península Valdés

Lo primero, el escaneo propiamente dicho. No encontré cómo hacerlo desde Python, así que lo más sencillo fue ejecutar (via subprocess) el utilitario scanimage con los parámetros adecuados (modo color, resolución 300, etc) lo que ya me deja la imagen "cruda" en disco (a menos que falle, como mencioné arriba, en cual caso la solución es simplemente volver a ejecutarlo).

Lo segundo, recortar las fotos. Eso no es más que "detección de bordes", así que busqué cómo usar OpenCV, que para este tipo de tareas hace MAGIA y tiene buena interfaz con Python. Encontré un ejemplo, lo toqueteé un poco, y listo. No funciona el 100% de los casos, porque en algunos casos se confunde (por ejemplo cuando hay un paisaje: corta por la linea del horizonte como si fuese el borde de la foto), pero es sorprendente lo bien que anda cuando anda :)

Terminé armando un script de linea de comandos (que subí a este proyecto), con la suma de las funcionalidades antedichas. Simple, pero muy útil.

Lago Nahuel Huapi

Cuando se ejecuta, nos pide que pongamos las fotos en el scanner. Luego le damos ENTER y por default escanea, recorta las fotos y las grabar como JPEG con un nombre de archivo armado con el día y la hora y el número de foto dentro de esa "escaneada".

Yo recomiendo tener abierto el directorio donde se ejecuta con algún visor de fotografías, para verlas "aparecer". Si vemos que las fotos están correctas, sacamos las del escaner, ponemos otras y le volvemos a dar ENTER. Pero si vemos que alguna está mal detectada (le faltará algun costado, lo cual nos damos cuenta más por el formato de la foto que por su contenido), le damos R y el script volverá a escanear las fotos pero ahora grabará la imagen "cruda" obtenida: un archivo .pnm que podemos abrir con el gimp y recortarla manual luego.

Con este script terminé procesando todos los álbumes un unas pocas horas de trabajo. Weee.

Ahora me falta procesarlas para corregirles la orientación, agruparlas por "evento" (porque en los álbumes estaban un poco mezcladas), tratar de ubicar en qué fecha fueron tomadas, y a compartirlas con la familia.

Comentarios Imprimir

Luego del PyCamp 2021: Video y supermosaico de imagencitas

Dos subproductos del PyCamp me quedaron para después, y este post es sobre eso.

El video

Le puse mucho, mucho amor al video de Cierre de Actividades.

¡Arranqué con la complejidad de que el audio y el video estaban desfasados! Al principio ni se notaba, pero se iba desfasando con el transcurrir del video y al final estaba un par de segundos corrido, lo cual era insoportable de ver.

Lo mejor que encontré para solucionarlo fue separar el video en sí y el audio del video original, toquetear el audio con audacity y luego usar eso. Quedó bastante bien, pero luego cuando laburé mucho con el video me terminé dando cuenta que el desfasaje no era "lineal" y que en algunas partes iba y venía. Eso lo fui corrigiendo ad-hoc durante la edición, quedó bastante bien pero no perfecto. ‾\_(ツ)_/‾.

Y claro, le puse mucha edición. No sólo una carátula y cortar los tiempos muertos, que es lo básico, sino también tratar de que los pases de un lado para el otro fuesen graduales, hacer zoom sobre las personas y la pantalla en lo posible, acelerar algunas partes que no tenía sentido ver lento, e incluso poner links a los proyectos como subtítulo.

Esos mismos links están en la descripción del video, pero también hay ahí una joyita: separación por capítulos, así que pueden saltar directamente al tema que quieran ver. Esto es más mérito de YouTube que mio, ya que arma esos capítulos automáticamente si uno pone en la descripción los tiempos y títulos. Un lujito.

La foto

Uno de los proyectos que llevé al PyCamp fue el de fotos2imagen. Bah, más que proyecto, lo que llevé fue una idea de proyecto, ya que no sólo no había tirado ni una linea de código, sino que tampoco lo había pensado demasiado (o sea, algo ideal para un PyCamp).

Ya se los había comentado en el post del PyCamp, pero acá les dejo la descripción que puse en el listado de actividades propuestas para el evento:

La idea es armar una imagen pero compuesta por miles de fotitos. Seguro que hay cosas por ahí que hacen algo parecido, pero parte de esto es jugar y aprender. Al programa se le pasa una imagen y un directorio con fotos, y arma la imagen con las fotitos.

Ya en casa, y luego de esperar que les participantes del evento terminen de compartir sus fotos, estuve tratando de armar un mosaico con esas imágenes.

Con "tratando" me refiero a ir jugando con los dos parámetros principales del sistema: el tamaño del cuadradito para recortar la imagen principal, y el tamaño de la imagen que se termina poniendo en ese lugar.

En un momento se me complicó porque para lo que quería lograr el programa tardaba muuuucho, así que decidí hacer algo de profiling y me terminé dando cuenta que lo que se llevaba la mayor parte del tiempo era grabar la imagen que se iba construyendo, lo que se hacía para poder mostrar "un progreso visual" del avance. Entonces toqueté el código para que sólo vaya grabando versiones intermedias si se usaba ese progreso visual, y ahí pude generar versiones más detallistas sin esperar una eternidad.

Al final, la que más me gustó es esta foto-mosaico que pueden comparar con la original:

La imagen original y el mosaico en tamaños similares para comparar

Si abren el mosaico y hacen zoom van a poder ver las fotitos con que está compuesta. Por ejemplo:

Zoom detalle de una parte del mosaico

Obvio que pueden hacer aún más zoom y verlas mejor :)

Si se ponen a jugar con fotos2imagen y hacen algunos mosaicos, ¡avisen y compartan!

Comentarios Imprimir

Procesamiento Paralelo de Vectores

Como parte de la investigación para el libro Python en Ámbitos Científicos que estoy escribiendo con Manuel Carlevaro estoy armando una charla sobre Procesamiento Paralelo de Vectores, que muestra distintas técnicas para hacer eso.

El fuerte del código y las técnicas es en Python, pero también hay una versión "serial" y "paralela" hecha en C++ para tener tiempos "base" contra los cuales comparar.

Para las distintas formas voy a mostrar un poquito de código, y las mediciones (va a haber un slide de cómo se midió, que no es trivial, pero es más "documentación de soporte", no pienso invertir tiempo de la charla ahí).

En paralelo

Si gusta, tengo ganas de dar la charla en algún evento presencial, pero como adelanto con Manu organizamos una charla virtual, ahora en Diciembre. Será el jueves 16 a las 19hs, por Zoom.

Están todos invitades, pero les pedimos por favor que llenen este form para conocer mejor la audiencia de la charla (y potencialmente del libro). Un par de días antes les mandaremos por mail el link para conectarse.

¡Nos vemos!

Comentarios Imprimir