En un mundo de dispositivos interconectados, los datos se generan a un ritmo sin precedentes. Para aprovechar estos datos, los ingenieros suelen emplear técnicas de aprendizaje automático (ML) que les permiten recopilar información valiosa e información útil. A medida que aumenta el volumen de datos, surge la necesidad de ejecutar los procesos de procesamiento de macrodatos a gran escala; su portátil no es suficiente.
Para ayudar a solucionar este problema, podemos usar marcos distribuidos como Spark, que nos permiten usar la computación distribuida para analizar nuestros datos. En esta serie de dos partes, darás un pequeño paso para ejecutar tus cargas de trabajo de datos a escala. Presentamos un tutorial práctico en el que aprenderá a usar los servicios de AWS para ejecutar su procesamiento en la nube. Para ello, lanzaremos un clúster de EMR con funciones de Lambda y ejecutaremos un script de PySpark de muestra. Necesitará una cuenta de AWS para seguir esta serie, ya que utilizaremos sus servicios.
En esta primera parte, analizaremos las tecnologías y la arquitectura de alto nivel y analizaremos un problema de muestra. En la parte 2, profundizaremos en los detalles, incluida la arquitectura y la configuración de la infraestructura necesaria.
Antes de profundizar en nuestro problema de muestra, revisemos brevemente la arquitectura y los servicios de AWS involucrados. Usaremos Spark, un marco de computación distribuida de código abierto para procesar grandes volúmenes de datos. Spark se puede ejecutar en EMR y utilizaremos su API de Python, PySpark. AWS Elastic MapReduce (EMR) es un servicio administrado que simplifica la implementación y la administración de los clústeres de Hadoop y Spark. Simple Storage Service (S3) es el servicio de almacenamiento de objetos de Amazon, que utilizaremos para almacenar nuestro script de PySpark.
Para crear el clúster de EMR, utilizaremos AWS Lambda, un servicio de procesamiento sin servidor que nos permite ejecutar código sin necesidad de aprovisionar o administrar servidores. El uso de Lambda para crear el clúster nos permite definir la infraestructura como código, de modo que podemos definir las especificaciones y configuraciones del clúster una vez y ejecutarlas varias veces. De este modo, podemos lanzar varios clústeres fácilmente con la misma función. Lambda también nos permite definir activadores automáticos, que podemos usar para aprovisionar clústeres automáticamente en función de un conjunto de acciones.
En nuestro ejemplo de caso práctico, crearemos un script de Python con la biblioteca de Python boto3 de AWS. Este script se cargará en AWS Lambda y hará que el clúster de EMR ejecute nuestro script PySpark de muestra. Este último se almacenará en S3, desde donde el clúster de EMR lo recuperará en tiempo de ejecución.
Hemos creado un script de Python muy simple para entrenar un modelo de aprendizaje automático con Spark. Generaremos datos aleatorios, calcularemos una combinación lineal de los mismos, añadiremos ruido a los resultados y entrenaremos un modelo para que pueda aprender cómo combinamos los datos. El modelo debería poder filtrar el ruido y calcular con bastante precisión los coeficientes que utilizamos para calcular la combinación lineal de los datos de entrada.
En esta sección, lo guiaremos a través del código, explicando los bloques de código y comentando las funciones utilizadas. Al final, tendrás el script completo disponible.
Usaremos argumentos para nuestro script, por lo que necesitamos importar argparse. Vamos a importar SparkSession para controlar la sesión de Spark en ejecución. Usaremos funciones definidas por el usuario, por lo que necesitamos pyspark.sql.types y pyspark.sql.functions. En este ejemplo, ajustaremos un modelo de regresión lineal del MLLib de Spark. Las funciones que necesita este modelo se formatean con VectorAssembler. Por último, el modelo se evaluará con el sistema RegressionMetrics incorporado.
A continuación, defina el número de filas de datos sintéticos que generaremos. En las líneas 14 a 22 configuramos el analizador de argumentos para poder pasar los parámetros al script. Esta es una gran característica que podemos usar a nuestro favor al realizar pruebas y aumenta la modularidad de nuestro código. Le indicamos al analizador los nombres de nuestros argumentos, si son necesarios para ejecutar el programa y su tipo de datos. Tenga en cuenta que los argumentos se pasan como cadenas en la función Lambda y que el analizador los convierte en el tipo especificado.
En la línea 25-28 obtenemos la Spark Session.
Entre las líneas 31 y 32, estamos inicializando un nuevo marco de datos con números que van desde cero hasta NUM_SAMPLES: 1. Aunque esto no es obligatorio directamente, es una forma sencilla de inicializar el marco de datos para nuestro propósito. Debido a la forma en que generamos el marco de datos, tiene una sola partición. Si ese es el caso, todo el procesamiento lo realizará una máquina que pertenezca al clúster. Vamos a reparticionar el marco de datos en cuatro particiones, de esta forma, el procesamiento se distribuirá en todo el clúster. Tenga en cuenta que esto es correcto para nuestro ejemplo actual, pero realizar esta operación en grandes cantidades de datos puede resultar en una reorganización costosa.
En las líneas 35 a 36 generamos dos columnas con valores aleatorios mediante la función rand de Spark. Esto genera números aleatorios distribuidos uniformemente en el rango [0,1). Los usaremos como características de nuestro modelo
En las líneas 43 a 46 calculamos una combinación lineal de las dos columnas generadas, utilizando los multiplicadores pasados por los argumentos. Luego generamos otra columna con muestras aleatorias llamada ruido en la línea 49. Como el ruido se genera en el rango [0,1), restamos 0.5 para cambiar el rango a [-0.5, 0.5). Luego, este ruido se suma a la combinación lineal que creamos en las líneas 56-58. El propósito es agregar ruido a los datos, porque si los datos fueran perfectos, solo se necesitarían un par de muestras para calcular los coeficientes.
En la línea 64, creamos una instancia de un modelo de regresión lineal del MLlib de Spark para que se ajuste. Como el modelo está equipado con un marco de datos de entrada, le indicamos qué columnas buscar cuando se le da un marco de datos, en nuestro caso features (inputs) y label (output objetivo).
Los modelos de MLlib requieren que la entrada de datos esté formateada de una manera específica, y el VectorAssembler nos ayuda a lograrlo. Vamos a pasar de dos columnas separadas que contienen valores flotantes a una DenseVector que contiene ambas características flotantes. En la línea 68 estamos creando una instancia del VectorAssembler y en la línea 70 lo estamos usando para transformar nuestros datos.
Como práctica habitual en los problemas de aprendizaje automático, dividimos los datos en entrenamiento y pruebas. Los datos de entrenamiento se utilizan para ajustar el modelo. Los datos de la prueba se utilizan para evaluar el modelo a partir de datos invisibles una vez que se ha ajustado. Es una especie de simulación de lo que sucedería en la producción. Para ello, utilizamos RandomSplit de Spark y le decimos que queremos el 80% de los datos para el entrenamiento y el 20% para las pruebas.
¡Aquí es donde ocurre la magia! En la línea 77 estamos montando el modelo. En las siguientes líneas, parte de la información y las métricas del proceso de entrenamiento se imprimen en formato estándar. Tenga en cuenta que también imprimimos los coeficientes aprendidos por el modelo. Si las cosas van bien, deberían estar muy cerca de los coeficientes que se aprobaron con los argumentos. Deberían estar cerca y no exactamente iguales debido al ruido que hemos introducido en los datos.
¿Recuerdas los datos de la prueba? Aquí es donde los usamos para evaluar el rendimiento del modelo en datos desconocidos. Estamos transformando el marco de datos de prueba con el modelo ya ajustado, lo que generará una nueva columna llamada predicción con el resultado. Al usar RegressionMetrics integrado en Spark, obtenemos dos métricas para los resultados de los datos de prueba. Estas son las mismas métricas que las que obtuvimos del resumen del entrenamiento, por lo que puedes comparar el rendimiento del modelo según los datos del entrenamiento con los datos de las pruebas.
Echemos un vistazo a la salida del script. El primer marco de datos que se muestra es el resultado de la línea 38 y contiene las entradas generadas aleatoriamente. El segundo es el resultado de la ejecución de la línea 61, donde mostramos los valores generados aleatoriamente, su combinación lineal, el ruido generado aleatoriamente y la suma de la combinación lineal y el ruido. A continuación, se imprime la información de entrenamiento, que incluye el número de iteraciones del algoritmo de regresión lineal, métricas como RMSE y r2, y los coeficientes calculados del modelo. Deberían estar muy cerca de los que estamos usando como entradas x1 y x2. Por último, se muestra una parte del marco de datos de prueba, incluidas las entradas (características), la etiqueta y la predicción del modelo. Las métricas de los datos de la prueba deben parecerse mucho a las del entrenamiento.
En esta primera parte de la serie, analizamos la arquitectura de alto nivel que utilizaremos para ejecutar el procesamiento de datos distribuidos en AWS. Con fines ilustrativos, configuramos un script de ejemplo extremadamente simple con PySpark, la API de Spark para Python. Revisamos el script y lo que hace.
En la parte 2, profundizaremos en los detalles de la ejecución de este script en EMR. Explicaremos las tecnologías que se utilizarán y configuraremos la infraestructura necesaria para ejecutar el ejemplo.
En un mundo de dispositivos interconectados, los datos se generan a un ritmo sin precedentes. Para aprovechar estos datos, los ingenieros suelen emplear técnicas de aprendizaje automático (ML) que les permiten recopilar información valiosa e información útil. A medida que aumenta el volumen de datos, surge la necesidad de ejecutar los procesos de procesamiento de macrodatos a gran escala; su portátil no es suficiente.
Para ayudar a solucionar este problema, podemos usar marcos distribuidos como Spark, que nos permiten usar la computación distribuida para analizar nuestros datos. En esta serie de dos partes, darás un pequeño paso para ejecutar tus cargas de trabajo de datos a escala. Presentamos un tutorial práctico en el que aprenderá a usar los servicios de AWS para ejecutar su procesamiento en la nube. Para ello, lanzaremos un clúster de EMR con funciones de Lambda y ejecutaremos un script de PySpark de muestra. Necesitará una cuenta de AWS para seguir esta serie, ya que utilizaremos sus servicios.
En esta primera parte, analizaremos las tecnologías y la arquitectura de alto nivel y analizaremos un problema de muestra. En la parte 2, profundizaremos en los detalles, incluida la arquitectura y la configuración de la infraestructura necesaria.
Antes de profundizar en nuestro problema de muestra, revisemos brevemente la arquitectura y los servicios de AWS involucrados. Usaremos Spark, un marco de computación distribuida de código abierto para procesar grandes volúmenes de datos. Spark se puede ejecutar en EMR y utilizaremos su API de Python, PySpark. AWS Elastic MapReduce (EMR) es un servicio administrado que simplifica la implementación y la administración de los clústeres de Hadoop y Spark. Simple Storage Service (S3) es el servicio de almacenamiento de objetos de Amazon, que utilizaremos para almacenar nuestro script de PySpark.
Para crear el clúster de EMR, utilizaremos AWS Lambda, un servicio de procesamiento sin servidor que nos permite ejecutar código sin necesidad de aprovisionar o administrar servidores. El uso de Lambda para crear el clúster nos permite definir la infraestructura como código, de modo que podemos definir las especificaciones y configuraciones del clúster una vez y ejecutarlas varias veces. De este modo, podemos lanzar varios clústeres fácilmente con la misma función. Lambda también nos permite definir activadores automáticos, que podemos usar para aprovisionar clústeres automáticamente en función de un conjunto de acciones.
En nuestro ejemplo de caso práctico, crearemos un script de Python con la biblioteca de Python boto3 de AWS. Este script se cargará en AWS Lambda y hará que el clúster de EMR ejecute nuestro script PySpark de muestra. Este último se almacenará en S3, desde donde el clúster de EMR lo recuperará en tiempo de ejecución.
Hemos creado un script de Python muy simple para entrenar un modelo de aprendizaje automático con Spark. Generaremos datos aleatorios, calcularemos una combinación lineal de los mismos, añadiremos ruido a los resultados y entrenaremos un modelo para que pueda aprender cómo combinamos los datos. El modelo debería poder filtrar el ruido y calcular con bastante precisión los coeficientes que utilizamos para calcular la combinación lineal de los datos de entrada.
En esta sección, lo guiaremos a través del código, explicando los bloques de código y comentando las funciones utilizadas. Al final, tendrás el script completo disponible.
Usaremos argumentos para nuestro script, por lo que necesitamos importar argparse. Vamos a importar SparkSession para controlar la sesión de Spark en ejecución. Usaremos funciones definidas por el usuario, por lo que necesitamos pyspark.sql.types y pyspark.sql.functions. En este ejemplo, ajustaremos un modelo de regresión lineal del MLLib de Spark. Las funciones que necesita este modelo se formatean con VectorAssembler. Por último, el modelo se evaluará con el sistema RegressionMetrics incorporado.
A continuación, defina el número de filas de datos sintéticos que generaremos. En las líneas 14 a 22 configuramos el analizador de argumentos para poder pasar los parámetros al script. Esta es una gran característica que podemos usar a nuestro favor al realizar pruebas y aumenta la modularidad de nuestro código. Le indicamos al analizador los nombres de nuestros argumentos, si son necesarios para ejecutar el programa y su tipo de datos. Tenga en cuenta que los argumentos se pasan como cadenas en la función Lambda y que el analizador los convierte en el tipo especificado.
En la línea 25-28 obtenemos la Spark Session.
Entre las líneas 31 y 32, estamos inicializando un nuevo marco de datos con números que van desde cero hasta NUM_SAMPLES: 1. Aunque esto no es obligatorio directamente, es una forma sencilla de inicializar el marco de datos para nuestro propósito. Debido a la forma en que generamos el marco de datos, tiene una sola partición. Si ese es el caso, todo el procesamiento lo realizará una máquina que pertenezca al clúster. Vamos a reparticionar el marco de datos en cuatro particiones, de esta forma, el procesamiento se distribuirá en todo el clúster. Tenga en cuenta que esto es correcto para nuestro ejemplo actual, pero realizar esta operación en grandes cantidades de datos puede resultar en una reorganización costosa.
En las líneas 35 a 36 generamos dos columnas con valores aleatorios mediante la función rand de Spark. Esto genera números aleatorios distribuidos uniformemente en el rango [0,1). Los usaremos como características de nuestro modelo
En las líneas 43 a 46 calculamos una combinación lineal de las dos columnas generadas, utilizando los multiplicadores pasados por los argumentos. Luego generamos otra columna con muestras aleatorias llamada ruido en la línea 49. Como el ruido se genera en el rango [0,1), restamos 0.5 para cambiar el rango a [-0.5, 0.5). Luego, este ruido se suma a la combinación lineal que creamos en las líneas 56-58. El propósito es agregar ruido a los datos, porque si los datos fueran perfectos, solo se necesitarían un par de muestras para calcular los coeficientes.
En la línea 64, creamos una instancia de un modelo de regresión lineal del MLlib de Spark para que se ajuste. Como el modelo está equipado con un marco de datos de entrada, le indicamos qué columnas buscar cuando se le da un marco de datos, en nuestro caso features (inputs) y label (output objetivo).
Los modelos de MLlib requieren que la entrada de datos esté formateada de una manera específica, y el VectorAssembler nos ayuda a lograrlo. Vamos a pasar de dos columnas separadas que contienen valores flotantes a una DenseVector que contiene ambas características flotantes. En la línea 68 estamos creando una instancia del VectorAssembler y en la línea 70 lo estamos usando para transformar nuestros datos.
Como práctica habitual en los problemas de aprendizaje automático, dividimos los datos en entrenamiento y pruebas. Los datos de entrenamiento se utilizan para ajustar el modelo. Los datos de la prueba se utilizan para evaluar el modelo a partir de datos invisibles una vez que se ha ajustado. Es una especie de simulación de lo que sucedería en la producción. Para ello, utilizamos RandomSplit de Spark y le decimos que queremos el 80% de los datos para el entrenamiento y el 20% para las pruebas.
¡Aquí es donde ocurre la magia! En la línea 77 estamos montando el modelo. En las siguientes líneas, parte de la información y las métricas del proceso de entrenamiento se imprimen en formato estándar. Tenga en cuenta que también imprimimos los coeficientes aprendidos por el modelo. Si las cosas van bien, deberían estar muy cerca de los coeficientes que se aprobaron con los argumentos. Deberían estar cerca y no exactamente iguales debido al ruido que hemos introducido en los datos.
¿Recuerdas los datos de la prueba? Aquí es donde los usamos para evaluar el rendimiento del modelo en datos desconocidos. Estamos transformando el marco de datos de prueba con el modelo ya ajustado, lo que generará una nueva columna llamada predicción con el resultado. Al usar RegressionMetrics integrado en Spark, obtenemos dos métricas para los resultados de los datos de prueba. Estas son las mismas métricas que las que obtuvimos del resumen del entrenamiento, por lo que puedes comparar el rendimiento del modelo según los datos del entrenamiento con los datos de las pruebas.
Echemos un vistazo a la salida del script. El primer marco de datos que se muestra es el resultado de la línea 38 y contiene las entradas generadas aleatoriamente. El segundo es el resultado de la ejecución de la línea 61, donde mostramos los valores generados aleatoriamente, su combinación lineal, el ruido generado aleatoriamente y la suma de la combinación lineal y el ruido. A continuación, se imprime la información de entrenamiento, que incluye el número de iteraciones del algoritmo de regresión lineal, métricas como RMSE y r2, y los coeficientes calculados del modelo. Deberían estar muy cerca de los que estamos usando como entradas x1 y x2. Por último, se muestra una parte del marco de datos de prueba, incluidas las entradas (características), la etiqueta y la predicción del modelo. Las métricas de los datos de la prueba deben parecerse mucho a las del entrenamiento.
En esta primera parte de la serie, analizamos la arquitectura de alto nivel que utilizaremos para ejecutar el procesamiento de datos distribuidos en AWS. Con fines ilustrativos, configuramos un script de ejemplo extremadamente simple con PySpark, la API de Spark para Python. Revisamos el script y lo que hace.
En la parte 2, profundizaremos en los detalles de la ejecución de este script en EMR. Explicaremos las tecnologías que se utilizarán y configuraremos la infraestructura necesaria para ejecutar el ejemplo.