1kakcqr5kwhppr7eegxedgw.png

Un método de detección de valores atípicos que admite datos categóricos y proporciona explicaciones para los valores atípicos marcados.

La detección de valores atípicos es una tarea común en el aprendizaje automático. Específicamente, es una forma de aprendizaje automático no supervisado: analizar datos donde no hay etiquetas. Es el acto de encontrar elementos en un conjunto de datos que sean inusuales en relación con los demás en el conjunto de datos.

Puede haber muchas razones para desear identificar valores atípicos en los datos. Si los datos que se examinan son registros contables y estamos interesados ​​en encontrar errores o fraudes, generalmente hay demasiadas transacciones en los datos para examinarlas manualmente, y es necesario seleccionar una cantidad pequeña y manejable de transacciones para investigar. Un buen punto de partida puede ser encontrar los registros más inusuales y examinarlos; Esto se debe a la idea de que los errores y el fraude deberían ser lo suficientemente raros como para destacarse como valores atípicos.

Es decir, no todos los valores atípicos serán interesantes, pero los errores y el fraude probablemente serán valores atípicos, por lo que, al buscarlos, identificar los valores atípicos puede ser una técnica muy práctica.

O bien, los datos pueden contener transacciones con tarjetas de crédito, lecturas de sensores, mediciones meteorológicas, datos biológicos o registros de sitios web. En todos los casos, puede resultar útil identificar los registros que sugieren errores u otros problemas, así como los registros más interesantes.

Además, a menudo la detección de valores atípicos se utiliza como parte de un descubrimiento científico o empresarial, para comprender mejor los datos y los procesos que se describen en los datos. Con datos científicos, por ejemplo, a menudo nos interesa encontrar los registros más inusuales, ya que pueden ser los más interesantes desde el punto de vista científico.

La necesidad de interpretabilidad en la detección de valores atípicos

En los problemas de clasificación y regresión, suele ser preferible utilizar modelos interpretables. Esto puede dar como resultado una menor precisión (con datos tabulares, la mayor precisión generalmente se encuentra con modelos mejorados, que son bastante ininterpretables), pero también es más seguro: sabemos cómo los modelos manejarán los datos invisibles. Pero, con los problemas de clasificación y regresión, también es común no necesitar entender por qué las predicciones individuales se hacen tal como son. Mientras los modelos sean razonablemente precisos, puede ser suficiente simplemente dejarles hacer predicciones.

Sin embargo, con la detección de valores atípicos, la necesidad de interpretabilidad es mucho mayor. Cuando un detector de valores atípicos predice un registro es muy inusual; si no está claro por qué puede ser así, es posible que no sepamos cómo manejar el elemento, o incluso si deberíamos creer que es anómalo.

De hecho, en muchas situaciones, realizar la detección de valores atípicos puede tener un valor limitado si no se comprende bien por qué se marcaron los elementos marcados como valores atípicos. Si estamos verificando un conjunto de datos de transacciones con tarjetas de crédito y una rutina de detección de valores atípicos identifica una serie de compras que parecen ser muy inusuales y, por lo tanto, sospechosas, solo podemos investigarlas de manera efectiva si sabemos qué tienen de inusual. En algunos casos esto puede ser obvio, o puede quedar claro después de pasar algún tiempo examinándolos, pero es mucho más efectivo y eficiente si la naturaleza de las anomalías queda clara desde el momento en que se descubren.

Al igual que con la clasificación y la regresión, en los casos en los que la interpretabilidad no es posible, a menudo es posible intentar comprender las predicciones utilizando lo que se denomina explicaciones post-hoc (a posteriori). Estos utilizan técnicas XAI (IA explicable), como importancias de características, modelos proxy, gráficos ALE, etc. Estos también son muy útiles y se tratarán en artículos futuros. Pero también existe un gran beneficio al tener resultados que sean claros desde el principio.

