Preparar datos para deep learning, es una tarea muy dependiente de la entrada que necesite nuestra red y de los datos que tenemos. En este capítulo vamos a ver como preparar datos para deep learning con databricks para un problema de clasificación aparentemente sencillo que es saber si un dominio de internet es malicioso o no simplemente con el texto del mismo.
Vamos a disponer de un conjunto de datos muy grande de dominios de internet que tienen la catalogación de “buenos” y “malos”, donde los “malos” son dominios generados por software malicioso. En principio no vamos a entrar en los detalles ahora del problema que queremos resolver ni del apartado relativo a la propia red neuronal, sino que vamos a verlo desde el punto de vista puro del tratamiento de datos.
La red neuronal que vamos a entrenar va ser fundamentalmente una arquitectura de tipo LSTM con capa de atención (no vamos a entrar en sus detalles ahora). Puesto que su tarea va a ser “clasificación”, lo que vamos a necesitar va a ser:
- Array de números con las características a utilizar para entrenar la red neuronal.
- Array de números con las etiquetas de cada dominio de internet.
Los datos que vamos a tener son un conjunto muy grande de dominios de internet y su categoria (junto a mas información irrelevante para este problema).
Vamos a disponer por tanto de algo así:
Y lo que buscamos es tener algo así:
Es decir, tendremos que convertir nuestros dominios a un array numérico y las etiquetas a números.
Como ves, si has trabajado con redes neuronales es un problema bastante sencillo, siendo aqui el único “problema” el volumen de datos que vamos a mover.
Respecto a los datos que vamos a utilizar: Disponemos de 93 tipos de malware detectados, teniendo algunos de ellos comprometidos mas de 100 millones de direcciones, por lo que puedes imaginarte que hablamos de bastantes datos y que nuestro laptop no va a poder en tiempo razonable procesarlo para poder prepararlos.
Para ello resumo a alto nivel lo que vamos a hacer:
- Crear cluster Databricks
- Montar nuestro blob storage en nuestro cluster
- Subir los ficheros a procesar
- Procesar los ficheros para preparar los datos para el modelo
- Limpiar los datos
- Calcular las clases
- Tokenizar nuestros dominios y transformarlos de texto a array de números
- Volcar los datos a un csv
- Destruir cluster Databricks (opcional)
- Destruir blob storage (opcional)
Crear cluster Databricks
Lo primero que vamos a hacer es crearnos nuestro cluster Databricks. Como es algo bastante sencillo y documentado, puede seguir esta estupenda guia de Microsoft
En lo que a nosotros nos afecta, solo quiero añadir que puesto que DBFS no permite subir ficheros de más de 2Gb de tamaño y que nuestro conjunto de datos sobrepasa eso con creces, lo que vamos a hacer es montar un Azure blob storage en nuestro cluster y para subir ahi nuestros datos con los que poder trabajar.
Desplegar nuestro blob storage
Tal como hemos comentado, vamos a necesitar un almacenamiento con el que poder trabajar, porque DBFS no nos va a dejar subir ficheros de más de 2Gb. Vamos en este caso a utilizar Azure Blob Storage por comodidad y precio. Para crear un blob storage te recomiendo que sigas esta guia oficial
Una vez creado, añadiremos nuestro contenedor para trabajar con databricks, que en este caso le voy a llamar sentinelml
Subir los ficheros a procesar
Y ahora añadimos los ficheros .csv como block blob:
Importante: Databricks por ahora solo permite trabajar con ficheros montados en modo block blob.
Montar nuestro blob storage en nuestro cluster
Para hacerlo, podemos seguir este snippet:
NOTA: Para más información ver https://docs.databricks.com/data/data-sources/azure/azure-storage.html#mount-azure-blob
- nombre del Azure Blob storage account (el que le pusieras)
- nombre del contenedor con los datos (el que le pusieras)
- DBFS path donde montaremos el contenedor (puedes poner lo que quieras aqui, se montará con el nombre que le des)
- Puede ser fs.azure.account.key..blob.core.windows.net o fs.azure.sas…blob.core.windows.net
- Yo con esto me lié un poco 😃. Lo que quiere decir, es que pongas cualquiera de los 2 strings de texto tal cual aparecen con el replace correspondiente, luego verás un ejemplo
- dbutils.secrets.get(scope = “”, key = “<\key-name>”) obtiene la key de los secrets de databricks (opción preferida para producción)
- En mi caso, puesto que va a ser para lanzar un procesado rápido, voy a ponerle la key1 de mi storage account directamente.
De forma que un posible ejemplo podría ser:
Ahora solo tienes que lanzarlo desde tu cluster y ya quedará montado para siempre (mientras no lo desmontes):
Y probar que efectivamente puedes acceder a tus ficheros:
Preparar los datos
En este paso vamos a realizar varias cosas, algunas en pyspark y otras en sparksql. Aqui ya es a gusto del desarrollador, yo simplemente me siento mas cómodo trabajando con SQL y por eso verás mucha query 😃
Limpiar los datos
Lo primero va a ser obtener un conjunto de datos nivelado por clases. Puesto que tengo 2M de dominios catalogados como “buenos” y más de 100M catalogados como “malos”, para minimizar el bias lo que voy a hacer es primero cargar cada clase con un conjunto de datos aproximadamente de 1M como mucho.
Al final, lo que ves aqui debajo es simplemente un procesado que va a leer todos los ficheros del blob storage y va a quedarse únicamente con el dominio y la clase a la que pertenece.
Salvar a parquet
Para poder chequear rápido datos y ver que todo es correcto, vamos a salvar los datos a parquet y así poder validar que la cosa va bien:
Meter los datos en base de datos (opcional)
En este caso finalmente me han salido unos ~20M de filas, que databricks se come en apenas 5s como parquet, por lo que no es necesario tampoco venirse arriba y cargar en BBDD…pero si quisieramos, podríamos hacer esto:
Con lo que ahora tendríamos accesible tambien los datos a nivel fijo en la BBDD llamada “sentinelml” que me cree yo previamente.
NOTA: La diferencia entre hacer esto o no, es que en los siguientes scripts tendrias que añadir “sentinelml.” justo delante del nombre de la vista. Si hicieste un createOrReplaceTempView, no haría falta ponerle la referencia a BBDD, pero estará ejecutando otro motor diferente, que a penas vas a notar para los pocos datos que hay
Chequeo de datos
Ahora vamos a chequear la distribución de datos para ver que no hay desmadres.
Duplicados
Vamos a ver cuántos duplicados tenemos:
Como vemos, tenemos un montón…que toca limpiar antes 😃
Limpiar duplicados
Para limpiar duplicados, vamos utilizar la estrategia de ROW_NUMBER:
De esta forma nos vamos a quedar con únicamente los dominios que no están duplicados (y una muestra de los duplicados), de forma que ya tenemos nuestro dataset listo para ser exportado…salvo porque nos interesa aprovechar y barajarlo.
Shuffeling de datos
Un requerimiento que vamos a tener a la hora de inyectar datos a la red neuronal que estamos montando va a ser que los datos estén barajados. Aprovechando que estamos en spark, vamos a hacer ese shuffeling con SQL y así nos ahorramos esa parte luego 😃
En este caso, realmente lo que vamos a barajar es el dataset sin los duplicados que hemos estado viendo antes, de esta forma la query quedará así:
Salvar a CSV
Ya por último solo nos falta salvar el resultado a un fichero CSV. En mi caso despues de revisar tamaños y demás, he visto que me es mas cómodo tenerlo todo en un único CSV, asi que lo que vamos a hacer es lanzar la query y salvar el resultado directamente a un CSV utilizando un único worker, por eso verás un “coalesce(1)”
El resultado de ese output estará dentro del blob storage de nuestro azure, en una carpeta llamada “prepared_top_level_domains” y su contenido, gracias a haber forzado “coalesce(1)” en un único fichero CSV con prefijo “part-” que es el que más tarde me llevaré para el entrenamiento de mi red.
Este dataset es el que contiene todos los dominios y sus clases, pero en modo texto, por lo que no podemos utilizarlo para entrenar nuestra red neuronal directamente, sino que tendremos que convertirlos a array de números, pero eso lo haremos en la siguiente parte de este post.
Cuántas clases tenemos
Como siguiente tarea, ahora nos queda saber cuantas clases tenemos, para que nuestro clasificador lo sepa y asignarles sus id a nombres correspondientes.
¡Y listo!, con esto ya tenemos las 2 cosas mínimas necesarias para comenzar a plantear las ultimas fases de preparación de datos para nuestra red
En el siguiente post, veremos cómo preparar el tokenizador y la conversión de estos dominios al array numérico que necesitamos.
Apéndice
SCALASQL
La otra opción que podemos utilizar es cargar los datos directamente y procesar mediante SQL.
Y luego montar una query que devuelva lo mismo de antes
El problema de hacerlo así es que como es para algo rápido y que tenemos un conjunto de ficheros variable…no es muy útil hacerlo así.
Nota: en este caso no necesitamos hacer nada más con la información, por lo que tampoco sería necesario cargarlo a parquet para hacer nada con ello.
¡Sigue Aprendiendo!
Si quieres que te ayudemos a poner en marcha este tipo de proyecto, no dudes en contactar con nosotros. También puedes aprovechar las formaciones existentes para ampliar tus conocimientos 👇🏼
>> Más infoEnrique Catalá
Soy Technical Leader en Verne TECH, MVP de Microsoft y Microsoft Certified Trainer (MCT). Estoy focalizado en motores relacionales de SQL Server y me encanta resolver problemas de rendimiento y escalabilidad en sistemas OLTP. He liderado más de 100 proyectos, no sólo en España, sino también en otros países como USA, Holanda, México, etc. siendo el principal arquitecto de soluciones como HealthCheck, QueryAnalytics y DatabaseObfuscator.