EDA desde un ángulo diferente

imagen

No hablaremos de alimentos, sino de análisis de datos exploratorios (EDA ), que es un preludio obligatorio para cualquier LD duro.

Seamos honestos, el proceso es bastante aburrido, y para obtener al menos algunas ideas significativas sobre nuestros datos, debe dedicar el tiempo suficiente activamente a su biblioteca de visualización favorita.

Ahora imagine que somos bastante vagos (pero curiosos) y seguiremos este postulado a lo largo de este artículo.

En base a esto, nos hacemos la siguiente pregunta: ¿existe una herramienta difícil en la naturaleza que simplemente le permita presionar CTRL + ENTRAR en su IDE favorito y mostrar en una sola pantalla (sin desplazarse hacia abajo e innumerables facetas microscópicas) una imagen completa con información útil sobre nuestro conjunto de datos?

Al mismo tiempo, tenemos en cuenta un pensamiento diferente: si existe un instrumento de este tipo, no reemplazará el clásico EDA, pero será de gran ayuda para nosotros en aquellos casos en que no tenga que pasar horas en la visualización para enfatizar rápidamente los patrones principales en nuestros datos.

La estructura de este artículo:

  1. Pequeño preprocesamiento
  2. Visualización de predictores
  3. Discretización de variables.
  4. Correlaciónfunnel
  5. Correlaciones cruzadas clasificadas
  6. easyalluvial

Terminamos con la introducción y tomamos como base un ejemplo práctico.

Enfoque de ejemplo
Inicialmente, quería tomar una matriz de datos oscura, pero al final me di cuenta de que, por ejemplo, esto no sería muy bueno: los patrones encontrados pueden parecer poco obvios y, por lo tanto, controvertidos, pero nuestro objetivo es preparar la matriz con algoritmos que no tienen información a priori y nos mostrarán qué ya lo sabemos, lo que confirma nuestra viabilidad.


El Titanic me pareció el más conveniente como ejemplo, su tamaño no es demasiado pequeño como el de Iris, tiene variables no informativas, está bien estudiado y tiene predictores claros y, lo que es más importante, una base histórica.

Además, encontré un artículo sobre Habré donde el autor realizó un EDA bastante meticuloso de este conjunto de datos y, en base a las imágenes, demostré los hallazgos. Este será un tipo de nuestra línea de base.

Enlace al artículo con un gran nombre para nuestro "Baseline_EDA":
Titanic en Kaggle: no leerás esta publicación hasta el final .

Para no molestarnos con la descarga / lectura de csv de la red, capturamos inmediatamente el conjunto de datos original de CRAN

install.packages("titanic") data("titanic_train",package="titanic") 

Breve preprocesamiento