En este artículo, analizamos específicamente los datos tabulares, aunque analizaremos otras modalidades en artículos posteriores. Existe una serie de algoritmos para la detección de valores atípicos en datos tabulares que se usan comúnmente en la actualidad, incluidos bosques de aislamiento, factor de valores atípicos locales (LOF), KNN, SVM de clase única y muchos otros. Estos suelen funcionar muy bien, pero lamentablemente la mayoría no proporciona explicaciones para los valores atípicos encontrados.

La mayoría de los métodos de detección de valores atípicos son fáciles de entender a nivel de algoritmo, pero, sin embargo, es difícil determinar por qué algunos registros recibieron una puntuación alta por parte de un detector y otros no. Si procesamos un conjunto de datos de transacciones financieras con, por ejemplo, un Bosque de Aislamiento, podemos ver cuáles son los registros más inusuales, pero podemos no saber por qué, especialmente si la tabla tiene muchas características, si los valores atípicos contienen datos raros. combinaciones de múltiples características, o valores atípicos, son casos en los que ninguna característica es muy inusual, pero múltiples características son moderadamente inusuales.

Factor de valores atípicos de patrones frecuentes (FPOF)

Ahora hemos repasado, al menos rápidamente, la detección y la interpretabilidad de valores atípicos. El resto de este artículo es un extracto de mi libro Detección de valores atípicos en Python (https://www.manning.com/books/outlier-detection-in-python), que cubre específicamente la FPOF.

FPOF (FP-outlier: detección de valores atípicos basada en patrones frecuentes) es uno de los pocos detectores que pueden proporcionar cierto nivel de interpretabilidad para la detección de valores atípicos y merece ser utilizado en la detección de valores atípicos más de lo que es.

También tiene la atractiva propiedad de estar diseñado para trabajar con datos categóricos, en lugar de numéricos. La mayoría de los datos tabulares del mundo real son mixtos y contienen columnas numéricas y categóricas. Sin embargo, la mayoría de los detectores asumen que todas las columnas son numéricas, lo que requiere que todas las columnas categóricas estén codificadas numéricamente (usando codificación one-hot, ordinal u otra).

Cuando los detectores, como FPOF, asumen que los datos son categóricos, tenemos el problema opuesto: todas las características numéricas deben agruparse para que estén en un formato categórico. Cualquiera de los dos es viable, pero cuando los datos son principalmente categóricos, es conveniente poder utilizar detectores como FPOF.

Y cuando se trabaja con la detección de valores atípicos, existe la ventaja de tener a nuestra disposición algunos detectores numéricos y algunos detectores categóricos. Como, lamentablemente, hay relativamente pocos detectores categóricos, FPOF también es útil a este respecto, incluso cuando la interpretabilidad no es necesaria.

El algoritmo FFOF

FPOF trabaja identificando lo que se llaman Conjuntos de artículos frecuentes (FIS) en una tabla. Se trata de valores de una única característica que son muy comunes o conjuntos de valores que abarcan varias columnas y que con frecuencia aparecen juntos.

Casi todos los cuadros contienen una colección importante de FIS. Los FIS basados ​​en valores únicos ocurrirán siempre que algunos valores en una columna sean significativamente más comunes que otros, lo que casi siempre es el caso. Y los FIS basados ​​en múltiples columnas ocurrirán siempre que existan asociaciones entre las columnas: ciertos valores (o rangos de valores numéricos) tienden a estar asociados con otros valores (o, nuevamente, rangos de valores numéricos) en otras columnas.

FPOF se basa en la idea de que, siempre que un conjunto de datos tenga muchos conjuntos de elementos frecuentes (que casi todos los tienen), la mayoría de las filas contendrán múltiples conjuntos de elementos frecuentes y los registros internos (normales) contendrán conjuntos de elementos significativamente más frecuentes que las filas atípicas. . Podemos aprovechar esto para identificar valores atípicos como filas que contienen muchos menos FIS y mucho menos frecuentes que la mayoría de las filas.

Ejemplo con datos del mundo real

Para ver un ejemplo del mundo real del uso de FPOF, observamos el conjunto SpeedDating de OpenML (https://www.openml.org/search?type=data&sort=nr_of_likes&status=active&id=40536con licencia CC BY 4.0 DEED).

La ejecución de FPOF comienza con la extracción del conjunto de datos para los FIS. Hay varias bibliotecas disponibles en Python para admitir esto. Para este ejemplo, usamos mlxtend (https://rasbt.github.io/mlxtend/), una biblioteca de uso general para el aprendizaje automático. Proporciona varios algoritmos para identificar conjuntos de elementos frecuentes; Usamos uno aquí llamado a priori.

Primero recopilamos los datos de OpenML. Normalmente usaríamos todas las características categóricas y numéricas (agrupadas), pero para simplificar aquí, solo usaremos una pequeña cantidad de características.

Como se indicó, FPOF requiere agrupar las funciones numéricas. Por lo general, simplemente usaríamos un número pequeño (quizás de 5 a 20) contenedores de igual ancho para cada columna numérica. El método pandas cut() es conveniente para esto. Este ejemplo es incluso un poco más simple, ya que solo trabajamos con columnas categóricas.

from mlxtend.frequent_patterns import apriori
import pandas as pd
from sklearn.datasets import fetch_openml
import warnings

warnings.filterwarnings(action='ignore', category=DeprecationWarning)

data = fetch_openml('SpeedDating', version=1, parser='auto')
data_df = pd.DataFrame(data.data, columns=data.feature_names)

data_df = data_df[['d_pref_o_attractive', 'd_pref_o_sincere',
'd_pref_o_intelligence', 'd_pref_o_funny',
'd_pref_o_ambitious', 'd_pref_o_shared_interests']]
data_df = pd.get_dummies(data_df)
for col_name in data_df.columns:
data_df[col_name] = data_df[col_name].map({0: False, 1: True})

frequent_itemsets = apriori(data_df, min_support=0.3, use_colnames=True)

data_df['FPOF_Score'] = 0

for fis_idx in frequent_itemsets.index:
fis = frequent_itemsets.loc[fis_idx, 'itemsets']
support = frequent_itemsets.loc[fis_idx, 'support']
col_list = (list(fis))
cond = True
for col_name in col_list:
cond = cond & (data_df[col_name])

data_df.loc[data_df[cond].index, 'FPOF_Score'] += support

min_score = data_df['FPOF_Score'].min()
max_score = data_df['FPOF_Score'].max()
data_df['FPOF_Score'] = [(max_score - x) / (max_score - min_score)
for x in data_df['FPOF_Score']]

El algoritmo a priori requiere que todas las funciones estén codificadas en caliente. Para esto, utilizamos el método get_dummies() de panda.

Luego llamamos al método a priori para determinar los conjuntos de elementos frecuentes. Para ello debemos especificar el soporte mínimo, que es la mínima fracción de filas en las que aparece el FIS. No queremos que sea demasiado alto, o los registros, incluso los más importantes, contendrán pocos FIS, lo que hará difícil distinguirlos de los valores atípicos. Y no queremos que esto sea demasiado bajo, o los FIS pueden no ser significativos y los valores atípicos pueden contener tantos FIS como los valores internos. Con un soporte mínimo bajo, a priori también puede generar una gran cantidad de FIS, lo que hace que la ejecución sea más lenta y la interpretabilidad más baja. En este ejemplo, utilizamos 0,3.

También es posible, y a veces se hace, establecer restricciones en el tamaño de los FIS, exigiendo que se relacionen con un número mínimo y máximo de columnas, lo que puede ayudar a limitar la forma de los valores atípicos que más le interesan.

Los conjuntos de elementos frecuentes luego se devuelven en un marco de datos de pandas con columnas para el soporte y la lista de valores de columna (en forma de columnas codificadas en caliente, que indican tanto la columna como el valor original).

Para interpretar los resultados, primero podemos ver los conjuntos de elementos frecuentes, que se muestran a continuación. Para incluir la longitud de cada FIS sumamos:

frequent_itemsets['length'] = \
frequent_itemsets['itemsets'].apply(lambda x: len(x))

Se han encontrado 24 FIS y el más largo cubre tres características. La siguiente tabla muestra las diez primeras filas, ordenadas por soporte.

Luego recorremos cada conjunto de elementos frecuentes e incrementamos la puntuación de cada fila que contiene el elemento frecuente establecido por el soporte. Opcionalmente, esto se puede ajustar para favorecer conjuntos de ítems frecuentes de mayor longitud (con la idea de que un FIS con un soporte de, digamos, 0,4 y que cubra 5 columnas es, en igualdad de condiciones, más relevante que un FIS con un soporte de 0,4 que cubra, digamos, 2 columnas), pero aquí simplemente usamos el número y el apoyo de los FIS en cada fila.

En realidad, esto produce una puntuación de normalidad y no de valores atípicos, por lo que cuando normalizamos las puntuaciones para que estén entre 0,0 y 1,0, invertimos el orden. Las filas con las puntuaciones más altas son ahora los valores atípicos más fuertes: las filas con los conjuntos de elementos menos frecuentes y menos comunes.

Al agregar la columna de puntuación al marco de datos original y ordenar por puntuación, vemos la fila más normal:

Podemos ver que los valores de esta fila coinciden bien con los FIS. El valor de d_pref_o_atractive es [21–100], que es un FIS (con soporte 0,36); los valores para d_pref_o_ambitious y d_pref_o_shared_interests son [0–15] y [0–15], que también es un FIS (soporte 0,59). Los otros valores también tienden a coincidir con los FIS.

La fila más inusual se muestra a continuación. Esto no coincide con ninguno de los FIS identificados.

Como los conjuntos de elementos frecuentes en sí son bastante inteligibles, este método tiene la ventaja de producir resultados razonablemente interpretables, aunque esto es menos cierto cuando se utilizan muchos conjuntos de elementos frecuentes.

La interpretabilidad se puede reducir, ya que los valores atípicos se identifican no por contener FIS, sino por no contenerlos, lo que significa que explicar la puntuación de una fila equivale a enumerar todos los FIS que no contiene. Sin embargo, no es estrictamente necesario enumerar todos los FIS faltantes para explicar cada valor atípico; enumerar un pequeño conjunto de los FIS más comunes que faltan será suficiente para explicar los valores atípicos a un nivel decente para la mayoría de los propósitos. Las estadísticas sobre los FIS que están presentes y los números y frecuencias normales de los FIS presentes en filas proporcionan un buen contexto para comparar.

Una variación de este método utiliza conjuntos de elementos poco frecuentes, en lugar de frecuentes, puntuando cada fila por el número y la rareza de cada conjunto de elementos poco frecuentes que contienen. Esto también puede producir resultados útiles, pero es significativamente más costoso desde el punto de vista computacional, ya que es necesario extraer muchos más conjuntos de elementos y cada fila se prueba con muchos FIS. Sin embargo, las puntuaciones finales pueden ser más interpretables, ya que se basan en los conjuntos de elementos encontrados, no faltantes, en cada fila.

Conclusiones

Aparte del código aquí, no conozco una implementación de FPOF en Python, aunque hay algunas en R. La mayor parte del trabajo con FPOF consiste en extraer los FIS y existen numerosas herramientas de Python para esto, incluida la biblioteca mlxtend. utilizado aquí. El código restante para FPOP, como se ve arriba, es bastante simple.

Dada la importancia de la interpretabilidad en la detección de valores atípicos, muy a menudo vale la pena intentarlo.

En artículos futuros, también repasaremos algunos otros métodos interpretables para la detección de valores atípicos.

Todas las imágenes son del autor.