top of page

COSAS VEREDES

  • 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:

ree

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:


ree

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:


ree

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


ree

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:


ree

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:


ree

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

 
 
 

En ocasiones hay cálculos que se tienen asumidos como muy sencillos pero que si no se tiene cuidado, para determinados casos, se puede caer en errores de bulto.


Uno de esos cálculos es ¿Cuál es la diferencia de días entre 2 fechas? Y quizás el papa Gregorio XIII tiene mucho que ver en eso como trataré de mostrar a continuación.


ree

 

Como imagino que sabéis estoy inmerso en la construcción de una biblioteca sobre la luna denominada RMoon y dado que tengo que emplear fechas antiguas, me he encontrado con problemas de cálculo que pensaba que en R estaban asumidos y veo que no. El hecho es que cuando se ponen las líneas:

 

diferencia1 <- difftime(as.Date("1582-10-04"), as.Date("1582-10-15"), units = "days")

diferencia1

 

El resultado que se obtiene es:

Time difference of -11 days

 

Y claramente está mal, es decir, no hay 11 días de diferencia entre esas 2 fechas si no tan sólo 1 y es que difftime no tiene en cuenta la reforma del calendario que llevo a cabo el citado papa. Para más inri, antes del 1582-10-04, las fechas que se suelen usar en la mayoría de los libros de historia (de nuestro entorno cultural) van con un criterio de Calendario Juliano, mientras que las que son posteriores se cambia el criterio a Gegoriano y ¿Qué significa esto? Pues cualquiera puede leer que Colón llegó a américo más o menos el 12 de Octubre de 1492 que por cierto, es cuando se celebra el día de la hispanidad y demás pero si nos fiamos de Rbase, dicha fecha ocurrió exactamente en un número de días entre el 4 de Octubre de 1582 y el 12 de Octubre de 1492 de 32963 días tal y como se puede observar haciendo simplemente:


difftime(as.Date("1582-10-04"), as.Date("1492-10-12"), units = "days")


Y entonces si se echa el tiempo atrás se llegaría a la conclusión de que la llegada sería el 13 y no el 12 ya que interfiere el año 1500 que según el calendario gregoriano no es bisiesto mientras que sí lo es en el Juliano, de hecho si se aplica la anterior fórmula a:


difftime(as.Date("1500-03-01"), as.Date("1500-02-28"), units = "days")


Se obtiene que la diferencia es 1 (y da error si se trata de usar “1500-02-29” ya que considera que no existe).


El no hacer el adecuado cambio de calendario antes y después de la reforma gregoriana tiene sus repercusiones, porque a nivel astronómico las definiciones de inicio de la cuenta de los días julianos cambiaría y además hay fases lunares e incluso eclipses que caen en 29 de Febreros y que están datados como tales y cambiarían.


En general todas los cálculos de diferencias de fechas pasan por una conversión a días Julianos, difftime es fiable desde 1582-10-15, pero si se mezclan fechas antes y después de esa fecha, deben usarse cálculos más finos que tengan en cuenta las restricciones mencionadas, así por ejemplo bajo la librería RMoon se ha creado la siguiente función que permite además hacer uso de matrices y calcular fechas simultáneamente por lo que vamos a ver varios ejemplos a la vez:


library(RMoon)

M1 <-matrix(nrow = 3, ncol = 6)

M2 <-matrix(nrow = 3, ncol = 6)

M1[1, ] <- c(1582,  10, 4, 0, 0, 0)

M1[2, ] <- c(1582, 10, 4, 0, 0, 0)

M1[3, ] <- c(1492, 10,  12,  0,  0, 0)

 

M2[1, ] <- c(1582, 10, 15, 0, 0, 0)

M2[2, ] <- c(1582, 10,  16, 0,  0,  0)

M2[3, ] <- c(1582,  10,  4,  0, 0, 0)


DiffDaysMeeus(M1, M2)


En este caso destaca el último valor que es un día más desde el 1582-10-04 hasta 1492-10-12, y ese día existió, se tiene que considerar porque era el calendario Juliano el imperante en la época, eliminarlo provocaría pequeños desfases que si se usan para hacer cálculos astronómicos (o incluso históricos) pueden tener su importancia.


Para finalizar, que nadie se asuste y se ponga a corregir los programas de R que haya hecho con difftime() sobre todo si los cálculos son con fechas recientes, para éstas no hay problemas.  Por otro lado, la anterior función está relacionada con otras de Rbase como julian.Date() y julian() que usan bases distintas a las consideradas por expertos como Jean Meeus y la comunidad astronómica, por lo que visto lo que pasa con difftime() si os vais a fechas remotas, tened cuidado con los cálculos y los criterios que se utilicen al usar también las mencionadas funciones.

 

 
 
 

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

bottom of page