En el ámbito del análisis de datos y el aprendizaje automático, uno de los desafíos más relevantes es determinar qué algoritmo ofrece la mayor precisión en problemas de regresión aplicados a series de tiempo, considerando el tiempo de entrenamiento como un factor crítico. La eficacia de un modelo no solo se mide por su capacidad para hacer predicciones precisas, sino también por el tiempo que requiere para entrenarse adecuadamente.
En este contexto, surge la pregunta: ¿Qué algoritmo logra la mayor precisión relativa al tiempo de entrenamiento en problemas de regresión sobre datos de series de tiempo, y cómo varía esta eficiencia entre diferentes frameworks, como PyTorch, TensorFlow, Keras y Scikit-learn?
Con el objetivo de abordar esta cuestión, llevaremos a cabo un análisis comparativo entre los frameworks mencionados, enfocados en identificar cuál de ellos permite un entrenamiento más eficiente sin comprometer la eficacia del modelo. Para establecer un criterio de evaluación, consideraremos como umbral de eficacia aquellos modelos que logren alcanzar valores superiores a 0.6 en su desempeño. De este modo, buscamos no solo optimizar el tiempo de entrenamiento, sino también garantizar resultados satisfactorios en la calidad de las predicciones.
Este conjunto de datos está diseñado para abordar problemas relacionados con Inteligencia Artificial (IA), donde se analizan algoritmos, frameworks, tipos de problemas y tipos de datos. Los valores numéricos representan métricas de desempeño, como la precisión o el tiempo de entrenamiento de los modelos. Diccionario de variables:
1.Algorithm (categórica): Tipo de algoritmo de IA utilizado(‘Neural Network’, ‘Random Forest’, ‘SVM’, ‘K-Means’).
2.Framework (categórica): Framework o biblioteca utilizada para la implementación del modelo de IA(‘TensorFlow’, ‘PyTorch’, ‘Keras’, ‘Scikit-learn’).
3.Problem_Type (categórica): Tipo de problema abordado por el modelo.(‘Classification’, ‘Regression’, ‘Clustering’).
4.Dataset_Type (categórica): Tipo de datos utilizados en el entrenamiento del modelo(‘Image’, ‘Text’, ‘Tabular’, ‘Time Series’.).
5.Accuracy (numérica, continua): Precisión del modelo en el conjunto de prueba (entre 0 y 1).
6.Precision (numérica, continua): Precisión del modelo (valor entre 0 y 1).
7.Recall (numérica, continua): Sensibilidad o capacidad del modelo para identificar correctamente los positivos (entre 0 y 1).
8.F1_Score (numérica, continua): Medida armónica entre precisión y recall (entre 0 y 1).
9.Training_Time (numérica, continua): Tiempo de entrenamiento del modelo en horas.
10.Date (fecha): Fecha en la que se realizó la evaluación del modelo, cubriendo el último año.
Para que quede más claro, expresemos todas las variables mediante una
tabla con la función kable
:
# Crear un dataframe con la información de las variables
variables_df <- data.frame(
Variable = c("Algorithm", "Framework", "Problem_Type", "Dataset_Type",
"Accuracy", "Precision", "Recall", "F1_Score",
"Training_Time", "Date"),
Naturaleza = c("Cualitativa/Categórica", "Cualitativa/Categórica", "Cualitativa/Categórica", "Cualitativa/Categórica",
"Cuantitativa/Numérica", "Cuantitativa/Numérica",
"Cuantitativa/Numérica", "Cuantitativa/Numérica",
"Cuantitativa/Numérica", "Cualitativa/Catégorica"),
Nivel_de_Medición = c("Nominal", "Nominal", "Nominal", "Nominal",
"Continua", "Continua", "Continua", "Continua",
"Continua", "Ordinal"),
Criterio_de_Clasificación = c("Tipo de algoritmo de IA", "Framework o biblioteca utilizada",
"Tipo de problema", "Tipo de datos",
"Precisión del modelo (0 a 1)",
"Precisión del modelo (0 a 1)",
"Capacidad de identificar positivos (0 a 1)",
"Medida armónica (0 a 1)",
"Tiempo en horas", "Fecha")
)
# Quitar los guiones bajos de los nombres de las columnas si fuera necesario
names(variables_df) <- gsub("_", " ", names(variables_df))
# Mostrar la tabla con kable y aplicar estilos
kable(variables_df, caption = "Tabla 1: Clasificación de Variables", align = "c") %>% # Alinear columnas al centro
kable_styling(full_width = TRUE, bootstrap_options = c("striped", "hover", "condensed", "responsive"), font_size = 15, fixed_thead = TRUE) %>%
column_spec(1, bold = TRUE, width = "10em") %>% # Resaltar la columna de Variable
column_spec(2, width = "12em") %>% # Ajustar ancho de Naturaleza
column_spec(3, width = "12em") %>% # Ajustar ancho de Nivel de Medición
column_spec(4, width = "22em") %>% # Ajustar ancho de Criterio de Clasificación
row_spec(0, bold = TRUE, background = "#ccc", color = "black") # Resaltar la primera fila (encabezado)
Variable | Naturaleza | Nivel de Medición | Criterio de Clasificación |
---|---|---|---|
Algorithm | Cualitativa/Categórica | Nominal | Tipo de algoritmo de IA |
Framework | Cualitativa/Categórica | Nominal | Framework o biblioteca utilizada |
Problem_Type | Cualitativa/Categórica | Nominal | Tipo de problema |
Dataset_Type | Cualitativa/Categórica | Nominal | Tipo de datos |
Accuracy | Cuantitativa/Numérica | Continua | Precisión del modelo (0 a 1) |
Precision | Cuantitativa/Numérica | Continua | Precisión del modelo (0 a 1) |
Recall | Cuantitativa/Numérica | Continua | Capacidad de identificar positivos (0 a 1) |
F1_Score | Cuantitativa/Numérica | Continua | Medida armónica (0 a 1) |
Training_Time | Cuantitativa/Numérica | Continua | Tiempo en horas |
Date | Cualitativa/Catégorica | Ordinal | Fecha |
Primero, iniciaremos haciendo un resumen de la base de datos con la
función summary
:
summary(Base)
## Algorithm Framework Problem_Type Dataset_Type
## Length:560 Length:560 Length:560 Length:560
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
##
## Accuracy Precision Recall F1_Score
## Min. :0.5038 Min. :0.4019 Min. :0.3001 Min. :0.4000
## 1st Qu.:0.6236 1st Qu.:0.5632 1st Qu.:0.4819 1st Qu.:0.5515
## Median :0.7578 Median :0.7195 Median :0.6493 Median :0.7086
## Mean :0.8779 Mean :0.8129 Mean :0.7486 Mean :0.8122
## 3rd Qu.:0.8824 3rd Qu.:0.8596 3rd Qu.:0.8404 3rd Qu.:0.8438
## Max. :9.7181 Max. :9.7320 Max. :9.3662 Max. :9.3740
## NA's :39 NA's :19 NA's :20 NA's :20
## Training_Time Date
## Min. : 0.1032 Min. :2023-03-08 11:26:21.07
## 1st Qu.: 1.2441 1st Qu.:2023-07-26 05:26:21.07
## Median : 2.4347 Median :2023-12-12 23:26:21.07
## Mean : 2.9910 Mean :2023-12-12 23:26:21.07
## 3rd Qu.: 3.8131 3rd Qu.:2024-04-30 17:26:21.07
## Max. :46.9856 Max. :2024-09-17 11:26:21.07
## NA's :20
La dimension de la base de datos es:
dim(Base)
## [1] 560 10
Es decir, se compone de 560 filas y 10 columnas.
Para comenzar, eliminaremos las entradas de la base de datos que contengan datos faltantes. Esto garantizará que solo se consideren registros completos y relevantes para el análisis, evitando cualquier sesgo o distorsión en los resultados debido a la falta de información clave.
Veamos la cantidad de NA mediante un gráfico:
missmap(Base, col = c("red", "blue"), legend = TRUE)
El gráfico nos indica que existe un 2% de información faltante. El primer indicio que nos permite aplicar la técnica de eliminación, es que la muestra o el porcentaje de valores valtantes no es mayor al 5%, por lo que, no se perdera mucha información; el segundo indicio, la base de datos fue generada aleatoriamente, lo que hace que los datos sean del tipo MCAR, por lo tanto, la eliminación no nos llevará a resultados sesgados. Analizemos cuantos NA hay:
# Calcular el número de NAs
na_counts <- sapply(Base[, c("Algorithm", "Framework", "Precision", "Training_Time",
"Problem_Type", "Dataset_Type", "Accuracy",
"Recall", "F1_Score", "Date")],
function(x) sum(is.na(x)))
# Usar una única llamada a cat() para mostrar el texto y resultados en un solo bloque
cat("Cantidad de NA o entradas vacías por columna:\n\n",
paste(names(na_counts), na_counts, sep = ": ", collapse = "\n"))
## Cantidad de NA o entradas vacías por columna:
##
## Algorithm: 0
## Framework: 0
## Precision: 19
## Training_Time: 20
## Problem_Type: 0
## Dataset_Type: 0
## Accuracy: 39
## Recall: 20
## F1_Score: 20
## Date: 0
# Crear un dataframe con la información de las variables
variables_df <- data.frame(
Variable = c("Algorithm", "Framework", "Problem_Type", "Dataset_Type",
"Accuracy", "Precision", "Recall", "F1_Score",
"Training_Time", "Date"),
Cantidad = c("0", "0", "0", "0",
"39", "19",
"20", "20",
"20", "0"),
Porcentaje = c("0", "0", "0", "0",
round(((39 * 100) / 560), 3), round(((19 * 100) / 560), 3),
round(((20 * 100) / 560), 3), round(((20 * 100) / 560), 3),
round(((20 * 100) / 560), 3), "0")
)
# Quitar los guiones bajos de los nombres de las columnas si fuera necesario
names(variables_df) <- gsub("_", " ", names(variables_df))
# Mostrar la tabla con kable y aplicar estilos
kable(variables_df, caption = "Tabla 2: Cantidad de NA por Variable", align = "c") %>% # Alinear columnas al centro
kable_styling(full_width = TRUE, bootstrap_options = c("striped", "hover", "condensed", "responsive"), font_size = 15, fixed_thead = TRUE) %>%
column_spec(1, bold = TRUE, width = "10em") %>% # Resaltar la columna de Variable
column_spec(2, width = "10em") %>% # Ajustar ancho de Naturaleza
column_spec(3, width = "10em") %>% # Ajustar ancho de Nivel de Medición
row_spec(0, bold = TRUE, background = "#ccc", color = "black") # Resaltar la primera fila (encabezado)
Variable | Cantidad | Porcentaje |
---|---|---|
Algorithm | 0 | 0 |
Framework | 0 | 0 |
Problem_Type | 0 | 0 |
Dataset_Type | 0 | 0 |
Accuracy | 39 | 6.964 |
Precision | 19 | 3.393 |
Recall | 20 | 3.571 |
F1_Score | 20 | 3.571 |
Training_Time | 20 | 3.571 |
Date | 0 | 0 |
La variable porcentaje es basada en el total de filas que hay, en otras palabras, representa la cantidad de NA, por ejemplo, los 39 datos faltantes representa cierto porcentaje del 560.
Sabiendo lo anterior, apliquemos la función na.omit
para
eliminar los NA de la base de datos.
Base_omit <- na.omit(Base)
head(Base_omit)
## # A tibble: 6 × 10
## Algorithm Framework Problem_Type Dataset_Type Accuracy Precision Recall
## <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
## 1 Neural Network Keras Clustering Image 0.885 0.595 0.969
## 2 SVM Keras Clustering Text 0.842 0.842 0.875
## 3 SVM Scikit-lea… Regression Tabular 0.723 0.686 0.301
## 4 K-Means PyTorch Regression Image 0.637 0.626 7.45
## 5 Neural Network Scikit-lea… Regression Image 0.713 0.676 0.480
## 6 SVM PyTorch Regression Image 0.897 9.73 0.781
## # ℹ 3 more variables: F1_Score <dbl>, Training_Time <dbl>, Date <dttm>
A continuación, verifiquemos la distribución de cada variable númerica para ver si hay un cambio o no.
# Cargar las librerías necesarias
library(ggplot2)
library(gridExtra)
# Crear una función para generar los histogramas
crear_histogramas <- function(data_original, data_sin_na, variable, nombre_variable) {
# Histograma de datos originales
ggp1 <- ggplot(data_original, aes_string(x = variable)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "#FFB3B3", color = "#FF6666", alpha = 0.8) +
geom_density(color = "#FF3333", size = 1) +
ggtitle(paste("Distribución original de", nombre_variable)) +
xlab(nombre_variable) + ylab("Densidad") +
theme_light() +
theme(plot.title = element_text(size = 14, hjust = 0.5, margin = margin(b = 10))) +
xlim(0, 2) # Ajusta este límite según tus datos
# Histograma de datos sin NA
ggp2 <- ggplot(data_sin_na, aes_string(x = variable)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "#B3D9FF", color = "#66B2FF", alpha = 0.8) +
geom_density(color = "#3399FF", size = 1) +
ggtitle(paste("Distribución sin NA de", nombre_variable)) +
xlab(nombre_variable) + ylab("Densidad") +
theme_light() +
theme(plot.title = element_text(size = 14, hjust = 0.5, margin = margin(b = 10))) +
xlim(0, 2) # Ajusta este límite según tus datos
# Mostrar ambos gráficos uno al lado del otro
grid.arrange(ggp1, ggp2, ncol = 2)
}
# Eliminar los NA una vez y guardar en una variable
Base_omit <- na.omit(Base)
# Lista de variables cuantitativas y sus nombres legibles
variables <- list(
Accuracy = "Accuracy",
Precision = "Precision",
Recall = "Recall",
F1_Score = "F1 Score",
Training_Time = "Training Time"
)
# Iterar sobre las variables y generar los histogramas
for (var in names(variables)) {
crear_histogramas(Base, Base_omit, var, variables[[var]])
cat("\n\n\n\n\n\n\n\n")
}
A partir de los histogramas, se puede observar que las distribuciones de las variables Accuracy, Precision, Recall, F1 Score, Training Time permacenen prácticamente inalteradas antes y después de la eliminación de los valores faltantes (NA). Lo que nos indica que la eliminación de los datos no afectó significativamente la estructura de los datos, por ende, nos permite trabajar con una base de datos más limpia y sin sesgos ni problemas derivados de los valores faltantes. Con la base de datos sin NA, podemos avanzar hacia los siguientes pasos de este análisis con mayor confianza en la viabilidad de los datos.
missmap(Base_omit, col = c("red", "blue"), legend = TRUE)
Después de la eliminación ya no queda ningún valor faltante en la base de datos.
combinations <- expand.grid(
Algorithm = c("Neural Network", "Random Forest", "SVM", "K-Means"),
Framework = c("TensorFlow", "PyTorch", "Keras", "Scikit-learn"),
stringsAsFactors = FALSE
)
combination_counts <- data.frame(Algorithm = character(), Framework = character(), Count = integer(), stringsAsFactors = FALSE)
for (i in 1:nrow(combinations)) {
algo <- combinations$Algorithm[i]
framework <- combinations$Framework[i]
count <- nrow(Base_omit[Base_omit$Algorithm == algo & Base_omit$Framework == framework, ])
combination_counts <- rbind(combination_counts, data.frame(Algorithm = algo, Framework = framework, Count = count))
}
combination_counts <- combination_counts %>%
mutate(Percentage = Count / sum(Count) * 100)
plot <- plot_ly(combination_counts,
labels = ~paste(Algorithm, "y", Framework),
values = ~Percentage,
type = 'pie',
textinfo = 'none',
insidetextorientation = 'radial') %>%
layout(title = "Distribución de combinaciones de Algoritmos y Frameworks", showlegend = TRUE)
plot
El análisis de la distribución de combinaciones de algoritmos y
frameworks muestra una visualización clara que permite identificar qué
combinaciones son más y menos frecuentes en el conjunto de datos. Al
observar el gráfico de torta, se puede notar que ciertas combinaciones,
como K-Means
con TensorFlow
con el
8.24% del total, son las más comunes, lo que podría
indicar una tendencia en la preferencia de estas herramientas en la
comunidad. Además, la identificación de combinaciones menos frecuentes
podría resaltar oportunidades para explorar modelos alternativos que,
aunque no sean ampliamente utilizados, podrían ofrecer resultados
competitivos. Asimismo, la identificación de combinaciones menos
frecuentes, como Random Forest
con Keras
con
solo el 3.83%. Este análisis preliminar proporciona un
contexto valioso que complementa la evaluación de eficacia y precisión
en los filtros posteriores.
A continuación, haremos un resumen estadístico de las variables catégoricas, creando tablas de frecuencia para tener una representación mejor a la hora de analizar. Cable aclarar que no se tomará en cuenta la variable Date para términos de eficiencia.
# Frecuencia absoluta
freq_absoluta <- table(Base$Algorithm)
# Frecuencia relativa
freq_relativa <- prop.table(freq_absoluta)
# Crear un data frame con las frecuencias absolutas y relativas
tabla_frecuencias <- data.frame(
Framework = names(freq_absoluta),
Frecuencia_Absoluta = as.numeric(freq_absoluta),
Frecuencia_Relativa = round(100 * as.numeric(freq_relativa), 2) # Convertir a porcentaje
)
# Quitar los guiones bajos de los nombres de las columnas si fuera necesario
names(tabla_frecuencias) <- gsub("_", " ", names(tabla_frecuencias))
# Mostrar la tabla con kable y aplicar estilos
tabla_alg <- kable(tabla_frecuencias, caption = "Tabla 3: Frecuencia de Algorithm", align = "c") %>% # Alinear columnas al centro
kable_styling(full_width = TRUE, bootstrap_options = c("striped", "hover", "condensed", "responsive"), font_size = 15, fixed_thead = TRUE) %>%
column_spec(1, bold = TRUE, width = "10em") %>% # Resaltar la columna de Variable
column_spec(2, width = "10em") %>% # Ajustar ancho de Naturaleza
column_spec(3, width = "10em") %>% # Ajustar ancho de Nivel de Medición
row_spec(0, bold = TRUE, background = "#9eb5d9", color = "black") # Resaltar la primera fila (encabezado)
# Gráfico de barras corregido
G1 <- ggplot(tabla_frecuencias, aes(x = Framework, y = `Frecuencia Absoluta`)) +
geom_bar(width = 0.7, stat = "identity", position = position_dodge(), fill = "#9eb5d9", color="black") +
ylim(c(0, max(tabla_frecuencias$`Frecuencia Absoluta`) + 10)) + # Ajustar el límite superior del eje Y para mejor visualización
labs(x = "Tipo de Algoritmo", y = "Frecuencias (Porcentajes)") +
# Añadir las etiquetas de texto
geom_text(aes(label = paste0(`Frecuencia Absoluta`, " (", `Frecuencia Relativa`, "%)")),
vjust = -0.9, color = "black", hjust = 0.5,
position = position_dodge(0.9), size = 4.5) +
# Estilo del texto en el eje X
theme(axis.text.x = element_text(angle = 0, vjust = 1, hjust = 1)) +
theme_bw(base_size = 16) +
# Añadir el título del gráfico
facet_wrap(~"Distribución de Algorithm")
# Mostrar el gráfico
tabla_alg
Framework | Frecuencia Absoluta | Frecuencia Relativa |
---|---|---|
K-Means | 163 | 29.11 |
Neural Network | 135 | 24.11 |
Random Forest | 126 | 22.50 |
SVM | 136 | 24.29 |
G1
La tabla nos muestra la distribución de las frecuencias de la variable Algorithm. Podemos destacar:
# Frecuencia absoluta
freq_absoluta <- table(Base$Framework)
# Frecuencia relativa
freq_relativa <- prop.table(freq_absoluta)
# Crear un data frame con las frecuencias absolutas y relativas
tabla_frecuencias <- data.frame(
Framework = names(freq_absoluta),
Frecuencia_Absoluta = as.numeric(freq_absoluta),
Frecuencia_Relativa = round(100 * as.numeric(freq_relativa), 2) # Convertir a porcentaje
)
# Quitar los guiones bajos de los nombres de las columnas si fuera necesario
names(tabla_frecuencias) <- gsub("_", " ", names(tabla_frecuencias))
# Mostrar la tabla con kable y aplicar estilos
tabla_alg <- kable(tabla_frecuencias, caption = "Tabla 3: Frecuencia de Framework", align = "c") %>% # Alinear columnas al centro
kable_styling(full_width = TRUE, bootstrap_options = c("striped", "hover", "condensed", "responsive"), font_size = 15, fixed_thead = TRUE) %>%
column_spec(1, bold = TRUE, width = "10em") %>% # Resaltar la columna de Variable
column_spec(2, width = "10em") %>% # Ajustar ancho de Naturaleza
column_spec(3, width = "10em") %>% # Ajustar ancho de Nivel de Medición
row_spec(0, bold = TRUE, background = "#d8bfd8", color = "black") # Resaltar la primera fila (encabezado)
# Gráfico de barras corregido
G2 <- ggplot(tabla_frecuencias, aes(x = Framework, y = `Frecuencia Absoluta`)) +
geom_bar(width = 0.7, stat = "identity", position = position_dodge(), fill = "#d8bfd8", color="black") +
ylim(c(0, max(tabla_frecuencias$`Frecuencia Absoluta`) + 10)) + # Ajustar el límite superior del eje Y para mejor visualización
labs(x = "Tipo de Framework", y = "Frecuencias (Porcentajes)") +
# Añadir las etiquetas de texto
geom_text(aes(label = paste0(`Frecuencia Absoluta`, " (", `Frecuencia Relativa`, "%)")),
vjust = -0.9, color = "black", hjust = 0.5,
position = position_dodge(0.9), size = 4.5) +
# Estilo del texto en el eje X
theme(axis.text.x = element_text(angle = 0, vjust = 1, hjust = 1)) +
theme_bw(base_size = 16) +
# Añadir el título del gráfico
facet_wrap(~"Distribución de Framework")
# Mostrar el gráfico
tabla_alg
Framework | Frecuencia Absoluta | Frecuencia Relativa |
---|---|---|
Keras | 124 | 22.14 |
PyTorch | 135 | 24.11 |
Scikit-learn | 134 | 23.93 |
TensorFlow | 167 | 29.82 |
G2
El gráfico muestra la distribución de la frecuencia de uso de diferentes frameworks de machine learning en el dataset. Podemos destacar lo siguiente:
# Frecuencia absoluta
freq_absoluta <- table(Base$Problem_Type)
# Frecuencia relativa
freq_relativa <- prop.table(freq_absoluta)
# Crear un data frame con las frecuencias absolutas y relativas
tabla_frecuencias <- data.frame(
Framework = names(freq_absoluta),
Frecuencia_Absoluta = as.numeric(freq_absoluta),
Frecuencia_Relativa = round(100 * as.numeric(freq_relativa), 2) # Convertir a porcentaje
)
# Quitar los guiones bajos de los nombres de las columnas si fuera necesario
names(tabla_frecuencias) <- gsub("_", " ", names(tabla_frecuencias))
# Mostrar la tabla con kable y aplicar estilos
tabla_alg <- kable(tabla_frecuencias, caption = "Tabla 3: Frecuencia de Problem Type", align = "c") %>% # Alinear columnas al centro
kable_styling(full_width = TRUE, bootstrap_options = c("striped", "hover", "condensed", "responsive"), font_size = 15, fixed_thead = TRUE) %>%
column_spec(1, bold = TRUE, width = "10em") %>% # Resaltar la columna de Variable
column_spec(2, width = "10em") %>% # Ajustar ancho de Naturaleza
column_spec(3, width = "10em") %>% # Ajustar ancho de Nivel de Medición
row_spec(0, bold = TRUE, background = "#bdecb6", color = "black") # Resaltar la primera fila (encabezado)
# Gráfico de barras corregido
G3 <- ggplot(tabla_frecuencias, aes(x = Framework, y = `Frecuencia Absoluta`)) +
geom_bar(width = 0.7, stat = "identity", position = position_dodge(), fill = "#bdecb6", color="black") +
ylim(c(0, max(tabla_frecuencias$`Frecuencia Absoluta`) + 10)) + # Ajustar el límite superior del eje Y para mejor visualización
labs(x = "Tipo de Problema", y = "Frecuencias (Porcentajes)") +
# Añadir las etiquetas de texto
geom_text(aes(label = paste0(`Frecuencia Absoluta`, " (", `Frecuencia Relativa`, "%)")),
vjust = -0.9, color = "black", hjust = 0.5,
position = position_dodge(0.9), size = 4.5) +
# Estilo del texto en el eje X
theme(axis.text.x = element_text(angle = 0, vjust = 1, hjust = 1)) +
theme_bw(base_size = 16) +
# Añadir el título del gráfico
facet_wrap(~"Distribución de Problem Type")
# Mostrar el gráfico
tabla_alg
Framework | Frecuencia Absoluta | Frecuencia Relativa |
---|---|---|
Classification | 175 | 31.25 |
Clustering | 196 | 35.00 |
Regression | 189 | 33.75 |
G3
El gráfico muestra la distribución de los tipos de problemas abordados en el dataset. Podemos destacar las siguientes conclusiones:
Clustering es el tipo de problema más común en el dataset (es la moda) con una frecuencia del 35% (196 casos). Esto indica que una proporción considerable de los modelos está orientada hacia la agrupación de datos.
Regression ocupa el segundo lugar, con un 33.75% (189 casos), lo que sugiere que también es un enfoque muy utilizado en los modelos de este conjunto de datos.
Classification tiene la menor frecuencia relativa, con un 31.25% (175 casos), aunque sigue siendo un tipo de problema importante dentro del dataset.
En general, no existe una diferencia abismal entre cada uno de los problemas. Es decir, son todos muy comúnes.
# Frecuencia absoluta
freq_absoluta <- table(Base$Dataset_Type)
# Frecuencia relativa
freq_relativa <- prop.table(freq_absoluta)
# Crear un data frame con las frecuencias absolutas y relativas
tabla_frecuencias <- data.frame(
Framework = names(freq_absoluta),
Frecuencia_Absoluta = as.numeric(freq_absoluta),
Frecuencia_Relativa = round(100 * as.numeric(freq_relativa), 2) # Convertir a porcentaje
)
# Quitar los guiones bajos de los nombres de las columnas si fuera necesario
names(tabla_frecuencias) <- gsub("_", " ", names(tabla_frecuencias))
# Mostrar la tabla con kable y aplicar estilos
tabla_alg <- kable(tabla_frecuencias, caption = "Tabla 3: Frecuencia de Data Type", align = "c") %>% # Alinear columnas al centro
kable_styling(full_width = TRUE, bootstrap_options = c("striped", "hover", "condensed", "responsive"), font_size = 15, fixed_thead = TRUE) %>%
column_spec(1, bold = TRUE, width = "10em") %>% # Resaltar la columna de Variable
column_spec(2, width = "10em") %>% # Ajustar ancho de Naturaleza
column_spec(3, width = "10em") %>% # Ajustar ancho de Nivel de Medición
row_spec(0, bold = TRUE, background = "#c78676", color = "black") # Resaltar la primera fila (encabezado)
# Gráfico de barras corregido
G3 <- ggplot(tabla_frecuencias, aes(x = Framework, y = `Frecuencia Absoluta`)) +
geom_bar(width = 0.7, stat = "identity", position = position_dodge(), fill = "#c78676", color="black") +
ylim(c(0, max(tabla_frecuencias$`Frecuencia Absoluta`) + 10)) + # Ajustar el límite superior del eje Y para mejor visualización
labs(x = "Tipo de Dato", y = "Frecuencias (Porcentajes)") +
# Añadir las etiquetas de texto
geom_text(aes(label = paste0(`Frecuencia Absoluta`, " (", `Frecuencia Relativa`, "%)")),
vjust = -0.9, color = "black", hjust = 0.5,
position = position_dodge(0.9), size = 4.5) +
# Estilo del texto en el eje X
theme(axis.text.x = element_text(angle = 0, vjust = 1, hjust = 1)) +
theme_bw(base_size = 16) +
# Añadir el título del gráfico
facet_wrap(~"Distribución de Data Type")
# Mostrar el gráfico
tabla_alg
Framework | Frecuencia Absoluta | Frecuencia Relativa |
---|---|---|
Image | 157 | 28.04 |
Tabular | 136 | 24.29 |
Text | 143 | 25.54 |
Time Series | 124 | 22.14 |
G3
El gráfico muestra los diferentes tipos de datos utilizados en la base de datos. Se puede destacar lo siguiente:
A continuación, haremos un resumen estadístico de las variables númericas, analizando las medidades de tendencia central. Cable aclarar que no se tomará en cuenta la variable Date para términos de eficiencia.
# Filtrar solo las variables numéricas
Base_numericas <- Base_omit %>% select_if(is.numeric)
# Crear una tabla con media, mediana, varianza, desviación estándar, rango, mínimo y máximo
resumen_estadistico <- data.frame(
Variable = colnames(Base_numericas),
Media = sapply(Base_numericas, function(x) round(mean(x, na.rm = TRUE), 4)),
Mediana = sapply(Base_numericas, function(x) round(median(x, na.rm = TRUE), 4)),
Moda = sapply(Base_numericas, function(x) round(mfv(x)[1], 4)),
Varianza = sapply(Base_numericas, function(x) round(var(x, na.rm = TRUE), 4)),
Desviacion_Estandar = sapply(Base_numericas, function(x) round(sd(x, na.rm = TRUE), 4)),
Minimo = sapply(Base_numericas, function(x) round(min(x, na.rm = TRUE), 4)),
Maximo = sapply(Base_numericas, function(x) round(max(x, na.rm = TRUE), 4)),
Rango = sapply(Base_numericas, function(x) round(max(x, na.rm = TRUE) - min(x, na.rm = TRUE), 4)),
Q1 = sapply(Base_numericas, function(x) round(quantile(x, 0.25, na.rm = TRUE), 4)),
Q3 = sapply(Base_numericas, function(x) round(quantile(x, 0.75, na.rm = TRUE), 4))
)
# Cambiar el nombre de la columna 'Desviacion_Estandar' a 'Desviación Estándar'
colnames(resumen_estadistico) <- gsub("Desviacion_Estandar", "Desviación Estándar", colnames(resumen_estadistico))
rownames(resumen_estadistico) <- NULL
# Mostrar la tabla usando kable con más espacio entre las columnas
kable(resumen_estadistico, caption = "Resumen Estadístico de Variables Cuantitativas") %>%
kable_styling(full_width = TRUE, bootstrap_options = c("striped", "hover", "condensed", "responsive"), font_size = 16) %>%
column_spec(1, bold = TRUE, width = "15em") %>% # Aumentar el ancho de la columna Variable
column_spec(2, width = "8em") %>%
column_spec(3, width = "8em") %>%
column_spec(4, width = "8em") %>%
column_spec(5, width = "8em") %>%
column_spec(6, width = "10em") %>%
column_spec(7, width = "10em") %>%
column_spec(8, width = "8em") %>%
column_spec(9, width = "8em") %>%
column_spec(10, width = "8em") %>%
column_spec(11, width = "8em") %>%
# Aumentar el ancho de las demás columnas
row_spec(0, bold = TRUE, background = "#ccc", color = "black") # Resaltar el encabezado de la tabla
Variable | Media | Mediana | Moda | Varianza | Desviación Estándar | Minimo | Maximo | Rango | Q1 | Q3 |
---|---|---|---|---|---|---|---|---|---|---|
Accuracy | 0.8458 | 0.7490 | 0.5038 | 0.6751 | 0.8217 | 0.5038 | 9.7181 | 9.2143 | 0.6183 | 0.8698 |
Precision | 0.8387 | 0.7275 | 0.4031 | 0.8664 | 0.9308 | 0.4031 | 9.7320 | 9.3289 | 0.5661 | 0.8670 |
Recall | 0.7611 | 0.6513 | 0.3001 | 0.6912 | 0.8314 | 0.3001 | 9.3662 | 9.0661 | 0.4898 | 0.8365 |
F1_Score | 0.8014 | 0.7031 | 0.4000 | 0.7655 | 0.8749 | 0.4000 | 9.3740 | 8.9740 | 0.5486 | 0.8396 |
Training_Time | 3.0598 | 2.4809 | 0.1032 | 21.5892 | 4.6464 | 0.1032 | 46.9856 | 46.8824 | 1.2982 | 3.8446 |
Aquí hemos creado una tabla con las medidas, rangos, y cálculos más importantes del resumen estadístico. Vamos a interpretarlos:
# Crear un data frame con las medias y desviaciones estándar
data_grafico <- data.frame(
Variable = colnames(Base_numericas),
Media = sapply(Base_numericas, mean, na.rm = TRUE),
Desviacion = sapply(Base_numericas, sd, na.rm = TRUE)
)
# Gráfico de barras con líneas de error utilizando ggplot
grafico_barras <- ggplot(data_grafico, aes(x = Variable, y = Media)) +
geom_bar(stat = "identity", fill = "steelblue", alpha = 0.8) +
geom_errorbar(aes(ymin = Media - Desviacion, ymax = Media + Desviacion), width = 0.2) +
ylab("Media con Desviación Estándar") +
xlab("Variable") +
ggtitle("Media y Desviación Estándar por Métrica") +
theme_minimal()
# Convertir el gráfico a interactivo con plotly
grafico_interactivo <- ggplotly(grafico_barras)
# Mostrar el gráfico interactivo
grafico_interactivo
El gráfico nos muestra la media y la distribución estándar de cada variable. Las variables Accuracy, F1 Score, Precision, Recall tienen una media similar, lo cual es lógico puesto que están limitadas con un rango de 0-1. Por otro lado, Training Time tiene una media más alta puesto que no esta limitada de alguna manera. Respecto a la desviación estándar, Accuracy, F1 Score, Precision, Recall no presentan una distribución tan alta, sin embargo, training time varia considerablemente en comparación con las demás métricas.
1.Algorithm (categórica): Tipo de algoritmo de IA utilizado(‘Neural Network’, ‘Random Forest’, ‘SVM’, ‘K-Means’).
cat("Frecuencia de Algoritmos:\n")
## Frecuencia de Algoritmos:
print(table(Base_omit$Algorithm))
##
## K-Means Neural Network Random Forest SVM
## 135 113 95 105
barplot(table(Base_omit$Algorithm), main="Frecuencia de Algoritmos", col="lightblue")
En la gráfica de frecuencia de algoritmos, se observa que K-Means es el algoritmo más utilizado con una frecuencia superior a 140 casos. Este alto uso puede deberse a su simplicidad y su aplicabilidad en problemas de agrupamiento. Neural Networks, con aproximadamente 120 casos, también es un algoritmo popular, especialmente en tareas que requieren modelado avanzado y reconocimiento de patrones complejos. Por otro lado, Random Forest y SVM muestran frecuencias similares, ambas alrededor de 100. Estos algoritmos, aunque robustos para clasificación y regresión, parecen ser algo menos utilizados en comparación con K-Means y Neural Networks, lo que podría reflejar su mayor complejidad.
2.Framework (categórica): Framework o biblioteca utilizada para la implementación del modelo de IA(‘TensorFlow’, ‘PyTorch’, ‘Keras’, ‘Scikit-learn’).
cat("Frecuencia de Frameworks:\n")
## Frecuencia de Frameworks:
print(table(Base_omit$Framework))
##
## Keras PyTorch Scikit-learn TensorFlow
## 97 111 98 142
barplot(table(Base_omit$Framework), main="Frecuencia de Frameworks", col="lightgreen")
Podemos observar que TensorFlow es el framework más empleado, con una frecuencia cercana a los 150 casos. Este resultado es consistente con la popularidad de TensorFlow en la industria, dado su amplio soporte para el desarrollo de modelos de aprendizaje profundo y su comunidad activa. PyTorch y Scikit-learn presentan frecuencias similares, alrededor de los 120 casos cada uno. PyTorch, conocido por su flexibilidad y eficiencia en la investigación, y Scikit-learn, por su facilidad de uso en modelos más tradicionales de machine learning, parecen ser opciones preferidas en varios contextos. Keras, con aproximadamente 100 casos, es el menos utilizado, probablemente porque muchos desarrolladores prefieren TensorFlow, que ahora incorpora Keras como una API de alto nivel.
3.Problem_Type (categórica): Tipo de problema abordado por el modelo.(‘Classification’, ‘Regression’, ‘Clustering’).
cat("Frecuencia de Tipos de Problemas:\n")
## Frecuencia de Tipos de Problemas:
print(table(Base_omit$Problem_Type))
##
## Classification Clustering Regression
## 139 153 156
barplot(table(Base_omit$Problem_Type), main="Frecuencia de Tipos de Problemas", col="lightcoral")
Existe un comportamiento equilibrado entre los tres tipos de problemas principales abordados por los modelos: Classification, Clustering y Regression, cada uno con una frecuencia cercana a 150. Este equilibrio refleja una diversidad de aplicaciones, lo que sugiere que se abordan tanto tareas de clasificación supervisada como de predicción continua y agrupamiento no supervisado. La Clasificación es clave en aplicaciones como el reconocimiento de patrones y el análisis de texto, mientras que la Regresión es fundamental para predicciones cuantitativas, como el pronóstico de ventas o precios. El uso frecuente de Agrupamiento indica un enfoque fuerte en el análisis exploratorio de datos.
4.Dataset_Type (categórica): Tipo de datos utilizados en el entrenamiento del modelo(‘Image’, ‘Text’, ‘Tabular’, ‘Time Series’.).
cat("Frecuencia de Tipos de Datos:\n")
## Frecuencia de Tipos de Datos:
print(table(Base_omit$Dataset_Type))
##
## Image Tabular Text Time Series
## 122 112 117 97
barplot(table(Base_omit$Dataset_Type), main="Frecuencia de Tipos de Datos", col="lightyellow")
El gráfico muestra que los datos tipo “Image
” son los
más utilizados en el entrenamiento de modelos, con una frecuencia
cercana a 130, mientras que los tipos
“Tabular
” y “Text
” tienen frecuencias
similares, alrededor de 110, indicando un uso
significativo pero menor que el de imágenes. Los datos tipo
“Time Series
” son los menos comunes, con una frecuencia
cercana a 90. Aunque hay una distribución relativamente
equilibrada entre los diferentes tipos de datos, se observa una ligera
preferencia hacia el uso de datos tipo imagen.
5.Accuracy (numérica, continua): Precisión del modelo en el conjunto de prueba (entre 0 y 1).
cat("Análisis de Accuracy:\n")
## Análisis de Accuracy:
hist(Base_omit$Accuracy, main="Distribucion de Accuracy", col="skyblue", breaks=20)
shapiro_test <- shapiro.test(Base_omit$Accuracy)
cat("Prueba de Normalidad (Shapiro-Wilk):\n")
## Prueba de Normalidad (Shapiro-Wilk):
print(shapiro_test)
##
## Shapiro-Wilk normality test
##
## data: Base_omit$Accuracy
## W = 0.22539, p-value < 2.2e-16
library(moments)
skewness_acc <- skewness(Base_omit$Accuracy, na.rm = TRUE)
cat("Simetría (Skewness) de Accuracy:\n")
## Simetría (Skewness) de Accuracy:
print(skewness_acc)
## [1] 8.121139
qqnorm(Base_omit$Accuracy)
qqline(Base_omit$Accuracy, col = "red")
El análisis de la variable Accuracy muestra una distribución altamente asimétrica y no normal. El histograma revela que la mayoría de los valores de precisión del modelo se agrupan en rangos muy bajos, lo que indica que el modelo tiende a tener una precisión limitada en el conjunto de prueba. El Q-Q plot confirma la falta de normalidad, ya que los datos se desvían significativamente de la línea de referencia, especialmente en las colas, sugiriendo la presencia de valores extremos (outliers). Esto es corroborado por el test de normalidad de Shapiro-Wilk, que arroja un valor de p extremadamente bajo (p < 2.2e-16), rechazando la hipótesis de normalidad. Además, la alta simetría positiva (skewness de 7.84) indica que la distribución está sesgada hacia la derecha, lo que refuerza la idea de que existen pocos casos con alta precisión, mientras que la mayoría están concentrados en valores bajos.
6.Precision (numérica, continua): Precisión del modelo (valor entre 0 y 1).
cat("Análisis de Precision:\n")
## Análisis de Precision:
hist(Base_omit$Precision, main="Distribucion de Precision", col="lightpink", breaks=20)
shapiro_test <- shapiro.test(Base_omit$Precision)
cat("Prueba de Normalidad (Shapiro-Wilk):\n")
## Prueba de Normalidad (Shapiro-Wilk):
print(shapiro_test)
##
## Shapiro-Wilk normality test
##
## data: Base_omit$Precision
## W = 0.26457, p-value < 2.2e-16
skewness_prec <- skewness(Base_omit$Precision, na.rm = TRUE)
cat("Simetría (Skewness) de Precision:\n")
## Simetría (Skewness) de Precision:
print(skewness_prec)
## [1] 7.305445
qqnorm(Base_omit$Precision)
qqline(Base_omit$Precision, col = "red")
El análisis de la variable Precision muestra una distribución marcadamente asimétrica, donde la mayoría de los valores se concentran en la parte inferior, cerca de 0, tal como se ilustra en el histograma. Esta gráfica revela que los modelos evaluados tienen predominantemente una precisión baja, con pocos casos que se extienden hacia valores más altos. La larga cola a la derecha del histograma indica la presencia de algunos valores atípicos que logran puntuaciones más elevadas, pero que son significativamente menos frecuentes. Además, el alto valor de skewness (7.85) refuerza la observación de esta asimetría positiva, indicando que la mayoría de las observaciones se agrupan en la parte inferior de la escala, mientras que unos pocos casos alcanzan valores más altos.
7.Recall (numérica, continua): Sensibilidad o capacidad del modelo para identificar correctamente los positivos (entre 0 y 1).
cat("Análisis de Recall:\n")
## Análisis de Recall:
hist(Base_omit$Recall, main="Distribucion de Recall", col="lightgreen", breaks=20)
shapiro_test <- shapiro.test(Base_omit$Recall)
cat("Prueba de Normalidad (Shapiro-Wilk):\n")
## Prueba de Normalidad (Shapiro-Wilk):
print(shapiro_test)
##
## Shapiro-Wilk normality test
##
## data: Base_omit$Recall
## W = 0.31101, p-value < 2.2e-16
skewness_rec <- skewness(Base_omit$Recall, na.rm = TRUE)
cat("Simetría (Skewness) de Recall:\n")
## Simetría (Skewness) de Recall:
print(skewness_rec)
## [1] 7.071078
qqnorm(Base_omit$Recall)
qqline(Base_omit$Recall, col = "red")
La variable Recall muestra una distribución altamente asimétrica y no normal, con una asimetría positiva significativa (Skewness = 7.10). La mayoría de los valores se concentran cerca de 0. Sin embargo, existen algunos valores atípicos altos, lo que refleja que en ciertas instancias el modelo logra un mejor desempeño. El Q-Q plot confirma la desviación significativa de la normalidad, en las colas, mientras que la prueba de Shapiro-Wilk (W = 0.31686, p < 2.2e-16) refuerza el rechazo de la hipótesis de normalidad. Por tanto, este comportamiento sugiere la necesidad de aplicar transformaciones o modelos robustos que no asuman una distribución normal para analizar y mejorar el rendimiento del modelo respecto a esta métrica.
8.F1_Score (numérica, continua): Medida armónica entre precisión y recall (entre 0 y 1).
cat("Análisis de F1_Score:\n")
## Análisis de F1_Score:
hist(Base_omit$F1_Score, main="Distribucion de F1_Score", col="lightgray", breaks=20)
shapiro_test <- shapiro.test(Base_omit$F1_Score)
cat("Prueba de Normalidad (Shapiro-Wilk):\n")
## Prueba de Normalidad (Shapiro-Wilk):
print(shapiro_test)
##
## Shapiro-Wilk normality test
##
## data: Base_omit$F1_Score
## W = 0.25105, p-value < 2.2e-16
skewness_f1 <- skewness(Base_omit$F1_Score, na.rm = TRUE)
cat("Simetría (Skewness) de F1_Score:\n")
## Simetría (Skewness) de F1_Score:
print(skewness_f1)
## [1] 7.718489
qqnorm(Base_omit$F1_Score)
qqline(Base_omit$F1_Score, col = "red")
El análisis de la variable F1_Score, que mide el balance entre precisión y recall, revela una distribución altamente asimétrica y no normal. El modelo tiene un bajo rendimiento en cuanto a la precisión y el recall combinados para la mayoría de las instancias. Al igual que en el análisis de Recall, algunos valores atípicos aparecen en el extremo superior, aunque son poco frecuentes. El valor de Skewness es extremadamente alto (7.64), lo que sugiere una asimetría positiva, mientras que la prueba de normalidad Shapiro-Wilk (W = 0.24849, p < 2.2e-16) confirma que los datos no siguen una distribución normal.
9.Training_Time (numérica, continua): Tiempo de entrenamiento del modelo en horas.
cat("Análisis de Training_Time:\n")
## Análisis de Training_Time:
hist(Base_omit$Training_Time, main="Distribucion de Training Time", col="orange", breaks=20)
shapiro_test <- shapiro.test(Base_omit$Training_Time)
cat("Prueba de Normalidad (Shapiro-Wilk):\n")
## Prueba de Normalidad (Shapiro-Wilk):
print(shapiro_test)
##
## Shapiro-Wilk normality test
##
## data: Base_omit$Training_Time
## W = 0.33971, p-value < 2.2e-16
skewness_tt <- skewness(Base_omit$Training_Time, na.rm = TRUE)
cat("Simetría (Skewness) de Training Time:\n")
## Simetría (Skewness) de Training Time:
print(skewness_tt)
## [1] 7.532192
qqnorm(Base_omit$Training_Time)
qqline(Base_omit$Training_Time, col = "red")
El análisis del tiempo de entrenamiento (Training_Time) revela que los datos no siguen una distribución normal, como lo indica la prueba de normalidad de Shapiro-Wilk (W = 0.3478, p-valor < 2.2e-16), lo que nos lleva a rechazar la hipótesis nula de normalidad. La simetría (skewness) de 7.55 muestra una distribución sesgada a la derecha. Esto se refleja en el histograma, donde la mayor frecuencia de datos se concentra en los tiempos más bajos. Además, el gráfico Q-Q normal respalda esta conclusión, mostrando desviaciones notables en los extremos, especialmente en la cola izquierda, confirmando la no normalidad de los datos.
10.Date (fecha): Fecha en la que se realizó la evaluación del modelo, cubriendo el último año.
cat("Análisis de Date:\n")
## Análisis de Date:
plot(Base_omit$Date, Base_omit$Accuracy, main="Accuracy a lo largo del tiempo", xlab="Fecha", ylab="Accuracy", col="blue", type="o")
El gráfico de dispersión muestra la precisión del modelo desde julio de 2023 hasta julio de 2024. En el eje horizontal se representan las fechas y en el eje vertical los valores de precisión, que varían de 0 a 10. La mayoría de los puntos de datos se agrupan cerca del valor de precisión cero, indicando que en general la precisión del modelo ha sido baja durante este período. Sin embargo, hay algunos valores atípicos que alcanzan hasta 10, lo que sugiere que en ciertas ocasiones el modelo ha logrado una precisión significativamente alta. Estos picos de alta precisión, aunque esporádicos, destacan momentos en los que el modelo ha funcionado excepcionalmente bien.
Para comenzar, imputaremos según sea necesario las entradas de la base de datos que contengan datos atípicos. Esto garantizará que solo se consideren registros completos y relevantes para el análisis, evitando cualquier sesgo o distorsión en los resultados.
Comenzaremos graficando los histogramas y caja de bigotes para verificar la presencia de datos atípicos:
# Librería necesaria
library(ggplot2)
library(patchwork)
# Crear gráficos
graf1 <- ggplot(data.frame(value = Base_omit$Accuracy), aes(x = value)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "#99CCFF", color = "black", alpha = 0.7) +
stat_function(fun = dnorm, args = list(mean = mean(Base_omit$Accuracy), sd = sd(Base_omit$Accuracy)), color = "red", size = 1) +
ggtitle("Histograma Acurracy") +
xlab("Acurracy") + ylab("Densidad") +
theme_minimal() +
theme(plot.title = element_text(size = 14, hjust = 0.5))
box1 <- ggplot(data.frame(value = Base_omit$Accuracy), aes(x = "", y = value)) +
geom_boxplot(fill = "#99CCFF", color = "black", outlier.colour = "red", outlier.size = 3, width = 0.4) +
ggtitle("Boxplot de Accuracy") +
ylab("Accuracy") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 14))
# Repetimos para Precision, Recall, F1_Score y Training_Time (mismo formato)
graf2 <- ggplot(data.frame(value = Base_omit$Precision), aes(x = value)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "#99CCFF", color = "black", alpha = 0.7) +
stat_function(fun = dnorm, args = list(mean = mean(Base_omit$Precision), sd = sd(Base_omit$Precision)), color = "red", size = 1) +
ggtitle("Histograma Precision") +
xlab("Precision") + ylab("Densidad") +
theme_minimal() +
theme(plot.title = element_text(size = 14, hjust = 0.5))
box2 <- ggplot(data.frame(value = Base_omit$Precision), aes(x = "", y = value)) +
geom_boxplot(fill = "#99CCFF", color = "black", outlier.colour = "red", outlier.size = 3, width = 0.4) +
ggtitle("Boxplot de Precision") +
ylab("Precision") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 14))
graf3 <- ggplot(data.frame(value = Base_omit$Recall), aes(x = value)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "#99CCFF", color = "black", alpha = 0.7) +
stat_function(fun = dnorm, args = list(mean = mean(Base_omit$Recall), sd = sd(Base_omit$Recall)), color = "red", size = 1) +
ggtitle("Histograma Recall") +
xlab("Recall") + ylab("Densidad") +
theme_minimal() +
theme(plot.title = element_text(size = 14, hjust = 0.5))
box3 <- ggplot(data.frame(value = Base_omit$Recall), aes(x = "", y = value)) +
geom_boxplot(fill = "#99CCFF", color = "black", outlier.colour = "red", outlier.size = 3, width = 0.4) +
ggtitle("Boxplot de Recall") +
ylab("Recall") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 14))
graf4 <- ggplot(data.frame(value = Base_omit$F1_Score), aes(x = value)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "#99CCFF", color = "black", alpha = 0.7) +
stat_function(fun = dnorm, args = list(mean = mean(Base_omit$F1_Score), sd = sd(Base_omit$F1_Score)), color = "red", size = 1) +
ggtitle("Histograma F1 Score") +
xlab("F1 Score") + ylab("Densidad") +
theme_minimal() +
theme(plot.title = element_text(size = 14, hjust = 0.5))
box4 <- ggplot(data.frame(value = Base_omit$F1_Score), aes(x = "", y = value)) +
geom_boxplot(fill = "#99CCFF", color = "black", outlier.colour = "red", outlier.size = 3, width = 0.4) +
ggtitle("Boxplot de F1 Score") +
ylab("F1 Score") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 14))
graf5 <- ggplot(data.frame(value = Base_omit$Training_Time), aes(x = value)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "#99CCFF", color = "black", alpha = 0.7) +
stat_function(fun = dnorm, args = list(mean = mean(Base_omit$Training_Time), sd = sd(Base_omit$Training_Time)), color = "red", size = 1) +
ggtitle("Histograma Training Time") +
xlab("Training Time") + ylab("Densidad") +
theme_minimal() +
theme(plot.title = element_text(size = 14, hjust = 0.5))
box5 <- ggplot(data.frame(value = Base_omit$Training_Time), aes(x = "", y = value)) +
geom_boxplot(fill = "#99CCFF", color = "black", outlier.colour = "red", outlier.size = 3, width = 0.4) +
ggtitle("Boxplot de Training Time") +
ylab("Training Time") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 14))
(graf1 + box1)
Se pueden ver a simple vista 6 valores atípicos por encima del tercer cuartil. Estos outliers podrían influir de manera significativa en la media y otros estadísticos. Además, la distribución de Accuracy presenta un sesgo hacia la izquierda, con la mayoría de los valores concentrados cerca de 0.
(graf2 + box2)
Se observan varios valores atípicos por encima del tercer cuartil (aproximadamente 7) en el boxplot de Precision. Estos outliers podrían estar afectando la media y otros estadísticos importantes, lo que será considerado en los análisis posteriores. La distribución de Precision está claramente sesgada hacia la izquierda, con la mayoría de los valores concentrados cerca de 0.
(graf3 + box3)
A simple vista se observan 7 valores atípicos por encima del tercer cuartil. La distribución está visiblemente sesgada hacia la izquierda, con la mayoría de los valores concentrados cerca de 0.
(graf4 + box4)
Se observan 6 valores atípicos por encima del tercer cuartil. Al igual que los otros estos outliers podrían estar afectando la media y otros estadísticos importantes. La distribución está sesgada hacia la izquierda, con la mayoría de los valores concentrados cerca de 0.
(graf5 + box5)
Se ven 6 valores atípicos por encima del tercer cuartil. También presenta un sesgo hacia la izquierda y como los otros la mayoría de sus valores concentrados cerca de 0.
Gracias a los histogramas y al diagrama de caja de bigotes nos dimos cuenta de dos cosas: Ninguna de las variables númericas sigue una distribución normal (Probado con Shapiro), y existen a simple vista valores atípicos. Con todo esto, haremos una prueba para comprobar la presencia de estos valores. Descartamos la prueba de Grubbs; porque nuestros datos no siguen una distribución normal; la prueba de Dixon; ya que la muestra es mayor a 25. Por lo que, proseguiremos con la prueba de Rosner:
test <- rosnerTest(Base_omit$Accuracy, k = 10)
test$all.stats
## i Mean.i SD.i Value Obs.Num R.i+1 lambda.i+1 Outlier
## 1 0 0.8457621 0.8216572 9.7180796 15 10.798076 3.833870 TRUE
## 2 1 0.8259135 0.7069241 8.2944274 196 10.564803 3.833271 TRUE
## 3 2 0.8091679 0.6125670 7.9008618 232 11.577010 3.832670 TRUE
## 4 3 0.7932315 0.5124044 7.1274667 110 12.361788 3.832068 TRUE
## 5 4 0.7789652 0.4151830 5.9788899 239 12.524415 3.831464 TRUE
## 6 5 0.7672273 0.3338475 5.2598564 77 13.457130 3.830859 TRUE
## 7 6 0.7570629 0.2565839 5.2005460 112 17.317859 3.830252 TRUE
## 8 7 0.7469870 0.1449455 0.9997069 200 1.743551 3.829643 FALSE
## 9 8 0.7464126 0.1446072 0.9983484 422 1.742208 3.829033 FALSE
## 10 9 0.7458388 0.1442696 0.9981670 99 1.749004 3.828422 FALSE
Basándonos en la prueba de Rosner, identificamos 7 valores atípicos en las observaciones: 15, 196, 232, 110, 239, 77 y 112. Estos valores, al estar por encima de 1 en una métrica que debe estar dentro del rango 0-1, no son correctos y afectan negativamente las medidas de tendencia central como la media.
test <- rosnerTest(Base_omit$Precision, k = 10)
test$all.stats
## i Mean.i SD.i Value Obs.Num R.i+1 lambda.i+1 Outlier
## 1 0 0.8386718 0.9308086 9.732008 6 9.55442 3.833870 TRUE
## 2 1 0.8187762 0.8310328 9.674189 223 10.65591 3.833271 TRUE
## 3 2 0.7989210 0.7180191 8.932619 250 11.32797 3.832670 TRUE
## 4 3 0.7806431 0.6061150 7.044472 439 10.33439 3.832068 TRUE
## 5 4 0.7665353 0.5286183 6.207645 111 10.29308 3.831464 TRUE
## 6 5 0.7542529 0.4614512 5.760933 433 10.84986 3.830859 TRUE
## 7 6 0.7429256 0.3955383 5.432777 241 11.85688 3.830252 TRUE
## 8 7 0.7322910 0.3266570 4.145151 157 10.44784 3.829643 TRUE
## 9 8 0.7245345 0.2834703 4.075645 288 11.82174 3.829033 TRUE
## 10 9 0.7169010 0.2341822 4.055990 96 14.25851 3.828422 TRUE
Basándonos en la prueba de Rosner, identificamos 10 valores atípicos, lo cual difiere de los 7 valores atípicos previamente observados en el boxplot. Esta diferencia puede deberse a la mayor sensibilidad de la prueba de Rosner para detectar outliers. Los 10 valores identificados, al estar por encima de 1 en una métrica que debe estar entre 0 y 1, no son válidos.
test <- rosnerTest(Base_omit$Recall, k = 10)
test$all.stats
## i Mean.i SD.i Value Obs.Num R.i+1 lambda.i+1 Outlier
## 1 0 0.7610971 0.8314054 9.3661823 114 10.350047 3.833870 TRUE
## 2 1 0.7418463 0.7255257 7.7377491 157 9.642529 3.833271 TRUE
## 3 2 0.7261605 0.6460189 7.4548096 4 10.415561 3.832670 TRUE
## 4 3 0.7110399 0.5622109 5.7659164 270 8.991068 3.832068 TRUE
## 5 4 0.6996551 0.5089064 5.7263733 88 9.877490 3.831464 TRUE
## 6 5 0.6883081 0.4497505 5.4998481 420 10.698244 3.830859 TRUE
## 7 6 0.6774222 0.3874519 5.4366692 308 12.283452 3.830252 TRUE
## 8 7 0.6666303 0.3144283 4.8590798 303 13.333562 3.829643 TRUE
## 9 8 0.6571020 0.2428199 3.4388274 221 11.455922 3.829033 TRUE
## 10 9 0.6507655 0.2034434 0.3000943 218 1.723680 3.828422 FALSE
Basándonos en la prueba de Rosner, identificamos 9 valores atípicos, lo cual difiere de los 7 valores atípicos previamente observados en el boxplot. Esta diferencia puede deberse a la mayor sensibilidad de la prueba de Rosner para detectar outliers. Los 9 valores identificados, al estar por encima de 1 en una métrica que debe estar entre 0 y 1, no son válidos.
test <- rosnerTest(Base_omit$F1_Score, k = 10)
test$all.stats
## i Mean.i SD.i Value Obs.Num R.i+1 lambda.i+1 Outlier
## 1 0 0.8013885 0.8749189 9.3740487 296 9.798234 3.833870 TRUE
## 2 1 0.7822103 0.7759213 9.2953593 316 10.971665 3.833271 TRUE
## 3 2 0.7631225 0.6634602 8.1785788 281 11.176942 3.832670 TRUE
## 4 3 0.7464585 0.5630661 7.7476843 437 12.434110 3.832068 TRUE
## 5 4 0.7306900 0.4548205 5.4997417 230 10.485569 3.831464 TRUE
## 6 5 0.7199247 0.3946604 5.3206680 333 11.657473 3.830859 TRUE
## 7 6 0.7095157 0.3286397 5.1312436 160 13.454635 3.830252 TRUE
## 8 7 0.6994892 0.2524146 4.6320729 267 15.579855 3.829643 TRUE
## 9 8 0.6905515 0.1689673 0.9993356 418 1.827479 3.829033 FALSE
## 10 9 0.6898481 0.1685139 0.9985770 422 1.832068 3.828422 FALSE
Basándonos en la prueba de Rosner, identificamos 8 valores atípicos, lo cual difiere de los 6 valores atípicos previamente observados en el boxplot. Esta diferencia puede deberse a la mayor sensibilidad de la prueba de Rosner para detectar outliers. Los 8 valores identificados, al estar por encima de 1 en una métrica que debe estar entre 0 y 1, no son válidos.
test <- rosnerTest(Base_omit$Training_Time, k = 10)
test$all.stats
## i Mean.i SD.i Value Obs.Num R.i+1 lambda.i+1 Outlier
## 1 0 3.059781 4.646419 46.985626 324 9.453699 3.833870 TRUE
## 2 1 2.961513 4.159537 46.838741 217 10.548585 3.833271 TRUE
## 3 2 2.863133 3.606191 44.586446 100 11.569913 3.832670 TRUE
## 4 3 2.769373 3.017332 44.357901 201 13.783214 3.832068 TRUE
## 5 4 2.675705 2.282925 28.294985 344 11.222129 3.831464 TRUE
## 6 5 2.617874 1.932676 20.933435 109 9.476788 3.830859 TRUE
## 7 6 2.576436 1.726646 20.251860 417 10.236856 3.830252 TRUE
## 8 7 2.536356 1.508782 13.791378 214 7.459672 3.829643 TRUE
## 9 8 2.510776 1.411524 4.997833 156 1.761966 3.829033 FALSE
## 10 9 2.505111 1.408117 4.986466 43 1.762179 3.828422 FALSE
Basándonos en la prueba de Rosner, identificamos 8 valores atípicos, lo cual difiere de los 6 valores atípicos previamente observados en el boxplot. Esta diferencia puede deberse a la mayor sensibilidad de la prueba de Rosner para detectar outliers. Los 8 valores identificados, al estar por encima de 2.5 (Mediana) en una métrica que esta alrededor de 2-4, los hace menos válidos.
Con las pruebas ya listas, vamos a imputar los datos con la técnica imputación con la Mediana, ya que los datos no siguen una distribución normal.
# Calcular la mediana de los valores que están en el rango permitido (0 a 1)
mediana_accuracy <- median(Base_omit$Accuracy[Base_omit$Accuracy <= 1], na.rm = TRUE)
# Reemplazar los valores atípicos (mayores a 1) por la mediana
Base_omit$Accuracy[Base_omit$Accuracy > 1] <- mediana_accuracy
boxp1 <- ggplot(data.frame(value = Base_omit$Accuracy), aes(x = "", y = value)) +
geom_boxplot(fill = "#99CCFF", color = "black", outlier.colour = "red", outlier.size = 3, width = 0.4) +
ggtitle("Boxplot de Accuracy") +
ylab("Accuracy") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 14))
mediana_2 <- median(Base_omit$Precision[Base_omit$Precision <= 1], na.rm = TRUE)
# Reemplazar los valores atípicos (mayores a 1) por la mediana
Base_omit$Precision[Base_omit$Precision > 1] <- mediana_2
boxp2 <- ggplot(data.frame(value = Base_omit$Precision), aes(x = "", y = value)) +
geom_boxplot(fill = "#99CCFF", color = "black", outlier.colour = "red", outlier.size = 3, width = 0.4) +
ggtitle("Boxplot de Precision") +
ylab("Precision") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 14))
# Calcular la mediana de los valores que están en el rango permitido (0 a 1)
mediana_3 <- median(Base_omit$Recall[Base_omit$Recall <= 1], na.rm = TRUE)
# Reemplazar los valores atípicos (mayores a 1) por la mediana
Base_omit$Recall[Base_omit$Recall > 1] <- mediana_3
boxp3 <- ggplot(data.frame(value = Base_omit$Recall), aes(x = "", y = value)) +
geom_boxplot(fill = "#99CCFF", color = "black", outlier.colour = "red", outlier.size = 3, width = 0.4) +
ggtitle("Boxplot de Recall") +
ylab("Recall") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 14))
# Calcular la mediana de los valores que están en el rango permitido (0 a 1)
mediana_4 <- median(Base_omit$F1_Score[Base_omit$F1_Score <= 1], na.rm = TRUE)
# Reemplazar los valores atípicos (mayores a 1) por la mediana
Base_omit$F1_Score[Base_omit$F1_Score > 1] <- mediana_4
boxp4 <- ggplot(data.frame(value = Base_omit$F1_Score), aes(x = "", y = value)) +
geom_boxplot(fill = "#99CCFF", color = "black", outlier.colour = "red", outlier.size = 3, width = 0.4) +
ggtitle("Boxplot de F1 Score") +
ylab("F1 Score") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 14))
Base_omit$Training_Time[Base_omit$Training_Time > 10] <- median(Base_omit$Training_Time, na.rm = TRUE)
boxp5 <- ggplot(data.frame(value = Base_omit$Precision), aes(x = "", y = value)) +
geom_boxplot(fill = "#99CCFF", color = "black", outlier.colour = "red", outlier.size = 3, width = 0.4) +
ggtitle("Boxplot de Training Time") +
ylab("Training Time") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5, size = 14))
Veamos los boxplot ahora:
(boxp1 | boxp2 | boxp3) / (boxp4 | boxp5)
grafi1 <- ggplot(data.frame(value = Base_omit$Accuracy), aes(x = value)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "#99CCFF", color = "black", alpha = 0.7) +
stat_function(fun = dnorm, args = list(mean = mean(Base_omit$Accuracy), sd = sd(Base_omit$Accuracy)), color = "red", size = 1) +
ggtitle("Histograma Acurracy") +
xlab("Acurracy") + ylab("Densidad") +
theme_minimal() +
theme(plot.title = element_text(size = 14, hjust = 0.5))
# Repetimos para Precision, Recall, F1_Score y Training_Time (mismo formato)
grafi2 <- ggplot(data.frame(value = Base_omit$Precision), aes(x = value)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "#99CCFF", color = "black", alpha = 0.7) +
stat_function(fun = dnorm, args = list(mean = mean(Base_omit$Precision), sd = sd(Base_omit$Precision)), color = "red", size = 1) +
ggtitle("Histograma Precision") +
xlab("Precision") + ylab("Densidad") +
theme_minimal() +
theme(plot.title = element_text(size = 14, hjust = 0.5))
grafi3 <- ggplot(data.frame(value = Base_omit$Recall), aes(x = value)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "#99CCFF", color = "black", alpha = 0.7) +
stat_function(fun = dnorm, args = list(mean = mean(Base_omit$Recall), sd = sd(Base_omit$Recall)), color = "red", size = 1) +
ggtitle("Histograma Recall") +
xlab("Recall") + ylab("Densidad") +
theme_minimal() +
theme(plot.title = element_text(size = 14, hjust = 0.5))
grafi4 <- ggplot(data.frame(value = Base_omit$F1_Score), aes(x = value)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "#99CCFF", color = "black", alpha = 0.7) +
stat_function(fun = dnorm, args = list(mean = mean(Base_omit$F1_Score), sd = sd(Base_omit$F1_Score)), color = "red", size = 1) +
ggtitle("Histograma F1 Score") +
xlab("F1 Score") + ylab("Densidad") +
theme_minimal() +
theme(plot.title = element_text(size = 14, hjust = 0.5))
grafi5 <- ggplot(data.frame(value = Base_omit$Training_Time), aes(x = value)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "#99CCFF", color = "black", alpha = 0.7) +
stat_function(fun = dnorm, args = list(mean = mean(Base_omit$Training_Time), sd = sd(Base_omit$Training_Time)), color = "red", size = 1) +
ggtitle("Histograma Training Time") +
xlab("Training Time") + ylab("Densidad") +
theme_minimal() +
theme(plot.title = element_text(size = 14, hjust = 0.5))
Observemos los histogramas ahora:
(grafi1 | grafi2 | grafi3) / (grafi4 | grafi5)
Tras la imputación de los valores atípicos detectados, los boxplots confirman que ya no hay outliers en la base de datos. Esto nos da más certeza y confianza en la calidad de los datos, lo cual es crucial para la precisión de los análisis y resúmenes estadísticos.
Procederemos a realizar un análisis detallado de las variables numéricas y categóricas mediante la aplicación de filtros de información. Dado que ya se ha calculado el resumen estadístico de las variables, el uso de estos filtros nos permitirá profundizar en el comportamiento individual de cada variable, proporcionando una comprensión más precisa y contextualizada de los datos analizados.
1: Distribución Uniforme de Precisión en Modelos con Valores Mayores a 0.7
# Filtrar las filas donde Precision es mayor a 0.7
Base_filtrada <- Base_omit %>% filter(Precision > 0.7)
# Crear un gráfico de densidad para visualizar la distribución de Precision filtrada
ggplot(Base_filtrada, aes(x = Precision)) +
geom_density(fill = "#FF6666", alpha = 0.7, color = "black") +
ggtitle("Distribucion de Precision (Mayor a 0.7)") +
xlab("Precision") +
ylab("Densidad") +
theme_minimal()
El gráfico tiene variaciones suaves en la densidad, no muestra grandes picos o caídas bruscas. Esto sugiere que los valores de precisión mayores a 0.7 están distribuidos de manera bastante uniforme. Se puede decir que es común encontrar modelos con precisiones cercanas a 1, lo que indica un buen desempeño de los modelos de machine learning.
2: Algoritmo con mayor eficacia en su tiempo de entrenamiento.
## Algorithm Mean_Time Entries
## 1 SVM 2.293516 105
## 2 Random Forest 2.427681 95
## 3 K-Means 2.606262 135
## 4 Neural Network 2.666324 113
El análisis revela que el algoritmo SVM
presenta el
tiempo de entrenamiento promedio más bajo con 2.29
horas, seguido de Random Forest
con
2.43 horas, como se observa en el gráfico de
barras que muestra la media del tiempo de entrenamiento para cada
algoritmo. Otros algoritmos, como K-Means
y
Neural Network
, tienen tiempos de entrenamiento de
2.61 horas y 2.67 horas,
respectivamente. Estos resultados sugieren que SVM
y
Random Forest
son altamente eficientes, permitiendo una
rápida implementación en escenarios donde el tiempo es un recurso
crítico. La identificación de estos algoritmos como los más eficientes
sugiere que pueden ser preferidos para proyectos que requieren una
respuesta rápida, especialmente cuando se trabaja con grandes conjuntos
de datos.
3: Framework con mayor eficacia en su tiempo de entrenamiento.
## Framework Mean_Time Entries
## 1 Scikit-learn 2.410524 98
## 2 PyTorch 2.422791 111
## 3 TensorFlow 2.541135 142
## 4 Keras 2.665840 97
Los resultados obtenidos muestran que Keras y TensorFlow tienen los tiempos de entrenamiento promedio más altos, con 2.67 horas y 2.54 horas, respectivamente. Estos frameworks cuentan con 97 y 142 entradas, lo que proporciona una base sólida para estos promedios. En contraste, Scikit-learn y PyTorch presentan tiempos de entrenamiento promedio más bajos, con 2.41 horas y 2.42 horas, respectivamente. Esta diferencia en los tiempos de entrenamiento sugiere que Scikit-learn y PyTorch podrían ofrecer una mayor eficiencia en el tiempo de entrenamiento, lo que permitiría a los desarrolladores trabajar de forma más rápida. Sin embargo, la elección del framework dependerá también de otros factores como la precisión y la facilidad de uso en cada caso.
4: Framework con presición mayor a 0.6.
suppressPackageStartupMessages({
library(dplyr)
library(ggplot2)
library(tidyr)
})
precision_intervals <- c(0.6, 0.7, 0.8, 0.9, 1.0)
precision_labels <- c("0.6-0.7", "0.7-0.8", "0.8-0.9", "0.9-1.0")
Base_filtered <- Base_omit %>% filter(Precision > 0.6)
precision_counts <- Base_filtered %>%
mutate(Precision_Range = cut(Precision, breaks = precision_intervals, right = FALSE, labels = precision_labels)) %>%
group_by(Framework, Precision_Range) %>%
summarise(Count = n(), .groups = 'drop') %>%
arrange(Framework, desc(Count))
if (nrow(precision_counts) > 0) {
ggplot(precision_counts, aes(x = Precision_Range, y = Count, fill = Framework)) +
geom_bar(stat = "identity", position = "dodge") +
labs(title = "Cantidad de Modelos por Intervalos de Precision por Framework",
x = "Intervalo de Precision",
y = "Cantidad de Modelos") +
theme_minimal() +
scale_fill_brewer(palette = "Set1") +
scale_y_continuous(trans = "reverse") # Invertir el eje y
} else {
cat("No hay modelos con precisión superior a 0.6.")
}
El gráfico muestra la distribución de la cantidad de modelos por intervalos de precisión (de 0.6 a 1.0) clasificados según los frameworks. En el intervalo de 0.6-0.7, TensorFlow y Keras dominan con apróximadamente 17-21 modelos cada uno, mientras que Scikit-learn y PyTorch tienen una menor representación. En el rango de 0.7-0.8, TensorFlow continúa liderando, aunque Keras, PyTorch, muestran una distribución más equilibrada con alrededor de 20 modelos cada uno. En el intervalo de 0.8-0.9, TensorFlow sigue siendo el dominante, con Scikit-learn y Keras manteniendo una representación intermedia. Finalmente, en el rango de 0.9-1.0, TensorFlow es el framework con la mayor cantidad de modelos, mientras que los demás tienen menos de 20.
En conclusión, TensorFlow es el framework con más modelos en los intervalos de precisión inferiores e intermedios. Keras muestra una fuerte presencia en los intervalos intermedios, mientras que PyTorch tiene una menor representación en general. Esto sugiere que la elección del framework puede influir tanto en la cantidad de modelos generados como en su capacidad para alcanzar altos niveles de precisión.
5: Algoritmo con mayor eficacia en su tiempo de entrenamiento y presición.
suppressPackageStartupMessages({
library(dplyr)
library(ggplot2)
})
Base_filtered <- Base_omit %>%
filter(Precision > 0.6 & Training_Time > 0)
Base_efficiency <- Base_omit %>%
mutate(Efficacy = Precision / Training_Time) %>%
group_by(Algorithm, Framework) %>%
summarise(Average_Efficacy = mean(Efficacy, na.rm = TRUE), .groups = 'drop') %>%
arrange(desc(Average_Efficacy))
if (nrow(Base_efficiency) > 0) {
ggplot(Base_efficiency, aes(x = reorder(paste(Algorithm, Framework), -Average_Efficacy), y = Average_Efficacy, fill = Algorithm)) +
geom_bar(stat = "identity") +
labs(title = "Eficacia Media por Algoritmo y Framework",
x = "Combinacion de Algoritmo y Framework",
y = "Eficacia Media") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_fill_brewer(palette = "Set1")
} else {
cat("No hay modelos con precision superior a 0.6 y tiempo de entrenamiento positivo.")
}
El análisis de la eficacia media por combinación de algoritmo y framework revela diferencias significativas en el rendimiento de los modelos. SVM con TensorFlow alcanza la eficacia media más alta, superando 0.75, lo que lo posiciona como la combinación más eficaz en el gráfico. K-Means con PyTorch y SVM con Scikit-learn también muestran un rendimiento elevado, con eficacias medias cercanas a 0.65. En contraste, combinaciones como Random Forest con Keras y SVM con PyTorch muestran eficacias medias más bajas, por debajo de 0.5, lo que sugiere un menor rendimiento. Esto resalta la importancia de la elección adecuada de la combinación de algoritmo y framework para maximizar la eficacia en aplicaciones específicas.
6: Eficacia en su tiempo de entrenamiento y precisión.
suppressPackageStartupMessages({
library(dplyr)
library(ggplot2)
})
Base_filtered <- Base_omit %>%
filter(Precision > 0.6 & Training_Time > 0)
Base_efficiency <- Base_filtered %>%
mutate(Efficacy = Precision / Training_Time) %>%
group_by(Framework) %>%
summarise(Average_Efficacy = mean(Efficacy, na.rm = TRUE), .groups = 'drop') %>%
arrange(desc(Average_Efficacy))
if (nrow(Base_efficiency) > 0) {
ggplot(Base_efficiency, aes(x = reorder(Framework, -Average_Efficacy), y = Average_Efficacy, fill = Framework)) +
geom_bar(stat = "identity") +
labs(title = "Eficacia Media por Framework",
x = "Framework",
y = "Eficacia Media") +
theme_minimal() +
scale_fill_brewer(palette = "Set1")
} else {
cat("No hay modelos con precisión superior a 0.6 y tiempo de entrenamiento positivo.")
}
El análisis de la eficacia media por framework revela diferencias significativas en el rendimiento de los modelos. En primer lugar, TensorFlow alcanza una eficacia media con más del 0.7, lo que lo posiciona como el framework más eficaz entre los evaluados. Scikit-learn se aproxima con una eficacia media ligeramente inferior, lo que resalta su competencia en términos de rendimiento. En contraste, PyTorch muestra una eficacia media moderada, situada entre 0.55, lo que indica que, aunque es menos eficaz que TensorFlow y Scikit-learn, sigue siendo una opción válida en muchos contextos. Por otro lado, Keras tiene la eficacia media más baja, sugiriendo que este framework es el menos eficaz en comparación con los otros, lo que podría limitar su uso en aplicaciones que requieren altos niveles de rendimiento Sin embargo, entre Keras y Pytorch no hay tanta diferencia. El framework más eficaz fue TensorFlow.
7: Mejor combinacion de algoritmo y framework con mayor precision en menor tiempo
suppressPackageStartupMessages({
library(dplyr)
library(ggplot2)
})
Base_filtered <- Base_omit %>%
filter(Precision > 0.6 & Training_Time > 0)
Base_best_combination <- Base_filtered %>%
mutate(Score = Precision / Training_Time) %>%
group_by(Algorithm, Framework) %>%
summarise(Average_Precision = mean(Precision, na.rm = TRUE),
Average_Training_Time = mean(Training_Time, na.rm = TRUE),
Score = mean(Score, na.rm = TRUE), .groups = 'drop') %>%
arrange(desc(Score))
if (nrow(Base_best_combination) > 0) {
ggplot(Base_best_combination, aes(x = reorder(paste(Algorithm, Framework), -Score), y = Score, fill = Algorithm)) +
geom_bar(stat = "identity") +
labs(title = "Mejor Combinacion de Algoritmo y Framework",
x = "Combinacion de Algoritmo y Framework",
y = "Score (Precision / Tiempo de Entrenamiento)") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_fill_brewer(palette = "Set1")
} else {
cat("No hay modelos con precision superior a 0.6 y tiempo de entrenamiento positivo.")
}
Finalmente, al evaluar la mejor combinación de algoritmo y framework,
podemos notar que la combinación de SVM
con
TensorFlow
también resulta ser la mejor opción en cuanto a
mayor precisión en menor tiempo de entrenamiento. Con un puntaje máximo
en el gráfico de aproximadamente 0.97, esta combinación
logra equilibrar de manera sobresaliente ambos factores. Como motivos,
sabemos que SVM
es conocido por ser muy eficaz en problemas
de clasificación y detección de patrones complejos, y
TensorFlow
maximiza su rendimiento al optimizar el uso de
recursos computacionales y reducir los tiempos de procesamiento. El
framework facilita el entrenamiento de modelos de gran escala sin
comprometer la precisión.
Análisis Bivariado con “Algorithm
”,
“Framework
”, “Precision
”, y
“Training_Time
” El objetivo de este análisis es explorar
las relaciones entre diferentes características relacionadas con la
implementación de modelos de inteligencia artificial (IA), como el tipo
de algoritmo, el framework utilizado, la precisión alcanzada por el
modelo y el tiempo de entrenamiento necesario. A continuación,
realizaremos un análisis detallado de las variables categóricas y
numéricas para identificar patrones relevantes que podrían influir en la
eficacia y eficiencia de los modelos.
Algorithm (Categórica): Tipo de algoritmo de IA utilizado, con categorías Neural Network, Random Forest, SVM, y K-Means.
Framework (Categórica): Framework o biblioteca utilizada para la implementación del modelo de IA, con categorías TensorFlow, PyTorch, Keras, y Scikit-learn.
Precision (Numérica, Continua): Precisión del modelo, con un valor entre 0 y 1 que mide qué tan preciso es el modelo en términos de clasificación.
Training_Time (Numérica, Continua): Tiempo de entrenamiento del modelo, medido en horas.
Paso 1: Análisis de “Algorithm” y “Precision”
Comenzaremos evaluando la relación entre el tipo de algoritmo
utilizado y la precisión alcanzada por el modelo, lo que nos permitirá
entender si ciertos algoritmos tienden a generar modelos más precisos
que otros. Para ello, primero calcularemos estadísticas descriptivas
(media, mediana, desviación estándar) de la variable
Precisión
para cada algoritmo. Esto nos ayudará a observar
si algunos algoritmos, como las Neural Network
, ofrecen en
promedio una mayor precisión comparado con otros, como
K-Means
. Posteriormente, utilizaremos un boxplot para
visualizar la distribución de la precisión por cada algoritmo, lo que
facilitará la comparación visual de la dispersión y las posibles
diferencias entre ellos. El objetivo final es comparar la precisión
entre los diferentes algoritmos y determinar si algunos tienen una
ventaja significativa en términos de exactitud.
# Resumen estadístico de Precision por Algorithm
summary_algorithm_precision <- Base_omit %>%
group_by(Algorithm) %>%
summarise(
mean_precision = mean(Precision, na.rm = TRUE),
median_precision = median(Precision, na.rm = TRUE),
sd_precision = sd(Precision, na.rm = TRUE)
)
summary_algorithm_precision
## # A tibble: 4 × 4
## Algorithm mean_precision median_precision sd_precision
## <chr> <dbl> <dbl> <dbl>
## 1 K-Means 0.721 0.750 0.175
## 2 Neural Network 0.693 0.718 0.159
## 3 Random Forest 0.698 0.704 0.171
## 4 SVM 0.724 0.724 0.171
# Prueba ANOVA para comparar Precision por Algorithm
anova_algorithm_precision <- aov(Precision ~ Algorithm, data = Base_omit)
# Mostrar el resultado de la ANOVA
summary_anova_algorithm_precision <- summary(anova_algorithm_precision)
summary_anova_algorithm_precision
## Df Sum Sq Mean Sq F value Pr(>F)
## Algorithm 3 0.082 0.02725 0.948 0.417
## Residuals 444 12.766 0.02875
# Interpretación:
# Si el valor de p en el resultado (Pr(>F)) es menor a 0.05, indica que hay diferencias significativas
# en las medias de precisión entre al menos dos algoritmos.
if (summary_anova_algorithm_precision[[1]]["Algorithm", "Pr(>F)"] < 0.05) {
cat("El resultado de la ANOVA muestra diferencias significativas en la precisión entre los diferentes algoritmos.\n")
# Prueba post-hoc Tukey HSD para determinar entre qué algoritmos existen diferencias
tukey_algorithm_precision <- TukeyHSD(anova_algorithm_precision)
tukey_algorithm_precision
cat("El test Tukey HSD identifica cuáles algoritmos tienen diferencias significativas en su precisión.\n")
} else {
cat("No se encontraron diferencias significativas en la precisión entre los algoritmos.\n")
}
## No se encontraron diferencias significativas en la precisión entre los algoritmos.
# Boxplot de Precision por Algorithm
ggplot(Base_omit, aes(x = Algorithm, y = Precision)) +
geom_boxplot() +
labs(title = "Distribucion de Precision por Algorithm",
x = "Tipo de Algoritmo",
y = "Precision del Modelo") +
theme_minimal()
El gráfico de Distribución de Precisión por Algoritmo revela la variabilidad en el rendimiento de los modelos basados en diferentes algoritmos. K-Means muestra una amplia distribución de precisiones, con una mediana cercana a 0.75, lo que indica que este algoritmo tiende a ser eficaz en la mayoría de los casos, aunque la dispersión sugiere que algunos modelos tienen un rendimiento menor. Neural Networks tiene una mediana de precisión más baja que K-Means, pero presenta variabilidad, lo que implica que, dependiendo de la configuración del modelo, las redes neuronales pueden tener tanto modelos altamente precisos como menos precisos. Random Forest presenta una mediana similar a la de K-Means, pero con menos dispersión, lo que sugiere que este algoritmo ofrece resultados más consistentes. Finalmente, SVM tiene una alta variabilidad en sus resultados, con una mediana de precisión alta (alrededor de 0.71), lo que indica que, en escenarios bien configurados, puede lograr modelos altamente precisos.
Paso 2: Análisis de “Algorithm” y “Training_Time”
Después, analizaremos el tiempo de entrenamiento (Training_Time) necesario para cada tipo de algoritmo, lo cual nos permitirá comprender si los modelos más complejos, como las redes neuronales, requieren más tiempo de entrenamiento que modelos más simples, como K-Means. Para ello, calcularemos estadísticas descriptivas como la media, mediana y desviación estándar del tiempo de entrenamiento por algoritmo, lo que nos permitirá identificar si algunos algoritmos consistentemente requieren más tiempo de cómputo. Posteriormente, visualizaremos esta información mediante un boxplot que mostrará la variabilidad y las diferencias en los tiempos de entrenamiento entre los distintos algoritmos. El objetivo es determinar si el tiempo de entrenamiento varía significativamente entre algoritmos y cómo esta diferencia se relaciona con la complejidad del modelo.
# Resumen estadístico de Training_Time por Algorithm
summary_algorithm_time <- Base_omit %>%
group_by(Algorithm) %>%
summarise(
mean_time = mean(Training_Time, na.rm = TRUE),
median_time = median(Training_Time, na.rm = TRUE),
sd_time = sd(Training_Time, na.rm = TRUE)
)
summary_algorithm_time
## # A tibble: 4 × 4
## Algorithm mean_time median_time sd_time
## <chr> <dbl> <dbl> <dbl>
## 1 K-Means 2.61 2.56 1.43
## 2 Neural Network 2.67 2.51 1.40
## 3 Random Forest 2.43 2.25 1.36
## 4 SVM 2.29 2.12 1.38
# Prueba ANOVA para comparar Training_Time por Algorithm
anova_algorithm_time <- aov(Training_Time ~ Algorithm, data = Base_omit)
# Mostrar el resultado de la ANOVA
summary_anova_algorithm_time <- summary(anova_algorithm_time)
summary_anova_algorithm_time
## Df Sum Sq Mean Sq F value Pr(>F)
## Algorithm 3 9.6 3.192 1.638 0.18
## Residuals 444 865.1 1.948
# Interpretación:
# Si el valor de p es menor a 0.05, hay diferencias significativas en el tiempo de entrenamiento
# entre los algoritmos.
if (summary_anova_algorithm_time[[1]]["Algorithm", "Pr(>F)"] < 0.05) {
cat("El resultado de la ANOVA muestra diferencias significativas en el tiempo de entrenamiento entre los diferentes algoritmos.\n")
# Prueba post-hoc Tukey HSD para determinar entre qué algoritmos existen diferencias
tukey_algorithm_time <- TukeyHSD(anova_algorithm_time)
tukey_algorithm_time
cat("El test Tukey HSD identifica cuáles algoritmos tienen diferencias significativas en el tiempo de entrenamiento.\n")
} else {
cat("No se encontraron diferencias significativas en el tiempo de entrenamiento entre los algoritmos.\n")
}
## No se encontraron diferencias significativas en el tiempo de entrenamiento entre los algoritmos.
# Boxplot de Training_Time por Algorithm
ggplot(Base_omit, aes(x = Algorithm, y = Training_Time)) +
geom_boxplot() +
labs(title = "Distribucion de Training_Time por Algorithm",
x = "Tipo de Algoritmo",
y = "Tiempo de Entrenamiento (Horas)") +
theme_minimal()
El análisis de la Distribución de Training Time por Algoritmo revela que K-Means tiene tiempos de entrenamiento relativamente cortos y estables, con una mediana cercana a las 2.5 horas y una dispersión moderada, sin outliers, lo que lo convierte en una opción eficiente. Por otro lado, las Neural Networks presentan una mayor variabilidad en los tiempos, que oscilan entre 1.5 horas y 4.1 horas, lo que indica que el tiempo de entrenamiento puede variar considerablemente según las configuraciones. Random Forest tiene una variabilidad moderada, con tiempos que van de 1.4 hora a 3.7 horas, siendo más estable que Neural Networks pero con una mediana similar, cerca de las 2.25 horas. Finalmente, SVM muestra una variabilidad más controlada, con una mediana en 2.12 horas, en general es más predecible en términos de tiempo. En resumen, K-Means es el más rápido y estable, mientras que Neural Network y Random Forest pueden tener tiempos de entrenamiento prolongados en ciertos casos, y SVM se encuentra en un punto intermedio, con tiempos generalmente más predecibles pero con valores altos.
Paso 3: Análisis de “Framework” y “Precision”
El siguiente análisis evaluará la relación entre el framework utilizado (Framework) y la precisión del modelo (Precision), ya que diferentes bibliotecas tienen optimizaciones y características que podrían influir en el rendimiento del modelo. Para esto, calcularemos estadísticas descriptivas como la media, mediana y desviación estándar de la precisión alcanzada por los modelos en cada framework. Además, utilizaremos un boxplot que mostrará la distribución de la precisión para cada framework, permitiendo observar visualmente cómo varía la precisión según la herramienta utilizada. El objetivo de este análisis es comparar el rendimiento de los frameworks en términos de precisión y determinar si alguno de ellos ofrece una ventaja significativa en ciertos contextos.
# Resumen estadístico de Precision por Framework
summary_framework_precision <- Base_omit %>%
group_by(Framework) %>%
summarise(
mean_precision = mean(Precision, na.rm = TRUE),
median_precision = median(Precision, na.rm = TRUE),
sd_precision = sd(Precision, na.rm = TRUE)
)
summary_framework_precision
## # A tibble: 4 × 4
## Framework mean_precision median_precision sd_precision
## <chr> <dbl> <dbl> <dbl>
## 1 Keras 0.693 0.704 0.163
## 2 PyTorch 0.701 0.724 0.173
## 3 Scikit-learn 0.735 0.746 0.171
## 4 TensorFlow 0.709 0.724 0.170
# Prueba ANOVA para comparar Precision por Framework
anova_framework_precision <- aov(Precision ~ Framework, data = Base_omit)
# Mostrar el resultado de la ANOVA
summary_anova_framework_precision <- summary(anova_framework_precision)
summary_anova_framework_precision
## Df Sum Sq Mean Sq F value Pr(>F)
## Framework 3 0.098 0.03276 1.141 0.332
## Residuals 444 12.749 0.02871
# Interpretación:
# Si el valor de p es menor a 0.05, hay diferencias significativas en la precisión entre los frameworks.
if (summary_anova_framework_precision[[1]]["Framework", "Pr(>F)"] < 0.05) {
cat("El resultado de la ANOVA muestra diferencias significativas en la precisión entre los diferentes frameworks.\n")
# Prueba post-hoc Tukey HSD para determinar entre qué frameworks existen diferencias
tukey_framework_precision <- TukeyHSD(anova_framework_precision)
tukey_framework_precision
cat("El test Tukey HSD identifica qué frameworks tienen diferencias significativas en la precisión.\n")
} else {
cat("No se encontraron diferencias significativas en la precisión entre los frameworks.\n")
}
## No se encontraron diferencias significativas en la precisión entre los frameworks.
# Boxplot de Precision por Framework
ggplot(Base_omit, aes(x = Framework, y = Precision)) +
geom_boxplot() +
labs(title = "Distribucion de Precision por Framework",
x = "Framework Utilizado",
y = "Precision del Modelo") +
theme_minimal()
El análisis de la Distribución de Precisión por Framework revela que los frameworks Keras, PyTorch, Scikit-learn y TensorFlow muestran medianas de precisión cercanas a 0.8, lo que sugiere que todos los frameworks ofrecen un rendimiento similar en cuanto a precisión. Sin embargo, se observa mayor variabilidad en Keras y PyTorch, ya que tienen una mayor dispersión en sus distribuciones, lo que sugiere que algunos modelos entrenados con estos frameworks pueden tener rendimientos menos consistentes. En cambio, Scikit-learn y TensorFlow presentan distribuciones más compactas, lo que indica que tienden a ofrecer una precisión más estable y predecible. Esto podría hacer que estos dos últimos frameworks sean opciones preferidas para proyectos donde la estabilidad en la precisión es crucial. No obstante, todos presentan un rendimiento casi igual.
Paso 4: Análisis de “Framework” y “Training_Time”
Finalmente, analizaremos la relación entre el framework utilizado y el tiempo de entrenamiento. Algunas bibliotecas, como TensorFlow o PyTorch, pueden estar más optimizadas para ciertos tipos de hardware o modelos, lo que afecta el tiempo necesario para entrenar un modelo. Para ello, calcularemos la media, mediana y desviación estándar del tiempo de entrenamiento para cada framework, lo que permitirá identificar cuáles bibliotecas ofrecen tiempos de entrenamiento más cortos o más largos. Luego, un boxplot del tiempo de entrenamiento por framework permitirá visualizar cómo varían los tiempos entre las diferentes herramientas y si algunos frameworks son más eficientes en términos de cómputo. El objetivo es evaluar la eficiencia de cada framework en términos de tiempo de entrenamiento y determinar si ciertas herramientas ofrecen ventajas significativas en cuanto a velocidad.
# Resumen estadístico de Training_Time por Framework
summary_framework_time <- Base_omit %>%
group_by(Framework) %>%
summarise(
mean_time = mean(Training_Time, na.rm = TRUE),
median_time = median(Training_Time, na.rm = TRUE),
sd_time = sd(Training_Time, na.rm = TRUE)
)
summary_framework_time
## # A tibble: 4 × 4
## Framework mean_time median_time sd_time
## <chr> <dbl> <dbl> <dbl>
## 1 Keras 2.67 2.80 1.45
## 2 PyTorch 2.42 2.48 1.33
## 3 Scikit-learn 2.41 2.26 1.34
## 4 TensorFlow 2.54 2.36 1.46
# Prueba ANOVA para comparar Training_Time por Framework
anova_framework_time <- aov(Training_Time ~ Framework, data = Base_omit)
# Mostrar el resultado de la ANOVA
summary_anova_framework_time <- summary(anova_framework_time)
summary_anova_framework_time
## Df Sum Sq Mean Sq F value Pr(>F)
## Framework 3 4.3 1.436 0.732 0.533
## Residuals 444 870.4 1.960
# Interpretación:
# Si el valor de p en Pr(>F) es menor a 0.05, indica que existen diferencias significativas
# en el tiempo de entrenamiento entre los frameworks.
if (summary_anova_framework_time[[1]]["Framework", "Pr(>F)"] < 0.05) {
cat("El resultado de la ANOVA muestra diferencias significativas en el tiempo de entrenamiento entre los diferentes frameworks.\n")
# Prueba post-hoc Tukey HSD para determinar entre qué frameworks existen diferencias significativas
tukey_framework_time <- TukeyHSD(anova_framework_time)
tukey_framework_time
cat("El test Tukey HSD identifica cuáles frameworks tienen diferencias significativas en el tiempo de entrenamiento.\n")
} else {
cat("No se encontraron diferencias significativas en el tiempo de entrenamiento entre los frameworks.\n")
}
## No se encontraron diferencias significativas en el tiempo de entrenamiento entre los frameworks.
# Boxplot de Training_Time por Framework
ggplot(Base_omit, aes(x = Framework, y = Training_Time)) +
geom_boxplot() +
labs(title = "Distribucion de Training_Time por Framework",
x = "Framework Utilizado",
y = "Tiempo de Entrenamiento (Horas)") +
theme_minimal()
El análisis de la distribución del tiempo de entrenamiento (Training_Time) por framework muestra que Keras, PyTorch, Scikit-learn y TensorFlow presentan medianas de tiempo de entrenamiento similares, alrededor de 2 a 2.8 horas, lo que indica una eficiencia comparable. Sin embargo, PyTorch y TensorFlow muestran una mayor variabilidad, como se observa en la longitud de sus cajas, lo que sugiere que algunos modelos requieren tiempos de entrenamiento más prolongados en comparación con Keras y Scikit-learn, que presentan distribuciones más compactas y consistentes. Esta menor variabilidad convierte a Keras y Scikit-learn en opciones más predecibles en cuanto al tiempo de entrenamiento. En general, Keras es la que presenta una mayor mediana, lo cual es indicio de que puede dar mejores resultados, sin embargo, tiene un variabilidad lo que puede llevar a mejores o peores resultados.
Paso 5: Análisis Combinado de “Algorithm”, “Framework” y “Precision”
Una vez completados los análisis anteriores, podemos explorar la interacción entre las tres variables: el tipo de algoritmo, el framework y la precisión alcanzada. Un gráfico de barras agrupadas permitiría visualizar cómo varía la precisión en función del algoritmo y el framework utilizados, proporcionando una visión clara de las combinaciones más efectivas.
El objetivo de este análisis es identificar si existe una combinación óptima de algoritmo y framework que maximice la precisión del modelo, lo que podría ser de gran utilidad para guiar futuras decisiones en la elección de herramientas y enfoques.
# Resumen estadístico combinado de Precision por Algorithm y Framework
summary_combined <- Base_omit %>%
group_by(Algorithm, Framework) %>%
summarise(
mean_precision = mean(Precision, na.rm = TRUE),
median_precision = median(Precision, na.rm = TRUE),
sd_precision = sd(Precision, na.rm = TRUE)
)
summary_combined
## # A tibble: 16 × 5
## # Groups: Algorithm [4]
## Algorithm Framework mean_precision median_precision sd_precision
## <chr> <chr> <dbl> <dbl> <dbl>
## 1 K-Means Keras 0.677 0.683 0.163
## 2 K-Means PyTorch 0.688 0.724 0.185
## 3 K-Means Scikit-learn 0.817 0.857 0.139
## 4 K-Means TensorFlow 0.708 0.724 0.181
## 5 Neural Network Keras 0.718 0.724 0.145
## 6 Neural Network PyTorch 0.675 0.723 0.170
## 7 Neural Network Scikit-learn 0.667 0.684 0.148
## 8 Neural Network TensorFlow 0.702 0.785 0.169
## 9 Random Forest Keras 0.707 0.713 0.184
## 10 Random Forest PyTorch 0.724 0.739 0.171
## 11 Random Forest Scikit-learn 0.630 0.582 0.165
## 12 Random Forest TensorFlow 0.722 0.709 0.162
## 13 SVM Keras 0.677 0.664 0.177
## 14 SVM PyTorch 0.717 0.724 0.168
## 15 SVM Scikit-learn 0.799 0.830 0.160
## 16 SVM TensorFlow 0.709 0.725 0.170
# Prueba ANOVA para evaluar la interacción entre Algorithm y Framework en Precision
anova_combined <- aov(Precision ~ Algorithm * Framework, data = Base_omit)
# Mostrar el resultado de la ANOVA
summary_anova_combined <- summary(anova_combined)
summary_anova_combined
## Df Sum Sq Mean Sq F value Pr(>F)
## Algorithm 3 0.082 0.02725 0.980 0.40184
## Framework 3 0.099 0.03294 1.185 0.31500
## Algorithm:Framework 9 0.658 0.07307 2.629 0.00573 **
## Residuals 432 12.009 0.02780
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Interpretación:
# Si el valor de p es menor a 0.05 para los efectos principales (Algorithm o Framework) o la interacción (Algorithm:Framework),
# entonces hay una influencia significativa de estas variables en la precisión del modelo.
if (summary_anova_combined[[1]]["Algorithm:Framework", "Pr(>F)"] < 0.05) {
cat("La interacción entre el tipo de algoritmo y el framework utilizado tiene un efecto significativo en la precisión del modelo.\n")
} else {
cat("No se encontraron efectos significativos en la precisión debido a la interacción entre el algoritmo y el framework.\n")
}
## La interacción entre el tipo de algoritmo y el framework utilizado tiene un efecto significativo en la precisión del modelo.
# Prueba post-hoc para el análisis combinado si es significativo
if (summary_anova_combined[[1]]["Algorithm:Framework", "Pr(>F)"] < 0.05) {
tukey_combined <- TukeyHSD(anova_combined)
tukey_combined
cat("El test Tukey HSD muestra qué combinaciones de algoritmo y framework tienen diferencias significativas en precisión.\n")
}
## El test Tukey HSD muestra qué combinaciones de algoritmo y framework tienen diferencias significativas en precisión.
# Gráfico de barras agrupadas para mostrar Precision por Algorithm y Framework
ggplot(Base_omit, aes(x = Algorithm, y = Precision, fill = Framework)) +
geom_bar(stat = "summary", fun = "mean", position = "dodge") +
labs(title = "Precision Media por Algorithm y Framework",
x = "Tipo de Algoritmo",
y = "Precision del Modelo",
fill = "Framework") +
theme_minimal()
El gráfico de barras ilustra la precisión media de los modelos en función del tipo de algoritmo utilizado (K-Means, Neural Network, Random Forest y SVM) y el framework (Keras, PyTorch, Scikit-learn, TensorFlow), proporcionando una visión comparativa que integra tres elementos clave: algoritmo, framework y precisión. En primer lugar, al analizar el algoritmo K-Means, se observa que la precisión media es bastante consistente entre los frameworks, destacando ligeramente TensorFlow y Scikit-learn por encima de Keras y PyTorch, lo que sugiere un rendimiento levemente superior en la implementación de este algoritmo. En el caso de las Neural Networks, Keras se posiciona como el mejor framework, mostrando la mayor precisión media en comparación con los demás; PyTorch y TensorFlow también ofrecen resultados competitivos, mientras que Scikit-learn presenta una precisión relativamente baja, indicando que podría no ser la mejor opción. En cuanto al algoritmo Random Forest, la precisión media entre los frameworks es bastante uniforme, sin diferencias significativas, lo que implica que los cuatro frameworks ofrecen un rendimiento similar en este caso, excepto por Scikit-learn que se quede bastante abajo comparandola con los otros. Finalmente, para el algoritmo SVM, Scikit-learn sobresale con la mayor precisión media, superando a Keras, PyTorch, y a TensorFlow, lo que indica que puede estar mejor optimizado para este tipo de algoritmo.
La pregunta inicial planteada fue: ¿Qué algoritmo logra la mayor precisión en relación al tiempo de entrenamiento en problemas de regresión sobre datos de series de tiempo, y cómo varía esta eficiencia entre diferentes frameworks como PyTorch, TensorFlow, Keras y Scikit-learn? A lo largo del análisis bivariado, encontramos varios hallazgos relevantes, pero uno de los más destacados fue el rendimiento del algoritmo K-Means. Este algoritmo no solo presentó el mejor tiempo de entrenamiento, con una mediana de 2.5 horas, sino que también se posicionó como el más preciso y eficaz en comparación con los demás algoritmos evaluados.
Además, al evaluar la precisión de los modelos en función del framework y el algoritmo, K-Means mostró ser adaptable y eficiente con los distintos frameworks, presentando resultados consistentemente altos. En conclusión, K-Means no solo fue el algoritmo que logró una mejor relación entre precisión y tiempo de entrenamiento, sino que también demostró ser eficaz en todos los frameworks considerados, destacándose como una opción robusta para resolver problemas de regresión en series de tiempo.