Este ejemplo está tan marcado en la red mediante el preprocesamiento hacia arriba y hacia abajo que no voy a engullir particularmente este tema, estoy haciendo cosas básicas: extraigo el nombre del gonoratora (título) como un predictor importante y lo uso para llenar los vacíos de edad.

 library(tidyverse) titanic_train %>% str d <- titanic_train %>% as_tibble %>% mutate(title=str_extract(Name,"\\w+\\.") %>% str_replace(fixed("."),"")) %>% mutate(title=case_when(title %in% c('Mlle','Ms')~'Miss', #   title=='Mme'~ 'Mrs', title %in% c('Capt','Don','Major','Sir','Jonkheer', 'Col')~'Sir', title %in% c('Dona', 'Lady', 'Countess')~'Lady', TRUE~title)) %>% mutate(title=as_factor(title), Survived=factor(Survived,levels = c(0,1),labels=c("no","yes")), Sex=as_factor(Sex), Pclass=factor(Pclass,ordered = T)) %>% group_by(title) %>% #  -      mutate(Age=replace_na(Age,replace = median(Age,na.rm = T))) %>% ungroup #             table(d$title,d$Sex) 

titulohombrehembra
Señor5170 0
La señora0 0126
Señorita0 0185
Maestro400 0
Señor80 0
Rev6 60 0
Dr6 61
Señora0 02

No todos los yogures son igualmente saludables ...


Por lo general, al comienzo del análisis, pongo a un lado las variables no informativas (dejo de lado y no elimino permanentemente, porque cuando obtengo el máximo del modelo, la ingeniería para algunas de las variables pendientes da un cierto porcentaje de la ganancia de calidad del modelo).

Las métricas para evaluar la "utilidad" de una variable son freqRatio (la relación de las frecuencias del valor más popular en relación con el segundo valor en frecuencia) y percentUnique (potencia o cardinalidad: la proporción de un número único de valores del número total de valores)
La ayuda detallada se puede ver en el paquete caret
?caret::nearZeroVar

 (feat.scan <- caret::nearZeroVar(x = d,saveMetrics = T) %>% rownames_to_column("featName") %>% as_tibble) 

imagen

Es más conveniente para mí monitorear variables en un plano bidimensional (registrando ambos ejes para que los puntos no se sobreploten en una pila pequeña debido a puntos atípicos).
Nunca me pregunté si este paso es EDA, pero mientras escribía este artículo pensé: ahora estamos realizando un análisis exploratorio de alguna utilidad de los predictores, su evaluación visual, entonces, ¿por qué no es EDA?

 # install.packages("ggrepel") library(ggrepel) ggplot(feat.scan,aes(x=percentUnique,y=freqRatio,label=featName,col=featName))+ geom_point(size=2)+ geom_text_repel(data = feat.scan,size=5)+scale_x_log10()+scale_y_log10()+theme_bw() 

imagen

Consideramos que los predictores atípicos no son informativos, ya sea en términos de potencia (eje X) o relación de frecuencia (eje Y) y, en consecuencia, reservamos:
Id. De pasajero Nombre; Boleto Cabaña

 useless.feature <- c("PassengerId","Name","Ticket","Cabin") d <- d %>% select_at(vars(-useless.feature)) 

Este universo es discreto


Para comprender cómo las bibliotecas enumeradas a continuación preparan los datos, en esta sección mostramos con pequeños ejemplos lo que sucede en estas bibliotecas en la etapa de preparación de datos.

En el primer paso, es necesario llevar todos los datos a un solo tipo; a menudo, los datos en un conjunto pueden ser categóricos y numéricos, además, los números pueden tener valores atípicos y los datos categóricos pueden ser categorías raras.

Para convertir variables continuas en categóricas, podemos descomponer nuestros números en contenedores con un cierto período de muestreo.

El ejemplo más simple de descomposición en 5 bin:

 iris %>% as_tibble %>% mutate_if(is.numeric,.funs = ggplot2::cut_number,n=5) 

imagen

Para obtener la fuerza y ​​la directividad de las relaciones de elementos individuales entre los predictores, se utiliza un segundo truco: una codificación activa

 library(recipes) iris %>% as_tibble %>% mutate_if(is.numeric,cut_number,n=5) %>% recipe(x = .) %>% step_dummy(all_nominal(),one_hot = T) %>% prep %>% juice %>% glimpse 

En lugar de 5 predictores, ahora tenemos 23 de ellos, pero binarios:

imagen

En general, los trucos de conversión terminan allí, pero el trabajo de 2 de 3 bibliotecas para nuestro EDA "no clásico" comienza con estas etapas.

A continuación, presento la funcionalidad de 3 bibliotecas de visualización:

  1. Correlationfunnel : muestra el efecto de los valores predictores individuales en un objetivo (es decir, puede denominarse aprendizaje supervisado EDA)
  2. Lares : muestra el efecto de los valores de predictores individuales sobre otros valores individuales de otros predictores (es decir, puede denominarse aprendizaje no supervisado EDA)
  3. easyalluvial : muestra la relación acumulativa de los valores agrupados de los principales predictores de "X" por objetivo (es decir, puede denominarse aprendizaje supervisado EDA)

Es evidente que su funcionalidad es diferente, por lo tanto, al demostrar estas bibliotecas, citaré las conclusiones del autor del artículo de nuestro "Baseline_EDA" dependiendo de la funcionalidad descrita anteriormente de este paquete. (Por ejemplo, si el autor muestra la dependencia de la edad en la supervivencia, entonces insertaré dicha cita en el Correlationfunnel, si la edad está en la clase, luego en Lares, etc.)

La primera biblioteca está en el escenario.

correlationfunnel


correlationfunnel es acelerar el análisis de datos exploratorios (EDA)
imagen

La metodología está bien descrita en la viñeta de la biblioteca; daré un fragmento de cálculo de la correlación por valores binarios

imagen

La biblioteca asume la presencia de un objetivo (variable dependiente) en nuestros datos e inmediatamente en una imagen muestra la fuerza y ​​la dirección de la relación y también se clasifica en orden descendente de esta fuerza formando un embudo visual (de hecho, de aquí proviene el nombre).

Las funciones de binarización integradas en la biblioteca le permiten reducir categorías pequeñas a Otros.

Como la biblioteca no funciona con variables enteras, las convertiremos a numéricas y volveremos a nuestro Titanic.

 #install.packages("correlationfunnel") library(correlationfunnel) d <- d %>% mutate_if(is.integer,as.numeric) d %>% binarize(n_bins = 5,thresh_infreq = .02,one_hot = T) %>% #    correlate(target = Survived__yes) %>% plot_correlation_funnel() # "interactive = T" - plotly! 

imagen

En el eje X, tenemos la fuerza y ​​la dirección de correlación, en el eje Y, nuestros predictores se clasifican en orden descendente. El primero siempre refleja el objetivo como él tiene la correlación más fuerte consigo mismo (-1; 1).

Veamos cómo las conclusiones de este gráfico se superponen con las conclusiones del autor de nuestro "Baseline_EDA".
El siguiente gráfico confirma la teoría de que cuanto mayor sea la clase de cabina de pasajeros, mayores serán las posibilidades de supervivencia. (Por "arriba", me refiero al orden inverso, porque la primera clase es más alta que la segunda y, especialmente, la tercera).
El embudo muestra que la clase es el tercer predictor en términos de fuerza de correlación, y de hecho, en la tercera clase, la correlación inversa, en la primera, es muy positiva.
Compare las posibilidades de supervivencia para hombres y mujeres. Los datos confirman la teoría expresada anteriormente.

(En general, ya podemos decir que los principales factores del modelo serán el género del pasajero)

El embudo muestra que el sexo del pasajero es el segundo según el grado de correlación, el género femenino se correlaciona con la supervivencia, el género masculino se correlaciona con la muerte.
También puede probar la hipótesis de que los más jóvenes sobreviven, porque se mueven más rápido, nadan mejor, etc.

Como puede ver, una dependencia explícita no es visible aquí.

El embudo realmente habla del significado débil de este predictor (recuerdo que el gonorante / título contiene la edad, por lo que la edad no es tan significativa), pero incluso aquí el embudo muestra que hay más posibilidades de sobrevivir en las categorías "menos infinito - 20 años" (es decir, niños ) y 30-38 (personas ricas, posiblemente 1 clase).
Presentemos un indicador como Porcentaje de supervivencia y analicemos su dependencia de los grupos que resultaron en la etapa anterior.

(el grupo del autor significa el título).

Funnel confirma completamente los hallazgos del autor.
Ahora veamos la información que se puede obtener del número de parientes en el barco.

Es muy probable que la ausencia de parientes, así como un gran número, afecte negativamente la supervivencia.

SibSP en el embudo dice claramente lo mismo.

Y, por supuesto, además de las conclusiones del autor, aquí puede ver otros patrones, dejaré el placer de la contemplación al lector.

Lares


Encuentre ideas con correlaciones cruzadas clasificadas

imagen

El autor de esta biblioteca fue aún más lejos: muestra las dependencias no solo del objetivo, sino también de todo.

Las correlaciones cruzadas clasificadas no solo explican las relaciones de una característica de destino específica con el resto, sino también la relación de todos los valores en sus datos en un formato tabular fácil de usar y comprender.

Convierte automáticamente las columnas categóricas en numéricas con una codificación activa (1s y 0s) y otras agrupaciones inteligentes como etiquetas de "otros" para valores no muy frecuentes y nuevas características desactualizadas.


Usando el enlace de arriba, puede ver un ejemplo en el que el autor alimenta el conjunto de datos de Star Wars a su paquete y demuestra las dependencias encontradas, me he quedado en su página, muy bien.

Probemos con nuestro ejemplo.

 # ,     : # devtools::install_github("laresbernardo/lares") library(lares) corr_cross(df = d,top = 30) 

imagen

Además de la intersección con las conclusiones basadas en citas, en Correlationfunnell presentamos algunas citas que podemos ver aquí independientemente del objetivo:
También se pueden encontrar otros patrones. Existe una correlación negativa entre la edad y la clase, que probablemente se deba a que los pasajeros mayores pueden pagar una cabina más cara con mayor frecuencia.

En la cita anterior, el autor saca esa conclusión sobre el análisis de correlación de 2 campos en total, pero en vista de One-Hot-Encoding, esto es evidente a partir de la fuerte correlación positiva entre Age + P_Class_1.
Además, el precio del boleto y la clase están estrechamente relacionados (alto coeficiente de correlación), lo cual es bastante esperado.

Tercera línea arriba: Tarifa + P_Class_1

Además de cruzarse con las conclusiones del autor, aquí se pueden enfatizar cosas mucho más interesantes, también dejaré el placer de la contemplación para el lector.

Además de la selección opcional de las X ideas más poderosas, también puede reflejar la imagen completa y el lugar de estos puntos significativos en la masa total

 corr_cross(df = d,type=2) 

imagen

easyalluvial


Exploración de datos con parcelas aluviales

imagen

Aquí, como en los 2 paquetes anteriores, el autor realiza la binarización de variables numéricas al principio, pero luego sus caminos con esas bibliotecas divergen: en lugar de {One-HotEncoding + correlation}, la biblioteca presenta la X superior de los predictores más interesantes (el usuario decide cuáles transferir) ) por valores, formando flujos cuyo color depende del objetivo, y el ancho de la secuencia en el número de observaciones en esta secuencia.

Las variables numéricas se descomponen en categorías HH (Alto Alto), MH (Medio Alto), M (Medio), ML (Medio Bajo), LL (Bajo Bajo)

Primero, tomemos los predictores más significativos basados ​​en el gráfico del correlationfunnel:

 cor.feat <- c("title","Sex","Pclass","Fare") 

A continuación, hacemos un horario.

 # install.packages("easyalluvial") library(easyalluvial) al <- d %>% select(Survived,cor.feat) %>% alluvial_wide(fill_by = "first_variable") add_marginal_histograms(p = al,data_input = d,keep_labels = F) 

imagen

Para las citas del autor, volvemos a dibujar el gráfico usando los predictores apropiados

 cor.feat <- c("Sex","Pclass","Age") al <- d %>% select(Survived,cor.feat) %>% alluvial_wide(fill_by = "first_variable") add_marginal_histograms(p = al,data_input = d,keep_labels = F) 

imagen

Por ejemplo, el siguiente gráfico muestra claramente que los principales grupos de sobrevivientes son mujeres de primer y segundo grado de todas las edades.

El gráfico también muestra que las mujeres sobrevivientes de grado 3 tampoco son un grupo pequeño

Y entre los hombres, todos los niños menores de 15 años sobrevivieron, excepto la tercera clase de servicio y una pequeña proporción de hombres mayores y principalmente de la primera clase.

Lo anterior se confirma, pero nuevamente vemos los flujos de hombres sobrevivientes de clase 3 en la categoría de edad LL, ML.

Todo lo anterior era sobre el paquete "easyalluvial", pero el autor escribió un segundo paquete "parcats" que en la parte superior de la gráfica hace que el gráfico anterior sea interactivo (como en el título de esta sección).
Esto hace posible no solo ver el contexto de la información sobre herramientas, sino también reorientar los flujos para una mejor percepción visual. (desafortunadamente, mientras que la biblioteca no está muy optimizada y se ralentiza en Titanic)

 # install.packages("parcats") library(parcats) cor.feat <- c("title","Sex","Pclass","Fare") a <- d %>% select(Survived,cor.feat) %>% alluvial_wide(fill_by = "first_variable") parcats(p = a,marginal_histograms = T,data_input = d) 

imagen

Bono


La biblioteca easyalluvial, además del análisis exploratorio de datos, también se puede utilizar como un intérprete para los modelos de caja negra (modelos que analizan los parámetros de los cuales no se pueden entender, por qué lógica el modelo da una respuesta basada en ciertos predictores).

Enlace al artículo del autor: Visualice la respuesta del modelo con gráficos aluviales
Y la peculiaridad es que de todas las bibliotecas que vi, el máximo en un gráfico explica la respuesta del cuadro negro en un sistema de coordenadas de no más de 2 dimensiones (una para cada predictor), el color explica la respuesta.

La biblioteca easyalluvial le permite hacer esto en más de 2 predictores al mismo tiempo (por supuesto, es mejor no dejarse llevar).

Por ejemplo, entrenemos un bosque aleatorio en nuestra matriz de datos y reflejemos la explicación de un bosque aleatorio utilizando 3 predictores.

 library(ranger) m <- ranger(formula = Survived~.,data = d,mtry = 6,min.node.size = 5, num.trees = 600, importance = "permutation") library(easyalluvial) (imp <- importance(m) %>% as.data.frame %>% easyalluvial::tidy_imp(imp = .,df=d)) #      #  N-     (   .  !)   dspace <- get_data_space(df = d,imp,degree = 3) #     pred = predict(m, data = dspace) alluvial_model_response(pred$predictions, dspace, imp, degree = 3) 

Además, el autor tiene un conector para los modelos CARET (no sé cuán relevante esto ahora está considerando tidymodels)

 library(caret) trc <- trainControl(method = "none") m <- train(Survived~.,data = d,method="rf",trControl=trc,importance=T) alluvial_model_response_caret(train = m,degree = 4,bins=5,stratum_label_size = 2.8) 

imagen

Conclusión


Una vez más, repito que no solicito el reemplazo del clásico EDA, pero estoy de acuerdo en que es bueno cuando hay una alternativa que ahorra mucho tiempo, especialmente teniendo en cuenta que las personas son lo suficientemente flojas, y esto, como saben, es el motor del progreso :)

Source: https://habr.com/ru/post/480532/


All Articles