top of page

COSAS VEREDES

Una de mis aficiones predilectas son los fractales, desde que los vería en la carrera allá por el año 97 – 98 siempre me han fascinado y ahora estoy retomando su estudio de mano de un libro que se publicó a principios de los 90 y que lleva por título Fractals for the classroom. Ya en esta época estaba bastante sólida la Teoría de los Fractales introducida por Benoit Mandelbrot en 1975 y que en 1982 publicó su famoso libro Fractal Geometry of Nature (que por cierto lo hojeaba bastante en aquellos años de carrera en la biblioteca y ahora se lo he pedido a los reyes).

Figura 1 Fotografía de la página 59 de la edición de 1992 del libro Fracta for the classroom

 

Pues bien, el primer libro que menciono bastante recomendable, comienza con un primer capítulo bastante sencillo de seguir y que recoge varios experimentos hechos con aparatos de finales de los 80 seguramente en los que se relaciona el tema fractal con la teoría del caos pero de lo que voy a tratar aquí es de un experimento muy sencillo que espero que todo el lector interesado pueda entender aunque no tenga formación matemática y que espero que le sorprenda.


En este libro se hace referencia al modelo de crecimiento población de Verhulst y que propone que, el crecimiento de la población en t debería ser proporcional a la diferencia entre el conteo de la población hasta el momento y el máximo tamaño alcanzable por dicha población, por tanto propone la siguiente fórmula de crecimiento:

              

 

Fuera de los usos de este modelo que también recibe el nombre de modelo logístico. Lo que me resultó sorprendente es lo que se observa en la figura 1 y es cómo una fórmula iterativa como la anterior que no parece muy complicada con valor inicial 0.01  y r = 3, diese con distintos aparatos (cuya única diferencia era que la Casio tenía hasta 10 cifras decimales y HP llegaba a 12) unas diferencias tan brutales con tan sólo 50 iteraciones, pero no sólo pasaba eso, sino que si se reorganizaban los factores de la anterior fórmula del siguiente modo equivalente:

                        

 

Sucedía esto bajo una misma máquina Casio de la época:

Figura 2 Fotografía de la página 61 de la edición de 1992 del libro Fracta for the classroom


Esto me parecía aún más terrible porque ya las iteraciones 45 se parecen como un huevo a una castaña y visto esto pensé que en los 80, las máquinas eran lo que eran, pero que ahora ya, seguro, que estas cosas no pasan y mucho menos con mi querido R y por tanto me puse con mi moderno HP Notebook de 32 GB a ejecutar el siguiente código en R replicando esta última figura 2:


options(digits=17)

options(scipen=999)

r <- 3

p1 <- 0.01

p2 <- 0.01

 

for (i in c(1:100)){

 

                              p1 <- p1 + r p1 (1 - p1)

                              p2 <- (1 + r) p2 - r p2**2

}

 

print(p1)

print(p2)

 

Pues bien, si ejecuto lo anterior obtengo el siguiente resultado:


Si bien es cierto, que he llegado hasta la iteración 100, ya en la 50 la diferencia no era tan brutal y sólo variaba la segunda cifra decimal, pero a pesar de la potencia de la versión 64 bits de R, el panorama está un poco mal.


Claro, en este momento me pongo a pensar en la risa que les tiene que dar esto a los tontacos de python que odian de forma natural a los que programamos en R (¡Ojo! Hay gente que programa en python muy bien y no son nada tontaco y no odian a lo que programamos en R, a esos los aprecio) y que seguro piensan: “Esto en python no pasa” y que me debería pasar a su lado. Pues, la verdad es que se equivocan, a mí que también me gusta bastante python y para algunas cosas está mejor que R y para otras no, precisamente en este tema, no hay ningún tipo de mejora, y es que tanto R como Python están hechos sobre la misma base de lenguaje C y por tanto “chorpresa!!!”:



Tiene lugar el mismo resultado con la misma disparidad y los mismos decimales. Por tanto, Python no nos va a solucionar la papeleta en este sentido tampoco.


Sobre el ejemplo de la Figura 1 no tenía a mano ninguna calculadora programable (y me tendría que poner a recordar cómo se hacía), pero lo que sí puedo hacer es repetir, por ejemplo en R lo anterior con redondeos en un caso hasta la 10 cifra decimal y en el otro hasta la cifra 12 y observo que pasa lo siguiente:


Con lo que queda más que comprobado que la precisión de la máquina influye en el resultado final.


Así pues, habiendo visto lo anteior y dado todo el hype que veo a mi alrededor de diversos entendidos que nos hacen creer que estamos en una época donde la inteligencia artificial poco le falta para superar al humano, creo que no en todos los casos la convergencia de los algoritmos está suficientemente garantizada, además si lo anterior ocurre con modelos tan sencillos ¿Qué no ocurrirá con los actuales LLM, sin olvidar los modelos de analitica más avanzada tipo xgb y otros? Máxime si se hace uso por lo general de espacios multidimensionales y por tanto no es que las condicioines iniciales sean importantes, sino que como hemos visto, en estos casos la característica de la máquina también lo son.


