Explorando el API de Anomaly Detector
Esta publicación es parte del Segundo Calendario de Adviento de C# en Español, una iniciativa liderada por Benjamín Camacho. Revisa este enlace para conocer más artículos interesantes sobre C# publicados por varios miembros de la comunidad. También está incluida en el Calendario de Adviento Xamarin organizado por Luis Beltrán. Revisa el resto de geniales aportes por parte de la comunidad en este enlace.
La detección de anomalías es el proceso de encontrar valores atípicos o eventos inesperados a partir de flujos de datos con una dimension del tiempo (“Mi valor actual no es lo que debería ser en este momento”) con el fin de tomar decisiones y resolver problemas generados por la anomalía.
En otras palabras, el proceso de detección de anomalías consiste en reconocer patrones inusuales de comportamiento en los datos, patrones que no van de acuerdo a los valores esperados.
Anomaly Detector es un nuevo servicio incluido en la oferta de Azure Cognitive Services que permite identificar situaciones extrañas en los datos. A través de una API, Anomaly Detector monitorea y analiza una serie temporal de datos y selecciona el modelo de detección de anomalías que mejor se ajusta con una precisión elevada.
¿Qué se puede construir con Anomaly Detector?
- Detección de intrusos
- Identificación de fraudes bancarios
- Sistemas de monitoreo de salud
- Detección de eventos en redes de sensores
El servicio de Anomaly Detector ofrece un API REST con tres modos de detección:
- Detección de anomalías como un lote (timeseries/entire/detect):
Esta operación genera un modelo utilizando la serie completa, donde cada punto se analiza con el mismo modelo para determinar si algún elemento se trata de una anomalía.
- Detección del estado de anomalía del punto de datos más reciente (timeseries/last/detect): Esta operación genera un modelo con todos los puntos excepto el último, es decir, se utilizan valores históricos para determinar si el último elemento es una anomalía. Un escenario de uso es el monitoreo en tiempo real de las métricas comerciales.
- Detección del punto de cambio de tendencia como un lote (timeseries/changepoint/detect): Esta operación es idéntica a la primera, se genera un modelo a partir de la serie completa y cada punto se analiza con el mismo modelo, la diferencia es que con este método se busca determinar si algún elemento representa un punto de cambio de tendencia.
Los datos de entrada para el API son una colección de datos numéricos registrados en una fecha determinada. Los datos deben estar ordenados. La serie de tiempo debe contener 12 puntos por lo menos (máximo 8, 640 puntos). Además, se debe indicar la granularidad, es decir, el periodo de tiempo de separación entre cada muestra (diario, semanal, mensual, etc.).
Otro elemento indispensable es la sensibilidad, la cual nos permite controlar el nivel/límite para indicar si un punto es anómalo o no.
Un nivel de sensibilidad alto significa que hay menos margen de tolerancia entre el dato real y el dato esperado, lo que levantará la alerta de anomalía. En el ejemplo mostrado a continuación, la serie contiene 11 anomalías con un nivel de sensibilidad del 99%.
Por tanto, una sensibilidad baja implica que los límites (boundaries) son mayores (más flexibilidad), resultando en menos anomalías. En la segunda imagen puedes observar que solo se detectaron 9 datos extraños bajando la sensibilidad al 95%
La serie de datos deben tener una marca de tiempo válida en hora universal (UTC) y un valor numérico. A continuación tienes un ejemplo válido que puedes suministrar al API en formato JSON:
Cada modo de detección genera una estructura de salida distinta (en formato JSON). Por ejemplo, a continuación se muestra el resultado de aplicar detección de anomalías como un lote sobre una serie de datos:
Lo último que debes conocer para ahora sí empezar con el código es que para utilizar el servicio de Anomaly Detector hay que crear un recurso en Azure, el cual nos dará una key y un endpoint que incluiremos en la cabecera de la petición así:
- Content-Type: application/json
- Ocp-Apim-Subscription-Key: tu llave del servicio
- Endpoint: se coloca en la URI de petición, por ejemplo https://westeurope.api.cognitive.microsoft.com/anomalydetector/v1.0/timeseries/last/detect
Después de la teoría, vamos a la práctica. Utilizaré una app de Xamarin para mostrar el uso de AnomalyDetector, aunque mucho de lo mostrado aplica para otras plataformas con C#:
Paso 1. En el Portal de Azure crea un nuevo recurso de tipo Anomaly Detector, indicando un nombre, suscripción, ubicación, precio y grupo de recursos.
Paso 2. Una vez provisionado el recurso, localiza la key y el endpoint. Cópialos, los necesitaremos en nuestra app.
Paso 3. En Visual Studio 2019, crea un proyecto de app móvil Xamarin.Forms.
Paso 4. Agrega las carpetas Data, Helpers, Models, Services, ViewModels y Models al proyecto de código compartido.
Paso 5. En la carpeta Data agrega el archivo data.csv con las propiedades Build Action como Embedded resource y Copy to Output Directory en el valor Copy Always. Este archivo contiene la información sobre Tasas de clics de publicidad en línea, donde las métricas son el costo por clic a través del tiempo.
Paso 6. En la carpeta Helpers crea la clase Constants con el código siguiente:
Paso 7. En la carpeta Models agrega el archivo AnomalyAnalisis, la cual contiene varias clases para realizar la petición y formatear la respuesta del servicio. Se muestran a continuación:
Paso 8. A continuación, en la carpeta Services crea la clase FileService, que servirá para leer el contenido del archivo data.csv que agregaste y almacenarlo en una colección de objetos DataPoint. El código se muestra a continuación:
Paso 9. Agrega el paquete Newtonsoft.Json a todos los proyectos de tu solución desde el Administrador de Paquetes Nuget.
Paso 10. En la misma carpeta Services agrega otra clase llamada AnomalyDetectorService, la cual prepara y realiza una petición al API de AnomalyDetector:
- En el método CreateHttpClient se establece la URL base (el endpoint de tu recurso en Azure) y se pasa la llave del servicio en el encabezado de la petición.
- El método AnalyzeData envía un objeto DataRequest al método de detección de anomalías por lotes y devuelve un objeto DataResult que nos dirá cuáles puntos representan una anormalidad en la serie.
El código se muestra a continuación:
Paso 11. En la carpeta ViewModels agrega la clase BaseViewModel, que es útil para implementar MVVM en nuestro proyecto, notificando cambios a la vista.
Paso 12. Agrega los paquetes Nuget Microcharts.Forms y Microcharts a todos los proyectos de la solución. Este plugin nos permitirá graficar la serie de tiempo.
Paso 13. En la carpeta ViewModels agrega la clase AnomalyViewModel, en donde se incluye lo siguiente:
- El Command AnalyzeDataCommand que ejecutará el método AnalyzeData.
- La propiedad Sensitivity, que permitirá al usuario ajustar la sensibilidad del método de detección de anomalías.
- Un objeto DataRequest que será enviado a Azure para detectar anormalidades en la serie de tiempo que contendrá.
- Un objeto DataResult que contendrá el resultado del análisis de los puntos por parte de Azure.
- La colección observable DataPoints, que es la serie de tiempo cargada con los datos contenidos en el archivo data.csv.
- La colección observable DataPointEx, que es la colección de puntos obtenidos a partir del análisis por parte de Azure.
- Un objeto Chart que contiene los datos a mostrar en la gráfica.
- El constructor, que llama a los métodos GetData y CreateChart.
- El método GetData, que construye el objeto DataRequest a partir de los datos leidos del archivo data.csv
- El método CreateChart, que crea una instancia de Chart a partir de los puntos contenidos en el objeto DataRequest.
- Finalmente, el método AnalyzeData, el cual llama al servicio de AnomalyDetector para que detecte anormalidades en los datos enviados (DataRequest). El resultado de la llamada permite construir la colección DataPointEx, con la cual se regenera la gráfica -que ahora incluirá las anomalías detectadas-.
El código se muestra a continuación:
Paso 14. Por último, vamos a agregar la ContentPage AnomalyView en la carpeta Views. El código de la interfaz se muestra a continuación, y básicamente:
- Se establece una instancia de AnomalyViewModel como BindingContext de la vista
- Se incluye un ChartView que graficará la serie de tiempo.
- El usuario puede ajustar el nivel de sensibilidad del detector de anomalías a través de un picker
- Con un Button se puede analizar la información
- También se incluye un ListView que muestra cada uno de los datos de la serie
El código por supuesto, se muestra a continuación:
Paso 15. Ya solo resta modificar App.xaml.cs para establecer la página de inicio del proyecto, que por supuesto será nuestra única vista: AnomalyView
Paso 16. Compila y ejecuta. Demos un vistazo al proyecto:
El código fuente del proyecto está disponible en mi repositorio de GitHub.
Recomendaciones finales:
- En los datos de entrada, los puntos de datos se recomienda que estén separados por el mismo intervalo de tiempo.
- El máximo de datos faltantes puede ser del 10% en relación al número esperado de puntos.
- Incluir por lo menos 12 puntos de datos si no existe un patrón estacional claro.
- O incluir al menos 4 ocurrencias de patrones en caso de que los datos tengan un patrón estacional definido.
Ya para concluir, comentar que detrás del API de Anomaly Detector, Microsoft ha concentrado todo un cúmulo de algoritmos, técnicas y conceptos avanzados que listaré por si quieres aprender más sobre cómo funcionan los sistemas de detección de anomalías:
- Transformadas de Fourier
- Extreme Studentized Deviate (ESD)
- Descomposición de series de tiempo en tendencias (STL)
- Umbral dinámico (Dynamic Threshold)
- Detector de Z-score
- Spectral Residual (SR)
- SR-CNN (SR con red neuronal de convolución)
Más información sobre Anomaly Detector:
Espero que esta publicación te haya sido de utilidad, no olvides compartirla en tus redes sociales, tal vez le sirva a alguien más =)
No olvides seguir el resto de las interesantes publicaciones del Segundo Calendario de Adviento C# en Español. También puedes seguir la conversación en Twitter con el hashtag #advientocsharp.
¡Gracias por la visita y hasta la próxima!
Luis