Finalmente y para no extenderme más, el anterior modelo no es estable claramente con ese parámetro r, si se cambia, dicha inestabilidad a veces se soluciona y otras veces no, así pues, pruébese con r = 2 y todo lo anterior no habrá sido más que un mal sueño …     

  • fjroar
  • 12 may 2024
  • 2 Min. de lectura

Una de las aplicaciones que me sorprendió del curso de Andrew Ng sobre entrenamiento no supervisado, fue la posibilidad de resumir la información dada en una imagen, a partir de todos sus píxeles, en un conjunto resumido de estos que permitiesen destacar ciertas zonas de esta.


Así pues, mientras en dicho curso se toma la fotografía de un pájaro (cuya especie no sé cuál es), a mi me dio por ver qué pasaba cuando tomaba una imagen hecha por mí mismo de algo que me gusta bastante, la fotografía planetaria, por tan tome como referencia la siguiente imagen, no tratada a ver qué es lo que sucedía:

En este caso lo que hice fue adaptar el código de Andrew Ng y preparar una versión más hispanizada que puede consultarse en:

 

                              https://github.com/FJROAR/CLUSTEREDIMAGE

 

Con python en esta ocasión puede leer fácilmente la imagen y tenerla separada por sus matrices, donde haciendo uso la función reshape() de la librería numpy, se preparan los datos para ser pasados por las funciones de ayuda que prepara se preparan en el propio curso (con alguna modificación por mi parte) y que son:

 

  • kMeans_init_centroids(X, K, seed = 155)

  • find_closest_centroids(X, centroids)

  • compute_centroids(X, idx, K)

  • run_kMeans(X, initial_centroids, max_iters=10)

 

Así pues, mediante la llamada run_kMeans se orquesta todo para generar una nueva matriz que de nuevo con la mencionada reshape() se convierte en una nueva matriz tridimensional donde haciendo uso matplotlib.pyplot se llega al siguiente resultado:



Lo que se ha hecho es básicamente aplicar la filosofía del kmeans generando sus centroides y asociándolos a los píxeles que se encuentren más cerca entre sí, de modo que finalmente se crean agrupaciones con menor cantidad de variaciones entre los datos.

 

Este tipo de tratamiento de imágenes es bastante conocido y en las técnicas astrofotográfica, muchas son empleadas para resaltar determinados elementos a partir de una imagen dada, pero a nivel instructivo, se observa que un algoritmo como el kmeans sin saber que lo que se le da es una imagen (o matriz tridimensional) organizada por píxeles y tras hacer un reshape() donde se transforma en una matriz bidimensional de (en este caso) 30.272 filas y 3 columnas, es capaz de asociar adecuadamente los datos para que de nuevo, tras la aplicación inversa, se recupere una nueva imagen con pleno sentido y no un desastre, tomando como lección que cuando en los datos hay patrones, estos son encontrados adecuadamente.


De hecho es sorprendente como cuando aumentamos el número de centroides, el resultado sigue siendo totalmente coherente destacándose claramente rasgos en la imagen que merecen ser también tenidos en cuenta:



Finalmente indicar que el algoritmo es un poco lento y con imágenes de cierto peso, no se ejecuta de modo rápido. Por supuesto hay opciones mejores para realizar lo anterior, no obstante aquí lo que se quería mostrar era simplemente un ejemplo instructivo sobre la capacidad del algoritmo kmeans de hacer asociaciones coherente cuando existen asociaciones entre los datos.

Unas páginas sin duda interesantes si se quiere tener datos astronómicos tanto en riqueza como en calidad son las de Fred Espenak más conocido como Mr Eclipse.


En esta salida voy a explicar cómo hacer un scrapping muy sencillo para la construcción de una tabla utilizable a partir de los datos dados y siempre teniendo en cuenta que el uso de esta información es para fines puramente didácticos o de investigación y por tanto los códigos los cedo libremente para quién le pueda interesar.


Muchos dicen que python para esto de scrapping es mejor y quizás sea cierto, no tengo argumentos contundentes (como sí parece que los tienen algunos pythonistas para tal afirmación), pero es que la librería rvest por su sencillez y versatilidad soluciona bastante problemas y será sobre esta en la que se detalla cómo crear una base de datos a partir de la información existente en https://www.eclipsewise.com



El link anterior permite alcanzar la siguiente información, interesando por tanto tratar adecuadamente el dato a mayor nivel de desagregación que existe en la tabla que está más a la derecha:



Entonces ¿Cómo “leer” y pasar todos los datos a una estructura tabular que permita ser trabajada en aplicaciones posteriores que se quieran realizar? Pues bien, la respuesta a esta pregunta es de lo que va esta entrada.

Más que describir minuciosamente el cómo hago el scrapping que me llevaría a un texto muy largo, lo que voy a hacer es dejar mi github https://github.com/FJROAR/EclipsesDataAccess los códigos que lo realizan y que resultan ser los siguientes:


01_EclipsesScrapping_Lunar.R

                                           01_EclipsesScrapping_Solar.R

 

Por tanto, lo que sí voy a hacer es comentar los pasos principales y por supuesto animo a que los ejecutéis en vuestro local, en menos de 3 minutos tendréis más de 14.000 de predicciones de Eclipses de Luna y de Sol realizados en un período de 6.000 años.


Obviamente, aunque los anteriores datos están disponibles fácilmente en RMoon, éstos se pueden obtener ya en R tecleando simplemente (si tenéis instalada RMoon claro está):


                                            library(RMoon)

                                            dfLuna <- LunarEclipsesDates

                                            dfSol <- SolarEclipsesDates


No obstante, con los códigos proporcionados anteriormente, vosotros podéis realizar y descargar los datos y posteriormente podéis guardarlos en vuestro disco duro con cualquiera de las opciones que ofrece R. Así pues, con dichos códigos, lo que se hace es un scrapping muy parecido en cada uno de ellos perocon ligeras modificaciones por temas de homogeneización de la información. Los pasos seguidos son los siguientes:

 

  • Paso 0. Definición de las funciones de ayuda al scrapping, se distinguen 2 funciones en cada código, una para extraer los datos BC (Before Crist) y otra para los AC (After Crist) en cada caso, sus denominaciones son respectivamente, extraeSigloNegLunar() y extraeSigloPosLunar() y dado un año base inicio de un siglo, extrae los datos de los 100 restantes haciendo uso de la parte esencial del código que es donde su usa rvest:

 

# Leer las tablas de la página

  tables <- url %>%

    read_html() %>%

    html_table()


Nótese que con una expresión anterior, se marca la url que se desea acceder y que también resulta esencial tenerla bien montada y que dependerá de la función a utilizar siendo, en caso de extraeSigloNegLunar() la siguiente:

 

                      url <- paste0("https://eclipsewise.com/lunar/LEcatalog/LE-",

                     yearbase2_aux,"--",yearbase_aux,".html")

 

  • Paso 1. Como los datos están cargados por siglos, se tiene que en cada uno se debe cambiar la url y por tanto hay que crear un bucle pero antes de ello hay que inicializarlo y para ello se toma lo que aquí se considera el año 0 y que en tiempos históricos sería el -1, por tanto como conjunto de datos inicial y por ser el más atípico, se crea un dataset inicial de nominado df con los datos del siglo I BC y que contiene al mencionado año 0

 

  • Paso 2. Se extraen todos los datos BC y se incorporan secuencialmente al dataset inicial df, nótese aquí el uso del vector sequencial siguiente que facilita enormemente la misión controlando los pasos del bucle:

 

seq(100, 2900, 100)

 

  • Paso 3. Se realiza lo mismo con los datos AC agregándose a los anteriores

 

  • Paso 4. Ahora comienza la limpieza y ordenación de más antiguo a más avanzado en el tiempo de los datos, nótese que el año 0000 que será en nuestra base de datos el -0001 se tiene que tratar independientemente.


Nótese que en esta parte del proceso el gran problema es la primera columna donde las fechas no tiene un formato muy adecuado para ser tratado por cualquier lenguaje y lo que se hace es:


Pasar de una estructura como esta:         A otra estructura como la siguiente:



Donde los datos quedan mejor ordenados y ordenables evitando además problemas idiomáticos con las fechas al tenerlas todas en formato (-)yyyy-mm-dd

 

Para acabar una serie de conclusiones:

 

  • No he encontrado gran dificultad usando rvest, los resultados del scrapping los ofrecía en listas que permitían su consulta y así es fácil ver dónde está la información de interés y cómo seleccionarla, dado el gran trabajo de Mr Eclipse de “colgar los datos” de un modo bastante adecuado, el acceso a ellos ha sido bastante sencillo

 

  • Como se puede observar una gran parte del código ha ido a la limpieza y preparación de las fechas. Sobre el tema de fechas y calendarios ya lo he tratado en post anterior, no es un tema trivial si se tratan fecha antiguas, especialmente aquellas de tipo BC

 

  • Con los datos tabulados así tabulados, sí se pueden realizar trabajos estadísticos e incluso astronómicos, por ejemplo para el próximo eclipse solar que se producirá en España el día 12 de Agosto de 2026 se tiene que según Fred Espenak se producirá a las 17:47:06 el momento de máxima ocultación, mientras que si se aplica el algoritmo de Meeus implementado también en RMoon mediante SolarEclipses("2026-08-01") el resultado es 17:47:23 ¿Cuál será el verdadero valor? ¿Quién se aproxima más? Por el momento son estimaciones y la observación final puede corregirlo (hay que notar que según el caso del ejemplo dado en el  libro Astronomial Algorithm del eclipse de 1993-05-21, el algoritmo Meeus es más de 30 segundos más certero que el usado por Fred)

 

  • Finalmente aunque pueda haber pequeñas discrepancias en algunos datos que se tienen que resolver por observación, animo a la comunidad de Data Scientist a ver si son capaces de mejorar las predicciones aquí dadas con una base de tiempo tan sumamente larga, claramente la potencia de un algoritmo matemático y el conocimiento profundo de los movimientos de la Luna parecen superar las modernas técnicas de predicción que por otro lado van enfocadas a resolver otros problemas

© 2021 by Francisco J. Rodríguez Aragón. Proudly created with Wix.com

bottom of page