Transcripciones
1. Introducción: Y pasé más de nueve años en Amazon.com e IMDB.com haciendo sentido a sus conjuntos de datos masivos. Y quiero enseñarte sobre la tecnología más poderosa que conozco para librar el big data en la Nube hoy. Eso es Apache Spark, usando el lenguaje de programación de Scala chispa y se clúster de
Hadoop para difundir tareas masivas de análisis de datos y aprendizaje automático en la nube. Y saber hacer eso es una habilidad muy caliente para tener en este momento, comenzaremos con un curso acelerado en el lenguaje de programación Scala. No te preocupes, es bastante fácil de recoger siempre y cuando hayas hecho alguna programación o scripting antes. Empezaremos con algunos ejemplos simples, pero trabajaremos hasta ejemplos más complicados e interesantes utilizando conjuntos de datos masivos reales. Al final de este curso, habrás ido de la mano con más de 15 ejemplos reales. Y te sentirás cómodo escribiendo, depurando y ejecutando tus propias aplicaciones de Spark usando Scala. Y algunos de ellos son bastante divertidos. Miraremos una red social de superhéroes y usaremos esos datos para averiguar quién es el Kevin Bacon del universo de superhéroes. También veremos un millón de calificaciones de películas de personas reales y en realidad construiremos un motor de recomendación de películas real que se ejecute en un clúster de Spark en la nube utilizando el servicio Elastic MapReduce de Amazon. También haremos algunas tareas de aprendizaje automático grandes usando la biblioteca Sparks ML Lib. Y haremos algún análisis gráfico usando la biblioteca Spark GraphX. Entonces pruébalo conmigo. Creo que te sorprenderá cómo solo unas pocas líneas de código pueden dar inicio un trabajo masivo de análisis de datos complejo en un clúster usando Spark. Entonces empecemos. Lo primero que tenemos que hacer es instalar el software que necesitamos. Entonces saquemos eso del camino ahora mismo.
2. Instalación de los materiales de la clase: Entonces vamos a configurar todo incluyendo Java e
inteligencia y todos los materiales del curso que necesitamos para todo el curso. Lo que vamos a hacer es empezar por ir a nuestra propia página web aquí, que te dirigirá a los materiales del curso donde podrás descargar todos los archivos del proyecto y los datos que necesites para este curso. Seguiremos adelante y pondremos eso instalado en tu sistema. Después instalaremos un Kit de Desarrollo Java si aún no tienes uno, solo
necesitamos asegurarnos de que tenemos un JDK entre las versiones ocho y 14 instalado en tu sistema. Las probabilidades son si eres desarrollador, ya lo haces. Después de eso, instalaremos la idea IntelliJ Community Edition. Es un entorno de desarrollo libre que puede, podemos usar para Scala y para Spark. Y la belleza de ella es que también integra algo llamado sbt. Por lo que consiguió un mango todo el trabajo sucio de realmente instalar Apache Spark para nosotros en Windows, sí
tenemos un paso extra. Tenemos que fingir ventanas para pensar que se está ejecutando Hadoop y te mostraré cómo hacer eso. No es demasiado duro. Y finalmente, montaremos nuestro proyecto en inteligencia. Ejecuta un pequeño problema helloworld sencillo en Apache Spark. Asegúrate de que todo funcione. Vamos a sumergirnos y te acompañaré a través de todo. Entonces, empecemos por poner todo listo que necesitas para este curso. Dirígete a medios Dotson dog, un dash soft.com slash Spark scala dot HTML. Presta atención a la capitalización y cada letra cuenta. Y debes llegar a esta página aquí que contiene todo lo necesario para ponerte en marcha. Pero lo más importante, vamos a instalar los materiales del curso, todos los guiones que necesitas para realmente conseguir a través de este curso práctico. Adelante y haz clic en este enlace aquí para inmediato Dotson perro dash, soft.com slash Spark Scala slash Spark Scala course dot zip. Si estás escribiendo eso a mano por alguna razón, asegúrate de prestar atención a la capitalización. Una vez que se descargue. Seguiremos adelante y lo descomprimiremos. Y en Windows solo puedo seguir adelante y hacer clic con el botón derecho en eso y decir extraer todo. En un Mac o Linux, por supuesto, simplemente
irías a un prompt de terminal y utilizarías el comando unzip. Y deberíamos conseguir es una carpeta del curso de Scala chispa
dentro de una carpeta del curso de Scala chispa, Eso es correcto. Eso es lo que queremos. Y dentro de ese segundo nivel de carpeta está todos los materiales en sí, todo el proyecto para este curso. Entonces, antes que nada, movamos esto a algún lugar donde no lo vamos a perder. Entonces voy a tomar esa carpeta de curso de
gala de chispas de nivel superior y la voy a mover a algún lugar seguro. Pongámoslo en mi unidad C. Muy bien, así que ahora en mi unidad C tengo una carpeta de cursos de Scala chispa. Y dentro de eso hay otra carpeta de curso de gala chispas. Y en Mac o Linux, claro que no tendrías un directorio C. Lo pondrías en tu directorio de inicio, solo en algún lugar donde no lo vas a perder. Muy bien, entonces a continuación tenemos que conseguir algunos datos de prueba aquí. Y desafortunadamente los términos de licencia de los datos que me gusta usar no me dejan incluirlo yo mismo. Entonces vas a tener que ir y descargar eso tú mismo. Ese es el conjunto de datos de MovieLens aquí. Para armar unas 100 mil calificaciones de películas ahí con las que vamos a usar para jugar a lo largo de este curso. Por lo que puedes usar este práctico enlace dandy para conseguirlo archivos doc Grouplens.org slash data slash slash movieLens slash ML dash 100, k dot zip. Adelante y descarga eso. Y si por alguna razón el sitio web de Grouplens.org está caído, eso sucede de vez en cuando. Generalmente puedes encontrar el archivo M L dash 100 K en Kaggle si es necesario. Adelante y descomprimamos eso también. Haga clic derecho en Extraer todo. Nuevamente, solo usa el comando unzip en Mac o Linux. Y la carpeta MLH1 100 K resultante debería contener este material. Vamos a tomar ese nivel aquí y vamos a copiar eso. Y voy a volver a mi carpeta de materiales del curso que acabo de crear, que para mí fue ver chispas curso de Scala. Y en el otro directorio de cursos de gala chispas bajo eso hay una carpeta de datos. Entra a la carpeta Datos y ahí es donde quiero poner mi carpeta AML dash 100 K. De acuerdo, así es como deben verse las cosas en este punto, ya sea que seas el sistema operativo en el que estés, quieres una carpeta del curso de Scala chispa. Dentro de eso, debería haber otra carpeta del curso de Spark Scala. Dentro de eso debería haber una carpeta de datos. Y dentro de eso debería haber una carpeta ML dash 100 K. Y dentro de eso deberían estar todos estos datos de prueba. De acuerdo, así que asegúrate de que todo se vea bien o de lo contrario te vas a tropezar con problemas raros y no vas a saber qué está pasando. Una vez que estés seguro de que está bien, Volvamos a nuestras instrucciones aquí. siguiente paso es instalar IntelliJ a, que va a ser nuestro IDE para desarrollar en este curso. Ahora solía decirle en realidad a la gente que instalara Eclipse y el IDE de Scala, pero parece que inteligente está ganando la batalla que están contra eclipse. Entonces voy a tener que instalar IntelliJ j ahora en su lugar. Ahora con el fin de ejecutar el código Scala, primero
necesitas un JDK y cualquier cosa entre versiones ayuda y 14 lo haremos para este curso. Pero si necesitas conseguir un JDK, aquí
hay un enlace handy-dandy para hacerlo. Simplemente puedes dirigirte a Oracle.com slash Java y seguir adelante
y llegar a la descarga del JDK 14 para tu sistema operativo. Para mí eso va a ser Windows 64. Tendrás que aceptar sus términos. Y espere a que eso se descargue. Parece que aquí hay un pequeño aviso de seguridad. Está bien. Confío en ello. Y vamos a bajar eso. Seguiremos adelante e instalaremos. Obviamente en Linux o Mac que probablemente usarás un medio alternativo para obtener Java. De hecho, probablemente ya tengas instalado Java si estás en Linux o Mac. Entonces esto es probablemente alguien esa cosa específica. Seguiremos adelante y pasaremos por el instalador aquí. Y una cosa en Windows es que cuando ejecutas código Linux como Apache Spark en windows, a veces se confunde cuando tienes espacios a tu paso. Por lo que ese espacio entre programa y archivos podría en realidad ser un problema. Sigamos adelante y cambiemos eso sólo para estar seguros. Y voy a decir esto en su lugar en un directorio C colon JDK 14. Bueno, que eso haga lo suyo. No debería tardar demasiado. Y ya terminamos. Está bien, terminamos con ese sitio, vuelta a nuestras instrucciones. Por lo que ahora podemos instalar la idea IntelliJ Community Edition. Esa va a ser nuestra identificación real. Sigamos adelante y pinchemos en ese enlace. Y queremos la edición comunitaria, la libre, la de código abierto. No necesitamos el último. Así que adelante y descarga eso para cualquiera que sea tu sistema operativo. Se ve la oferta que para Windows, Mac, y Linux. Y esto es alrededor de medio trabajo. Y así nos tomaremos unos segundos para bajar. Vuelve cuando eso esté hecho. Correcto, el instalador descargó y sigamos adelante y patearlo. Y bastante instalador estándar aquí. Sigamos adelante y solo caminemos a través de él. Y si sí quieres atajos de escritorio o como asociaciones de archivos, puedes hacerlo totalmente a tu altura. Yo sólo voy a dejar estos como está. Y eso también está bien. Tarda alrededor de un minuto en instalarlo, así que solo volveré cuando eso haya terminado. Está bien, bien bien. Vamos a seguir adelante y pulsar el botón Ejecutar para lanzarlo realmente. No quiero importar ninguna configuración existente. Y preferencia personal, si te gusta un tema oscuro o un tema claro, me gusta un tema claro. Entonces seleccionaré eso, haz lo que quieras aunque. Y ahora vamos a instalar plugins. A lo mejor el único plugin que realmente necesitamos es el plugin de Scala. Y desafortunadamente no lo veo ofrecido aquí, así que sólo voy a seguir adelante. Yo tampoco lo veo ofrecido aquí. Entonces si sí ves el plug-in de Scala, adelante y aprovecha para instalarlo. No lo hice aunque. Entonces tengo que ver con el camino difícil, que no es tan difícil. Solo voy a dar clic en el botón Configurar aquí desde la pantalla de bienvenida y seleccionar Plugins. Y desde ahí puedo encontrar el plugin de Scala. Adelante e instalemos eso. Bien. De acuerdo, y podemos reiniciar el IDE para recoger eso. Y ahora una cosa más necesitamos decirle qué JDK usar. Así que vuelve al menú configure aquí y ve a estructura para nuevos proyectos. Y si necesitas seleccionar un JDK aquí, selecciona el que acabamos de instalar, eso va a ser 14 para nosotros y golpea Ok. Ahora hay un paso más que tenemos que hacer eso es sólo para Windows. Entonces si estás en Mac o Linux, puedes,
puedes ignorar este siguiente paso, necesitamos una especie de ventanas engañosas para que piensen que Hadoop se está ejecutando en él. Y para hacer eso, bueno, es un poco torpe. Las instrucciones están en la página de materiales de tu curso aquí debajo de la sección sólo Windows aquí, solo tienes que seguir sus instrucciones. Adelante y crea un directorio bin C Hadoop. Entonces voy a ir a mi unidad C. Voy a crear una nueva carpeta llamada Hadoop. Y dentro de esa carpeta Hadoop, voy a crear otra carpeta llamada bin. Ahora voy a volver a mis materiales del curso, que está bajo curso de gala de chispas. Y verás un archivo EXE cuando utils dot ahí. Voy a seguir adelante y copiar eso y pegarlo en C. Hadoop sido. A continuación necesito configurar un par de variables de entorno. Por lo que la forma más fácil de hacerlo es simplemente ir a su barra de búsqueda de Windows aquí abajo y escribir variables de entorno. Apenas ENV es probablemente suficiente. Y seleccione editar las variables de entorno del sistema las cuales le llevarán al panel de control del sistema. A partir de aquí, se puede pulsar el botón de variables de entorno. Y vamos a crear uno nuevo llamado Hadoop underscore home all caps. Y el valor será C colon barra invertida, Hadoop. También necesitamos editar nuestra variable de entorno path. Si no tienes uno, puedes hacer uno, pero probablemente ya lo tengas. Entonces sólo voy a editar el que tengo un añadir una ruta adicional a ella haciendo doble clic aquí y escribiendo en signo de porcentaje, Hadoop subrayado home por ciento sign, Eso es slash bin. Golpea OK y OK otra vez y Ok otra vez. Muy bien, así que ahora estamos listos, listos para intentar realmente importar el proyecto para el propio curso. Volvamos a IntelliJ. Ahora, antes de cargar ese proyecto, siempre
es buena idea reiniciar sus aplicaciones después de cambiar las variables de entorno. Entonces si estás en Windows, sigue
adelante y cierra la idea de IntelliJ y reinicia. Debe estar en tu menú de inicio. Y ahora vamos a dar click en Abrir o Importar. Y queremos navegar a la carpeta Materiales del Curso, chispa de Scala y la carpeta del curso de Scala chispa dentro de eso, ese es nuestro proyecto real para el curso en sí. Hit Ok. Y que haga lo suyo. Va a intentar automáticamente darle sentido a lo que hay en esa carpeta. No quiero propina. Y si tenemos suerte, todo va a funcionar. Está bien. Ve algo demasiado alarmante, vamos a golpear el icono de construcción solo para asegurarnos de que se construyó con éxito. Ese es este pequeño icono de martillo de aquí arriba. También lo encontrarás en el menú Construir si lo prefieres. Y parece que funcionó. Entonces vamos a darle una oportunidad. Adelante y abramos aquí la carpeta del curso de Spark Scala para el proyecto, y luego abrimos la carpeta fuente. Y debajo de eso abren principal, y luego Scala y com dot sun dot software dot dot chispa. Estos son todos los guiones para el curso aquí. Entonces todo lo que tenemos que hacer es escoger uno y ver si funciona. Incluí un guión helloworld muy sencillo. Entonces hagamos doble clic en eso. Y se puede ver aquí no está haciendo mucho, pero en realidad está usando Apache Spark. Por lo que en realidad verificará que tienes todo configurado correctamente y configurarlo de la manera correcta aquí. Simplemente va a configurar un SparkContext y cargar el archivo de datos dentro de nuestro conjunto de datos MovieLens que instalamos anteriormente. Por lo que esto también asegurará que tengas eso en el lugar correcto también. Todo lo que va a hacer es hacer girar un trabajo de Apache Spark para contar el número de líneas en ese archivo. Entonces una forma muy complicada de hacer eso, pero verificará que funciona. Y luego cuando esté hecho, imprimirá Hello World. El archivo de datos tiene esperemos 100 mil líneas porque ese es el conjunto de datos de 100 mil. Entonces veamos si funciona. Basta con hacer clic derecho en HelloWorld y decir correr hello-mundo. Y en este punto hay una muy buena posibilidad de que vayas a conseguir un error de clase no encontrado si lo haces, es solo un bug e inteligencia. Si dejas de inteligente y lo relanzas, debería aclararlo. Y eso debería dar inicio a Spark. Verás algunas advertencias son seguras para ignorar sin embargo. Y ahora en realidad se está ejecutando y funcionó. Entonces ahí lo tienes. Helloworld, el archivo de datos tiene 100 mil líneas. Entonces si ves eso, felicitaciones, configuras Spark y Scala e inteligencia en Java todo con éxito. Y todo está funcionando. Y ahora todo lo que tenemos que hacer es pasar por todo el resto de estos guiones lo largo del resto del curso y hablar de lo que hacen y aprender en el camino. Si no viste esa salida sin embargo,
vuelve atrás, probablemente te perdiste unos pequeños spots en algún lugar. Siempre hay algo cosita y siéntete libre de publicar en la Q y un o comentarios de este curso para obtener ayuda si la necesitas. Pero ojalá eso funcione para ti y podamos seguir adelante y empezar a aprender.
3. Introducción a Apache Spark: Entonces déjame presentarte a Apache Spark a un alto nivel y solo hablar de cómo funciona y qué es para muy rápido. Por lo que la descripción oficial de Spark es que es un motor rápido y general para el procesamiento de datos a gran escala. Y bueno, esa es una descripción bastante buena. Básicamente la idea es que se puede escribir un script muy simple potencialmente que describa cómo se quiere transformar una enorme cantidad de datos o analizar una enorme cantidad de datos y chispear
averiguar cómo distribuir ese trabajo a través de un clúster de computadoras para usted. Por lo que es un motor para averiguar cómo paralelizar el procesamiento de tus datos. Todavía puedes decirle lo que quieres. ¿ Lo sabes? ¿ Quiero tomar un montón de archivos de registro y extraer algo de información y ponerla en otro lugar. Bien. Spark irá y descubrirá cómo hacerlo en todo tu clúster y hacer que eso suceda lo más rápido
posible utilizando los recursos de decenas o incluso cientos de máquinas individuales para hacerlo. Por lo que la clave para esto es su escalabilidad. Entonces de nuevo, solo escribes un solo programa de conductor, lo llamamos. Es igual de simple script escrito en Scala o Python o Java. Eso le dice a Spark qué quieres hacer a tus datos. Es entonces el problema de Sparks averiguar cómo paralelizar eso y hacer que escale casi toda una flota de computadoras. Entonces la visión clave aquí es que no estás limitado a la potencia informática de una máquina aquí con Apache Spark, puedes tomar un,
un conjunto de datos masivo que no esperabas procesar en una sola PC y en realidad distribuir ese procesamiento a través de toda una flota de computadoras en paralelo al mismo tiempo. Este tipo de enfoque de dividir y conquistar es cómo podemos procesar conjuntos de datos
masivos y manejar lo que llamamos big data. Desde el punto de vista de la arquitectura, tu programa de conductores es solo algo que escribes. Como dije, es un guión diverso, potencialmente un guión muy sencillo. Y eso se entrega a un gestor de cluster de alguna tienda. Necesitas algún tipo de sistema que orqueste todo tu clúster de computadoras. Y eso podría ser un clúster de Hadoop, en cuyo caso el gerente de cluster de hilados de Hadoop estaría entrando en juego allí. Y eso va a ser preocupante de cómo hacer girar los recursos que necesitas, cómo distribuir esa obra y dónde poner los diferentes trabajos en el lugar más óptimo. Piensa en cosas como ¿cómo ejecuto el código en el lugar donde los datos son más accesibles? Entonces si mis datos, por ejemplo, están divididos en un sistema de archivos distribuido, el administrador de clústeres podría decir, vale, voy a ir a ejecutar los datos que procesen ese trozo de los datos en esa misma máquina para que se ejecuten incluso más rápido. No obstante, no es necesario usar Hadoop. Spark tiene su propio Administrador de Cluster incorporado también. Entonces, si solo quieres ejecutar Spark en un entorno independiente, puedes hacerlo para solo instalar Spark y cada máquina de tu clúster y configurarlo correctamente. Y sólo va a funcionar para Spark y correr por su cuenta. No necesariamente tiene que correr encima de Hadoop, aunque sí puede. En ocasiones, querrá ejecutar otras aplicaciones Hadoop en el mismo clúster y establecerlo canalizaciones de operaciones más complejas. Por lo que puede haber ventajas de correr realmente encima de Hadoop, pero no tienes que hacerlo. Por lo que una máquinas individuales, hay diferentes nodos que los llamamos. Y estos estarán ejecutando diferentes ejecutores. Y cada proceso ejecutivo que se puede distribuir a lo largo de todo tu clúster tiene su propia caché y tiene su propia tarea que está tratando de operar con tus datos. Y se puede ver con todas las flechas aquí que prácticamente todo está hablando entre sí. Su programa de conductor envía comandos al administrador
de clústeres y también directamente a los ejecutores cuando sea necesario. Y los ejecutores se están hablando entre sí y sincronizando entre ellos. Y por supuesto, un administrador de clústeres está hablando también con todos esos procesos ejecutores, tratando de orquestar. Qué se ejecuta donde y luego chocar esos resultados nuevo juntos para obtener ver tu resultado final cuando todo esté hecho. Entonces esa es la arquitectura sparc a un nivel muy alto. ¿ Por qué es tan popular Spark? Bueno, Spark es más o menos reemplazado. Hadoop MapReduce porque puede ser hasta 100 veces más rápido si se basa en ejecutarse en la memoria. Entonces si tienes suficiente memoria en tu clúster, esa es una aproximación realista. Si realmente estás leyendo datos directamente desde el disco
, seguirá siendo aproximadamente 10 veces más rápido. ¿ Por qué es tanto más rápido que MapReduce? Bueno, es por lo que llamamos un motor de gráfico acíclico dirigido o un motor DAG. Básicamente, va a mirar el flujo de trabajo que has descrito en tu script de conductor y lo optimizará automáticamente. En contraste, en MapReduce, estás algo metido en una sola forma de pensar en procesar datos. Tienes que mapear explícitamente todos tus datos en paralelo y luego definir alguna forma de reducir esos datos de nuevo a una respuesta final. Con el motor DAG sin embargo, puede ser un poco más flexible. Puede organizar ese flujo de trabajo de una manera más compleja y potencialmente más óptima también. Y debido a que Spark se basa en memoria, eso también le da una ventaja muy enorme también. Por lo que es rápido y también es muy fácil de usar. También hace calor, es una muy utilizada. Esta es en realidad una lista muy antigua de personas que usan Spark y hay muchas, muchas, muchas, muchas más personas que la usan ahora. Pero el punto de esta diapositiva es sólo para mostrarte que Es tecnología probada. Está siendo utilizado por corporaciones muy grandes. Es una tecnología muy madura. Ha estado fuera por un tiempo. Ya sabes, las nuevas características en Spark o tipo de ralentización un poco, al
menos en el mundo del código abierto. Y eso está bien porque prácticamente hace todo
lo que hay que hacer y lo hace de manera bastante confiable en este punto. Por lo que para el procesamiento de datos distribuidos, Spark es una tecnología madura y es muy adoptada. Tampoco es tan difícil. Por lo que tienes tu opción de escribir tu código en Python o Java o Scala. Obviamente en este curso nos vamos a centrar en Scala y hablaremos de por qué en un momento. Pero Es fácil de usar si conoces SQL Structural Query Language, ese es el mismo lenguaje que usas para interactuar con cualquier base de datos relacional. Te vas a sentir como en casa porque Spark tiene características llamadas conjuntos de datos de chispa y Spark DataFrames que operan de manera muy similar a las sentencias SQL. E incluso puedes darle comandos SQL directamente a través de una función llamada Spark SQL. Entonces si conoces SQL, puedes usar Spark. Simplemente es así de fácil. Pero no todo es un problema SQL. No todos los análisis o transformación de datos se pueden definir a través de un comando SQL. Y si quieres llegar a una API de nivel más bajo y
más bajo que está disponible para la API original para Spark se llama Dataset Distribuido Resilient o el RDD para abreviar. Vamos a entrar en mucha más profundidad sobre cómo funciona eso en un, en un momento aquí. Pero con la API RDD, puedes conseguir un nivel más bajo y a veces te puedo dar un rendimiento aún mejor. Y también te da más flexibilidad en lo que puedes hacer. Pero para las tareas de transformación o análisis de datos más comunes, probablemente
pueda definirlo como un comando SQL. Y la mayoría de las veces, estarás usando conjuntos de datos, marcos o la API Spark SQL. Desde el punto de vista de la arquitectura de software, es como se presenta Spark, y esto se remonta a la arquitectura original de Sparks. Las líneas se han difuminado en algunas de estas en los últimos años. Pero en su núcleo está, bueno, Spark Core y ahí es donde viven los RDD de igual manera, ¿verdad? Entonces eso es un poco como el motor subyacente de Spark en sí. Y puedes ir directamente a chispa Core. Bueno, ya veremos eso en acción. Pero hay estas otras API de nivel superior construidas sobre Spark Core también para que tu vida sea más fácil para tareas específicas. Cuando su Spark Streaming, es decir,
es obviamente una tecnología muy poderosa para ingerir datos en tiempo real o casi en tiempo real. Se podría imaginar, por ejemplo, tener una flota de servidores por ahí ejecutando su sitio web que están alimentando datos a Spark a través de la transmisión de Spark desde sus archivos de registro de forma continua. Y en tiempo real, chispa puede monitorear esos datos, mirar una ventana de esos datos a lo largo del tiempo, darte análisis sobre esa ventana de tiempo y tomar alguna acción en base a ella. Ejemplo sencillo, digamos que quieres tener algún tipo de alarma sobre 500 errores en tu sitio web. Puedes tener una configuración del sistema de streaming de Spark para que los registros se estén transmitiendo a Apache Spark. Y en tiempo real es contar cuántos 500 errores hay más en el pasado, nuestro último minuto, lo que quieras monitorear y tomar alguna acción si supera algún umbral. Y obviamente también están disponibles operaciones mucho más complejas. A lo mejor una aplicación más común sería transformar esos datos de registro y ponerlos en otro lugar. Por lo que podría tener un proceso de streaming de Spark que ingiera datos de mis registros, lo
transforma en algún formato que quizá Elastic Search quiera ver o algo así. También contamos con Spark SQL y que existen para permitirte integrarte con comandos
Spark SQL para que puedas tratar chispa igual que una base de datos gigante que se distribuye en la naturaleza. Entonces si puedes definir tus datos en términos de una estructura de tabla, que normalmente puedes, y puedes definir el problema que quieres resolver en términos de un comando SQL que probablemente puedas. Simplemente puedes usar Spark SQL para definir lo que quieres que haga. Y sparkle averiguar cómo paralelizar eso a través de toda una flota de computadoras. Entonces eso es realmente emocionante, ¿verdad? Te da toda la flexibilidad de una base de datos relacional. Pero ya no estás limitado a una sola máquina. En realidad se puede escalar horizontalmente esa base de datos. Ahora, solía ser que tenías que elegir entre como bases de datos NoSQL si quieres, computación
distribuida y una gran base de datos relacional monolítica si no lo hacías. Y todavía hay algunas limitaciones aquí. Tenga en cuenta que hacer grandes combinaciones todavía no va a ser muy eficiente en un entorno de servidor con particiones horizontalmente. Pero puedes hacerlo si quieres escribir. Entonces es un poco lo mejor de ambos mundos. Ahora, como mencioné, las líneas están borrosas en algunos casos aquí. Entonces estas API más modernas que vamos a ver más adelante
en Spark utilizando marcos de datos y conjuntos de datos. También son muy similares a SQL en su estructura y cómo se usan. Entonces, ya sabes, hace eso, ¿considera los marcos de datos y conjuntos de datos parte de Spark SQL o Spark Core. Nuevamente, las líneas un poco borrosas ahí, pero las interfaces basadas en SQL se están convirtiendo en la forma predominante de usar Spark. También contamos con ML Lib, Biblioteca de Aprendizaje Automático de
Sparks. Y si sí quieres hacer
aprendizaje automático distribuido en Apache Spark, también puedes hacerlo. Se trata de un conjunto de algoritmos algo limitado, aunque hay la mayoría de los que necesitarías en la práctica. Entonces veremos eso en una sección posterior del curso también. Y eso es realmente emocionante, ¿verdad? Porque si tienes aprendizaje automático que quieres procesar en un conjunto de datos masivo, ya
no estás limitado a lo que puedes hacer en una sola máquina? Hay algunos algoritmos que hasta el día de hoy, ya
sabes, son difíciles de escalar, pero Spark lo ha descubierto para muchos de los algoritmos de aprendizaje automático más populares que quizás quieras estar usando. Y por último, esta gráfica X, no quiero hablar demasiado de eso. Está un poco caído por el camino. Graphx no se trata, ya sabes, gráficos y gráficos están imprimiendo, ya sabes, pequeñas líneas y cosas así. Es más gráficas en el sentido de la informática. Entonces estamos hablando como redes de información. Por ejemplo, una red social donde tienes usuarios que están conectados a otros usuarios es una gráfica en ese sentido. Y los gráficos pueden hacer cosas como, ya
sabes, analizar esas gráficas de información, decirte atributos al respecto, y dejarte una especie de iterar a través de esas de una manera distribuida. Esa gráfica x es, otra vez un poco caído por el camino. Realmente no se ha mantenido bien últimamente y hay API alternativas
más nuevas en estos días que son más populares. Hablaremos de eso más al final del curso. En este curso, estamos utilizando el lenguaje de programación Scala. ¿ Por qué, por qué estamos usando Scala? Eso es una especie de lenguaje oscuro, ¿no? Bueno, hay algunas razones. Una es que la propia Spark está escrita en Scala. Entonces al escribir tus guiones en Scala, eres como acercarte más a cómo se escribe Spark en optimizado. Entonces, ya lo sabes,
eso puede conducir potencialmente a un mejor desempeño. El otro es que Scala es lo que llamamos un lenguaje de programación funcional. Y como tal, realmente es un buen ajuste para el procesamiento distribuido. Scala realmente impone que escribas tu código de tal manera que tus funciones se puedan distribuir en todo un clúster. tanto que otros lenguajes como Java y Python realmente no intentan forzarte a eso. Por lo que al escribir tus guiones de conductor de Spark en Scala, es más probable que
estés escribiendo código que se pueda paralelizar de forma segura y fácil. También te da un rendimiento rápido. Entonces escala se compila hacia abajo al código de byte de Java. Entonces, al final del día se está ejecutando en la JVM,
el intérprete de Java, y eso es bastante jodidamente rápido en la mayoría de los sistemas. Obviamente, Java también te dará un rendimiento rápido porque eso también compilará hasta códigos de byte Java. Pero contrasta eso con escribir tus guiones de chispa en Python, lo que puedes hacer. Pero hay que pasar por otra capa ahí, ¿verdad? Así, el código python necesita
transformarse de alguna manera en bytecode Java al final del día. Por lo que escribir en Scala solo porque te acercas un poco a ese último nivel inferior donde tu código realmente se estará ejecutando. Ahora para ser justos, pitón es bastante jodidamente rápido en Spark estos días. Entonces la diferencia no es tan grande como solía ser, pero aún hay una pequeña diferencia. La otra ventaja de Scala si quieres ponerlo contra Java, es que es más fácil de usar. Entonces va a haber mucho menos código. Tienes que escribir mucho menos cosas repetidas de las que
tendrías que escribir si estás codificando en Java. Java tiene una gran cantidad de sobrecarga asociada en términos de cómo realmente puedes compilar ese código y distribuido y cosas por el estilo. Es mucho más fácil en Scala resulta. Y como dije, en comparación, Python más lento, no es tan lento como solía ser. Todavía vas a conseguir un poco de ventaja con Scala,
pero esa comparación de velocidad se ha ido cerrando a lo largo del tiempo. Pero, ¿dónde están los inconveniente de Scala? Bueno, una es que quizá aún no conozcas a Scala. Ya sabes, no es un lenguaje muy común. Entonces vas a tener que ir a aprender los fundamentos de la casa Gallo trabaja, pero no es tan difícil como piensas. Por ejemplo, echemos un vistazo a este pequeño fragmento de código. Estamos haciendo lo mismo aquí en Python y en Scala. Nos va a gustar escribir algún código para cuadrar los números en un conjunto de datos. Cosas bastante simples. Entonces en la versión de Python y la versión de Scala, si la miras, no son tan diferentes, ¿verdad? Tan sintácticamente hay pequeñas cosas como, ya
sabes, hay que declarar en Scala que es una constante
inmutable que estás usando diciendo val. La sintaxis para definir una lista de cosas es ligeramente diferente. El sintaxis para las funciones Lambda es un poco diferente, pero es la misma idea, ¿verdad? Entonces Scala es una sintaxis extraña. A veces las cosas pueden ir un poco al revés y vamos a hablar de eso. No te preocupes por ello. Pero al final del día, no se ve tan diferente del código Python en el contexto de un script de controlador chispa. Y con eso, en realidad vamos a sumergirnos en un curso acelerado en Scala si lo necesitas. En esta siguiente sección, en realidad vamos a entrar en los conceptos básicos de Scala. ¿ Qué tiene de diferente, Qué tiene de raro? Yo sí espero que vas a tener alguna experiencia previa en escribir código en alguna parte,
algún lenguaje de scripting o programación. No estoy aquí para enseñarte a programar desde cero chicos. Ese sería un curso diferente. Pero si tienes algo de Python bajo tu cinturón, o C o Java o algo así, creo que puedes recoger, escalar bastante rápido. Entonces en esta siguiente sección, si lo necesitas, tenemos un poco de introducción a Scala que desmitificará la sintaxis para ti. Y a medida que pasemos por el curso, verás muchos y muchos ejemplos de usar Scala. Y creo que simplemente se hundirá mirándolo lo suficiente y viendo suficientes ejemplos. Entonces, sumémonos en nuestro curso de choque de Scala si lo necesitas. Si no te sientes libre de saltarte la siguiente sección y solo nos sumergimos en cómo funciona Spark.
4. [Actividad] conceptos básicos de Scala: Hola, soy Frank cane y bienvenido a mi oficina. Vamos a empezar haciendo un pequeño curso acelerado sobre el propio lenguaje de programación de Scala. Ahora obviamente, si ya estás familiarizado con Scala, puedes saltarte esta sección y eso está bien. Pero si eres nuevo en Scala, pero antes has tenido algo de experiencia en programación, encontrarás una sección muy útil para entender el código que vamos a estar viendo a lo largo de este curso. Basta con ser peligroso, ¿verdad? Entonces, no esperes una introducción integral al curso de Scala aquí en esta sección, pero es suficiente para que pases por este curso al menos y a través los ejemplos que pasaremos en esta sección y los ejemplos más adelante en el curso. Creo que terminarás este curso con una comprensión bastante buena de cómo funciona
Scala e incluso cómo escribir tu propio código de Scala. No obstante, si eres nuevo en la programación por completo, esto no va a ser suficiente para ti. Yo los animaría a ir a buscar un curso introductorio sobre Scala que primero entre más profundidad para luego volver a este. Pero para el resto de ustedes, vamos a arar adelante y aprender Scala. Muy bien, aprendamos Scala solo para establecer expectativas. No vas a ser un experto en Scala al final de ver videos conmigo. Entonces lo que realmente estoy tratando de hacer aquí es simplemente familiarizarte con la sintaxis
del lenguaje de programación Scala e introducir algunos de los constructos básicos como ¿cómo llamo a una función en Scala? Cuáles son el trabajo de control de flujo donde algunas estructuras de datos básicas que podría usar con Scala, te
mostraré suficiente código de Scala que no te va a parecer aterrador e intimidante a medida que pasemos por el resto del curso. Entonces con eso, hablemos primero de escala a un alto nivel. En primer lugar, ¿por qué aprender Scala? Bueno, probablemente nunca habías oído hablar de él antes. A lo mejor lo has hecho, pero seguramente no lo sabes. Se utiliza en su mayoría para la programación de Spark. Pero es singularmente adecuado para spar porque está realmente estructurado de
una manera que se presta a hacer un procesamiento distribuido de datos sobre un clúster. Y ya verás por qué un poco más tarde. También es con lo que se construye la propia Spark. Por lo que al aprender Scala, obtendrás acceso a todas las funciones de chispa más recientes y más grandes a medida que salgan. Y por lo general puede tomar un tiempo bastante largo para que esas características goteen hacia abajo para decir soporte de Python dentro de Spark. Y también va a ser la forma más eficiente de ejecutar el propio código de Spark. Por lo que al usar Scala, tendrás los trabajos de Spark más rápidos y confiables que posiblemente puedas crear. Y creo que te sorprenderías bastante de cuánto más rápido y cuánto más confiable. El mismo trabajo de chispa escrito en Scala se compara para decir, el mismo trabajo de chispa escrito en Python. Entonces a pesar de que podría ser tentador salir y seguir con el lenguaje que ya conoces. Aprender Scala vale la pena el esfuerzo y realmente no es tan difícil. La verdad es el mismo código de Spark para Scala y Python se ven muy similares entre sí al final del día. Ahora, el propio cráneo corre encima de la máquina virtual Java. Por lo que solo se compila hasta el código de byte de Java y se ejecuta por la JVM. Entonces una cosa agradable de eso es que también tienes acceso a todo Java. Si hay una biblioteca Java que quieres meter en tu código de Scala, puedes hacerlo. Por lo que no te limitas a lo que hay en el propio lenguaje Scala. En realidad puedes llegar hasta la capa de Java y tirar hacia arriba. Es un trabajo que tú también quieres usar. Y lo haremos más adelante en este curso, por ejemplo,
por tratar con expresiones regulares en un asunto un poco más intuitivo de lo que podrías de otra manera. Otro punto clave sobre Scala es que está enfocado en torno a lo que se llama programación funcional. Donde las funciones son algo así como el meollo de lo que estamos tratando. Las funciones se pasan a otras funciones y se
encadenan juntas de formas a las que podría no estar acostumbrado. Pero así es realmente como funciona Spark a un nivel fundamental. Básicamente tomamos una abstracción sobre un trozo de datos y le asignamos una función para hacer algún procesamiento sobre esos datos. Y la programación funcional en Scala hace que eso sea muy intuitivo de hacer desde el punto de vista del lenguaje. Muy bien, así que saltemos justo al fondo
de la piscina y nos hundamos o nadamos con Scala, solo
vamos a escribir un código y ver qué pasa y ensuciarnos las manos. Ahora en realidad no te proporcioné una copia de este código por el que voy a estar
pasando porque en realidad hay un valor y escribirlo tú mismo para hacer una especie de hundirse. Entonces, empecemos por crear lo que se llama una hoja de trabajo Nueva Scala. Esto nos va a dar un entorno interactivo donde podemos simplemente especie de experimento con el código Scala y evaluado de forma interactiva. Entonces ve a tu menú de archivos e inteligencia y di Nueva hoja de trabajo de Scala. Y llamaremos a éste aprendiendo Scala uno. Y en esta primera conferencia, sólo
vamos a hablar de la sintaxis y estructura
del lenguaje Scala porque es un poco raro en comparación con otros idiomas que hay por ahí. Entonces, en primer lugar, si quieres un comentario, solo
puedes hacer una doble barra como lo harías en muchos otros idiomas. Y primero vamos a hablar de valores. Por lo que los valores son constantes inmutables. Entonces ese es un ejemplo de una línea de comentarios ahí. Ahora en otros idiomas tenemos el concepto de variables. Ya sabes, es algo muy universal y programación
asignar algún valor a una variable con nombre, ¿verdad? Y como usa eso a lo largo de tu código. Ahora en Scala, hay dos tipos diferentes cuando se llama valores que son inmutables y variables que son inmutables. Y en Scala quieres quedarte con los valores tanto como sea posible. Entonces, aquí hay un ejemplo de cómo definir uno. Podríamos decir val para valor, Hola, colon, cadena igual a cita Ola. Y si realmente quieres ejecutar eso, solo
podemos pulsar un pequeño botón de juego aquí. O puedes ver también hay un atajo de teclado de Control Alt W que utilizaré a partir de ahora. Y está creando un ambiente para ejecutar eso en este momento y ahí lo tenemos. Por lo que se puede ver que realmente ejecutó ese comando y asignó el valor o ley a una cadena llamada Hello. Entonces pasemos algún tiempo hablando de la sintaxis aquí porque es un poco al revés de muchos otros idiomas, ¿verdad? Entonces empezamos diciendo que esto es un valor. Eso significa que estamos definiendo una constante inmutable. Una vez que definamos realmente qué es hola, no
podemos cambiarlo nunca más. Entonces vamos a llamar a este valor Hola. Y luego después del colon, tenemos que declarar de qué tipo es. Entonces estamos diciendo que hola es un tipo de cadena. Entonces eso es al revés de la mayoría de los otros idiomas, ¿verdad? Por lo general verás como cadena hola, pero en Scala es hola, cadena de colon. Y luego lo asignamos a un valor. Nada demasiado raro. Son sólo la cuerda hola entre comillas. De acuerdo, entonces eso tiene sentido, ¿verdad? Está un poco al revés, pero te acostumbras bastante rápido. Ahora hablemos de variables. Por lo que las variables son inmutables. Eso significa que en realidad puedes cambiarlos después de haberlos definido. Entonces para definir una variable, es lo mismo. Simplemente usas un var en lugar de un Val. Entonces podemos decir var hola ahí, que también es una cadena, y pondremos eso en Hola. Vamos a asignar eso al valor de la cadena constante, la constante inmutable hola. Entonces voy a decir Control Alt, W. Y se puede ver ahí que hola ahí se le ha asignado el valor de cadena o ley porque eso fue almacenado en nuestro valor inmutable. Hola tiene sentido hasta ahora. Pero hola, hay una variable, podemos cambiarla ahora no está pegada a ser Hola. Entonces podríamos decir algo así como hola ahí equivale hola más espacio allá y Control Alt W. Y puedes ver que en realidad hemos modificado Hola también ahora contienen la cadena Hola. Ahí hay Ola más bien. Entonces, como se puede ver, las variables se pueden cambiar valores sin embargo, no. También podríamos usar el comando print line para imprimir ese valor explícitamente. Imprimir línea hola ahí, que hace exactamente lo que pensarías. Se imprime el valor de esa variable en una línea Control Alt W por ahí. Está bien, así que has visto algunas cosas básicas aquí. En primer lugar, el concepto de valores en variables y valores nuevamente son inmutables. Una vez que las definas, no puedes cambiarlas. Si bien las variables son mutables, no
puedes cambiarlas después de definirlas. Y también tenga en cuenta la sintaxis aquí de declarar valores y variables. Es valor var, el nombre del identificador, dos puntos, el tipo, y luego es igual a lo que quieras que lo establezca. De nuevo, eso es al revés de muchas otras lenguas. Y sólo para mostrarte lo que pasa y para demostrarte que los valores no se pueden cambiar. Cambiemos ese var2 eval y veamos qué pasa si tratamos de volver a ejecutar esto, Control Alt W. Puedes ver que tenemos algunos errores aquí ahora, reasignación eval, no podemos decir hola ahí igual hola más allá porque no puedes cambiar un val. Un valor es inmutable. Vamos a cambiar eso de nuevo a var y ejecutado de nuevo Control Alt W. Todo bien, Hasta ahora
tan bien, ¿verdad? Ahora, ¿por qué tenemos esta distinción entre valores y variables en Scala? Bueno, es porque esto es lo que llamamos un lenguaje de programación
funcional para escalar está algo centrado en torno a la idea de pasar funciones alrededor y potencialmente ejecutarlas en paralelo. Por eso es un buen partido para Apache Spark. Y la razón por la que queremos quedarnos con constantes inmutables siempre que
podamos es evitar un montón de temas de seguridad de hilos y para especie de encabezarlos en el paso. Entonces imagina que tienes una función que tiene una variable en ella que obtienes, que puede cambiar y pasas esa variable a muchos, muchos hilos. ¿ Qué pasa si un hilo está tratando de cambiar esa variable al mismo tiempo que otro hilo está tratando de cambiarla por otra cosa, los resultados se vuelven indefinidos, ¿verdad? Por lo que evitamos muchas de estas condiciones de carrera tratando de usar constantes inmutables siempre que sea posible. Si nuestras funciones solo están actuando y procesando datos inmutables, no
tenemos que preocuparnos por todos esos hilos,
seguridad y condiciones de carrera. Ahora esto no te limita tanto como podrías pensar. Todavía se puede hacer mucho solo usando valores constantes inmutables. Entonces por ejemplo, si quería hacer la operación anterior y construir la cadena o la allí desde el valor Hola. Todavía puedo hacer eso usando valores. Podría decir algo así como val inmutable hola ahí igual hola más allá. ¿ Verdad? Y podría imprimir ese resultado. Control Alt W. Y eso funciona porque estoy definiendo hola inmutable allá en la misma línea aquí estoy tomando un valor previamente inmutable, agregando otro valor inmutable y asignando eso a un valor inmutable. Entonces eso está bien con las variables. Lo hicimos de una manera diferente. Al igual que empezamos por establecer hola allá a hola, y luego en otra operación, le agregamos la cadena ahí. Entonces mientras hagamos todo en una línea,
en una operación atómica, seguimos apegándonos a las reglas de usar valores siempre que sea posible. Está bien, así que hemos visto el tipo de datos de cadena aquí en acción, ¿verdad? Por lo que hay muchos otros tipos de datos disponibles en Scala. Hablemos de los tipos de datos. Entonces, por ejemplo, podríamos decir val número uno. Whoops, si escribo bien, número uno colon int. Entonces un int es exactamente lo que crees que es un entero, un número entero, un número entero. También podríamos decir val. La verdad es un booleano. Y pondremos eso en realidad. Tenga en cuenta que en Scala, constantes
verdaderas y falsas son todas minúsculas. Hay idiomas en los que capitalizarías a verdadero y falso, pero no en Scala. Entonces eso es sólo un valor booleano, verdadero o falso. También podemos tener personajes. Por lo que podemos decir val, letra a. Como tipo de auto, un solo carácter, un único valor ascii. También tenemos unos números de doble precisión, por supuesto. Entonces podemos decir que Pi es un doble. Y ponlo a 3.14159265 o lo que sea. Y también podemos representar un solo valor de punto flotante de precisión con precisión simple Pi. Y lo declararemos como flotador, que es una única variable de punto flotante de precisión. Y pondremos eso en 3.14159265 F, lo que significa precisión única de punto flotante. Vamos a Controlar Alt W para ver que tenemos hasta ahora está funcionando. Por lo que se puede ver que todas estas variables se han definido como se esperaba. Sigamos adelante. También hay un tipo de datos largo, digamos val gran número. Definimos eso como un largo. Y pondremos eso en algún entero grande. 1, 2, 3, 4, 5, 6, 7, 8, 9, fuera en lo que quieras. Y podríamos decir también un solo número de carácter. Podemos ahorrar todo número pequeño. Declarar que como un byte es igual a 127. Entonces un byte es básicamente un número que está abarrotado en un solo byte. Por lo que sólo puede representar números del 127 negativo al 127 positivo. O si se quedara sin firmar 0 a 255, Control Alt W para ejecutar esos. Está bien, se ve bien. Pasando adelante, hablemos de cómo realmente imprimir y mostrar sus datos y dar formato a su salida. Eso siempre es algo importante, ¿verdad? Entonces digamos que queremos concatenar un montón de cuerdas juntas o un montón de valores juntos e imprimirlos. Obviamente, quieres poder ver los resultados de tus programas de Spark. Entonces así es como harías eso. Podríamos decir línea de impresión. Aquí hay un desorden. Y el secreto aquí es que solo puedes usar el operador plus para concatenar cosas juntas e imprimirlas como una cuerda grande. Y no sólo tiene que ser cuerdas tampoco. Puede ser cualquier tipo de datos. Convierte implícitamente eso en una cadena. Entonces puedo decir que aquí hay un desastre más Número 1 más verdad, más letra a, más pi, más gran número. Y eso debería funcionar. Control Alt W. Ahí está. Cangrejo todo junto porque no inserté ningún espacio entre todo, pero funciona. Nota también por cierto, no hay punto y coma ni nada al final de las líneas aquí. Simplemente asume que cada nueva línea es un nuevo comando básicamente. Por lo que no hay necesidad de terminar explícitamente tus líneas de código en Scala. ¿ Qué quieres hacer como imprimir estilo F, si vienes de un fondo de como C o C plus, podrías estar familiarizado con el comando print f, que te permite poner en especie de indicios de formato para cómo visualizar realmente datos numéricos o insertar cadenas y otros datos en una cadena existente. Así se ve eso en Scala. Podemos decir imprimir línea F, lo que significa que queremos imprimir formato. Cotización pi es sobre signo de dólar pi, precisión
única, por ciento 0.3 F. De acuerdo, así que vamos a descomponer eso un poco. Entonces, en primer lugar, tenga en cuenta que tenemos ese signo de dólar ahí que está indicando que tenemos un nombre de variable o nombre de valor más bien, en este caso, siguiendo ese signo de dólar. Por lo que Pi es única precisión se va a insertar el valor de Pi sola precisión. Y por ciento 0.3 f significa que es un valor de punto flotante que vamos a mostrar ahí. Eso es lo que significa la F. Y por ciento 0.3 significa que después del punto decimal, sólo
queremos que se muestren tres dígitos de precisión. Entonces sigamos adelante y golpeemos Control Alt W. Y se puede ver que hizo exactamente lo que dijimos. Pi es alrededor de 3.142. Por lo que solo mostraba esos tres dígitos siguiendo el punto decimal ahí porque eso es todo lo que queríamos. Eso puede ser útil si estás mostrando una doble precisión o incluso un solo número de precisión que tiene un enorme número de dígitos establecido tiene más precisión de la que necesitas. También puedes hacer cosas como vamos a ver cómo funciona eso con enteros. Entonces por ejemplo, podríamos decir imprimir línea F, Otra vez sólo indicando imprimir f formato 0, relleno a la izquierda. Signo de dólar número 1, por ciento 05 D. Muy bien. Entonces esta vez estamos diciendo que vamos a insertar el valor del número 1 y el por ciento 05 D. El D sólo significa que es un número, un entero, y por ciento 05 significa que quiero tener al menos cinco dígitos a la izquierda de el punto decimal. Entonces veamos qué hace eso. Control. Alt W. Y obtenemos 000 000 001, prometiendo los cinco dígitos de precisión de la izquierda que queríamos. Eso puede ser útil cuando intentas alinear la salida y las columnas, ¿verdad? Entonces eso también es un truco práctico a veces. También si solo quieres sustituir variables en una cadena sin especificar realmente el formato. Eso también es fácil de hacer. Por ejemplo, imprimir línea S para cotización sustituta. Puedo usar el prefijo S para usar variables como signo de dólar número uno, verdad, y letra a. Muy bien, Control Alt W. Y funcionó. Por lo que puedes ver que es una forma muy fácil de insertar nombres de
valor en tu cadena allí sin tener que usar innecesariamente el operador de concatenación. Entonces sólo una forma diferente de hacerlo. De acuerdo, ¿qué más podemos hacer? Podemos incluir expresiones en nuestros comandos de impresión. Entonces déjame mostrarte cómo funciona eso. Imprimir línea S. El prefijo S no se limita a variables. Puedo incluir cualquier expresión como Ross, un signo de dólar, corchete rizado abierto, uno más dos. Y automáticamente completó esa línea para mí. Entonces la clave aquí son esos corchetes rizados. Después de que tengas un corchete rizado establecido después de un signo de dólar, en realidad
va a evaluar la expresión dentro de esos corchetes rizados e imprimir el resultado de eso como parte de la cuerda Control Alt W. Y si nos desplazamos, deberíamos ver que imprimió el número tres. Entonces ese es un truco ordenado para escribir. Por lo que esos corchetes rizados tras signo de dólar podrían en realidad evaluar una expresión dentro de un comando de línea de impresión si usa el prefijo S. También hay expresiones regulares. Entonces, si estás familiarizado con esos, esa es una poderosa herramienta para realmente manchar tus datos de cadena. Veamos cómo funciona eso. Entonces empecemos con una cuerda que es Val, la respuesta definitiva. Definimos eso como una cadena. De nuevo, no estábamos volviendo a cómo definir un valor. Y pondremos eso a la vida, al universo. Y todo es 42. Y si reconoces esa referencia, entonces U2, nuestro fan de The Hitchhiker's Guide to the Galaxy. Bienvenido. De acuerdo, entonces tenemos esta cuerda y queremos hacer es escribir una expresión regular que extraiga la respuesta a la pregunta última de la vida, el universo, y todo. Entonces vamos a configurar una expresión regular para extraer ese número del final de esa cadena. Por lo que podemos decir patrón val equivale a cotizaciones triples 123. Y luego lo vamos a escribir en una expresión regular para extraer la información que queremos de esa cadena. Estrella de punto, paréntesis, corchete cuadrado, barra trasera d, n corchete cuadrado. Además cerrar estrella de punto paren, y luego esas tres comillas, punto r Vale, entonces el punto R significa que esta es una expresión regular que estamos definiendo aquí. Y repasar cómo funcionan las expresiones regulares probablemente esté fuera de alcance para este curso. Pero hay una herramienta muy útil para cosas como extraer información de archivos de registro y cosas así. Un rápido desglose de lo que está pasando aquí. El punto estrella significa igualar cualquier cosa en esa cuerda seguida de un espacio. Y luego dentro de los paréntesis está lo que estamos tratando de extraer de ese patrón. Y los corchetes y la barra inversa d significa que quiero extraer un número. Muy bien, y cualquier número de números, Eso es lo que significa el signo más, seguido de cualquier otro personaje. Vale, Entonces buscando un montón de personajes seguidos de un espacio y luego un número seguido de cualquier otra cosa que vaya a sacar ese 42 de esa cuerda. No necesitamos ese control Alt W solo para asegurarnos de que eso esté funcionando. Está bien, genial. Entonces echemos un vistazo aquí. Entonces tenemos esa cuerda que definimos para dar vida al universo y todo es 42. Y ahora hemos definido un objeto de expresión regular coincidente que consiste en esa expresión regular. De acuerdo, Entonces eso fue lo que pasó con esta línea de aquí. Ahora para aplicar esa expresión regular a la cadena, es muy sencillo. Podemos simplemente decir val pattern, paréntesis Respuestas, string es igual a la respuesta definitiva. De acuerdo, entonces la sintaxis Hay un poco raro. Significa que vamos a tomar la expresión regular que definimos en patrón. Vamos a asignar la salida de eso para responder cadena. Entonces la sintaxis aquí, básicamente es decir, quiero tomar lo que hay en estos paréntesis y transferir ese resultado a lo que está en estos paréntesis. De acuerdo, Esa es una forma de pensarlo. Y vamos a asignar la respuesta definitiva a ese patrón. Entonces la sintaxis ahí otra vez, un poco atrás de cómo podrías estar pensando en las cosas en otros idiomas. Y entonces sólo podemos imprimir cuál es esa respuesta. Primero, vamos a convertirlo en un entero. Podemos decir val, respuesta es igual a Respuestas cadena a int. Entonces eso es solo mostrarte cómo convertir realmente un tipo a otro. Ayudaría si escribiera la cadena de respuesta correctamente. Y entonces puedo imprimir eso. Imprimir línea, contestar. De acuerdo, así que hemos definido una cadena, hemos definido una expresión regular para
extraer información de esa cadena, definimos una declaración. En realidad aplica esa expresión regular a la cadena y almacena el resultado en algún lugar. Estamos llamando a esa cadena de respuesta. Hemos convertido eso de una cadena a un entero, y luego vamos a imprimir que hiere Control Alt W. Y funcionó. Para que veas que extraimos la cuerda 42. Convertimos eso a un entero 42 y lo imprimimos cuando terminamos. Muy bien, adelante. Hablemos de los booleanos. Tan cosa realmente fácil que funcionan exactamente como cabría esperar. Entonces hablemos de los booleanos. Entonces, por ejemplo, podríamos decir que val es mayor y ponerlo igual a uno mayor que dos. ¿ A qué crees que saldrá eso? ¿ Es uno mayor que dos? No, la respuesta es falsa. Por lo que eso funciona más o menos de la forma que esperarías. Diría que Val es menor igual, uno, menos de dos. Eso es cierto. Podríamos decir que val imposibles iguales es mayor y menor. Y se puede ver que podemos usar un solo ampersand ahí. Eso está bien. Pero también podríamos decir un doble ampersand. Veamos qué hacen esos. Control Alt W. Así que estos en realidad no son lo mismo aquí. Entonces al igual que en C o C
plus, además de un doble ampersand es en realidad un final lógico donde es un solo ampersand es un bit a bit. Y así la única razón por la que esto funciona en absoluto es porque es mayor y menor alas pueden evaluar abajo a ceros y unos y todavía termina funcionando. Y simplemente convertimos implícitamente eso a verdadero o falso. Pero si estás tratando de hacer una operación lógica, que es lo que realmente estamos tratando de hacer aquí. Deberías estar usando el doble ampersand. Ese es el operador lógico o booleano. Entonces sí te dan el mismo resultado en este caso, pero realmente es mejor forma usar el doble ampersy ahí funciona de la misma manera con o si quieres decir que es mayor o menor, eso funciona. Eso sería cierto, presumiblemente, sí. Entonces se te ocurre la idea. Los booleanos trabajan más o menos como esperarías de otros idiomas. Vamos a jugar con él un poco más. Y podríamos decir val, la carta, que es una cuerda, y ponerla igual a Pickard. Y podemos decir val mejor capitán. Otro valor solo con un nombre diferente. También una cadena es igual a Pickard. Y podemos decir que Val es mejor. Declara eso como booleano. Y le pondremos eso a Picard. Igual igual a mejor capitán. Entonces sigamos adelante y ejecutemos eso y Control Alt W hace lo que podrías pensar. Por lo que es igual, igual aquí es realmente ir dentro de esas cadenas y comparar los valores de las cadenas. Entonces eso significa que en realidad queremos comparar los valores de esas dos cosas y ver si son idénticas. Por lo que en realidad no es comparar los propios objetos ni la dirección de los propios objetos. En realidad es entrar en esa cuerda y comparar las cuerdas entre sí. Entonces si quieres comparar dos cadenas, solo usa el operador igual a igual. Eso puede ser algo que es un poco raro en algunos idiomas. Por lo que es importante señalar eso aquí. Y si sí quieres debatir en la Q y un clima, Picard es el mejor capitán. Acojo con beneplácito esa discusión. Está bien. Si querías ensuciarte las manos, jugar con estas cosas, hacer algunas cosas más, seguir adelante, chicos. Entonces, por ejemplo, podrías escribir algún código que tome el valor de pi y lo duplica y luego lo imprime dentro una cadena con tres decimales de precisión a la derecha. De acuerdo, Así que en realidad voy a pegar eso aquí como un pequeño reto para ti. Y es realmente fácil. Ni siquiera te voy a dar la respuesta. Ustedes pueden platicar en la Q y a si quieren hablar de la solución real. Pero ahí está mi reto para ti. Ve y aplica lo que acabas de aprender y haz eso. Sí, solo escribe un pequeño fragmento de código que tome el valor de Pi. Definimos, lo multiplicamos por dos, e imprimimos dentro de una cadena con tres decimales de precisión a la derecha. Todo lo que necesitas hacer para lograr eso debe estar por encima de ti aquí. Tan poca manera sencilla de conseguir algo de exposición práctica. Así que ensuciate las manos, juega un poco más. Y luego pasaremos al siguiente capítulo de aprendizaje de Scala.
5. [Ejercicio] Control de flujo en Scala: Por lo que sigue adelante, si quieres guardar lo que has hecho hasta ahora, solo
puedes decir Control-S, cerrar eso es mantenerlo alrededor para futura referencia si quieres. Y hagamos más bien otro cuaderno de Scala o hoja de trabajo de Scala. Y llamaremos a éste el nombre creativo de aprender Scala. Y esta vez vamos a hablar de control de flujo. Entonces veamos cómo funcionan las declaraciones de lo contrario. Trabajan exactamente de la misma manera que en otros idiomas. Aquí no es nada demasiado raro. Por ejemplo, podríamos decir si uno es mayor que tres, línea de impresión, imposible. Else línea de impresión. El mundo tiene sentido. Entonces exactamente como cualquier otro idioma que hay, si alguna expresión es cierta, haces esta expresión, lo
contrario haces alguna otra expresión. Y si quieres hacerlo todo en una línea, eso es lo que parece. Por lo que Control Alt W, el mundo tiene sentido como debería. Ahora si quieres dividir eso en múltiples líneas, la sintaxis de nuevo te resulta bastante familiar. Aquellos de ustedes que han programado antes, sólo
podríamos decir si uno es mayor que tres corchete rizado. Y esto nos permite poner múltiples expresiones en ese caso positivo. Por lo que podríamos decir línea de impresión imposible. Y si quisiéramos, podríamos imprimir otra vez otra cosa. De verdad lo contrario, haz alguna otra cosa. Podemos decir línea de impresión, el mundo tiene sentido. Y aún así, no lo sé, me estoy inventando esto. Control Alt W. El mundo tiene sentido, aún frío. Entonces no hay nada demasiado sorprendente ahí. Es muy similar a otros idiomas ahí. Bueno, entonces ya sabes cómo podemos tener como declaraciones de cambio en algunos idiomas donde tipo de tener como coincidencia entre diferentes casos. Bueno, ¿qué aspecto tiene eso en Scala? Veamos un ejemplo de eso. Por lo que podríamos decir número val igual a 3 SAT el número 32, un valor llamado número. Y podemos decir número match corchete rizado, caso uno. Poco rara flecha allí es igual signo mayor que la línea de impresión 1, caso 2. Se puede ver adónde voy con esto. Imprimir línea 2, caso 3, línea de impresión tres. Y entonces podemos decir caso, subrayado, línea de impresión, otra cosa. Probablemente adivina qué hace Control Alt W. Obtenemos el valor libre impreso. Entonces lo que está pasando aquí es que tenemos esta declaración de caso aquí donde podemos tener una lista de diferentes casos que vamos a comprobar contra el número de valor. Es igual a 1. Ejecutaremos esa expresión. Si es igual a 2 más q, esa expresión es igual a 3, ejecutamos esa expresión, que resulta ser. Y este subrayado es un poco como un catch-all. Es como la declaración por defecto de donde cualquier otra cosa, cualquier otro caso que no
coincidimos, vamos a golpear eso en su lugar. Entonces, por ejemplo, podríamos poner esto 30 y eso debería golpear esa declaración final de catch-all, ¿verdad? Control Alt W. Seguro que conseguimos algo más y cambiamos eso a, para llegar a. Entonces así funciona una declaración de coincidencia. Eso no se ve con demasiada frecuencia en Scala, pero está ahí si lo necesitas. A continuación, hablemos de for-loops. Algo muy común que hacer en la mayoría de los lenguajes de programación, ¿verdad? Entonces, ¿cómo funciona eso? Es un poco raro en términos de sintaxis. Entonces. Una forma de hacerlo es por x menos que dash uno a cuatro. Y entonces podemos decir val cuadrado es igual a x veces x e imprimir línea al cuadrado. Entonces lo que esto hace es iterar a través de los valores uno a cuatro. Y en cada momento a través de ella, si firma ese valor actual de esa iteración actual al valor x. Y entonces calculamos un nuevo valor llamado cuadrado que multiplica x por sí mismo e imprime el resultado. Entonces lo que deberíamos ver, nuestros cuatro resultados aquí, cada uno con el cuadrado de los números uno a cuatro, Control Alt W. Y ahí están, 14916 porque eso es uno al cuadrado, dos al cuadrado, tres al cuadrado, y cuatro al cuadrado. Así que prácticamente funciona de la manera que esperarías, ¿verdad? También tenemos loops while, igual que lo harías en otros idiomas. Por lo que también podríamos hacer algo así como var x es igual a 10. Y tenga en cuenta que estoy usando una variable mutable aquí. Esto generalmente no es una buena práctica en Scala. Y diré mientras x mayor que o igual a 0, corchete
rizado, línea de impresión x, y luego x menos es igual a uno. Entonces vamos a empezar ajustando x a 10. Si bien x es mayor o igual a 0, vamos a imprimir el valor de x y luego restarle uno. Por lo que puedes ver tuvimos que hacer de x una variable ahí para seguir modificando el valor de x Así que no una estructura. Vas a ver con demasiada frecuencia en Scala, pero no puedes hacerlo si es necesario. Solo asegurémonos de que funcione. Control Alt W. Y lo suficientemente seguro cuenta atrás desde 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0. Enfriar. Interesante cómo formateó la hoja de trabajo que por
cierto, está saliendo de su camino para tratar de mantener las cosas compactas. Eso es un poco guay. Otra estructura para el control de flujo es el do while loop. Nuevamente, similar a otros idiomas. Por lo que también podríamos establecer x igual a 0. Seguimos usando esa misma variable que definimos antes. Y podemos decir Do print line x, coma x más es igual a uno, mientras que x menor o igual a 10. Entonces esta vez vamos a empezar en 0 e imprimir cada valor contando por uno, mientras que x es menor o igual a 10. Entonces estamos haciendo esa comparación al final del bloque en lugar del principio. Así es como funciona do-while. Control Alt W y sin embargo funciona 0123, todo el camino a 10. De acuerdo, de eso se trata para el control de flujo, hablemos más de expresiones. Entonces, pasando, expresiones. Entonces una cosa que es un poco rara de Scala es que cuando alguna vez tienes una expresión, es una especie de implícitamente devuelve el valor de esa expresión automáticamente dentro de ese bloque. Entonces, por ejemplo, digamos que el corchete rizado Val X equivale a 10 punto y coma, x más 20 punto y coma. ¿ Qué, qué va a pasar aquí? ¿ Qué hace eso en realidad? Control Alt W. Entonces lo que hizo fue realmente devuelto el valor 30, a
pesar de que en realidad no dijimos,
quiero imprimir esto , no dije explícitamente, quiero devolverlo, solo el acto de tener esa expresión es lo último en ese bloque, significa que eso es lo que bloquea las salidas como resultado. Entonces esto es algo importante para envolver tu cabeza en términos de programación funcional y expresión, cualquier tipo de bloque de código como este
se puede pasar por ahí ya que una función tiene su propia pequeña entidad. Y lo que esta función devuelve es lo que sea lo último y esa expresión sea. Ahora puedes devolver explícitamente las cosas a como un cañón otros idiomas. Pero implícitamente lo último que sucede dentro de un bloque de código va a ser el valor devuelto de esa expresión. Entonces este pequeño trozo de código aquí es una función en sí misma implícitamente. Y regresa en este caso, el valor 30. De acuerdo, eso es algo importante. En realidad podría simplemente imprimir eso. Y puedo decir línea de impresión. E imprimir esa expresión, val x es igual a diez, punto y coma x más 20, así como así. Y eso en realidad imprimirá ojalá el valor 30. De acuerdo, a ver cómo funciona eso. Punto importante ahí, porque ese es probablemente uno de los puntos más confusos de Scala. Si aprendes programación en un idioma diferente, lo que para la mayoría de las personas es el caso. Ese último poquito dentro del bloque es el valor de retorno de esa expresión. Y se puede tratar esa expresión como su propia entidad. De acuerdo, eso va a ser importante cuando hablemos de funciones a continuación. Está bien, ya basta para esta cuadra de aquí. Entonces de nuevo, te voy a dar un reto aquí para que practiques lo que has aprendido. Déjame copiar y un poco de ejercicio lo escribí a un lado aquí. Por lo que pudo haber oído hablar de la secuencia de Fibonacci. Y eso es lo que es. Básicamente es una secuencia donde cada número es la suma de los dos números que tiene ante sí. Por lo que tus resultados deben ser 011235 y así sucesivamente. A ver qué está pasando aquí. Entonces tenemos, entonces empezamos con un valor 01, y luego iteramos sumando los valores de los dos números antes de eso. Entonces 0 más 1 es 1, 1 más 1 es 2, 1 más 2 es 3. 2 más 3 es 5. 3 más 5 es 8, y así sucesivamente y así sucesivamente. Entonces tu reto es escribir un pequeño fragmento de código en Scala que haga eso. Entonces vas a tener que aplicar lo que aprendiste sobre el control de flujo aquí y valores y variables para sacar eso, esto es un poco más de un ejercicio desafiante. De nuevo, no te voy a dar la respuesta. Puedes buscarlo con bastante facilidad si te quedas atascado. Pero esta es una pregunta de entrevista bastante común por mostrarle a la gente que sabes codificar y que puede envolver la cabeza alrededor de algoritmos. Entonces sí te animo a tomarte el tiempo para superar ese ejercicio porque mi vienen a mano en una entrevista de trabajo algún día. Y también es una buena práctica para el control de flujo dentro del lenguaje Scala. Así que ve a divertirte con eso. Y cuando regresemos, aprenderemos un poco más.
6. [Ejercicio] funciones en Scala: Pasando adelante, esta próxima conferencia es una más corta, pero es muy importante. Vamos a hablar de funciones en Scala. Y dado que es un lenguaje de programación funcional, obviamente eso es de gran importancia. Cerremos el esqueleto de aprendizaje y creemos otra hoja de trabajo, Nueva hoja de trabajo de Scala, y llamaremos a éste, ¿adivina qué? Aprendizaje Scala tres. Y esta vez vamos a hablar de funciones. Por lo que el formato de una función en Scala va a ser la muerte. Nombre de la función, parámetro, nombre, tipo de
colon para tantos parámetros como tenga. Y luego el tipo de retorno de colon es igual, y luego alguna expresión que define lo que hace esa función. Esta es una sintaxis realmente, realmente extraña si estás acostumbrado a otros lenguajes de programación no funcionales. Entonces, veamos algunos ejemplos. Podemos decir, por ejemplo, def cuadrarlo. X colon int, colon int es igual corchete rizado x veces x. Entonces así es como definirías una función que toma en un valor y cuadrados devuelve el cuadrado de ese valor. Vamos a descomponer esto. Entonces de nuevo, comenzamos con def para definir una función, el nombre de la función, en este caso, la cuadramos. Un parámetro. En este caso sólo tenemos un parámetro llamado x, y eso es de tipo entero. Entonces x colon int significa que el primer parámetro es un entero llamado x. Y entonces el valor de retorno de esta función va a ser un entero en sí. Entonces ese colon int es el valor de retorno, nuevo, totalmente al revés de muchos otros idiomas. Entonces tenemos que decir iguales para asignar esa función a alguna expresión. Entonces estamos diciendo que esta definición de función es igual a esta expresión en los corchetes rizados, x veces x No olvides que es igual, ese es un error muy común. Entonces, de nuevo, no estamos devolviendo explícitamente un valor. Simplemente esa última cosa que se evalúa dentro de la función es el valor de retorno implícito de esa función. Entonces eso es todo lo que hay a ello. Otro ejemplo, digamos def cobit x int, colon int es igual a x veces x veces x. Así que podríamos hacer todo eso en una línea a esto es simplemente para un one-liner rápido. Veamos estos en acción. Por lo que podemos decir imprimir línea, cuadrarla, pasando en el parámetro dos. Y podemos decir imprimir línea de codos, pasando en el parámetro tres. Controlemos Alt W y ejecutemos todo eso. Y se puede ver que asignamos la función raíz cuadrada y la cubimos. Y en realidad pasamos en el valor 2 para cuadrarlo y obtuvimos el valor para atrás. Pasamos en el valor tres a Cuba y recuperamos 27. Entonces así como debería estar funcionando. Entonces de nuevo, es enfocarse por un momento en esa sintaxis. Se necesita algo acostumbrarse a def nombre de la función, colon de
parámetro, tipo de valor de retorno de colon es igual, y luego la expresión que define la función en sí. Ahora, aquí es donde se pone raro. Si no pensaras que eso era lo suficientemente raro. Las funciones en realidad pueden tomar otras funciones como parámetros. Es como un inicio. Si no consigues esa referencia de cultura pop, me disculpo, pero digamos por ejemplo, death transform ints. Y lo tomaremos en X, que es un parámetro entero. Y también un f, que va a definir una función que toma un entero y devuelve un entero como su valor de retorno. Y esta función de transformación misma devolverá un entero y lo pondremos igual a la siguiente expresión, f de x. Está
bien, esto toma algo de pensamiento, correcto, entonces ¿qué está pasando aquí? Estamos definiendo una nueva función llamada transform int. Toma tanto un valor, un valor entero llamado X. Y también toma una función que toma un entero y devuelve otro entero. Entonces esa puede ser cualquier función que tome un entero y lo transforme en algún otro entero. Sabemos que esto a su vez devolverá un entero y se establece a la expresión f de x. Así que vamos a tomar la función que pasamos llamada f y pasar a esa función, el parámetro x que pasamos a transformarla. Si necesitas sentarte ahí y pensar un poco en cómo funciona eso, no tengas miedo de presionar pausa porque ese es un concepto muy importante para la programación funcional. Veamos qué hace en realidad cuando intentamos usarlo. Diremos Val resultado es igual a transform int, y pasaremos en dos y la función lo cube. Entonces, ¿qué crees que va a pasar aquí? Estamos pasando en el valor dos en x, el codo de función en F. Así que vamos a terminar llamando al cubit en el valor dos aquí dentro transformarlo. Por lo que luego transformamos int. Vamos a llamar a la función cúbica que pasamos con el valor X. Así que deberíamos volver a cubed, ¿verdad? Control Alt W. Seguro que nos dieron el valor ocho. De acuerdo, otra vez, fideos en eso. Y si realmente quieres imprimir ese resultado, en lugar de simplemente depender de lo que eso evaluó, podríamos decir imprimir línea, resultado, Control Alt W y volver evaluar explícitamente ahí. De acuerdo, Entonces aún más importante es el concepto de funciones Lambda, o a veces se llaman funciones anónimas son literales de función, ya
sabes, es una terminología muy diferente para esto. Pero básicamente, se puede declarar una función en línea sin siquiera darle un nombre. Y verás que esto sucede mucho en el código Spark. Por ejemplo, podría decir transform int tres x signo igual mayor que x veces x veces x. Entonces lo que he hecho es eludir la necesidad de definir realmente una función cúbica allí. Y solo me gusta encontrar esa función en línea aquí con si llamar a una función lambda o a una función anónima o a una función literal. Nuevamente, terminología diferente para lo mismo. Entonces esto hace lo mismo que 3 codos. Pero en lugar de definir realmente una función cúbica, solo
estamos definiendo las agallas de esa función cúbica aquí en línea como parte de esta línea. Entonces estamos diciendo transformar int el valor 3, eso va a pasar a x. Y ahora pasando al parámetro f transformarlo. Estamos pasando en esta expresión, Ross dice que vamos a tomar un parámetro de entrada x y devolver x veces x veces x Así que es sólo una especie de abreviatura de pasar en expresiones realmente cortas como funciones. Y vamos a asegurarnos de que haga lo que creemos que hace. Entonces si golpeamos Control Alt W, eso sí nos devuelve el valor 27 porque está pasando en tres, pasando tres en x y luego cubitando eso. Está bien. Echemos un vistazo a otro ejemplo. Misma idea, transformar int 10 x x dividido por dos. Entonces esto está definiendo algo nuevo que no hemos visto antes. Y vamos a utilizar esta transformación y pase de función en diez en x y en f Estamos pasando en este tipo de función lambda en línea que toma x y lo divide por dos. Entonces esperarías que eso regresara 1, 5, ¿verdad? Suficiente seguro. Otro ejemplo, podríamos decir transformar int a x. Y eso irá a, y podemos poner, nos complicamos más aquí. Podríamos decir val y es igual a x veces 2 punto y coma y veces y. De acuerdo? Y cierra eso. Creemos que va a pasar con este. Entonces lo que estamos haciendo aquí es pasar en una expresión multilínea aquí, en lugar de solo una sola línea, puedes hacer eso, eso es genial. Entonces aquí estamos configurando un valor llamado y y configurando eso en x veces 2. Entonces de nuevo, dos se están pasando a esta función como x. Entonces vamos a empezar diciendo 2 veces 2, que es 4. Y luego vamos a decir y veces y, así 4 veces 4. Entonces deberíamos conseguir 16, ¿verdad? Control Alt W. Seguro que obtenemos 16. Para que puedas ver esas funciones lambda pueden contener expresiones
multilínea si solo las pones entre paréntesis rizadas, eso está bien. Entonces es sólo una especie de nuevo, una abreviatura de definir una pequeña función corta sin definir realmente la función misma. Por lo que viene muy bien a veces, pero puede ser un poco confuso. Está bien. Eso es mucho para envolverte la cabeza. Como dije, aquí no hay mucho material, pero es difícil hundirse para ayudarte a que se hunda. De nuevo, tengo un reto para ti. Entonces aquí está su ejercicio para esta lección. Por lo que las cuerdas, resulta tener el método de punto toUpperCase incorporado. Entonces, por ejemplo, podrías decir foo dot a mayúsculas y te devolverá FU en todas las gorras. Entonces rabia modo tweet, si se quiere, su, su ejercicio, su reto es escribir una función que convierta una cadena mayúscula y luego usar esa función para unas cuantas cadenas de prueba. Y luego quiero que hagas lo mismo usando un literal de función. Esas son estas pequeñas funciones en línea aquí, en lugar de usar una función con nombre separado. Así que practica hacer a mayúsculas usando una función tradicional y luego usar una función literal usando estas pequeñas funciones lambda en línea aquí en su lugar. No demasiado duro, pero es buena práctica. Así que apártate y cuídate de eso. Y te veré en la siguiente lección.
7. [Ejercicio] Estructuras de datos en Scala: Muy bien, adelante, Hagamos aún más hojas de trabajo de Scala. Y llamaremos a este, nunca
adivinarás aprendiendo Scala cuatro. Y esta vez vamos a hablar de estructuras de datos. Concepto muy importante en cualquier idioma. Y esto va a ser una especie de largo unos chicos, así que atengan conmigo. Por lo que hay muchos tipos diferentes de estructuras de datos en Scala. Tenemos tuplas. Esa es una muy común cuando estamos tratando con el código de Spark. Tenemos listas inmutables. Y se puede pensar en esos como campos de base de datos o columnas de datos. Y esos pueden ser útiles para pasar alrededor de filas enteras de datos juntas, correcto, así que veamos cómo se ve eso. Podemos decir cosas del capitán val. Y si no estás familiarizado con Star Trek II, pido disculpas por las referencias de la cultura pop aquí. Picard, empresa D, NCC 17, 0, 1, D, realmente no importa lo que signifiquen estos. Ahí hay una lista de cuerdas que se juntan en lo que llamamos una tupla aquí. Ahora, a pesar del nombre de tupla, no necesariamente tiene que tener tres cosas en ella. Simplemente le pasa en este caso. Entonces tenemos aquí este trío de diferentes objetos, estas tres cuerdas que se agrupan en estos paréntesis. Y podemos tratar eso como una sola entidad a la que estamos llamando cosas de
capitán. Imprimamos eso. Control Alt W. Y se puede ver que eso imprime como ese objeto en sí, las tres cuerdas, Picard enterprise D, y NCC 17, 100 one-d. Dentro de esos paréntesis, en realidad es un solo objeto al que hemos llamado cap and stuff, y ese objeto contiene esas tres cadenas. Ahora podríamos desgarrarlo y referirnos a esos componentes individuales individualmente. Y eso lo hacemos al referirnos a ellos en base a su único índice basado que es importante. Consulte los campos individuales con un índice basado en uno. Esto puede ser confuso porque en muchos lenguajes de programación empiezas a contar desde 0, ¿verdad? No es el caso en este ejemplo en particular. Entonces por ejemplo, una línea de impresión, cosas de
capitán, subrayado de puntos. Una es la sintaxis aquí. Digamos Control Alt W, que imprime una tarjeta, el primer elemento de esa tupla. De igual forma, podemos decir imprimir línea capitana cosas subrayan dos, y imprimir las cosas del capitán de línea subrayan tres. Y obtenemos a cada uno de esos elementos despojados de su tupla original. Entonces así es como te refieres a elementos individuales de una tupla usando ese formato de subrayado empezando por uno. De acuerdo, ¿qué más podemos hacer? Podemos crear pares de valores clave, igual que lo hacemos en muchos otros idiomas usando el operador de flecha. Entonces por ejemplo, podríamos decir val cards ship es igual a la cadena Picard dash mayor que pequeño símbolo de flecha allí, enterprise dash d. Y luego podría referirme a la parte de valor de eso con una sintaxis similar. Podría decir línea de impresión, nave de
Picard, punto subrayado dos, eso me devolverá ese valor. Control Alt W. Así que puedes ver hemos creado ese mapeo de Pixar a Enterprise D. Y si queremos extraer ese valor en particular, solo
podemos usar subrayado dos para obtenerlo. Y en realidad puedes mezclar diferentes tipos dentro de una tupla. Por cierto, podemos decir val, un montón de cosas iguala entre paréntesis Kirk, que es una cadena, 1964, que es un número. El año en que salió Star Trek, claro. Y un booleano, Vamos a correr un booleano, cierto. ¿ Eso es algo válido para hacer? ¿Eso es legal? Sí, lo es. Por lo que puedes tener una tupla que contenga diferentes tipos de datos también. En este caso una cadena y int y un booleano. Eso está perfectamente bien en Scala. Hablemos de listas a continuación. Por lo que las listas son un poco como una tupla, pero son un objeto de colección real que tiene más funcionalidad. Y las listas no pueden contener elementos de diferentes tipos. Entonces como una tupla, pero más funcionalidad debe ser del mismo tipo. De acuerdo, pequeña nota para ti ahí, por ejemplo. En realidad es una lista de vínculos individuales bajo el capó si te gustan las estructuras de datos. Entonces podemos decir val, lista de barcos es igual a una lista, mayúscula L, empresa, desafiante, Voyager, Espacio Profundo nueve. Olvidé el índice 01, el mejor de todos de todos modos. Entonces, ¿qué hace eso? Control Alt W. Y sin embargo tenemos un objeto de lista que tiene una lista de cadenas. Entonces de nuevo, la lista debe contener el mismo tipo de objeto. En este caso es una lista de objetos de cadena. ¿ Y qué podemos hacer con él? Entonces como con una tupla, podemos extraer elementos individuales de esa lista, pero la sintaxis va a ser completamente diferente. Entonces digamos por ejemplo, línea de impresión, nave, lista, paréntesis, uno, así como así. ¿Qué crees que hará eso? Devolvamos empresa o me hará volver a encontrar,
averigüemos Control Alt W me da definirlo. Entonces, a diferencia de la sintaxis de tupla, en realidad
estamos basados en cero aquí. Muy bien, Así que nave era 0 nos devolvería empresa. Déjenme demostrárselo. Pero la lista de barcos 1 nos va a dar definirlo. Porque estamos empezando a contar desde 0 en este caso, que es un poco más de lo que esperarías. También contamos con operadores de cabeza y cola disponibles. Por lo que podríamos decir línea de impresión, nave, lista, cabeza de punto. Y podemos decir print line, ship, list dot tail, head probablemente hace lo que esperas. Eso te va a dar el primer elemento de la lista, pero la cola probablemente no lo sea. ¿ Qué esperas? En realidad te devuelve todos los artículos restantes. Más allá de la primera, Vamos a ver, Control Alt W. Y nos desplazaremos hacia abajo hasta el fondo. Entonces head nos dio lo primero en la lista empresa que se espera, pero tail nos da todo lo demás. Entonces eso nos da la lista de voyager definido y DSpace nueve, especie de sublista excluyendo el primer ítem. Poco rara alquimia SQL, rara a veces. Digamos que quieres iterar a través de cada elemento de una lista. Eso es algo bastante común que hay que hacer, ¿verdad? La sintaxis para eso es bastante simple. Podemos decir por paréntesis,
barco menos que, así que arroje al operador de flecha izquierda su lista de barcos. Y luego alguna expresión que operará en barco. Solo imprimámoslo. Está bien. Por lo que esto va a iterar a través de cada elemento de la lista de listas de barcos, extraer cada una de esas cadenas y asignarlo a enviar, y luego imprimirlo. Vamos a ver. Sí, funcionó. De tal manera que imprimió cada nombre de barco individual. Y ya sabes, si no estuviéramos en el ajuste de la hoja de trabajo, eso sería en líneas separadas, por
supuesto, pero está tratando de ser inteligente en conservar espacio para nosotros, lo cual es agradable. De acuerdo, vamos a ponernos raros. Apliquemos un literal de función a una lista. De acuerdo, esto es programación funcional. Podemos hacer cosas así. Por lo que podemos usar mapa, la función de mapa para aplicar cualquier función que queramos a cada elemento de una colección. Veamos cómo funciona eso. Podemos decir, por ejemplo, los val hacia atrás es igual a la lista de barcos mapa de puntos. Entonces esto significa que vamos a mapear cada elemento de esa lista a alguna función que vamos a proporcionar. Y aquí viene esa función. Simplemente vamos a hacer eso como una función literal dirá que empezamos con la nave que es una cuerda. Y eso se va a transformar en entre corchetes
rizados ship dot reverse porque hay un operador inverso incorporado en el operador de cuerda. De acuerdo, entonces vamos a expandir un poco eso. Vale la pena ver todo eso en una sola exhibición ahí. De acuerdo, así que envuelve tu cabeza alrededor de eso. Ahora esto es una especie de atar mucho de lo que ya hablamos. Entonces vamos a tomar una lista. Vamos a utilizar la función de mapa, que es muy importante en el mundo de la computación distribuida, para mapear alguna función a cada elemento de esa lista. Y esa función va a ser una función literal donde sólo estamos diciendo que algunas naves cadena se va a mapear al revés y devolver eso. Por lo que después de ejecutar esto, deberíamos tener una nueva lista llamada naves atrasadas que contenga todas las naves en reversa. Entonces sigamos adelante y vamos a imprimirlos. Con cuatro nave. De nuevo barcos al revés, sólo
estamos iterando a través de todo en esa lista como vimos antes. Imprimir línea nave. De acuerdo, entonces veamos qué hace. Ahí lo tienes. Por lo que los barcos atrasados se asignaron a esta lista donde aplicamos la función inversa a cada uno de los elementos de esa lista de buques. Y acaba de hacer cada palabra al revés. Y luego pasamos por un iterado a través de cada uno de esos elementos en esa lista de barcos atrasados y los imprimimos. Por lo que funcionó. Enfriar. Bueno se va a hacer. Entonces. Vimos mapa. Quizás has oído hablar de MapReduce. Entonces vamos a reducir. Mismo concepto. Entonces como teníamos un mapa, podemos usar reducir para combinar juntos todos los elementos de una colección usando alguna función que vamos a proporcionar. ¿ De acuerdo? Entonces, por ejemplo, digamos que la lista de números val es igual a la lista que contiene 1, 2, 3, 4, 5. ¿ De acuerdo? Suficiente simple. Ahora vamos a decir suma val igual número lista de puntos reducir. Por lo que el mapa aplicaría una función a cada elemento de la lista. Pero reducir va a pasar por cada elemento de la lista y ejecutar la misma función en él, deja que acumules todos los resultados de eso. Tendrá más sentido con un ejemplo. Por lo que podríamos decir, por ejemplo. Paréntesis y luego imprimir el c x colon int y colon int. Mapa eso a X más Y. ¿De acuerdo? Entonces pensemos en lo que está pasando aquí. Por lo que reducir básicamente mantiene un total corriendo de algún tipo. Por lo que va a tomar la salida anterior de la función de reducción de la iteración anterior, pasar eso a x Después se tomó la iteración actual, el número que está mirando en este momento llama a eso Y y aplicar alguna operación a
eso. Y la salida de esa operación se va a alimentar a la siguiente etapa cuando pasemos al siguiente elemento. Entonces déjame caminar un poco por lo que está pasando aquí. Vamos a empezar con uno. Y vamos a decir 1 más 2, que es 3, entonces pasará eso a la siguiente iteración. Y tendremos 3 más 3. El resultado de eso serán seis. Después tenemos seis más cuatro. El resultado de eso será 10, y luego 10 más 5 debe ser 15. De acuerdo, así es como funciona Reducir. Cuando terminemos, imprimiremos ese valor, imprimir línea alguna. Vamos a ejecutarlo. Suficiente, tengo 15. Así que reduzca. Es sólo una forma de algo así como colapsar de alguna manera todos los resultados en una sola respuesta final. Y a menudo eso se usa para computar como un gran total o algo así. Se podría pensar en formas más directas de hacer esto. Pero lo bonito de mapear y reducir las funciones es que son muy paralelizables. Por lo que es muy fácil aplicar funciones de mapa en paralelo y luego combinar los resultados de esas funciones de mapa en algún tipo de etapa de reducción para obtener la respuesta final que desee. Ya veremos que más en acción con ejemplos más adelante en el curso. ¿ Qué más podemos hacer esto una operación de filtro también. Si quieres quitar cosas que no quieres. Por lo que el filtro elimina cosas. Por ejemplo, podríamos hacer una nueva lista llamada Odio cincos y pasaré, asignarle eso al filtro de puntos de lista numérica, pasando en ella otra función en línea aquí. Función literal, si se quiere. X-naught igual a cinco. ¿ Está bien? Entonces lo que esto va a hacer es aplicar esta función de filtro. Hace x nada igual a cinco y sólo devuelve eso de vuelta dentro de nuestra lista resultante si eso es cierto. Entonces veamos qué hace eso. Eso nos devuelve una lista 1234 porque excluyó el valor cinco. Entonces así funciona un filtro. Puede filtrar información inválida, valores atípicos, lo que quieras hacer. Es una buena manera de limpiar los datos. Nuevamente, de una manera que es paralelizable. Hacemos lo mismo. Podríamos decir en una sintaxis ligeramente diferente. Val Odio 3s igual número lista de puntos filtro. Y esto es una especie de subrayado abreviado, no igual a tres. Entonces en lugar de como realmente escribir esa x darle un nombre
a ese valor x, realmente no necesitamos un nombre. Simplemente queremos tomar el valor que haya y comprobar eso contra tres. Entonces esa es una especie de expresión abreviada de hacer eso usando el carácter de subrayado. Entonces veamos qué hace eso. 12, 45. Sintaxis tan equivalente, notaste usar tres en lugar de cinco y un poco más fácil de escribir. Entonces si ves esa sintaxis, eso es lo que está pasando ahí. El subrayado es básicamente un tenedor de lugar para cada elemento de la lista. ¿ De acuerdo? Está bien. Ahora vale la pena señalar que Spark tiene sus propias funciones MapReduce y de filtro que distribuyen estas operaciones. Trabajan exactamente de la misma manera. Por lo que Scala tiene su propio MapReduce y filtro incorporado. Spark también tiene su propio MapReduce y filtro. La diferencia es que Spark va a estar seguro de paralelizar
eso a través de todas las máquinas de su clúster si puede. De acuerdo, oye, en realidad entiendes MapReduce ahora por cierto, ese es el concepto fundamental detrás de MapReduce. Es bastante simple, tan poco Bonus Army para ti. Algunas operaciones de lista más que puedes hacer. ¿ Cómo concatenato listas? Sintaxis para eso? Digamos Val, vamos a crear otra lista. Entonces tenemos algo con lo que jugar. Más números equivale a lista 678. Y podemos decir val, muchos números son iguales a lista de números más, más más más números. Por lo que para concatenar dos listas juntas, use ese operador doble plus. A ver qué hace eso. Control Alt W. Así que ahí lo tienes. Tenemos una nueva lista llamada montones de números. Puedo concatenar la lista numérica que contiene 1, 2, 3, 4,
5 y los más números listados 678 en una sola lista, 1, 2, 3, 4, 5, 6, 7, 8. Tenga en cuenta que no recuperamos una tupla de dos listas. Se trata de una lista única que contiene todos los valores de esas dos listas. Algunas cosas más aleatorias que podemos hacer con listas. Entonces nos volvemos atrás. Lo que hay en una lista con revertida igual número lista de puntos reverso, Cinco 4321. Y en realidad solían ser una pregunta de entrevista que le daría a gente en Amazon revertir las palabras en una cadena o revertir los elementos de una lista solían ser, eso era algo difícil de hacer y la mayoría de los lenguajes de programación, pero si te metes en su uso de Scala, puedes hacerlo en una línea de código. Tan poca manera de hacer trampa. Están clasificando. Se puede decir val ordenada es igual a punto invertido surtido. Oops, espero deletrear invertido, ¿verdad? Entonces sigamos adelante y ordenemos eso. Y eso está de vuelta en orden ordenado. 1, 2, 3, 4, 5. Easy-peasy. ¿Qué más votarías? Un montón de duplicados. Igual lista numérica más, más innumerable. Entonces concatenemos las dos listas juntas y veamos qué pasa. Estamos concatenando una lista a sí mismo y ves que podemos hacer eso. 1234512345. Por lo que los elementos de una lista no necesitan ser únicos. No se pueden tener duplicados ahí dentro. Eso es lo que te estoy mostrando con ese pequeño ejemplo. Pero si no querías nada más que valores distintos, también puedes hacer eso. Podríamos decir que los valores distintos val son iguales a muchos duplicados, puntos distintos. Y eso devolverá sólo estos valores distintos dentro de esa lista. Y se puede ver que estamos de vuelta al 12345. No hay duplicados en ese distinto. Yo solo quiero obtener el máximo, el valor máximo en una lista Eso es fácil. Valor máximo de vocal es igual a número lista punto x. y eso es cinco. Si quisieras obtener el total, podríamos decir val total es igual a número list dot. Alguna forma un poco más sencilla de hacerlo que usar una función reducida. Eso también funciona. Obtuvimos el valor 15. Hay mucho más sencillamente. Y podríamos decir, si quieres comprobar si existe un elemento dentro de una lista, eso también es fácil de hacer. Val tiene tres iguales, odio los tres. Dot contiene tres, así que estamos revisando la lista yo odio tres que hicimos antes Para ver si contiene el valor tres, no debería. Suficientemente seguro que volvió como falso. Está bien, estamos llegando chicos. De lo último de lo que quiero hablar es de mapas. Por lo que podría saber estos ya que los diccionarios y otros idiomas son una búsqueda de valor clave en claves distintas. Estructura de datos muy útil en muchas situaciones diferentes. Entonces hablemos de cómo funciona eso. Vamos a configurar un mapa llamado mapa de naves. Poco comentario aquí. Entonces sabemos que estamos hablando de apps que son importantes. Por lo que eval shit map va a ser igual a un mapa mayúscula M que contiene los siguientes pares de valores clave. Entonces por ejemplo, Kirk, arrow, enterprise, coma Picard, arrow enterprise D, Cisco, Deep Space Nine, AEway, Voyager. Podría seguir, Archer y así sucesivamente. Pero te perdonaré el Tipeaje. De acuerdo, entonces lo que hemos hecho aquí es configurar un objeto de mapa. Asegúrate de cerrar eso correctamente. Y se puede ver que recuperamos un objeto de mapa ahí que mapea cadenas a cadenas. Nuevamente, los tipos de datos deben ser los mismos. Por lo que estamos mapeando capitán con nombre de cuerdas a su nave llamadas cuerdas. Y puedes tener cadenas mapeadas a ints o algo así,
pero tienes que tener un tipo consistente dentro de cada par de valores clave, al
menos. Eso tiene sentido. Entonces ahora si quisiéramos usar ese mapa, podríamos decir algo como línea de impresión, mapa enviado, AEway entre paréntesis, y Control Alt W, Eso nos devuelve Voyager. Por lo que puedes ver tenemos una pequeña tabla de búsqueda rápida ahí que hemos definido usando un mapa que nos va a devolver el valor Voyager dado el nombre clave de Janeway. Cosa muy útil en muchas situaciones. ¿ Qué pasa con las llaves faltantes? Por lo que en realidad omití intencionalmente uno de los capitanes de barcos ahí. Digamos línea de impresión. Nave, mapa punto contiene arquero. Archer no está en mi lista en mi mapa allí. Eso vuelve como falso. ¿Cómo me ocupo de eso? ¿ Qué pasa si trato de gustarme mirar arriba arquero, donde no existe en el mapa. Bueno, probémoslo. Val arqueros nave igual a util punto try. Entonces vamos a hacer un try-block aquí, mapa de la nave,
Archer, conseguir o de lo contrario Desconocido. Muy bien, entonces estamos haciendo algún manejo de excepciones aquí. Y luego imprimiremos línea o barco turístico. Uops, línea de impresión, arqueros, nave, Control, Alt W. Muy bien. Entonces básicamente estamos haciendo como un pequeño manejo de excepciones aquí. Entonces estamos haciendo un intento y conseguir nuestro bloque de mas aquí. Entonces al envolver el mapa de porquería Archer en este try-block, eso significa que no le va a gustar ir balístico porque nuestra verdad no existe. Estamos recuperando una especie de valor indefinido en ese caso. Entonces la excepción try ahí, se desencadena. Y es esta cláusula getter else en su lugar y devuelve una cadena desconocida en ese caso. Entonces esa es una forma de manejar los valores que
faltan en un mapa o lidiar con la posibilidad de que falten valores en un mapa. De acuerdo, Eso definitivamente es suficiente. Y terminamos con lo básico de Scala. Entonces, ya sabes, justo lo suficiente para ser peligroso aquí. Ahora, vamos a conseguir mucha más práctica a medida que
pasemos por el curso viendo muchos ejemplos diferentes. Y así es realmente como lo vas a aprender. Pero espero que esto desmitifice parte de la sintaxis para ti, al menos. Un último ejercicio para ti. Déjame copiar esto en el pequeño último reto. Entonces aquí es para ti. Tu reto, si eliges aceptarlo, crea una lista de los números del uno al 20. Y quiero que impriman los números que son uniformemente divisibles por tres. Y hay algunas pistas aquí en el texto aquí que podrían guiarte. Nuevamente, esta es una pregunta de entrevista muy común que solía dar
a la gente durante las pantallas telefónicas y Amazon, te sorprendería cuánta gente no podía hacer esto con éxito en cualquier idioma que quisieran probar y hacerlo en Scala. Hay un operador de modulo, como en otros idiomas de los que hablo aquí que te da el resto después de división. Entonces cualquier cosa que sea divisible por tres debería tener un modulo 3 que regrese como 0. Entonces esa es tu primera pista. Por lo que solo iterar a través de todos los elementos en las pruebas de lista. Esa prueba de modulo es que vas y
luego puedes hacerlo de nuevo usando una función de filtro en la lista en su lugar. Por lo que un par de maneras puedes ir al respecto. Adelante y practica ahí. Y después de eso, creo que sabrás suficiente esqueleto ser peligroso. Y vamos a seguir adelante y de hecho nos meteremos en las entrañas del propio Apache Spark.
8. El dato.: Así que vamos a sumergirnos en la propia Spark y empezaremos con una visión general de Spark y también su API original, el RDD. Hablaremos de lo que eso significa en breve. Esa fue la primera API que chispa salió dentro de Spark uno. Y a pesar de que ha sido superada en gran medida versiones
posteriores por API más nuevas, sigue ahí fuera. Todavía vas a necesitar usarlo de vez en cuando. Y hay algunos problemas como veremos, donde los RDD siguen siendo la solución más eficiente. También tienes que toparte algunas bibliotecas de terceros que quizás quieras usarla
usan RDD y es posible que tengas que mirar algún código heredado también que use un dos, por lo que aún vale la pena aprender. Sin embargo, después de esta sección, vamos a cambiar nuestro enfoque hacia API más modernas como dataframes y datasets. Pero por ahora, empecemos con lo básico y aprendamos el núcleo en sí Spark, el RDD. Entonces, empecemos hablando de las raíces chispas y esa es la interfaz RDD. Rdd significa Resilient Distributed Dataset, que
no debe confundirse con conjuntos de datos en Spark, eso es algo diferente. Los conjuntos de datos se construyen más bien confusamente encima de los RDD. Se trata de una API de nivel superior. Pero en su núcleo, Spark es todo sobre RDDs. ¿ Y qué es esto? Bueno, básicamente un RDD es un montón de filas de datos de algún tipo. Y debido a que está dividida en filas, esas filas se pueden distribuir a diferentes computadoras y ser procesadas en paralelo en esas diferentes computadoras. Entonces por eso se distribuye. Entonces es un conjunto de datos porque es un montón de filas de información se distribuye porque potencialmente podemos dividir esas filas entre múltiples computadoras. Y es resistente porque, bueno, chispa se asegura de que el procesamiento que estás haciendo en el RDD se haga de una manera u otra, ¿verdad? Por lo que es un problema de chispas averiguar qué pasa si un nodo baja en medio de tu operación para girar uno nuevo para ocupar su lugar. Entonces lo primero que debes hacer antes de crear un RDD y Spark es crear un contexto de Spark. Y tu programa de conductores hará esto como una de las primeras cosas que hace. Por lo que el objeto de contexto Spark es el responsable de hacer que esos RDD sean resistentes y distribuidos. No tienes que escribir el código para asegurarte de que no puedes manejar fallas ni fallas de hardware. No tienes que escribir el código para averiguar cómo distribuir esos datos en todo tu clúster. El propio RDD dentro del contexto de Spark está averiguando cómo hacer eso por ti. Todo lo que debes preocuparte es cómo transformar tus datos. Por lo que tu contexto de Spark creará los RDD que solicites. Y si realmente estás usando el shell de Spark de forma interactiva, creará un objeto para ti automáticamente, ese será tu contexto de Spark. Tienes que crearlo explícitamente, ya está ahí. Esto tendrá más sentido cuando veamos algún código. Entonces, ¿cómo creo un RDD? Por lo general es bastante simple. Una forma es simplemente darle una lista explícita de cosas. Entonces el primer ejemplo hubo diciendo val nums es igual a paralelizar lista 1, 2, 3, 4. Eso va a crear un RDD llamado nums que solo contiene en cada fila 1, 2, 3 y 4. Obviamente eso no es terriblemente útil en el mundo real porque si eres capaz de escribir y codificar lo que hay en tu RDD. Probablemente no sea big data y probablemente tampoco sea datos reales. Ya
sabes, para probar cosas,
probar casos a veces eso es útil. Más a menudo, estarás cargando datos de algún archivo de texto en algún lugar. Y para hacer eso, solo puedes decir SC, asumiendo que ese es tu archivo de texto de Spark dot txt y pasarlo el, la ruta a tu archivo de texto gigante y esas cosas. Y eso creará un RDD donde cada línea de ese texto archiva su propia fila en el RDD. Y no tiene que venir del sistema de archivos local. Ahora un poco derrotar el propósito del big data, ¿verdad? Por lo que también puede leerlo desde sistemas de archivos distribuidos incluyendo HDFS, que es el Hadoop Distributed File System, o incluso Amazon
S3, S3 y n serían el prefijo para eso. Entonces siempre hay extensiones para cargar datos en un Spark RDD desde diversas fuentes de datos distribuidas porque chispas todo sobre big data, ¿verdad? Por lo que su capacidad para cargar datos de data stores
distribuidos es algo fundamental para lo que estás haciendo. No tiene que ser un archivo de texto sin embargo. Incluso se podría crear un,
un RDD a partir de un, de un contexto colmena. Por ejemplo, si estás usando Hive, y luego puedes dar la vuelta y simplemente ejecutar comandos
SQL en ese alto de contexto si lo deseabas también. Entonces esa es una forma de hacer SQL en el entorno Hadoop. También puedes crear RDD directamente desde JDBC. Entonces si tienes una base de datos por ahí en alguna parte, puedes transformar eso con bastante facilidad en un RDD y Spark. Se puede hablar con ninguna base de datos SQL como Cassandra o Hbase. También puedes integrarlo con Elastic Search si quieres. Y no tiene que ser un archivo de texto tampoco puedes usar datos estructurados como JSON o CSV o archivos de secuencia o archivos de objeto. Y también soporta diversos formatos comprimidos también. Nuevamente, con el big data, a veces los datos se comprimen. Y mientras sea algún formato sin pérdidas que pueda paralizarse,
entonces puedes crear un RDD a partir de él también. Una vez que tienes un RDD, ¿qué haces con él? Bueno, probablemente quieras transformarlo de alguna manera y hay varias operaciones para hacerlo. Mapa, por ejemplo, funciona igual que MapReduce realmente. Permite aplicar alguna función a cada fila de tu RDD en paralelo. Y veremos un ejemplo de eso en breve. Flatmap es similar. La única diferencia entre mapa y FlatMap es que el mapa tiene una relación uno a uno. Entonces mapa tomará una fila de tu RDD y transformará eso en una fila de otra RDD. Plano, quien pueda dividir las cosas. Por lo que FlatMap podría tomar una fila de un RDD y crear varias filas en otro RDD. Entonces, por ejemplo, si tuvieras como una lista de cosas en cada fila, FlatMap podría dividirlo en filas individuales para cada cosa. Y lo veremos en un ejemplo en breve. También puedes hacer filtros. Entonces si quieres eliminar datos, limpiar datos, puedes hacerlo también. Se puede definir una función de filtro contra la que se probará cada fila. Y si esa función devuelve falso, tirará en el RDD resultante. Entonces esa es una buena forma de limpiar tus datos y de deshacerte de los datos que faltan, cosas así. También puedes ejecutar distinto en él. Si deseas eliminar valores duplicados en tus RDD, puedes tomarlo como muestra. Y si solo quieres tomar una pequeña muestra de un RDD con fines de experimentación o lo que sea. Y también puedes hacer operaciones booleanas de fantasía entre RDD, como la unión de dos RDD, la intersección de dos RDD, puedes restar un RDD de otro o hacer un producto cartesiano entre dos RDD también. Esos son casos de uso más avanzados. Vamos a verlo en acción. Entonces digamos que solo quiero cuadrar todo en mi RDD. Digamos que tienes un RDD al que estoy llamando a RDD verdadero nombre creativo, ¿verdad? Y lo hemos hecho haciendo de nuevo ese truco paralelizado, sólo
tenemos un RDD de cuatro filas donde cada fila contiene respectivamente 1234. En la siguiente línea, estamos creando un nuevo RDD llamado cuadrados simplemente
llamando a RDD dot map x a x veces x Entonces lo que esto está haciendo es pasar la función, tomar X y transformar eso en x tiempos x y aplicarlo a cada fila en el RDD, RDD, el RDD resultante se llamará cuadrados. Entonces cuando estemos, después de que terminemos de ejecutar esa operación de mapa, cuadrados contendrán las siguientes filas, 1, 4, 9 y 16, ¿verdad? Entonces seguimos, sígueme allí. Y la belleza de la misma es que, que se puede distribuir. Entonces si ya D era realmente masivo, en realidad podría dividir ese procesamiento y manejar ese cuadrado en diferentes trozos de ese RDD en nodos diferentes,
diferentes dentro de tu clúster, y luego chupar todos esos vuelve a tu script de conductor para obtener las respuestas finales que quieras. Entonces esa es una sintaxis un poco extraña ahí. Podría no haber visto eso antes. Esa x a x veces x cosa de lo que está pasando ahí? Bueno, de esto estamos hablando cuando decimos programación funcional. Por lo que muchos métodos RDD van a aceptar una función como parámetro y no solo un valor. Y eso es lo que está pasando aquí. Entonces sintácticamente x y luego la flecha funky a x veces x es lo mismo exacto que definir una función para cuadrado algo. Lo estamos llamando cuadrado. Y esta diapositiva que toma algún entero llamado x y devuelve x veces x En realidad la palabra clave return sería opcional y Scala, solo
puedes decir x veces x y simplemente funcionaría. Y luego diciendo RDD dot map pasando en la función raíz cuadrada, aplicaría esa función de raíz cuadrada a todo en ese RDD. Pero sintácticamente es lo mismo exacto que decir RDD dot map x, funky arrow x veces x. Así que tendes a ver esa taquigrafía. Si tienes una transformación muy simple que estás haciendo, que puedes meterte en una línea ahí. Pero eso es todo lo que es. Al igual que estamos pasando esa función alrededor. Entonces en este ejemplo, estamos definiendo una función sobre cómo cuadrar números. Y estamos pasando esa función al RDD a través del operador de mapas ahí. Y eso es todo que entiendes la programación funcional. Ahora, ese es el concepto clave. Solo estamos pasando funciones por ahí. Y la visión más grande aquí es que, ya sabes, el lenguaje de escala en sí es una especie de forzarte a escribir estas funciones que se pueden distribuir. Entonces las características de escala y hacen que sea más fácil hacer esto un poco, pero eso es, eso es todo. Eso es todo lo que queremos decir por programación funcional. Ya sabes, estamos pensando en paralelo y aplicando funciones, dos grandes conjuntos de datos al pasar esas funciones alrededor a cosas como RDD sobre eso, Eso es todo. No son tan duros chicos. Muy bien, una vez que realmente has transformado todo en tu RDD de la manera que lo deseas. ¿ Qué haces con él? ¿Cómo recuperas tus resultados? Bueno, de eso se trata toda una acción de RDD. Entonces una acción es básicamente algo que hace que tu RDD colapse y te devuelva un resultado a tu script de conductor. Algo que podrías hacer es llamar a cobrar en el RDD que solo te dará todo en ese RDD de vuelta como una estructura de datos gigante en Scala. Ya sabes, si es un gran conjunto de datos que no va a tener mucho sentido más a menudo vas a estar tratando de sacarle más de una operación reducida. Por ejemplo, podríamos decir contar si solo queremos contar cuántas cosas hay en el RDD, podemos decir contar por valor. Si desea obtener un recuento de cuántas filas existen para cada valor único dado en un par clave-valor. Podrías tomar solo, ya sabes, especie de muestra de un cierto número de filas desde la parte superior de RDD para tomar las primeras filas o reducir para obtener algún tipo de gran total de todas las filas de tu RDD. Y también hay más acciones. Pero la idea básica es que una acción de RDD te dé alguna respuesta a tu script de conductores. Entonces tiene una fuerza Spark para salir y decir: Está bien, te ejecutor procesos terminaron lo que estás haciendo y dame una respuesta. Y vamos a devolverle esa respuesta a mi guión de conductor. Entonces eso es lo que hace una acción. Y la forma en que funciona es algo interesante. Por lo que hay que recordar eso en Spark. En realidad no pasa nada en tu programa de chófer hasta que llames a una acción. Es una especie de estrategia de evaluación perezosa aquí. Y hay una muy buena razón para eso. Entonces hasta que Spark sepa lo que estás tratando de lograr a través de la acción que estás tratando de conseguir al final, no sabe optimizar todas las operaciones que has hecho. Entonces recuerda que la clave o una clave para el desempeño de Spark es que puede construir esta gráfica acíclica dirigida que está muy optimizada para el resultado final que quieres lograr. Entonces esto puede ser un poco confuso ya que estás depurando tus scripts de controlador de Spark porque, ya sabes, puedes llamar a alguna operación de mapa o algún tipo de transformación en tu RDD. Y parecerá que no ha pasado nada en tu código. No es hasta que realmente llames a una acción que en realidad cualquier cosa se va a ejecutar y enviar a los diversos nodos de tu clúster y en realidad obtendrás un resultado. Entonces esto puede hacer que la depuración sea un poco complicada, ¿verdad? A veces necesitas meter un poco de acción temporal ahí para volver y dar resultado intermedio. Asegúrate de que es lo que esperas ya que estás depurando los scripts del controlador Spark. Entonces algo de lo que tener en cuenta, sobre todo mientras estás depurando estas cosas. Y con eso, vamos a sumergirnos en algunos detalles más a continuación.
9. Ejemplo de Histograma de la valoración: Entonces, generalmente es mejor entender las cosas a través de un ejemplo, ¿verdad? Entonces hagámoslo. Aprendamos sobre los RDD mirando un ejemplo realmente simple de usarlos. Por lo que vamos a sumergirnos en un ejemplo simple en los materiales de nuestro curso que solo cuenta el número de una calificación dada dentro de nuestro conjunto de datos de MovieLens. Entonces como recuerdan, el conjunto de datos de MovieLens es un conjunto de datos de 100 mil calificaciones de películas, donde la gente calificó un montón de películas de una a cinco estrellas. Y digamos que solo queremos averiguar cuántas calificaciones de una estrella hay,
cuántas calificaciones de dos estrellas,
cuántas calificaciones de tres estrellas, etcétera? Bueno, eso es algo que podemos hacer con Apache Spark. Entonces, antes de sumergirme en el código aquí y lo que está haciendo, Vamos a ejecutarlo y familiarizarnos con
lo que está haciendo y algo así como a sentirnos cómodos con el código en sí. Entonces vamos a hacer eso. Entonces si abres la inteligencia y vas al archivo del contador de valoraciones aquí,
ese es el que vamos a estar jugando aquí y sumergiéndonos ese es el que vamos a estar jugando aquí y sumergiéndonos ejemplo
muy simple de un guión de conductor apache Spark aquí. Y vamos a hablar de cada línea y de qué hace con más detalle. Pero a un nivel alto, lo que estamos haciendo es cargar el conjunto de datos de MovieLens a través de cada núcleo de CPU de nuestra máquina aquí. Y vamos a contar cuántas veces se produce
cada valor de calificación único dentro de ese conjunto de datos. Entonces vamos a cargar cada línea que represente cada calificación en ese conjunto de datos. Y vamos a dividir eso en su propio RDD. Vamos a contar cuántas veces aparece realmente cada calificación, ordenar los resultados e imprimirlos. Y vamos a ejecutarlo y
convencernos de que funciona y hace algo interesante, ¿verdad? Entonces vamos a hacer clic derecho en contador de calificaciones y digamos Ejecutar. Y si hacemos click, ahí vamos. Y eso debería dispararse en spin up Spark. Y ahí están nuestras respuestas. Entonces lo que esto nos está diciendo es que teníamos 61101 calificaciones de estrellas, 11,372 calificaciones de estrellas, 27,145, valoraciones de
tres estrellas, y así sucesivamente y así sucesivamente. Y este dato en sí es algo perspicaz, ¿verdad? Al igual que nos dice que la calificación más común para una película es de cuatro estrellas. Y hay una cantidad justa de tres estrellas y cinco estrellas no están ahí también. Pero la gente tiende a ser que parecía tener una escala razonable de cómo están leyendo estas películas. Y sí parecen estar reservando una estrella es para lo peor de lo peor. Entonces de un 100 mil calificaciones, solo 6000 y algún cambio, en realidad
estamos calificados de una estrella. Entonces eso nos da cierta confianza en que estos datos son significativos justo en este guión muy simple aquí, incluso. Entonces, volvamos atrás y hablemos más de lo que está haciendo este código. Entonces recorremos lo que está haciendo este código en cada paso aquí. Entonces empezamos importando lo que necesitamos. Y sólo decimos que estamos declarando esto dentro del paquete que hemos nombrado com Dotson dogs software, chispa de punto. Ya sabes, esa es una especie de convención en el mundo Java de cómo le das a tus paquetes un nombre único. En este caso, estoy usando algún nombre de dominio que tengo. Y luego importamos los paquetes que necesitamos. Simplemente estamos importando todo desde Spark y todo desde log para J porque vamos a usar un log para J para ajustar nuestro nivel de error en nuestro registro. Eso es todo lo que es. A continuación montamos un contexto de Spark, como ya hablamos antes. Por lo que ponemos SC a un nuevo contexto de Spark. El paréntesis local estrella significa que vamos a estar corriendo justo en nuestra máquina local. Entonces, en realidad no tenemos un clúster corriendo en nuestra sala de estar aquí, ¿verdad? Entonces. Para fines de experimentación y aprendizaje, sólo
vamos a estar corriendo en nuestra propia máquina única. Pero esa estrella significa que voy a dejar que se paralelice, al
menos a lo largo de los múltiples núcleos de CPU que podrían existir en mi máquina. Entonces, a pesar de que está en un sistema, en realidad podría girar más de un proceso y
aprovechar los diversos núcleos de CPU que tengo. Y contador de calificaciones es justo lo que estamos nombrando a esta aplicación. A continuación cargamos los datos y solo creamos un RDD de líneas
llamando al archivo SC dot txt con una ruta relativa hacia donde se encuentran esos datos. En nuestro código, ese camino es más explícito en cuanto a dónde reside
realmente en nuestros materiales del curso, pero se obtiene la idea. Por lo que tiene una ruta al archivo de datos u dot, que es el archivo de datos que contiene toda la información de lecturas y el formato de eso. Ejemplo de ello está aquí en la esquina superior izquierda. Entonces cada fila se ve así. Comienza con un ID de usuario y luego un ID de película, y luego una calificación y luego una marca de tiempo. Por lo que todo está codificado en algún tipo de identificación numérica aquí. Es decir, no sé qué es usuario/usuario 196 ni qué película de película ID 242. Ahí hay un archivo separado para buscar esos. Pero el usuario ID 106 película calificada 2423 estrellas. Y lo hicieron en esta época, que se traduce en alguna, ya sabes, alguna fecha y que podríamos humanamente codicia pero computadoras como Epoch segundos. Entonces ese es solo el formato de estos datos. Entonces lo primero que vamos a hacer es cargar las 100 mil filas de ese archivo en el RDD de una línea, donde cada fila representa una fila de ese archivo de datos. ¿ De acuerdo? Y de nuevo, estamos empezando con RDD aquí. Vamos a hablar en la siguiente sección de cómo
hacer todas estas cosas usando conjuntos de datos en su lugar, que es la API más moderna. Pero de nuevo, ambos son herramienta útil. A veces los RDD van a ser más rápidos que los conjuntos de datos. A veces los RDD te permiten hacer más. Entonces estamos, estamos empezando con lo básico, la API de nivel inferior aquí de los RDD. Y descubrirás que usar conjuntos de datos no es realmente tan diferente. Pero empecemos con los RDDs aquí. Entonces ahora mismo tenemos un RDD de línea. A continuación, necesitábamos hacerle algo a esos datos. Entonces lo primero que queremos hacer es extraer la información que realmente nos importa de ese RDD. Entonces vamos a llamar a mapa en las líneas RDD, pasándolo en función de cómo queremos transformar cada fila de ese RDD. Y en este caso la función está tomando cada línea y llamándola x. Y luego en esa línea, esa cadena, vamos a convertirla explícitamente en una cadena y llamar a split en ella, dividiéndose en el carácter tabulador porque esto es datos delimitados por tabuladores y extraer ajustar el campo número 2. Ahora recuerda en informática muchas veces empezamos a contar desde 0. Entonces dos es en realidad la tercera columna de datos. Entonces lo que esto está haciendo es extraer esa tercera columna, que es la propia calificación, y nada más. Por lo que es extraer esa calificación de cada línea e insertar eso en un nuevo RDD llamado ratings. Sígueme. Entonces empezamos con unas líneas RDD, eso son las de la esquina superior izquierda de ahí. Llamamos a una función de mapa en él para aplicar esta función a cada fila de las líneas RDD para extraer esa tercera columna de datos, la calificación en sí. Y eso entra en un nuevo RDD llamado ratings, que en este ejemplo sólo contendría 33 uno a uno en cada línea de las calificaciones RDD respectivamente. Entonces para eso se está utilizando el mapeo
ahí es solo para extraer los datos que nos importan. Y ya sabes, en algunos casos podrías reformatear cosas o ponerlas en un formato diferente que algún proceso downstream quiere. Pero generalmente de eso se trata el mapeo. Entonces ahora necesitamos hacer algo con toda esa información. Entonces en este caso vamos a realizar una acción y nuestra acción en este caso es contar por valor. Esto es lo que va a hacer que nuestros datos se derrumben y nos devuelvan una respuesta. Entonces ese mapeo que hicimos en la diapositiva anterior podría haberse distribuido entre muchos nodos ejecutores, ¿verdad? Pero al decir queremos contar los valores, Eso nos va a devolver una respuesta explícita y
devolver algún resultado de nuevo a nuestro guión como objeto Scala. Entonces en este caso, estamos diciendo que las calificaciones contarán por un valor. Eso hará lo que diga. Darle un recuento de cuántas veces aparece cada valor único. Por lo que en este ejemplo, tenemos 23 calificaciones. Entonces recuperamos el valor tres coma dos, lo que significa que para la calificación 3, hay dos de ellos. Para la calificación uno, hay dos de ellos también. Y para la calificación dos, sólo hay uno de ellos. Entonces eso es lo que devuelve el recuento por valor. Y en este caso no nos está devolviendo un nuevo RDD. Es pasar eso de vuelta a nuestros guiones de conductores que está entrando en
un, un nuevo valor llamado resultados a nivel Scala. Por lo que al llamar a esta acción, hemos tomado esos resultados de vuelta
del clúster y los hemos vuelto a poner en nuestro disco o script local. Y en este punto ya no estamos en Spark land estaban de vuelta en línea Scala. Estamos de vuelta dentro de nuestro guión de conductor. Ahí es donde vive el estado en este punto. Y en ese punto sólo queremos ordenarlo y mostrarlo. Entonces tenemos un pequeño código Scala simple aquí para tomar ese conjunto de resultados, convertirlos en una secuencia y ordenarlos por el segundo campo. Y luego simplemente los imprimimos aplicando la función de línea de impresión a cada fila de ese resultado final, a cada fila de esa secuencia que definimos, ¿verdad? Entonces de nuevo, esto es sólo sintaxis de Scala aquí. Estamos tomando los resultados, convirtiéndolo en una estructura de datos de secuencia, ordenándolo por esa segunda columna. Y luego por cada fila de esa secuencia dentro de Scala, estamos aplicando la función de línea de impresión para imprimir el contenido de eso. Y así vemos aquí nuestro resultado final. Donde teníamos ver que tenemos que 1 calificaciones de estrellas, 12 de estrellas, y dos de tres estrellas. Entonces es tan fácil. Otra vez. Vamos a ejecutarlo y simplemente convencernos de nuevo de que funciona ahora que tenemos más de una apreciación de lo que está haciendo el código. Entonces ahora que hemos hablado de ese código con más profundidad, si volvemos a mirar esto, debería tener un poco más de sentido. Entonces algunas cosas de las que no hablamos. Entonces, en primer lugar, hemos envuelto todo este código y la integración es contador objeto. Entonces eso es sólo una especie de, ya sabes, cómo se necesitan estructurar las cosas para un guión de conductor y en Scala. Por lo que dentro de este objeto contador de radio, definimos una función principal. Esta es básicamente la estructura a la que todo script de controlador necesita ajustarse para Apache Spark. Y lo primero que hicimos, de lo que realmente no hablamos con establecer el nivel de error en nuestros registros a error. Y desafortunadamente, como usted vio aquí, algunas advertencias se deslizaron antes de que ese código fuera ejecutado en realidad por Spark. Pero una vez que el script del conductor realmente comienza a ejecutarse, eso va a evitar que
se muestren los mensajes de registro que sean algo menos que un error. Y eso es solo para reducir nuestro lapso y dejarnos ver los resultados. Entonces queremos ver más que un montón de advertencias de las que no podemos hacer nada al respecto. Después de eso, nos estamos metiendo en el código del que hablamos en las diapositivas. Por lo que creamos nuestro nuevo contexto de Spark. Lo llamamos como C. Está configurado para usar cada núcleo en nuestra máquina local y llamamos al nombre de la aplicación o contador de calificaciones. Nos cargamos desde los datos ML dash 100 K directory ru dot data file, que contiene cada fila de cada calificación individual en ese conjunto de datos. Esta es la carne de todo aquí. Aquí es donde llamamos a la función de mapa en las líneas RDD y aplicamos esta función que se divide y cada línea en sus campos individuales basados el delimitador de tabulación y extrae el tercer campo. Nuevamente, empezamos a contar desde 0. Eso pasa a ser el valor real de la calificación en sí. Eso se lanza a un nuevo RDD llamado ratings, que contiene cada calificación individual. Entonces llamamos al recuento de acciones por un valor a para que Spark vaya y nos dé una respuesta y descubra la forma óptima de obtenerlo. Una vez que eso se ejecuta, tenemos aquí
una estructura de resultados que solo está viviendo dentro de nuestro guión de conductor ahora. Por lo que ya no estamos teniendo nuestros datos sobre el clúster. Hemos colapsado eso de nuevo en algunos resultados dentro del guión. Y ahora podemos tomar esa estructura de datos de vieira resultante convertida en una secuencia ordenada por su segundo campo real allí, que es el valor de calificación real. Y luego aplicar la línea de impresión a cada resultados ordenados para imprimir la respuesta final. Y vamos a correr una vez más sólo por diversión. Por lo que de nuevo, podemos simplemente hacer clic en escáner 3D y hacer clic derecho y ejecutar. Pero como ya lo hicimos una vez, va a estar en un atajo aquí arriba también, solo
podemos pulsar el botón de reproducción y volver a hacerlo. Y ahí está otra vez. Tan cool. Muy bien, así que hemos hablado del código y cómo funciona, y tienes una idea aproximada de cómo usar RDD y practicar. De nuevo, vamos a hablar de conjuntos de datos más tarde, muy pronto, no te preocupes, estamos llegando. Pero primero hablemos de más de lo que pasó bajo el capó cuando corrimos todo esto dentro de nuestro clúster.
10. Internals de Spark: Entonces, ¿qué pasó en realidad bajo el capó cuando todo esto corrió? Hablemos de eso en un poco más de profundidad. Entonces cuando nuestro script de conductor llegó a esa acción, el comando de conteo por valor y plan de
ejecución se creó a partir de esos RDD que definimos. Entonces es un poco averiguar qué necesito hacer para realmente obtener esa respuesta final. En este caso, se ve así, ¿verdad? Por lo que empezamos con ese archivo de texto, los datos brutos de nuestro RDD. Y vamos a llamar a una operación de mapeo que se puede aplicar en paralelo a través múltiples procesos o múltiples computadoras incluso para extraer las calificaciones que queremos ahí. Y luego finalmente, vamos a hacer una acción de conteo por valor para sumarlos todos. Entonces el plan de ejecución, va a decir, oye, puedo hacer todo ese primer mapeo totalmente en paralelo. Pero esa acción te va a requerir estas notas que hablan entre sí alguna
manera y especie de comunicación y Coli, sus resultados. Entonces lo que pasa es que el trabajo se descompone en etapas en función de cuándo es necesario reorganizar los datos. Para que el mapeo paralelo pueda ser todo una etapa que no requiera ningún tipo de reorganización de los datos en sí. Pero el conteo por valor baraja un poco las cosas, ¿verdad? Por lo que esa necesita ser su propia etapa separada en el proceso. Y luego cada etapa se rompe en tareas que se pueden distribuir por todo el clúster. Entonces tal vez en la etapa uno, ya sabes, esas flechas moradas están procesando partes de los datos y eso se irá a uno ejecutores. Ejecutor, quizá los verdes se vayan a otro ejecutor y el azul se vaya a un tercer albacea, ¿verdad? Entonces piensa en cómo distribuyo estos datos manera efectiva y que cuentan por operación de valor, bueno, eso no es fácilmente paralelizable. Entonces eso se convierte en una especie de estrategia diferente ahí. Y finalmente, las tareas están programadas en todo
tu clúster y ejecutadas y obtienes tu respuesta. Entonces bajo el capó, Eso fue lo que pasó a obtener realmente nuestra respuesta final de cuántos de cada tipo de calificación existían en nuestro conjunto de datos. No son tan duros, pero bajo el capó, eso es un poco lo que está pasando.
11. La clave con la RDD's, el ejemplo de los amigos promedio por la edad: Por lo que vimos algunos RED muy simples estos en uso con nuestro contrejemplo de calificaciones previamente. Pero también hay un tipo especial de RDD llamado el valor clave RDD. Y con estos RDD, hay algunas operaciones adicionales que puedes realizar que pueden ser útiles. Y veremos esto con un ejemplo con nuestros amigos por edad guión aquí. Lo que vamos a tratar de hacer al final del día aquí, o al final de esta lección de todos modos, es averiguar cómo calcular el promedio de amigos por edad. Entonces estamos empezando con un conjunto de datos que tiene un montón de personas individuales, sus nombres, su edad, y cuántos amigos se han imaginado que conseguimos esto de alguna red social en alguna parte, ¿verdad? Entonces en este caso vamos a estructurar nuestros datos en pares de valores clave. Rdds puede sostener estas cosas. En nuestro caso. En este caso la clave será la edad y el valor será el número de amigos. Porque queremos buscar las cosas por la edad, escribir, consolidar las cosas y reducirlas a esa edad. Entonces en lugar de solo una lista de edades o lista de número de amigos y un RDD. Podemos almacenar esto de una manera más estructurada donde cada rover
RDD consiste en una tuple de una edad determinada, un número de amigos para un individuo, la edad y número de amigos para otro individuo, etcétera, etcétera. Por lo que ahora tenemos estos pares de valor clave en cada fila de nuestro RDD. ¿ Cómo se crean estos sintácticamente? En realidad no es nada demasiado especial en Scala. Todo lo que necesitas hacer es mapear pares de tus datos en el RDD usando tuplas. Entonces, por ejemplo, si solo quisiera tomar un RDD que tuviera una cosa ahí dentro y crear un par de valor clave de esa cosa como la clave y el número 1 es el valor. Podría simplemente llamar a una operación de mapa que diga tomar la fila, todo su texto es x y transformar eso en la tupla x coma uno. Y eso se convierte en un par de valores clave donde la clave es x y el valor es uno. Eso es todo lo que hay a ello. Ahora tienes un valor clave, RDD, y no te limitas a tener una cosa y la clave son una cosa y el valor o bien podrías tener tuplas u otro tipo de objetos como valores también. Entonces en lugar de una, podría tener otra tupla incrustada dentro de eso. Para que pueda tener x colon, imprimir el mar, ya
sabes, algo coma algo coma algo más. Cierra paréntesis si quisiera también. Por lo que no puedes tener tipos de datos más complejos incrustados como parte de tu valor a veces eso resulta útil. Por lo que una vez que tendrías estos pares de valor clave en tus RDD, Spark puede hacer algunas cosas especiales con ellos. Hay algunas nuevas funciones que están disponibles para ti. Uno se reduce por clave, y eso es útil para combinar todos los valores para la misma clave juntos de alguna manera. Entonces básicamente proporcionaste una función que define ¿cómo
combino todos los valores juntos para una clave dada? En este caso, estamos pasando en esta pequeña función que dice x, y, funky arrow x plus y. entonces eso significa que para combinar algún tipo de valores en esos valores, voy a usar el operador de adición para combinarlos juntos. Y esto es un poco confuso lo que está pasando aquí bajo el capó. Por lo que podría ser mantener un total corriendo ya que
pasa por cada valor por una llave única debajo del capó allí. Por lo que x podría representar nuestro total corriente corriente. Y por qué represento el nuevo valor que está viendo desde una nueva fila y agregándolo a eso. Entonces lo que es importante aquí es ese operador del lado derecho aquí. En este caso, estamos diciendo explícitamente, queremos sumar todo en todos los valores para este RDD y devolvernos una respuesta para cada clave única. ¿ Cuál es la suma? Todos los valores asociados a esa clave tienen sentido. Si no lo hace, tendremos un ejemplo que tendrá más sentido cuando lo veas en acción. También podemos decir grupo por clave. Por lo que eso sólo te devolverá un grupo de todos los valores para una determinada cualquier clave. No necesariamente reducir las cosas, sino que solo te permite organizar mejor tus datos y tal vez pasar eso a alguna otra operación. Posteriormente. También podemos ordenar por clave. Entonces si tienes pares de valores clave, puedes hacer esa clasificación dentro de tu clúster. Recuerda de nuevo en nuestro ejemplo anterior para el contador de calificaciones, realidad obtuvimos nuestros resultados de vuelta a
nivel Scala dentro de nuestro script de conductor y los
ordenamos ahí. Esa no es realmente la forma más escalable de hacer las cosas, ¿verdad? Es, sería preferible si pudiéramos ordenar en el clúster. Y si tuviéramos un par clave-valor en su lugar, podríamos haber hecho eso. Además, tenemos claves y valores, por lo que podemos extraer todas las claves o extraer todos los valores de un par clave-valor. Si necesitas volver en la otra dirección y crear un RDD de solo las claves o un RDD de solo los valores que te permita repartirlos de un par clave-valor. Además, es posible hacer combinaciones de estilo SQL si tienes dos RDD clave-valor y tendremos un ejemplo de eso más adelante. Es decir, esto sí se mete en el área de donde podrías preguntarte por qué estás usando RDD si estás haciendo operación SQL. Por lo que solo notaré que puedes hacerlo. Pero en la práctica, obviamente probablemente estés usando conjuntos de datos son DataFrames son la Spark SQL API para hacer este tipo de operaciones en chispa moderna. Además, si tienes que hacer algún tipo de operación de mapeo en un valor clave RDD y solo vas a estar transformando la parte de valor. Un pequeño truco es usar los valores de MapValues o FlatMap. De esa forma solo puedes aplicar tu transformación solo a la parte de valor que va a ser más eficiente que
tratar de averiguar cómo mantener la clave alejada a un lado y solo afectar la parte de valor. Por lo que es una, tanto una más eficiente en una forma más fácil de aplicar una operación de mapeo a sólo los valores de un valor clave RDD. Entonces recuerda eso. Entonces vamos a sumergirnos un poco más en nuestro ejemplo. Entonces de nuevo, lo que estamos tratando de hacer es averiguar el número promedio de amigos para una edad determinada, dado algún pequeño conjunto de datos falso aquí. Entonces de nuevo, imagina que tenemos una red social de algún tipo, donde tenemos un montón de personas que están en nuestra red social. Y para cada persona, conocemos su edad en años, y sabemos cuántos amigos tienen dentro de nuestra red social. Entonces, por ejemplo, cada fila podría verse así. Algún tipo de ID de usuario seguido de su nombre, seguido de su edad, seguido de su número de amigos. Por lo que will tiene 33 años y tiene 385amigos. John Luke tiene 33 años y tiene dos amigos. Tenía 55 años y tiene 221amigos y así sucesivamente y así sucesivamente. Entonces lo primero que tenemos que hacer es mapear esos datos de
entrada y dividirlos en algún tipo de estructura. Y aquí estamos definiendo una función de línea de análisis que toma en cada línea individual de ese RDD y la divide en base a la coma. Delimitador, extrae el campo H y llama a la edad, extrae el campo del num amigo y lo llama num friends. Y luego regresamos una tupla, un par clave-valor de edad num amigos. Entonces la edad en este caso es la clave y el valor es amigos entumecidos. Y vemos aquí en la siguiente línea que creamos las líneas RDD cargando los falsos amigos dot-dot-dot CSVs datos crudos. Entonces llamamos mapa con esa función de línea de análisis para transformar esos datos sin procesar en un nuevo RDD llamado RDD que contiene pares clave-valor. Por lo que la salida aquí de RDD se verá así en la parte inferior. A pares clave-valor. Por ejemplo, 33 es la clave, el año, la edad, y 385 es el número de Francia. Por lo que de nuevo, número de edad de Francia. El clave es la edad, los valores número de Francia y otros 33 años tenían dos amigos. Un niño de 55 años tenía 221amigos, así sucesivamente y demás. Y puedes ver aquí podemos tener valores duplicados para claves, ¿verdad? Por lo que las claves no tienen que ser únicas en este contexto, no hasta que reduzcamos las cosas. A continuación, sí queremos empezar a reducir estos datos a la baja sin embargo. Entonces para poder calcular el promedio, necesitamos tener dos cosas, ¿verdad? Tenemos que tener la gran suma total de cuántos amigos existieron para una edad determinada y cuántas personas lo representan. Entonces para calcular el promedio, Vamos a comer ese número total de amigos a los que se les da edad y el número de personas que existían para esa edad. Y al dividir esos dos se obtendrá el promedio que queríamos al final del día. Por lo que el siguiente paso es computar esos totales. Y eso es lo que está pasando aquí. Ahora a menudo verás en los guiones de conductores de Spark, gente un poco juntando las cosas en una gran línea larga. Por lo que bien puedes acostumbrarte a ello. Ahora, hablemos de qué, vamos a descomponer lo que está pasando aquí, ¿verdad? Entonces, dividamos esto en sus dos componentes. Estamos empezando con los valores de mapa de puntos de RDD X a X coma uno. Entonces lo que esto va a hacer es tomar cada valor y transformar eso en su propia tupla de ese valor y luego uno. Ahora el método a esta locura es pero que al asociar uno con cada valor ahí, puedo sumar todas esas entradas individuales y obtener el gran total de cuántos existían para esa edad. Está bien. Entonces esa sólo está diciendo que voy a contar cada fila individual como una, y voy a resumir eso más adelante para conseguir un gran total, un poquito de truco ahí. Entonces después de este punto, cuando ejecutemos esa operación MapValues, así será nuestro RDD. Entonces por ejemplo, 33, 35, que nos decía que un joven de 33 años tenía futuro 95. Francia se va a transformar en lo mismo. El clave sigue siendo 33, pero el nuevo valor es una tupla de 385 coma uno. Y lo hacemos por cada fila en ese RDD. Y a continuación decimos punto reduceByKey. Por lo que no asignamos explícitamente el resultado de eso a un nuevo RDD llamado. Simplemente íbamos a pasar ese nuevo RDD directamente a otra operación aquí, en este caso la acción ReduceByKey. Entonces esta operación aquí sumará ambos elementos de esa tupla en el valor, ¿no? Entonces lo que está pasando aquí es que estamos diciendo que vamos a tomar 22 entradas aquí de nuestro RDD que estamos reduciendo, llamarlos x e
yVamos a sumar el primer elemento de ambas tuplas y el segundo elemento de ambas tuplas, y sumarlos todos para cada clave única. ¿ De acuerdo? Entonces a ver adónde vamos con esto. Entonces, en este punto, lo que tenemos aquí es para todos los de 33 años que hay por ahí, hemos reducido esos datos a la baja en el gran total de todos los amigos que tenían los 33 años y el número total de 33 años había existido. Entonces piensa en esto por un minuto. Es un poco complicado. Nuestra estrategia aquí era volver aquí, vale, mapeamos todo a estas tuplas de 433 años para cada individuo, teníamos una tupla del número de amigos que tenía esa persona en el número de uno. Y este truco aquí es que al hacer esto y sumarlos todos juntos. Si sumamos todo el primer elemento de esa tupla de cuántos amigos tenía cada uno, cada uno de 33 años de edad, obtenemos el gran total de cuántos amigos de 33 años tenían. Y luego sumándolo juntos, todos esos, obtenemos un recuento de cuántos de 33 años había. Y eso nos da las dos cosas que necesitamos para calcular el promedio que queríamos. Y eso es lo que hacemos en el siguiente paso. Decimos valores de mapa y todo lo que hacemos es pasar por
cada valor, cada tupla con la que terminamos, y dividirlos entre sí para obtener el número promedio final que queremos en el resultado final. ¿ De acuerdo? En ese punto sólo podemos recoger y mostrar los resultados. Entonces vamos a decir cobrar para recuperar esos valores promediados reducidos. Y vamos a ordenarlos y llamar a la línea de impresión y a cada uno para mostrar el resultado final. Entonces con eso, vamos a seguir adelante y en realidad ejecutarlo en nuestra próxima conferencia.
12. [Actividad] cómo dirigir el ejemplo de tus amigos con la edad: Muy bien, Vamos a sumergirnos en el código y ver cómo
funciona todo en acción aquí y lo ejecutaremos y veremos si funciona. Entonces esto es todo lo que hablamos en las diapositivas anteriores. Muy bien, Así que pasemos por el código aquí una línea a la vez. Entonces comenzamos declarando qué paquete vivimos dentro de ese tipo de cosa estándar para cualquier guión de Scala. Y luego importamos los paquetes de los que dependemos. En nuestro caso, estamos siendo un poco perezosos y solo importando todo desde Apache Spark y también desde log para J. Seguidamente
definimos los objetos en los que vive nuestro guión. Lo vamos a llamar amigos por edad, que debe coincidir con el nombre del archivo. Voy a omitir la función de línea de parcela por ahora y bajar a la función principal porque ahí empezará la ejecución por
decir que lo estamos haciendo de nuevo es establecer el nivel de registro a error para que no tengamos un montón de logs spam sobre advertencias de que no podemos hacer nada al respecto. Habrá unos cuantos que se resbalaron antes de que esto sea ejecutado, pero atraparemos a la mayoría de ellos, al menos. A continuación creamos nuestro contexto de Spark, nuevamente configurado para ejecutarse en nuestra máquina local utilizando cada núcleo de CPU. Y le daremos a nuestra aplicación nombre amigos por edad. Lo siguiente que hacemos es cargar nuestros datos crudos y hay un guión de amigos falsos, sin archivo CSV heterodoxo. Esa es una versión de los datos que no tiene fila de encabezado que pueda, que te puede estropear. Así que ten conocimiento de eso. Y vamos a cargar eso hasta en RDD de
una línea donde cada línea representa una fila de esos datos. Entonces, ¿qué aspecto tienen esos datos? Echémosle un vistazo rápido sólo para recordárnoslo. Entonces se ve así. Recuerda la primera columna es el ID de usuario, la segunda es el nombre y la edad y el número de amigos y todo lo que nos importa por nuestro problema son esas dos últimas columnas, ¿verdad? Realmente no me importa si el ID de usuario es, no
me importa si su nombre era. Solo estoy tratando de averiguar el promedio de amigos por cada dado un para poder tirar esas dos primeras columnas. Y eso es lo que hacemos en la función de línea de análisis aquí. Entonces vamos a tomar la función de línea de análisis, mapear eso a cada una de esas filas de entrada y obtener un nuevo RDD llamado RDD. Veamos qué hace la línea de paquetería. Entonces lo que eso está haciendo es dividir cada línea por una coma porque es un archivo de valor separado por comas. Y extraemos los campos 2 y 3. Esas son las dos últimas columnas de nuestros datos. Les llamará edad y amigos del NAIM y regresará una tupla de edad y amigos del NAIM. Y de nuevo, esa tupla se convertirá en nuestro par de valor clave en nuestro RDD, RDD. Por lo que ahora la edad va a ser nuestra clave y los amigos del NAIM serán nuestro valor para cada persona individual que tengamos en nuestro conjunto de datos. Entonces ahí es donde estamos. Y ahora tenemos esa línea realmente complicada de la que pasamos mucho tiempo hablando.
13. Filtrar los RDD, y el ejemplo de la temperatura mínima: Entonces a continuación hablemos de filtrado. Tus RDDs. El filtrado es una operación muy sencilla que solo te permite limpiar datos de tus RDD y encontrarás que el mismo concepto se traslada a las otras API en las ofertas de chispa también. Ilustraremos esto con un par de ejemplos usando datos meteorológicos. Se trata de datos del mundo real de dos estaciones meteorológicas diferentes en Europa. Y lo que vamos a hacer es usar el filtrado para especie de limpiar que los datos antes de extraerlo para la temperatura mínima y máxima se registra dentro de un año determinado en esas estaciones meteorológicas. Usar un filtro es bastante sencillo. Todo lo que haces es proporcionar una función que devuelva un booleano. Y si ese booleano devuelve verdadero, entonces mantenemos esa línea, lo contrario, la quitamos del RDD. Entonces, por ejemplo, si quisiéramos filtrar las entradas que no tienen T min como segundo elemento en la tupla de datos, podríamos decir líneas analizadas filtro de puntos,
suponiendo que las líneas de paralizar es esa RDD que contiene esas tuplas. Y pasando a la función donde cada fila de datos se llama x. Y comprobamos si el segundo elemento de x es igual al equipo en. Si lo es, entonces lo guardamos. Si no lo hace, entonces lo quitamos en el Min resultante tienta a RDD. So Min terms contiene los resultados filtrados de las líneas analizadas. Aquí hay un ejemplo de esos datos sin procesar que están en nuestros datos de origen para este ejemplo. Entonces lo que vamos a tratar de hacer aquí es encontrar la temperatura mínima dentro de un año para una estación meteorológica determinada. Y ese primer identificador, esa primera columna de información en nuestros datos de entrada es el identificador de la estación. Por lo que eso sólo representa donde se tomó esa lectura de temperatura. Después de eso es el año y fecha reales en que se tomó esa medición. Por lo que se puede ver que se trata de un conjunto de datos bastante antiguo que se remonta al año 1800. Y se puede ver que tenemos muchos tipos diferentes de datos siendo registrados en este conjunto de datos. Tmax indica la temperatura máxima registrada ese día en esa estación meteorológica. T min es la temperatura mínima registrada y la precisión es la cantidad de precipitación registrada. Y el formato de esos datos de temperatura es un poco raro. Son grados Celsius multiplicados por 10. Por lo que negativo 75 es en realidad negativo 7.5
grados centígrados necesitarán lidiar con eso a medida que analizamos datos e importarlos. Así es como se ve ese código que sí analiza esos datos. Entonces por cada línea que recibimos que leemos para ese archivo de texto CSV de 8800 puntos, vamos a usar esa función de línea de paralizar para realmente darle sentido. Se puede ver que al principio lo divide en función del delimitador de coma. Extrae el ID de estación, que es el primer campo, y el tipo de entrada, que es un segundo campo. Y finalmente el número de temperatura en sí. Y puedes ver aquí que empezamos multiplicando eso por 0.1 para conseguir dos grados centígrados. Y luego convertimos eso a grados Fahrenheit porque vivo en Estados Unidos, que creo que es uno de los últimos países que todavía utiliza la escala Fahrenheit. Pero de todos modos, si quieres mantener esa parte alejada y mantenerla en centígrado, bien por mí, no le diré a nadie lo que regresamos es una tupla que contiene el ID de la estación, el tipo de entrada, que en este caso será equipo en T max o precipitación y la temperatura asociada a esa entrada. Entonces a continuación, necesitamos filtrar la información que no queremos. Por lo que sólo nos interesan las entradas T min porque la pregunta que estoy respondiendo es cuál fue la temperatura mínima durante todo el año para cada estación meteorológica. Por lo que no me importan las temperaturas máximas que se registraron. No me importa la precipitación. Voy a tirar toda esa información. Entonces, solo diciendo que las líneas de análisis filtro de puntos, comprobando si ese segundo campo es igual a T min. Puedo tirar todos los datos donde eso no es cierto, ¿verdad? Entonces si x dot subrayado dos es igual al equipo y voy a preservar esa fila y el resultante Min temps RDD. De lo contrario lo voy a filtrar. Por lo que esto eliminará todas las demás cosas además de equipo en entradas. Entonces eso es filtro en acción. Después de eso, podemos crear los pares de
valores clave de temperatura ID de estación porque queremos hacer algunos trucos con RDD de valor clave, aprovechando nuestra lección anterior. Entonces vamos a mapear esa temperatura mínima a una nueva tupla que solo consiste en el ID de la estación y la temperatura. Ya no necesitamos a ese equipo en campo tipo de
entrada ahí porque sabemos que todo está un equipo en, así que eso es solo espacio desperdiciado, ¿verdad? Entonces vamos a convertir eso en tan solo un ID de estación y la temperatura de la temperatura mínima para cada fila que calificó. Y llamaremos a esta nueva estación RDD resultante temps. Y luego definir el mínimo. Todo lo que podemos hacer es decir ReduceByKey. Entonces de nuevo, estamos usando una especie de truco clave-valor aquí y haciendo una operación de reducción en él. Entonces básicamente queremos tomar cada total corrido que tenemos para la temperatura mínima actual, comparar eso con una nueva fila. Entonces eso va a ser x e y. y vamos a ejecutar los hombres de operación mínima para sólo preservar el valor mínimo visto. Entonces básicamente va a seguir pasando fila
por fila todas las temperaturas mínimas para una clave dada, donde cada clave representa una estación meteorológica. Y va a seguir, tratando de hacer un seguimiento de la temperatura mínima vista. Entonces mirará la primera fila. Mira la segunda fila es una secundaria o menor que la primera fila. Vale, genial, Ese es el nuevo mínimo. ¿ Es genial el tercer rerow, menos que la segunda fila? No. Está bien. El segundo sigue siendo el mínimo quieto, por lo que simplemente sigue pasando por hacer un
seguimiento de esa temperatura mínima que se encuentra. Y con lo que acabaremos es con un RDD mucho más pequeño llamado intentos de minutos por estación que solo contiene todas las claves únicas. En este caso, solo dos identificadores de estaciones meteorológicas diferentes y la escena de temperatura mínima para cada estación. En ese punto, todo lo que tenemos que hacer es recolectar los resultados. Por lo que llamaremos a la acción de cobro para ir y forzar son RDDs para ir y realmente hacer algo en nuestro clúster. Y luego iteraremos a través de cada resultado después de
clasificarlos y extraeremos el ID de la estación y la temperatura, formatearemos la temperatura usando un formato de impresión como
ya hablamos en la introducción a las lecciones de Scala. E imprimirlo nuevamente usando el formato de sustitución del que también hablamos. Así que algo de poner en acción algunas de esas cosas de
formato de cadena que aprendimos antes en el curso aquí. Entonces sólo vamos a imprimir el ID de la estación, las palabras colon temperatura mínima, y luego la temperatura formateada con dos puntos decimales de precisión después del punto decimal. Entonces vamos a hacerlo y a ver si funciona.
14. [Actividad] cómo ejecutar el ejemplo de la temperatura mínima y Modifying para el máximo: Entonces si abres el guión Min temperature en inteligencia aquí, deberías ver este guión aquí. Caminemos por ella línea por línea. Y dado que podrías ser nuevo en escala, voy a pasar un poco más de tiempo pasando por la sintaxis aquí. Es un ejemplo bastante sencillo, por lo que no debería tardar demasiado. Entonces abramos este bloque de importación aquí solo para asegurarnos de que vemos todo con eso que estamos usando. Entonces, como de costumbre, comenzamos declarando el paquete en el que estamos. Calma Dotson dogs software dot Spark, e importamos todas las cosas de las que dependemos. lo que estamos importando todo desde Apache Spark, desde log para J. Y también necesitamos Scala dot Math.min con el fin utilizar esa función Min para hacer un seguimiento de las temperaturas mínimas que nos encontramos. Por lo que lo declaramos en temperaturas. Objeto para que coincida con el nombre de nuestro archivo aquí. Y de nuevo, saltaré más allá de la función de línea de análisis por ahora e iré directamente a la función principal porque ahí es donde comienza la ejecución. Lo primero que hacemos es ajustar el nivel de registro a error para tratar de deshacernos de todos esos mensajes de advertencia que desbaratarán nuestros resultados. Después creamos un contexto de Spark. Y aquí estamos diciendo que el maestro será estrella local, diciendo que lo ejecutaremos o máquina local usando todos los núcleos de CPU disponibles y el nombre de la aplicación es Temperaturas Min. Ahora hablemos un poco de la sintaxis aquí. Por lo que el maestro es igual y el nombre de la aplicación es igual o simplemente pequeñas notaciones que inteligente insertó para nosotros con fines de visualización. En términos generales, no tienes que
decir realmente Master es igual a tu nombre de aplicación igual a que solo puedes pasar en los parámetros y lo
alineará con los parámetros esperados para esa función. Por lo que sabemos que un constructor de SparkContext comienza con el maestro y luego el nombre de la aplicación para los dos primeros parámetros. Pero si sí quieres ser más explícito al nombrarlos, puedes hacerlo de esta manera también. Esa es la sintaxis también es una válida y que puede conducir a un código más legible. Entonces si estuviera mirando esto fuera de Intel J, podría no saber realmente lo que significa Min temperature o estrella
local al poner explícitamente en esos nombres de parámetros, hace que el código
sea un poco más legible y fácil de entender . Vimos lo mismo aquí arriba en logger, get lager name igual org. No teníamos que decir nombre igual a 0, sólo podemos decir 4D, pero eso deja más claro que el nombre de ese parámetro que estamos configurando es nombre, y eso nos dice qué es. Después de obtener el registrador para el nombre de la organización, estamos configurando el error de punto nivel dos para decir que solo
queremos mensajes de error y no advertencias ni mensajes informativos. Continuando, lo primero que hacemos es cargar nuestros datos de entrada. Entonces decimos líneas val. Entonces estamos haciendo un valor inmutable aquí llamado líneas que se establece en el archivo de texto de la barra de datos 1800 puntos csv. Entonces eso tomará cada fila de ese formato CSV y simplemente pondrá el texto sin procesar de cada fila en el RDD de la línea. Echemos un vistazo rápido a cómo se ven esos datos. Por lo que esta es una visualización de ese archivo CSV en Microsoft Excel. Se puede ver la primera columna es el ID de la estación, y sólo hay algunos de ellos aquí, seguido de la fecha, que es en formato de fecha año, mes. Por lo que 8800, 1 de enero. Y todo este archivo contiene todos los datos del año 1800. Por lo que no tenemos que hacer nada especial que decir. Solo queremos datos del año 1800. Eso es todo lo que tenemos. Esta tercera columna es qué tipo de medición se registra en esta línea de datos. Por lo que temperatura máxima, temperatura mínima o precipitación. Y el siguiente es el valor asociado a esa medición. Y de nuevo, es una especie de formato extraño. Entonces creo que la palabra técnica es como deci centi grado o algo así. No lo sé. Básicamente se establece en grados centígrados veces 10. Entonces de nuevo, negativo 75 solo significa negativo 7.5 grados centígrados. Las columnas restantes no se utilizan para nuestros propósitos, por lo que podemos simplemente fingir que no existen. Entonces eso es lo que estamos leyendo en nuestras líneas RDD. Después utilizamos nuestra función de líneas de análisis y aplicamos eso para mapear cada fila de las líneas RDD para producir un nuevo RDD llamado líneas analizada. Entonces echemos un vistazo a lo que está haciendo la línea de análisis. Entonces de nuevo, vamos a bajar un poco la velocidad aquí en el formato. Recuerda, la forma en que declaramos funciones en Scala es que empezamos con def, el nombre de la función, y cualquier parámetro. Y recuerda declaramos parámetros un poco al revés de otros idiomas. Entonces empezamos con el nombre colon y luego el tipo. Muchos otros idiomas o escribe el nombre en Scala, su nombre luego escribe. Por lo que el parámetro se llama línea y se espera que sea de una cadena. Y entonces tenemos un colon, y esto es lo que va a salir por la función. Entonces, de nuevo, eso es al revés de cualquier otro idioma. Muchas veces pones el tipo de retorno antes del nombre de la función en Scala, es después de él. Entonces ve figura. Entonces lo que estamos devolviendo es una tupla que contiene una cadena, una cadena, y un número de coma flotante. Y establecemos esta función igual al siguiente bloque de código. En primer lugar, comenzamos con el valor de un campo que va a dividir esa línea usando el delimitador de comas. Y de nuevo el nombre de expresión regular de ese parámetro se está insertando aquí para nuestra conveniencia. Después extraemos el primer campo. Empezamos a contar desde 0 aquí. Por lo que Fields 0 está extrayendo al primer miembro de eso y llamándolo ID de estación. Extraer el tercer campo y llamar a ese tipo de entrada y al cuarto campo, y llamamos a esa temperatura después de convertirlo a Fahrenheit. Entonces, ¿qué está pasando aquí? Estamos tomando ese cuarto campo, que es una cadena con la que empezar porque lo dividimos de un dato de cadena. Por lo que tenemos que convertir explícitamente eso a un número de coma flotante antes de poder hacer operaciones numéricas sobre él. Entonces estamos diciendo flotar, para que eso se convierta en un número de punto flotante, vamos a multiplicar eso por 0.1 porque como ustedes recuerdan, todo se multiplicó por diez y los datos de origen. Por lo que en este punto tenemos grados reales centígrados. Después hacemos la conversión a grados Fahrenheit multiplicándose por nueve quintos y sumando 32. Si querías pegarte en centígrado, eso es genial. Simplemente saca esa parte y estarás en centígrado. Lo que regresamos es lo último que está en esta función, por lo que no tenemos que devolverlo explícitamente. Y solo lo último que hay ahí es devuelto implícitamente por esta función. Y eso va a ser una nueva tupla que consiste en el ID de la estación, que de nuevo es una cadena, el tipo de entrada, que de nuevo es una cadena. Y eso puede ser equipo y T, max o priciple. Y la temperatura que calculamos como valor de punto flotante. Entonces eso es lo que la, cada fila individual de nuestras líneas analizadas resultantes RDD va a contener en este punto. A continuación queremos filtrar todo menos al equipo en entradas porque todo lo que estamos tratando de computar es la temperatura mínima para todo el año para cada estación, ¿verdad? Para que podamos tirar todas esas entradas de TMax. Podemos tirar todas estas entradas de precipitación. Y eso lo hacemos aquí con esta línea. Entonces estamos diciendo filtro, que es todo el punto de este ejercicio, pasando en esta pequeña función en línea aquí. Entonces vamos a llamar a cada fila entrante de las líneas de parcela ya dx. Entonces vamos a sacar el segundo campo de x. y recordemos que será el tipo de entrada. Por lo que mirando aquí arriba, el segundo campo es el tipo de entrada. Y vamos a comprobar si ese tipo de entrada es igual a t Min. Si eso devuelve verdadero, entonces esa fila se pasa al Min temps RDD lo contrario tienen filtros que entran y no entra en MiniTab. Por lo que las mintues resultantes RDD solo contiene las filas que coinciden con t min y ese segundo campo. A continuación vamos a tirar a ese equipo en ese campo tipo de entrada porque ya no lo necesitamos. Sabemos que cada fila y temperatura mínima en este punto. Por lo que podemos mapear esto nuevamente para sólo extraer el primer campo, que va a ser el ID de la estación y el tercer campo. Y solo para estar seguros, diremos explícitamente que es un número de coma flotante. Por lo que nuestra nueva estación, temps RDD sólo va a contener identificadores de estación, que es una cadena y una temperatura, que es un número de punto flotante en Fahrenheit. Ahora podemos decir ReduceByKey, simplemente haciendo un seguimiento del valor mínimo que
encontramos al pasar por cada intento de estación de fila. Entonces a medida que pasemos por las tentaciones de la Estación, vamos a seguir comparando el mínimo actual cada fila entrante y devolver el mínimo entre esos dos que
tendrán el efecto de hacer un seguimiento de los más bajos registrados temperatura para cada clave porque estamos reduciendo por clave. Por lo tanto, recuerda que cada clave es un ID de estación. Entonces con lo que los hombres carpas por Estación termina es un RDD mucho más pequeño que solo contiene una fila por cada clave única que contiene ese nombre clave y la temperatura mínima asociada a esa estación meteorológica ID. Después recogemos los resultados de nuevo a nuestro script y lo ponemos en el objeto de resultados. Entonces lo ordenamos con los resultados de punto ordenados e iteramos a través de él con este for loop. Entonces para resultado, resultados ordenados, que pasa por cada línea de resultados ordenados cada entrada, y extrae cada una como resultado. Para cada uno, extraemos el primer campo de esa tupla llamada estación. El segundo campo es la temperatura. Formateamos esa temperatura. El F significa que vamos a usar un formato de impresión f. Y el porcentaje 0.2 F significa que queremos dos puntos decimales de precisión a la derecha del punto decimal. Y ponemos una F al final para indicar que es Fahrenheit. Entonces sólo tenemos que imprimirlo con línea de impresión. Y vamos a sustituir el uso estación de signo de
dólar por el valor de la estación, temperatura mínima, y luego formatear una temp, el signo del dólar nuevamente indicando que estamos sustituyendo en ese valor inmutable llamado temp formateado. Entonces, corrámoslo y veamos qué pasa. Haga clic derecho en Temperaturas Min y ejecute Temperaturas Min. Fuera va. Y ahí lo tenemos. Por lo que podemos ver que para las dos estaciones meteorológicas que tenían temperaturas mínimas asociadas a ellas, la primera se llamaba Easy Easy algo u otro. Y la temperatura mínima registrada ahí fue de 7.7 grados Fahrenheit. Y para ITE, sea lo que sea, la temperatura mínima fue de 5.36 grados Fahrenheit. Por lo que parece haber funcionado muy cool. Ahora si quieres ensuciarte las manos, siempre
te animo a ir de la mano por aquí. Aquí tienes un reto realmente rápido para ti. ¿ Y si quisieras hacer un seguimiento de la temperatura máxima para cada estación meteorológica en lugar de la temperatura mínima. Bueno, el, los cambios asociados a eso deberían ser bastante sencillos. Si quieres un poco de reto, toca pausa ahora mismo y ve y prueba eso tú mismo. Vea si puede modificar este script para imprimir las temperaturas máximas en lugar de las mínimas. Y hace una pausa si quieres hacer eso. Si no, te voy a mostrar cómo lo hice. Entonces es bastante simple, pero necesitas cambiar, ¿verdad? Entonces, en primer lugar, se quiere cambiar el nombre del objeto y el archivo a temperaturas máximas por consistencia, el análisis de los datos será el mismo, ¿no? Eso no va a cambiar. El formato de datos no ha cambiado en nosotros. Pero lo que extraigamos va a ser diferente, ¿verdad? Temperaturas mín quieren cambio. El suceder de la temperatura máxima es probablemente lo que vamos a hacer esto sin embargo, filtrar todo con TMax en lugar de t min. Entonces eso nos dará todo menos las entradas T max. Y luego aquí abajo cuando hacemos nuestra operación de reducción o reduceByKey, solo
queremos cambiarlos en un máximo. Y eso debería ser más o menos que cambió cómo estamos mostrando los resultados para decir que es una temperatura máxima. Supongo que tenemos que importar math.max esquelético también, ¿verdad? Cosas bastante sencillas, pero es bueno ponerte en tus manos y algo de confianza en hacer
cambios en el código de Scala y el código de Spark y ver que puedes hacerlo,
Se trata más de tu confianza en cualquier cosa. Si quieres ver cómo lo hice,
basta con hacer doble clic en el guión de temperatura máxima aquí. Y hace todo lo que acabo de decir. Por lo que estamos importando scala dot math.max. Cambié el nombre del mismo, cambié el nombre del archivo. Ahora lo estamos llamando temperaturas máximas. Estamos filtrando para TMax y reduciendo
en base a la función max e imprimiendo la temperatura máxima. Eso es más o menos. Adelante y corremos eso y veamos qué hace. Y ahí lo tienes, lo. Resulta que fue que ambos tienen el mismo. Eso es algo curioso, ¿no? Por lo que para ambas estaciones más bien, la temperatura máxima fue de 90 punto 104 grados Fahrenheit. Y creo que eso corresponde a un buen número redondo y grado de
incentivo que simplemente pasa a ser el mismo para ambas estaciones. Por lo que no demasiado lejos el uno del otro. Por lo que no es demasiado enorme de sorpresa. Y ahí lo tienes filtro en acción. Y también otro ejemplo de escribir un sencillo script Apache Spark usando RDDs. Encontrarás que esto no es todo muy diferente. Estaremos hablando de diferentes API, pero de nuevo, son reales pronto.
15. [Actividad] contar la palabra que se presenta con Flatmap(): Por lo que hemos visto hasta ahora varios ejemplos de usar la operación de mapa en Spark, Hablemos de FlatMap, que es un poco diferente. Y tenemos un ejemplo sencillo para ilustrarlo, donde contamos el número de cada palabra en un libro para mostrar cómo funciona. Entonces revisemos qué hace el mapa. Entonces, por ejemplo, si tuviéramos un archivo de texto de entrada que contenía la lectura rápida en una línea y Fox saltó en otra línea y sobre el perezoso en otra línea y los perros marrones en la última línea. Podríamos leer eso en un RDD llamado líneas donde cada línea de texto corresponde a una fila de ese RDD. Y luego en este caso, estamos llamando a mapa en las líneas RDD, pasándole una función para convertir cada línea en mayúsculas. Entonces lo que obtenemos es una nueva rabia gorra RDD que simplemente capitaliza cada línea o cada fila en lugar de esa entrada RDD. Entonces lo que hay que señalar aquí es que existe una relación uno a uno entre el RDD de entrada y el RDD de salida. Y cuando llamas a mapa, mapa toma cada fila de entrada y lo convierte de alguna manera en una y sólo una fila de salida. Entonces empezamos con cuatro filas y el RDD de la línea, y terminamos con cuatro filas y la salida de rabia gorra RDD, mapa siempre tiene esa relación uno a uno. Entra una fila, sale
una fila. Flatmap, sin embargo, elimina esa restricción. Entonces con FlatMap, puedes devolver cualquier número de filas para una fila de entrada, podría ser 0, podría ser 20, podría ser 200, cualquier cosa que quieras. Entonces en este ejemplo diferente aquí, comenzamos con la misma entrada. Rdd se llaman líneas, pero ahora estamos llamando a FlatMap. Y estamos pasando como una función ahí para tomar en cada fila, llamarla x, y luego dividirla en función del carácter espacial. Por lo que esto tiene el efecto de dividir cada fila en sus palabras individuales. Y como estamos llamando a FlatMap, cada palabra individual termina en su propia nueva fila en las palabras resultantes RDD. Entonces usando FlatMap aquí, empezamos con cuatro filas, pero terminamos con muchas más filas que en las palabras RDD de salida, donde tenemos una fila para cada palabra en contraposición a una fila para cada línea. Y de nuevo, FlatMap puede generar cualquier número de filas que desee, incluyendo 0. Para ver esto en acción, hagamos un pequeño ejemplo de código simple donde contamos cuántas veces ocurre cada palabra dentro de un libro entero. Y no estoy tratando de venderte este libro, a pesar de que lo escribí, no tiene nada que ver con Apache Spark, pero es un libro donde tengo los derechos de él para
poder usarlo como ejemplo sin pagar regalías. Entonces sigamos adelante y sumémonos y veamos con qué frecuencia aparece cada palabra individual en mi libro. Por lo que tenemos aquí un guión muy sencillo para ilustrar el uso de FlatMap. Se llama conteos de palabras. Así que adelante y abre Word Count e inteligente si
quieres seguir guion realmente simple. Y esto se utiliza a menudo como una especie del ejemplo de HelloWorld para los programas de Spark. Empezamos como siempre declarando nuestro paquete, importando lo que necesitamos para dependencias, y declarando el objeto en el que vivimos. Nuestra función principal comienza diciendo que el nivel de registro es siempre y declarando un nuevo SparkContext que se ejecuta en nuestro PC local. Ahora nos metemos en la carne de la misma. Por lo que lo llamamos Archivo de texto SparkContext con una ruta a todo
el contenido del texto de ese libro entero que vive en la barra de datos Book dot txt archivo. Y llamamos a eso resultante RDD nuestra entrada, donde cada fila de esa entrada RDD corresponde a una línea de texto del libro. Y ahora al igual que vimos en las diapositivas, llamamos FlatMap en ese dividir cada fila por el carácter espacial, que más o menos nos da las palabras individuales dentro de ese libro. Por lo que ahora FlatMap ha generado nuevas palabras RDD, donde cada fila de las palabras RDD es una palabra en el libro y puede haber palabras repetidas ahí dentro. Es cada palabra individual, aunque ocurra más de una vez, va a ser una fila en ese RDD y secuencia. Y ahora vamos a utilizar la acción conteo por valor para contar cuántas veces aparece cada palabra única en las palabras RDD. Entonces esa es una forma de hacer una sola línea lo que de
otra manera sería una operación bastante complicada, ¿verdad? Y la belleza de Spark es que en realidad puede paralelizar eso a través de todo un clúster si quieres, o en nuestro caso, cada núcleo de nuestra CPU. Todo lo que hacemos entonces es iterar a través cada resultado en ese objeto de conteo de palabras que obtuvimos de Spark. Y llamamos línea de impresión en cada uno de esos resultados para imprimir cada resultado en su propia línea. Entonces sigamos adelante y corramos y veamos qué pasa. Haremos clic con el botón derecho en conteo de palabras, digamos ejecutar WordCount, fuera de él va. Y a pesar de que este es un libro entero, debería hacer un trabajo corto de él. Ahí lo tenemos. Interesante. Entonces si te desplazas por esto, puedes ver cuántas veces aparece cada palabra en mi libro. El término cash aparece 18 veces, sólo 77 veces. Autónomo, sólo 10 veces. Algo sorprendente ahí porque es un libro sobre el autoempleo. Pero también hay algún tipo de palabras únicas aquí, como idea solo aparece una vez. El envío directo solo aparece una vez. tan cool. Entonces en nuestro funcionó. Ese es un ejemplo de flatmap en acción. Pero al mirar a través de estos resultados, se
puede ver que aquí hay algunos temas en los que podríamos querer trabajar. Entonces, vamos a explorar esto en conferencias posteriores aquí, por ejemplo, dependiendo de la capitalización, podría tratarlas como palabras diferentes. ¿ Se incluyó realmente la palabra productos sólo una vez? Lo único que realmente significa es que los productos solo aparecieron una vez con P mayúscula, tal vez al principio de una frase o algo así, ¿verdad? Por lo que hay formas de mejorar estos resultados para ser más interesantes. Y también es como cosas raras como es open dash terminó una palabra o dos. ¿ Qué pasa con la puntuación? Debería estar despojando esos signos de interrogación y comas y periodos, ¿verdad? Por lo que los propietarios comas aparecen dos veces, pero eso no es realmente hablar de la palabra dueños. Entonces hay algo de margen de mejora y cómo analizamos estos datos. Entonces, vamos a explorar eso.
16. [Actividad] Mejorar el guión de Word Count con expresiones regulares: De acuerdo, así que para revisar en nuestra lección anterior, hicimos un ejemplo sencillo de usar FlatMap para contar cuántas veces aparece cada palabra en mi libro. Y muy ingenuamente solo analizamos esos datos
dividiéndolos en función de caracteres espaciales para tratar de obtener palabras individuales, que al principio se ruborizan pensarías que funcionarían. Pero como se puede ver en los resultados aquí, no lo hace. Terminamos consiguiendo puntuacion ahí dentro. Entonces por ejemplo, cita, y cuenta como una palabra única individual. Aquí también importa la capitalización. Por lo que Y mayúscula se contaría como una palabra diferente a la minúscula y. tenemos cosas como comas, signos de puntuación y mayúsculas que afectan nuestros resultados. Entonces arreglemos eso. Así que vamos a cerrar WordCount punto Scala y en su lugar abrir Word Count mejor. Y aquí vamos a usar una expresión regular en su lugar para obtener mejores resultados. Clv, nada realmente diferente aquí es que en lugar de tener esa función que se divide en función de un carácter espacial, cuando dividimos los datos de entrada, en cambio vamos a usar una expresión regular. Por lo que en este caso vamos a decir x punto split y establecer la expresión regular a este formato de expresión regular, barra
contraria, barra inclinada hacia atrás mayúscula W plus. Y en la tierra de expresión regular, eso sólo significa que quiero romper las cosas en base a palabras enteras. El W mayúscula significa palabra. Por lo que las expresiones regulares saben lo que es una palabra. Se va a filtrar toda la puntuación y todos esos personajes especiales y sólo nos deja con palabras que contienen los personajes reales. Entonces eso tiene que deshacerse de todos los temas que la puntuacion estropeando nuestros resultados. No obstante, todavía tenemos el problema de la capitalización, ¿no? Entonces mayúscula R Y recuerda va a ser una palabra diferente a la r minúscula. Y recuerda, incluso después de despojar cualquier puntuación que pudiera haber existido allí. Entonces para cuidar ese problema, vamos a además un mapa nuestros resultados a minúsculas. Por lo que vemos aquí comenzamos mapeando plano nuestros datos de entrada en palabras individuales. Pero en este caso estamos dividiendo en palabras de expresión
regular en lugar de sólo en caracteres espaciales, lo cual es más robusto. Y luego hacemos un mapa regular para tomar cada palabra individual y mapear eso de uno a uno a su versión en minúscula. Por lo que al normalizar todo a caracteres minúsculas, podemos estar seguros de que estamos contando todas las palabras igual independientemente de las mayúsculas. Y luego nos bajamos y sí contamos por valor en las palabras minúsculas resultantes RDD e imprimimos esos resultados. Entonces veamos si eso nos da algo un poquito mejor. Hagamos clic derecho en conteo de palabras mejor y ejecutemos eso. Y está bien, eso se ve un poco mejor, ¿verdad? Entonces eso es genial. Entonces ahora no tenemos ninguna puntuación extraña pasando aquí. Todo es minúscula, así que estamos obteniendo resultados que tienen un poco más de sentido esperemos. Entonces por ejemplo, la palabra publicidad aparece 41 veces en el libro que parece creíble. Religioso sólo un caché 19 veces. Busquemos aquí una palabra realmente popular, sin embargo, que aparece 1292 veces. Entonces no demasiado sorprendente ahí, esa es una palabra muy común. Enfriar. Entonces parece haber funcionado como creo que estamos recibiendo palabras válidas aquí. Todo parece normalizado. No nos estamos estropeando. Yo puntuacion, así misión cumplida, pero esto no es terriblemente útil todavía en cómo usarlo, ¿verdad? Tengo que ir a pescar palabras comunes aquí. No debería tener que hacer eso. ¿ No sería mejor que pudiera ordenar estos resultados por la frecuencia con que aparece cada palabra. Por lo que habrá más útiles. Puedo encontrar muy fácilmente las palabras más comunes y las menos comunes en el libro. Y eso podría incluso darme alguna idea de lo que trata el libro. O quizá palabras que estoy sobreusando o algo así, eso es bueno. En realidad tengo una aplicación práctica para escritores. Entonces sigamos adelante y hagamos que este guión sea aún mejor en nuestra próxima conferencia y en realidad ordenemos esos resultados para que podamos sacar más sentido de ello.
17. [Actividad] clasificación de los resultados de la cuenta de palabras: De acuerdo, entonces en nuestra lección anterior, refinamos nuestro ejemplo de conteo de palabras para ser un poco más inteligentes en cuanto a identificar palabras. Por lo que tenemos una salida realmente buena aquí de los conteos de cada palabra única dentro de todo nuestro libro. Pero no es terriblemente útil porque no está ordenada por la frecuencia con que ocurre cada palabra. Entonces tengo que ir a pescar para averiguar cuáles son las palabras más comunes y menos comunes en mi libro. Entonces eso no es muy útil, ¿verdad? Entonces arreglemos eso. Queremos ordenar los resultados en función de la frecuencia con que ocurre cada palabra. Podemos ver rápidamente las palabras más utilizadas en mi libro. Ahora en conferencias anteriores de este curso, lo
habríamos hecho solo ordenando los resultados finales que obtuvimos de Spark que fueron devueltos a nuestro guión de conductor y simplemente ordenándolos en Scala. Pero esa no es realmente la forma del big data de hacer las cosas, ¿verdad? Sería mejor si pudiéramos ordenar estos en el clúster si tuviéramos tantas palabras que en realidad no pudiéramos procesarlo todo en una sola máquina. Tendrías que hacer eso, ¿verdad? Es decir, eso es una especie de ejemplo enrevesado. Es poco probable que tengas tantas palabras en un libro, pero te das la idea. Va a ser preferible hacer esa clasificación distribuida en el clúster si podemos. Entonces hagámoslo así y veamos cómo podría funcionar eso. Entonces vamos a abrir el conteo de palabras mejor ordenado ejemplo aquí. Sólo un pequeño refinamiento en la palabra anterior contar mejor guión aquí, es más o menos lo mismo excepto por el nombre del guión todo el camino hasta este punto aquí. Por lo que hemos cargado nuestro libro en un RDD de entrada. Lo dividimos en palabras usando FlatMap. Entonces ahora tenemos unas palabras RDD que contienen cada palabra del libro, y luego mapeamos eso a minúsculas para normalizar esos datos. Entonces ahora, anteriormente habríamos usado conteo por valores, ¿no? Si volvemos a nuestro ejemplo anterior aquí usamos recuento por valor para obtener
rápidamente el número de veces que ocurre cada palabra en ese RDD. Pero queremos ordenarlo al mismo tiempo. Entonces tenemos que hacerlo de la manera difícil. Entonces, desglosemos lo que está pasando en este tipo de línea complicada aquí. Entonces primero vamos a mapear ese resultado a x r1. Tome cada fila, cada palabra individual, y mapee eso a una tuple de la palabra y el número 1. Ahora ya hemos visto este truco antes, ¿verdad? Entonces lo que estamos diciendo es que vamos a hacer que cada tupla individual tenga esa palabra y representen que ocurrió una vez en esa fila. Y ese es un pequeño truco que podemos usar porque eso nos
permitirá resumir todo, correcto, y obtener el número de veces que ocurre cada palabra única cuando hacemos una operación de reducción. Y eso es lo que estamos haciendo aquí. Estamos diciendo reducir por clave, sumando todos esos totales. Entonces, repasemos por esto otra vez. Estamos transformando cada palabra en una tuple de la palabra y la número uno. Y porque se trata de una tupla con dos cosas en ella que podrían considerarse un valor clave, RDD, donde la clave es la palabra y el valor es el número uno. Entonces ahora podemos decir ReduceByKey porque básicamente tenemos un RDD clave-valor que resume todos los valores, ¿de acuerdo? Entonces por cada palabra única, vamos a contar todos los valores, que es sólo el número 1. Entonces cuando sumamos todo el número uno para cada ocurrencia de palabra, terminamos con un recuento de cuántas veces ocurrió esa palabra. De acuerdo, lo siguiente que queremos hacer es ordenarlo. Entonces en este punto la operación ReduceByKey nos ha dejado con un conteo de palabras RDD que contiene pares clave-valor, nuevo, donde la clave es la palabra y el valor es el número de veces que ocurre esa palabra. Ahora chispa ofrece una función ordenar por clave aquí que podemos usar, pero va a ordenar por la clave y el valor que queremos ordenar por el, con
qué frecuencia ocurre cada palabra. Entonces necesitamos voltear eso primero. Entonces eso es todo lo que estamos haciendo en esta operación de mapa. Estamos tomando el recuento de palabras RDD y volteándolo para que el valor clave RDD se esté volteando a la clave de valor si se quiere. Y así estamos tomando el RDD de entrada, que contiene conteo de palabras, y volteando eso para contar palabra transformándola en x dot t2 y x-dot one. El segundo campo en el primer campo. Una vez que tengamos eso, podemos usar ordenar por clave para ordenar los resultados por el número de veces que ocurre cada palabra. Entonces conmigo aquí, pasémoslo rápidamente una vez más. Todo esto es lo mismo desde antes. Pero en este caso vamos a tomar nuestras palabras minúsculas RDD, que tiene cada palabra única en su propia fila. Vamos a mapear eso a un par clave-valor donde la clave es la palabra y el valor es el número uno. Hacemos una operación ReduceByKey para sumar cuántas veces ocurre cada clave única, cada palabra única. Y luego necesitamos voltear ese par clave-valor resultante en su cabeza para que realmente
podamos usar ordenar por clave para ordenar por el número de veces que aparece cada palabra. Después pasamos e imprimimos los resultados, un poco como lo hicimos antes. Y deberíamos conseguir algo más útil. Entonces sigamos adelante y probémoslo. Haga clic con el botón derecho en conteo de palabras, mejor ordenado y decir correr. Y ahí lo tenemos. Y se ordena en orden ascendente. Por lo que las palabras más populares serán al final. Y eso es interesante. Entonces mis palabras más comunes fueron también y tú no en un pozo, me alegro de que usé las palabras tú en tu más de lo que yo y yo. Esa es una mejor manera de escribir. Ella quiere conectarse con tu lector y no hablar mucho de ti mismo. Entonces voy a llamar a eso una victoria. Pero sí, un en lo poco profundo aparecen con bastante frecuencia. Y de todas las palabras comunes que esperarías ver ahí, hay es decir, un negocio aparece mucho. Entonces cuando perforas hacia abajo en la luz, las palabras más interesantes puedes decir de qué se trata el libro sólo por cuáles son las palabras más comunes, ¿verdad? Entonces la primera palabra que un poco tiene significado hay negocios, y es una mirada sobre los negocios. Tiempo de desplazamiento hacia arriba. Ya sabes, sí hablamos mucho de gestión del tiempo debido a hacer producto. Está bien. Sí, hablamos mucho sobre cómo seleccionar qué producto vender. Entonces sí, en realidad puedes obtener algunas ideas sobre lo que se
trata el libro solo de mirar estos datos ahora. Y si nos desplazamos hasta las palabras más menos comunes, no
deberíamos conseguir algunas cosas bastante oscuras aquí. Espuma sólo usaba eran teléfono. Me pregunto de dónde salió eso. Swot citado. Entonces, sí, cosas interesantes. Por lo que realmente se puede decir de qué se trata el libro con sólo mirar estos datos. Entonces nos gusta ver la evolución del guión. Y en el camino de hacer más útil este guión, hemos aprendido no sólo sobre cómo usar FlatMap, sino también cómo usar expresiones regulares y cómo ordenar hacer uso
creativo de ReduceByKey y ordenar por clave para obtener los resultados que quieren. Ahora de nuevo, encontraremos que esto es un poco más sencillo al usar conjuntos de datos en SQL. Pero estamos llegando ahí. Simplemente queremos gustarnos, empezar con lo básico aquí y los fundamentos de Spark, que se construyen sobre RDD. Y en los casos en que necesites usar RDD, es bueno conocer estos trucos.
18. [Ejercicio] Encuentra el número total del número del cliente: De acuerdo, creo que ya has aprendido lo suficiente sobre RDD y has visto suficiente código Scala en este punto para intentar hacer algo por tu cuenta. Entonces es un pequeño reto, un poco de actividad práctica. Te voy a hacer crear un programa de Spark muy sencillo en
Scala que solo contará la cantidad total de
dinero que ordena cada ID de cliente individual y una pequeña base de datos falsa de datos de comercio electrónico. Entonces les voy a proporcionar un archivo CSV que contenga cosas en este formato. Y esto representará un ID de cliente y también un ID de artículo y la cantidad gastada en ese artículo. Por lo que cada fila de estos datos falsos representa
algunas transacciones, alguna compra a una persona ficticia hecha. Vas a escribir algún código y dar salida al gran total de cuánto gastó cada ID de cliente único. Entonces en este ejemplo en particular, se
puede ver que el ID de usuario 44 compró algo para 37, 19, y otra cosa para 4064. Por lo que el gran total para nuestro usuario 44 es de 77, 83. Y queremos hacer eso por cada cliente individual en nuestra base de datos. Entonces te deletrearé un poco esto si estás un poco ansioso por ello, no, no,
no mires si sí quieres probar esto por tu cuenta, pero alguna orientación general sobre la estrategia para hacer esto. Quiero empezar dividiendo cada línea delimitada por comas en sus campos únicos. Y como dije, eso va a ser ID de usuario, ID artículo y cantidad gastada. A continuación, asignará cada línea a un par clave-valor de ID de cliente y cantidad en dólares. Y utilice la operación ReduceByKey para sumar el monto total gastado por ID de cliente. Cuando haya terminado, recoja los resultados e imprímelos. Bastante sencillo. Y deberías poder resolverlo
estudiando los ejemplos anteriores en este curso. Son bastante similares. Pareja de fragmentos de código útiles si eres nuevo en Scala, eso podría ser útil si quieres dividir un campo delimitado por comas en sus campos individuales,
esta línea lo haría por ti, los campos Val es igual a la coma de división de punto de línea. Y también necesitarás en algún momento asegurarte de que tratas el campo 0 es un entero y siéntete como un número de punto flotante. Por lo que ese pequeño fragmento de código es importante recordar también. Sí necesitas lanzar explícitamente estos en su representación numérica real y no solo cadenas como ellas salen del archivo rock. Así que buena suerte. Y antes de que te suelte, te
voy a mostrar de verdad brevemente dónde encontrar los datos para esto y cómo crear un nuevo objeto en nuestros proyectos para que realmente puedas jugar con él y empezar. Entonces déjame mostrarte eso de verdad rápido y luego te soltaré. Entonces primero permítanme dirigir su atención hacia donde viven los datos para este ejercicio. lo que dentro de su carpeta de materiales del curso, entra al curso de Spark Scala y luego a la carpeta de datos. Y es el archivo de pedidos de dash del cliente que vamos a estar viendo aquí. Abramos eso, veamos cómo se ve. Ahora recuerda que esto es valores separados por comas. Entonces, a pesar de que Excel lo está mostrando como una hoja de cálculo, son realmente columnas individuales separadas por comas que estamos leyendo aquí. Y este dato se genera completamente aleatoriamente. Se puede ver que hay bastante de ello, 10 mil filas de datos aquí, pero todo es falso. La primera columna representa el ID de usuario, seguido de un ID de artículo y la cantidad gastada en ese artículo. Por lo que cada línea representa una sola compra. Y sí, podrías notar que
esa segunda columna no es realmente necesaria para lo que estamos haciendo, ¿verdad? Simplemente necesitamos la cantidad gastada por el cliente. El ID del ítem realmente no entra en juego, así que mucho tiempo, así que limpiar tus datos va a ser una gran parte del trabajo y ese es el caso y este pequeño ejercicio sencillo también. Ahora para que empieces en esto, déjame mostrarte cómo realmente ir sobre la creación de un nuevo objeto en una tele j Así que hago clic en Calm dot sundown software dot Spark y decir New Scala class y darle algún nombre único. Pon tu nombre ahí solo para estar seguro para asegurarte de que sea único. Entonces algo así como cantidad total gastada F bastón para mí, sea cual sea tu nombre para ti. Y haga doble clic en objeto porque queremos un objeto y no una clase. Muy bien, así que ahora tienes el calderazo aquí de un nuevo objeto aquí tiene el nombre correcto del paquete porque lo ponemos en el lugar correcto. Y tu objeto está todo configurado. Y ahora todo lo que tienes que hacer es escribir algún código y probarlo. Entonces, cuando estés listo para probar eso, solo
puedes hacer clic derecho en esa clase y puedes construirla. Y luego después de eso en realidad puedes intentar ejecutarlo y ver qué pasa. Y sí, eso es todo. Entonces ve a tener en ello. No es un ejemplo muy difícil, ni un ejercicio duro por cualquier medio, pero quiero que te ensucien las manos y te consuela al escribir código de Scala. Tendremos algunos más desafiantes más adelante en el curso, por
supuesto, Así que estamos empezando fácil. Entonces ve a darle una oportunidad a eso. Y cuando estés listo vuelve a la siguiente conferencia y te mostraré mi solución, que está aquí en los materiales del curso. Podrías haberla visto ya, así que resiste la tentación de mirarlo. Prueba esto tú mismo primero.
19. [Ejercicio] Consulta tus resultados y Sort con el espacio total de la cantidad de dinero: Entonces, ¿hiciste tu tarea? Eso espero. Bueno, si quieres comparar tus resultados con los míos y comparar tu código con el mío, incluí mi solución en los materiales de tu curso también. Por lo que ojalá aún no los hayas cogido. Simplemente abre el total gastado por clase de cliente aquí. Y así es como lo hice. Entonces pasemos por este código aquí. Empieza con la declaración de paquete que ya
debes tener e importando lo que necesitamos. Necesitamos de todo desde Spark y registro para J. Esperanza no te tropezaste con incluir esos. Y llamamos a nuestro objeto aquí total gastado por el cliente. Este es mi archivo de solución aquí. Y saltemos a la función principal y empecemos por ahí. Por lo que empezamos ajustando nuestro nivel de registro a error como lo hemos hecho antes. Y montamos un nuevo SparkContext. Y lo único único único de esto es que dijimos un nombre de aplicación que es diferente a los otros ejemplos. En este caso, total gastado por el cliente. Ahora nos metemos en la carne de todo. Cargamos nuestro archivo de texto, que es el cliente dash pedidos dot archivo CSV al que te dirigí antes. Y sólo vamos a cargar eso en una entrada de nombre RDD. Ahora necesitamos analizar esos datos. Entonces por eso hemos escrito este extracto de los pares de precios del cliente funcionan aquí arriba. Por supuesto, podrías haberle llamado lo que quisieras. Tomará en toda una línea de Valores Separados por Comas y solo llamaremos a esa línea de cadena y devolveremos una tupla de un entero y un flotador. Entonces esos serán nuestros pares de valor clave que tengamos más adelante, donde la clave va a ser el ID del cliente, que es el primer campo, y un valor de punto flotante. Estamos representando la cantidad gastada en algún artículo para ese cliente en esa transacción. Empezamos dividiendo los campos de
esa línea en función del carácter de coma usando división de punto de línea. Y asignamos eso al valor de los campos. Y luego acabamos de devolver la tupla que contiene el primer campo convertido a un entero, y el tercer campo convertido a un número de coma flotante. Y recuerda de nuevo, empezamos a contar desde 0 en este formato en particular. Por lo que en este punto, hemos mapeado nuestra entrada en un nuevo RDD de entrada mapeada que contiene tuplas de ID de clientes y cantidad gastada. Y ese es en realidad un par de valores clave porque es una tupla de dos cosas, ¿verdad? Por lo que nuestra clave ahora es el ID del cliente y nuestro valor ahora es el monto gastado en esa transacción. Ahora sólo tenemos que reducir eso hacia abajo usando la operación ReduceByKey. Y usamos esta sintaxis aquí para mantener un total corriente
del total general gastado por cada ID de cliente. Por lo que estamos reduciendo por clave por cada cliente y sumando esos valores a medida que entran. Por lo que esto toma en un par de dos valores asociados a la clave. Y vamos a decir que queremos sumar esos porque queremos el gran total. Y lo que recuperamos es el total por parte del cliente RDD, que contendrá las claves, cada clave única, cada ID de cliente único, y el total gastado por cada ID de cliente. Podemos entonces recoger los resultados de vuelta. Entonces esa va a ser nuestra acción que recupere los resultados y lo devuelva a nuestro script,
a nuestro script de conductor que se ejecuta localmente aquí. Y entonces solo podemos llamar a ForEach con la función de línea de impresión para imprimir cada línea de esos resultados. Entonces vamos a ejecutarlo y a ver si funciona. Voy a hacer clic derecho en total gastado por cliente y decir ejecutar total gastado por cliente. Fuera va. Y ahí lo tenemos. Muy cool. Está bien, bueno parece haber funcionado. Entonces, por ejemplo, el ID de usuario 91 gastó $4,642.26, y así sucesivamente y así sucesivamente. El usuario 53 gastó $4,495. Todos están más o menos en el mismo barrio porque
todo esto fue datos generados aleatoriamente con distribución aleatoria uniforme. Pero eso es entrar en mi curso de ciencia de datos, supongo. De todos modos, funcionó. Por lo que ojalá tengas una salida similar para escuchar. El orden puede ser diferente, está bien. Pero ya sabes, deberías poder ver que para un ID de usuario en particular, puedes buscar ese ID de usuario y obtener el mismo número esperemos. Entonces si quieres buscar al usuario 89 y asegurarte de que tienes 4851947, 95. Esa podría ser una buena idea. Está bien, así que te voy a desafiar más ahora, puedes hacer que esto sea aún mejor tipo de como lo hacemos en nuestro ejemplo de cuenta de palabras. Será mucho más útil si esto se ordenara, ¿verdad? Entonces si me interesaba más ver quiénes son mis grandes gastadores, podría realmente querer ver este Datastore ordenado por cantidad gastada. Entonces de esa manera pude ver fácilmente quién estaba gastando la menor cantidad de dinero en mi sitio y quién estaba gastando la mayor cantidad de dinero en mi pequeño sitio de comercio electrónico falso aquí. Entonces ese es tu reto. Adelante y ve si puedes ordenar
los resultados por cantidad gastada para un equipo extra de bonos añadidos, quiero ver si puedes formatear que en realidad tengan dos puntos decimales de precisión ahí después del signo de dólar ahí. Entonces haz que eso se parezca más a la moneda real. Pero lo son, tu único reto real ahora mismo es ordenar esos resultados por cantidad gastada. Y otra vez, refiriéndose al recuento de palabras mejor ordenado ejemplo que teníamos antes. Mismo truco exacto ahí. Entonces no estoy tratando de que pienses demasiado duro aquí. Yo solo quiero que te pongas algo de práctica aquí y apliques lo que has aprendido en este apartado. Como dije, pronto nos pondremos más desafiante. Así que vete y dale una oportunidad a eso. Ahora, mira si puedes ordenar esos resultados por cantidad gastada y darle una oportunidad. Y volveremos en la próxima conferencia y podrás comparar tus resultados en tu código con los míos.
20. Consulta tus resultados y la aplicación contra la mina: De acuerdo, entonces espero que hayas tenido la oportunidad de intentar ordenar esos resultados por cantidad gastada para que podamos obtener allí un resultado más útil. Comparemos tu solución con la mía otra vez. Por lo que si quieres mirar el mío, puedes hacer click en total gastado por clientes ordenados. Haga doble clic en eso y vea cómo lo hice. Más o menos lo mismo el código original por el que pasamos en la conferencia anterior. Entonces no voy a reiterar todas las cosas que no cambiaron. Todo lo que hicimos cambió fue este pedacito aquí. Por lo que en este punto aquí tenemos el monto total por cliente. Por lo que hemos reducido nuestros datos a la baja para tener pares de valor clave donde tenemos identificadores
individuales de clientes asociados a la cantidad gastada por ese cliente en toda la base de datos. Entonces al igual que hicimos en el ejemplo de conteo de palabras ordenado, vamos a voltear eso en su cabeza e intentar aprovechar
el tipo por operación clave que ofrece la chispa. De esa manera podemos realmente distribuir la clasificación de esto en el clúster si queremos. Entonces para hacer eso, necesitamos hacer nuestros valores, las claves y las claves los valores porque queremos ordenar por los valores, la cantidad gastada. Entonces estamos creando este RDD volteado. Eso es simplemente mapear total por cliente para tomar el par clave-valor de entrada x y tomar el segundo elemento y hacerlo primero. Y tomamos el primer elemento y lo hacemos segundo. Entonces es solo voltear la clave y el valor para hacer la nueva clave, la cantidad gastada y el nuevo valor, el ID de usuario. Entonces ordenamos por clave para ordenar realmente eso por la cantidad gastada ese primer valor allí. Después podremos recolectar los resultados de vuelta e imprimir cada línea. Entonces, veamos si funciona. Haga clic derecho en total gastado por los clientes ordenados y ejecutarlo. Y deberíamos ver quiénes son los grandes gastadores. Está bien, parece que funcionó. Por lo que tenemos en la primera columna ahora la cantidad gastada. Por lo que podemos ver que lo más que alguien ha gastado con $6,375.45 y eso fue por los números de usuario 68. Por lo que podemos ver que el usuario 68 fue nuestro mayor gastador. Y si fuéramos a desplazarnos hacia arriba, podemos ver a nuestro gastador más barato, si se quiere. $3,309 fueron para el usuario 45. Y de nuevo, si quieres empujarte más allá, podrías intentar dar formato a esta salida un poco más bien. No voy a pasar por eso contigo, pero si sientes que quieres aún más de un reto, ver si puedes imprimir cada línea solo para decir más verbosamente, ID de
usuario, lo que gastó tanto dinero y formatear el dinero en real formato monetario, signo de
dólar, algún punto entero dos puntos decimales, ¿verdad? Y eso no va a ser realmente un problema de chispas. Es más un problema de Scala. Pero si quieres ir más allá, Esa es una forma de hacerlo. Pero sí, eso es suficiente por ahora. Por lo que hemos aprendido acerca de los RDD. Rdds son la API original para Apache Spark, volviendo a Spark one, y aún tienen su lugar para muchos tipos de problemas. Pueden ofrecer el mejor rendimiento y la mayor flexibilidad y lo que puedes hacer. Pero es hora de seguir adelante. Entonces vamos a hablar de los dataframes y conjuntos de datos a continuación, porque esa es realmente la forma más moderna de hacer el código Spark. Y volveremos a visitar estos ejemplos, haciéndolos de nuevo utilizando conjuntos de datos en la siguiente sección.
21. Introducción a SparkSQL: Por lo que en nuestra siguiente sección estamos introduciendo Spark SQL. Y con ello vienen las API más modernas de Spark DataFrames y datasets en el mundo de Scala, nos vamos a centrar más en datasets porque eso es aún más eficiente. Entonces esta va a ser la interfaz más moderna para Spark. Y nos vamos a centrar en esto adelante en el curso. Se trata de una capa encima de Spark Core. Pero si puedes pensar en tus problemas en términos de un comando SQL, que la mayoría de los problemas de análisis de datos pueden ser Spark SQL y los dataframes y datasets ofrecen una
solución muy eficiente y fácil de usar para obtener las respuestas que deseas a través de un clúster entero. Entonces, sumémonos y veamos cómo funciona. Por lo que hablamos mucho de la interfaz RDD en Spark hasta ahora esa era la interfaz original y Spark en todo se construye encima de ella. En ocasiones sigue siendo útil volver a eso y realmente bajar a un nivel bajo para la mejor optimización para problemas más simples. Pero empezando con Spark to, realmente
empezaron a enfatizar la interfaz Spark SQL y Apache Spark en su lugar. Y Spark SQL trae a la tabla cosas como dataframes y datasets. Hablemos de esos. Por lo que DataFrames llegó primero. Extendieron RDD a un objeto de marco de datos. Y un DataFrame se parece mucho a una base de datos relacional. Contiene objetos de fila que contienen algún tipo de información estructurada. Tiene un esquema. Y de esa manera podemos almacenar las cosas de manera más eficiente. Y debido a que tenemos un esquema y estas filas, simplemente
podemos tratarlo como una base de datos SQL y ejecutar consultas SQL reales en nuestros DataFrames. Y debido a que se parece mucho a una base de datos real, se
puede tener mucha interoperabilidad con bases de datos y formatos de archivo relacionados con bases de datos. Para que puedas leer y escribir en formatos JSON o VIH o parquet. E incluso puedes comunicarte directamente a través de una interfaz JDBC u ODBC o usando Tableau. Por lo que en realidad podemos parecernos a una base de datos relacional, pesar de que es Apache Spark ejecutándose en un clúster. Bastante guay, ¿verdad? Y porque puede pensar en cosas en términos de consultas SQL, eso también trae a la mesa todo el mundo de las tecnologías de optimización de consultas, ¿verdad? Por lo que más allá de las habituales optimizaciones de gráficos acíclicos dirigidas que suceden con Spark, también
podemos ver tus consultas SQL reales que estás intentando emitir en un DataFrame y hacer lo mismo que son bases de datos
relacionales harían a optimizar esa consulta. Entonces, como tal, si estás haciendo las cosas de una forma SQL con un DataFrame, a veces
puedes obtener aún más optimización de la que lo harías con un RDD. Entonces salimos con conjuntos de datos y DataFrames y DataFrames son algo lo mismo. Técnicamente, un DataFrame es solo un conjunto de datos de objetos de fila. Entonces una fila es sólo una fila de cosas, ¿verdad? Entonces el punto importante aquí es que también se puede tener un conjunto de datos que envuelve ayuda y tipo
explícito y estructura explícita o inexplícita donde conocemos el esquema real por anticipado en tiempo de compilación. Por ejemplo, podría crear un conjunto de datos de una clase de caso de persona que defina exactamente cuáles son los campos que definen a una persona y cuáles son esos tipos. O podría crear un conjunto de datos que diga explícitamente que quiero una cadena y un doble en cada fila. Y al hacer eso, sabrá cuáles son esas columnas desde el principio. Entonces, a diferencia de un DataFrame donde todo lo que sé es que tengo un dataset de filas en esa fila. Fila podría contener cualquier cosa hasta que lo defina, una nariz de conjunto de datos por delante, ¿qué tipos hay dentro de ella? Y debido a eso, el conjunto de datos conoce su esquema en tiempo de compilar. Esto significa que los errores relacionados con el tipo se detectarán cuando
construya su script, a diferencia de cuando realmente ejecute el script. Y eso es enorme, ¿verdad? Porque ejecutar un script a menudo es una operación muy costosa cuando lo estás haciendo en un clúster grande. Entonces una gran ventaja de los conjuntos de datos es que vas a detectar esos errores relacionados con ese tipo en tiempo de compilación. Y eso hace que tu desarrollo sea un poco más fácil. También conduce a una mejor optimización. Eso significa que en realidad podemos hacer algo de optimización mientras estamos compilando en lugar de en tiempo de ejecución. Y eso también es un gran beneficio. Ahora la captura con los conjuntos de datos es que debido a que está haciendo todas estas cosas en tiempo de compilación, solo se pueden
usar realmente en lenguajes que se compilan. Eso significa Java o Scala en el mundo de Spark. Por lo que esta es otra razón para usar Scala en lugar de Python. Si no puedes, a pesar de que Python parece ser mucho más popular. Con Python, estamos limitados a DataFrames porque no
puede hacer esa optimización del tiempo de compilación. Entonces con Scala, sin embargo, podemos ser los chicos cool. Podemos usar conjuntos de datos y podemos saber cuáles son nuestros tipos por delante. Python, sin embargo, se va a limitar a DataFrames. Ahora, no tienes que entrar todo con conjuntos de datos si no quieres, en realidad
puedes convertir un RDD a un dataset con dos ds y puedes ir al revés también. Por lo que es posible tener lo mejor de ambos mundos y hacer algo de procesamiento usando RDD y hacer algún procesamiento posterior con datasets y hacer lo que tenga sentido. Como veremos, los RDD siguen siendo más útiles para algunas operaciones. Pero para SQL como consultas, obviamente vas a querer usar Conjuntos de datos. Conjuntos de datos realmente son la nueva picor. La tendencia general en el desarrollo de Spark es usar RDD menos y conjuntos de datos más. Y en realidad consigo algunos estudiantes que se
enojan de que hasta cubro los RDDs ahora, pero realmente sí tienen su lugar. Conjuntos de datos, quien sea a menudo más eficiente, se
pueden serializar de manera muy eficiente. Y debido a esos planes de ejecución que estaban determinando en tiempo de compilación, si estás haciendo una consulta SQL, eso a menudo puede ser mucho más eficiente, como dije, entonces solo usar un datasets RDD también permiten una mejor interoperabilidad, no sólo con formatos de archivo externos y bases de datos, sino también dentro de los diversos componentes de la propia Spark. Por lo que la biblioteca de Sparks Machine Learning y Spark Streaming Engine usan conjuntos de datos como su API principal en lugar de RDD ahora, así que si quieres mover tus datos entre estos diferentes componentes de Spark, vas a estar usando conjuntos de datos como ese tipo de forma de hacerlo dentro de Scala. Y también a veces usar un conjunto de datos realmente puede simplificar su desarrollo. Si solo estás haciendo operaciones SQL y puedes pensar en lo que estás tratando de hacer con tu análisis sobre Spark en términos de un comando SQL, vas a encontrar que es realmente,
realmente, muy fácil hacerlo con un conjunto de datos. En tanto que podría haber sido mucho más desafiante hacer eso con un RDD. Ahora, cuando estás usando Spark SQL, incluyendo conjuntos de datos dentro de Scala, aquí
hay alguna diferencia en la estructura de cómo te acercas a tus scripts. Y lo veremos con algunos ejemplos en breve. El principal es que vas a crear un objeto SparkSession en lugar de un contexto de Spark cuando estás iniciando tu script. Si vas a estar usando Spark SQL o conjuntos de datos, necesitas encender sesión. Piensa en eso como una sesión de base de datos. Y sí necesitas detener explícitamente esa sesión cuando termines. Ahora una vez que tengas esa sesión, en realidad
puedes obtener un SparkContext de ella y usarlo para emitir consultas SQL en tus conjuntos de datos. O simplemente puedes usar la API de Dataset up recta, un poco así. Entonces, una vez que sí tienes un objeto de conjunto de datos cargado, puedes hacer cosas como mostrar o seleccionar o filtrar o GroupBy. Y notarás que esto se parece mucho a comandos SQL, ¿verdad? Por lo que el formato debería parecer muy familiar. Si conoces SQL, por ejemplo, selecciona cotización algún nombre de campo que haga exactamente lo que crees que haría. En realidad selecciona la fila de nombre de campo algunos de su conjunto de datos y devuelve eso a un nuevo conjunto de datos. Filtrado. Esa es una sintaxis interesante ahí, ¿verdad? Por lo que en realidad podemos decir filtro con algún nombre de campo en mi conjunto de datos mayor a 200. Podemos poner esa expresión como parámetro dentro de nuestro comando de filtro y recuperar ocho. Es un conjunto de datos donde simplemente estamos filtrando cosas que son mayores a 200. Agrupar por, eso funciona igual que no SQL también. Por lo que en realidad podríamos agrupar todo en algún nombre de campo. Y eso va a ser lo mismo que una operación de reducción, ¿verdad? Y entonces podemos say.me para computar automáticamente el promedio de cada uno de esos resultados. Entonces en una línea ahí, creo que acabamos de hacer todo el ejercicio, uno de nuestros ejemplos anteriores usando RDD, ¿verdad? Entonces ese es un buen ejemplo de cómo las cosas pueden ser más simples. Y si sí necesitas hacer algo más de bajo nivel, aún puedes. Podrías convertir eso de nuevo a un RDD y pasar tu propia función de mapa personalizado si lo deseas también. Entonces como dije, puedes mezclar y emparejar aquí y obtener lo mejor de ambos mundos con datasets y RDDs. Los conjuntos de datos abren algunas otras posibilidades también. Como dije, no se puede hablar con nosotros, JDBC o ODBC. Entonces es posible abrir realmente un shell
para encender SQL y lidiar con él igual que es una base de datos, lo cual es algo impresionante, ¿verdad? Es decir, eso te da una especie de esta base de datos horizontalmente escalable, si quieres, a través de todo tu clúster de Spark. ¿ Qué tan guay es eso? Y algunos de los detalles aquí están listados aquí en la diapositiva si quieres más detalle, pero no quiero meterte demasiado el cerebro con esto porque no
vamos a estar haciendo esto en los ejercicios, pero solo sepan que es posible. También puedes tener funciones definidas por el usuario si quieres. En ocasiones esto será más fácil de hacer fuera de los conjuntos de datos, pero tú ahí, aquí si los necesitas. Entonces, por ejemplo, podríamos crear una función simple definida por el usuario solo importando org dot apache Spark dot SQL dot, dot UDF. Podríamos construir un UDF llamado cuadrado que solo contiene la expresión tomar x y hacerlo x veces x. Y entonces podríamos, por ejemplo, decir columna de ancho y agregar una nueva columna llamada cuadrado, que solo llama a eso funciones cuadradas definidas por el usuario. Por lo que también puedes hacer eso, igual que puedes tener UDF en bases de datos. También puedes tener UDF en conjuntos de datos. Por lo que esto tendrá mucho más sentido con algunos ejemplos. Entonces, solo sumémonos y pasemos el resto de esta sección mirando ejemplos prácticos. Por lo que vamos a volver a nuestros datos falsos de redes sociales que usamos antes en el curso con RDDs. Y te mostraré un par de formas de usar conjuntos de datos para explorar esos datos. Entonces primero lo consultaremos realmente con un comando SQL real, y luego volveremos atrás y usaremos funciones de la API del dataset para consultarlo sin usar comandos SQL reales. Pero el código aún se parecerá mucho a SQL. Y después de eso, volvamos a nuestros ejemplos de RDD y rehacerlos con conjuntos de datos y veremos cuáles son más simples ahora y cuáles son más complejos. Y habrá una buena manera de entender las fortalezas y debilidades tanto de los RDD como de los conjuntos de datos. Y puedes aprender sobre cómo elegir realmente qué API usar para un problema dado. Entonces, sumémonos con la siguiente conferencia y volvamos a nuestra red social falsa y juguemos con ella.
22. [Actividad] con SparkSQL: Así que juguemos con Spark SQL y Conjuntos de datos y DataFrames en realidad con este pequeño ejemplo simple aquí, abra el ejemplo de conjunto de datos Spark SQL en sus materiales aquí. Y pasemos por lo que está pasando en este. Por lo que vamos a volver a nuestra base de datos de amigos falsos o conjunto que se utilizó para nuestros amigos por ejemplo de edad de vuelta en la primera sección. Y vamos a consultar estos datos usando interfaces SQL SAL en su lugar usando Spark SQL. Por lo que declaramos un paquete es siempre n Ahora tenga en cuenta que
solo estamos incluyendo org dot apache, Spark dot SQL. Nos estamos limitando a las API de Spark SQL. Para este ejemplo, tenemos registro para J también. Estamos creando nuestro objeto y empezamos creando una clase de caso. ¿ De qué se trata todo eso? Entonces esta es una característica de Scala de la que no hemos hablado antes. Entonces una clase de caso es solo una forma muy compacta de definir una definición de clase y objeto, si se quiere. Entonces al decir persona de clase de caso, estamos diciendo que queremos definir un objeto de persona. Y contendrá los siguientes campos con los siguientes tipos. Entonces si estás familiarizado con como C plus, por ejemplo, es como declarar una estructura. Pero la sintaxis de aquí es un poco más compacta. Entonces estamos diciendo que una persona se compone de cuatro campos diferentes. Contiene un campo ID y este nombre es significativo, eso sí se mantiene bien. Y ese ID es un entero. Contiene un campo de nombre de tipo string y H campo de tipo entero, y el campo de tipo entero de un amigo también. ¿ De acuerdo? Y esto en realidad se utilizará para construir las tablas de base de datos virtuales que consultarán usando Spark SQL. Entonces cuando terminemos, esto corresponderá a los nombres de las columnas y
los tipos de columna en nuestra tabla tendrán una columna ID que contiene enteros, tendrá una columna de nombre que contiene cadenas y así sucesivamente y así sucesivamente. Entonces con esa sola línea, hemos definido el esquema de nuestros datos. De acuerdo, eso es muy importante. Con conjuntos de datos. Necesitamos tener ese esquema definido en tiempo de compilación. No podemos simplemente inferirla a partir de los datos mismos. Entonces con eso en la mano, entraremos en nuestra función principal. Establecemos nuestro nivel de registro. Y ahora en lugar de crear un SparkContext, estamos creando una sesión de Spark. De nuevo, se puede pensar en eso como similar a una sesión de base de datos. Entonces para crear esa sesión de chispa, decimos constructor de puntos SparkSession. Para crear nuestro, para construir realmente nuestra sesión. Le damos un nombre de app era Spark SQL. Decimos que nuestro maestro es estrella local, misma sintaxis exacta que antes, diciendo que vamos a ejecutar en su máquina local y voy a núcleos de
CPU y obtener o crear. Eso significa que en realidad podemos crear una nueva sesión de Spark o reutilizar una existente. Ahora recuerda que te dije que tienes que parar estas cosas cuando termines. Si nos saltamos un poco adelante aquí, vemos que sí decimos punto de chispa parada al final para cerrar esa sesión. Posible que estas sesiones sigan funcionando más allá de la vida útil de este script de controlador. Entonces si no lo detuviste explícitamente, o se detiene inesperadamente, esa sesión aún podría estar ejecutándose en tu clúster y conseguir nuestra caja
simplemente reutilizaría esa sesión existente en lugar de crear una nueva en ese caso. Cosas tan interesantes. Ahora carguemos nuestros datos. Entonces recuerda que nuestros datos existen en falsos amigos dot CSV. Y sólo vamos a cargar eso usando Spark dot read. Entonces Spark dot read en el objeto SparkSession leerá ese archivo CSV. Vamos a decirle que tiene una fila de encabezado. Y te vamos a pedir que en un principio deduzca el esquema a partir de lo que hay en esa fila de encabezado. Por lo que la información de fila de encabezado coincide con los mismos nombres que dimos en nuestra clase de casos aquí arriba, el encabezado es id, nombre, edad, y amigos. Y es importante que, eso coincida en este caso. Entonces en este punto, después de decir spark dot read.csv, tenemos un DataFrame. En este punto el esquema se ha inferido en tiempo de ejecución, ¿verdad? Esa es la principal diferencia entre un marco de datos y un conjunto de datos. Pero aún queremos usar conjuntos de datos. Queremos todos los beneficios de esa comprobación de tipo de tiempo de compilación. Entonces voy a tomar ese DataFrame que solo consiste en estos objetos de fila con esquemas inferidos y convertirlo en un dataset con un esquema explícito diciendo punto como persona. Entonces ese punto como persona toma ese DataFrame que leemos del CSV y lo convierte un dataset con un esquema que conocemos en tiempo de
compilación usando la clase de caso de persona conmigo hasta ahora. De acuerdo, tendrá más sentido cuando lo ejecutemos. Lo primero que vamos a hacer es imprimir ese esquema para asegurarnos de que sea lo que esperábamos. Entonces en este punto tenemos un conjunto de datos de personas esquema. Y ahora podemos crear una vista de base de datos en ella diciendo crear o reemplazar vista temporal. Nuevamente, eso o bien creará uno nuevo o reemplazará uno existente con el mismo nombre. Y vamos a llamar a eso pocas personas. Esto tendrá el efecto de crear básicamente una tabla de base de datos llamada personas para todos los efectos y propósitos. Y podemos consultar esa tabla ahora solo diciendo Spark dot SQL. Estamos llamando al SparkSession dot SQL con un comando SQL real aquí. Vamos a decir estrella selecta de la gente. Esa es la opinión que creamos a partir de nuestro conjunto de datos. Cuando la edad sea mayor o igual a 13 años y la edad sea menor o igual a 19. Entonces estamos creando aquí una declaración SQL real y devolviendo los resultados en una nueva estructura llamada adolescentes, un nuevo conjunto de datos. Después recolectaremos el contenido de esos resultados e iteraremos a través de ellos, imprimiéndolos todos, y detendremos la sesión cuando hayamos terminado. Entonces sigamos adelante y corremos eso y veamos qué pasa. Genial, funcionó. Entonces podemos ver ese esquema inferido aquí, en realidad el esquema explícito que le dimos para el conjunto de datos, ¿verdad? Por lo que podemos confirmar que tenemos un campo id, nombre, edad, y amigos de los tipos que esperamos entero, entero de
cadena, y un entero. Entonces ese es el esquema de nuestro
conjunto de datos de personas de esquema que configuramos ahí y leemos desde ese archivo CSV. Y entonces tenemos los resultados de nuestra consulta aquí. Y vemos que aquí tenemos a todos los adolescentes en nuestro conjunto de datos. Se trata de jóvenes de 19 años y 18 años, y supongo que solo generaron datos a partir de los 18 años en adelante. Entonces ese es el resultado de nuestra consulta ahí. Parece que funcionó. Bastante impresionante. Por lo que en realidad ejecutamos un comando SQL real en un conjunto de datos en Apache Spark a través de todo un clúster potencialmente. Entonces qué genial es que tengas todo el poder
del lenguaje SQL a tu disposición con Apache Spark usando conjuntos de datos. Y sí quiero hacer un punto más aquí antes de seguir adelante. Entonces no tuve que usar un conjunto de datos aquí. Podría haber usado un DataFrame. Déjame mostrarte cómo funcionaría eso. Entonces si acabo de comentar esta línea, en este punto, mi gente de esquema va a ser un DataFrame. Va a tener ese esquema inferido en tiempo de ejecución. No lo estoy diciendo explícitamente con esa clase de caso cuál es el esquema. Entonces al comentar eso, estoy perdiendo todas las comprobaciones de errores en tiempo de
compilación y optimizaciones en tiempo de compilación que obtendré con los conjuntos de datos. Pero seguirá funcionando. Simplemente funcionará en tiempo de ejecución. Entonces sigamos adelante y corremos eso y asegurémonos de que no te estoy diciendo una mentira. Y se puede ver aquí que obtuvimos la misma respuesta. Entonces aquí la misma consulta resulta de 18, 19 años de edad que queríamos, y los esquemas siguen igual también. Por lo que todo sigue funcionando como DataFrame. Es solo que al usar un conjunto de datos y darle ese esquema explícito, sí
obtenemos un mejor rendimiento y una mejor comprobación de errores en tiempo de compilación. Vamos a sumergirnos en otro ejemplo a continuación.
23. [Actividad] utilizando DataSets: Por lo que en nuestra conferencia anterior, hablamos de usar comandos SQL directamente en nuestros falsos amigos y datos de nuestra red social falsa. Echemos un vistazo a otra forma de hacerlo sin usar realmente comandos SQL, pero en lugar de usar las funciones similares a SQL disponibles en los conjuntos de datos. Entonces echa un vistazo a esta forma alternativa de hacer las cosas. Abra el dataset DataFrames, script de controlador. Y echemos un vistazo a esto. Por lo que la configuración y carga real de nuestros datos va a ser idéntica desde la última vez, vamos a volver a configurar una clase de caso de persona que defina el esquema de los datos que pretendemos cargar. Y de nuevo, tenemos un ID que es un entero, un nombre que es una cadena, y la edad que, eso es un entero. El número de amigos que también es un entero. Dentro de nuestra función principal. Al igual que antes de establecer nuestro nivel de registro, creamos aquí un objeto SparkSession con un nombre
y maestro dados y lo obtenemos o lo creamos. Y luego de nuevo, lo leemos desde el archivo CSV usando Spark dot read. Y en realidad forzamos que sea un conjunto de datos al decir punto como persona al final para convertir ese esquema implícitamente definido en tiempo de ejecución a un esquema codificado forzándolo a la clase de caso de persona aquí. Por lo que tipo de glosé sobre esto inicialmente, el punto de chispa de importación implícita línea de subrayado de punto es importante en cualquier momento que tengas inteligente inferyendo implícitamente el esquema, debes asegurarte de que estás importando ese paquete justo antes tú lo haces. La sintaxis aquí es un poco rara. Normalmente sus declaraciones de importación estarían en la parte superior de su archivo. Pero en este caso lo queremos justo antes de que realmente
lo vamos a usar porque sólo queremos aplicar a este ámbito específico aquí. Entonces en cualquier momento tienes un comando de que somos los esquemas que se infieren. Y aquí es bastante explícito que estamos haciendo eso mientras que decir chispa dot read para usar el encabezado en el archivo CSV. Y estamos inferyendo el esquema inicialmente a partir de ese encabezado CSV, necesitamos implícitos desatados para poder realmente sacar eso. Ahora cuando terminemos, estamos,
estamos convirtiendo eso en un conjunto de datos con un esquema explícito. Pero ese paso intermedio requiere implícitos de punto de chispa. Hay otras formas de cargar conjuntos de datos que veremos más adelante que no requieren ese paso intermedio de un esquema inferido, pero llegaremos allí. De todos modos, imprimimos ese esquema como lo hicimos antes. Y ahora tenemos una forma diferente de jugar con nuestros datos aquí que estamos viendo. Entonces esto es lo nuevo ahora. Entonces, empecemos seleccionando sólo la columna de nombre. Una cosa que hicimos en nuestros ejemplos de RDD, así que eso fue bastante común, fue descartar columnas de información que no necesitábamos. Y esta es una forma de hacerlo usando conjuntos de datos. Podemos decir gente dot select, name dot show, y eso sólo seleccionaría la columna de nombre y nada más. En este caso, no vamos a asignar eso a un nuevo conjunto de datos. Solo vamos a llamar a dot show para realmente forzar a Spark a salir y obtener ese resultado y en realidad mostrárnoslo desde nuestro guión de conductor. Entonces así como podrías decir seleccionar nombre, estamos diciendo aquí, seleccionar nombre entre comillas aquí en lugar de un comando SQL, Sintaxis similar, misma idea, solo una forma diferente de hacerlo que no requiere una vista de base de datos real para hacerlo. También podemos hacer algo parecido a nuestros amigos por ejemplo de edad, donde solo vamos a filtrar a cualquier persona mayor de 21 años. Por lo que podríamos decir People dot filter, gente envejece menos de 21 puntos show. Entonces eso es lo mismo que decir select name donde la edad es menor a 21 y SQL, pero lo estamos haciendo de manera más explícita a través de funciones en el propio conjunto de datos. Entonces esto es un poco raro, ¿verdad? Ya sabes, si estás acostumbrado, otros idiomas son idiomas no funcionales. La idea de tener una expresión como esta, las personas envejecen menos de 21 años y pasar eso como parámetro a una función podría parecer extraña. Pero en Scala, puedes hacer eso. En realidad funciona. Entonces es bastante guay. Entonces solo decimos gente y pasamos en nombre de la columna que queremos filtrar en menos de 21. Y esa expresión al pasar por la función de filtro de un conjunto de datos, solo funciona. Hace lo correcto. Es casi mágico. Nuevamente, mostraremos los resultados, los mostraremos, a diferencia de almacenar eso en un nuevo conjunto de datos en nuestro ejemplo aquí. También en SQL, tenemos el grupo por función. Y esto es básicamente lo mismo que la operación GroupByKey que teníamos en RDD. Por lo que va a agrupar todos los valores distintos de las edades y enloquecerlos a todos juntos. Y entonces además llamaremos a contar con eso para solo conseguir un gran total de cuántas personas existen en cada edad, año y mostrar los resultados en una línea aquí hemos hecho algo que tuvimos que hacer un poco más enrevesado usando RDDs, ¿verdad? Si recuerdas, habríamos tenido que transformar las cosas con una operación de mapa para que me gustara insertar un número uno para cada persona individual y luego hacer una operación ReduceByKey para agregarlas todas para hacer esto antes. Pero en este caso, podemos usar más de un tipo SQL de sintaxis aquí y hacerlo todo en una sola línea de código. Para que aquí se puede ver el poder de los conjuntos de datos. Y además, ya que estamos usando conjuntos de datos, también puede ser más eficiente. Entonces, sí, solo piensa un poco más en esto. Nos vamos a agrupar por edad. Por lo que básicamente combina todas las entradas en personas por números AGE únicos. Contamos cada uno dentro de cada edad y mostramos los resultados. Y aquí hay otro ejemplo interesante aquí. En este caso, vamos a seleccionar a toda la gente. Y sólo vamos a seleccionar la columna de nombre. Y luego también vamos a seleccionar personas mayores de 10 años. Por lo que esto va a mostrar una exhibición de dos columnas. Una es la columna de nombre del conjunto de datos de personas original. Y la segunda columna que mostrará que estamos seleccionando aquí va a ser la columna de edad con 10 actitud lo. Entonces de nuevo, podemos tener estas expresiones dentro de funciones cuando en Scala, y en realidad funciona. Podemos decir que las personas envejecen más 10 y pasen eso como parámetro a la función selecta. Es un poco raro si estás acostumbrado a otros idiomas de nuevo, pero así es como lo haces en Scala y chispas, en realidad funciona. Y recuerda siempre detener tu sesión cuando termines. De lo contrario, seguirá corriendo y dando vueltas y usando recursos que no quieres estar usando. Y podría confundirte cuando estás ejecutando cosas en carreras posteriores también. Nunca olvides detener tu sesión cuando hayas terminado. Entonces sigamos adelante y veamos esto en acción y convencernos de que realmente funciona. Haremos clic con el botón derecho en DataFrames, Conjuntos de datos y digamos correr , va. Está bien, y pasemos por lo que pasó aquí. Subamos a la parte superior aquí voy a desplazarme hacia arriba. Lo primero que hicimos fue imprimir el esquema de manera directa, y ahí está. Por lo que podemos convencernos de que
en realidad sí consiguió la estructura de conjunto de datos correcta allí. mí me parece bien. Por lo que estamos inferyendo un nombre ID, edad y columna de amigos de tipos entero, cadena, entero, y entero respectivamente. Nuestro primer paso aquí con la selección de la columna de nombre. Y ahí estaba este comando aquí, gente dot select col igual nombre dot show. Y hizo exactamente lo que esperabas. Y se parece mucho a que esperarías ver de una salida real de base de datos relacional, ¿no? Ya sabes, lo son, realmente están tratando de cerrar la brecha entre Spark y usar una base de datos relacional y haciéndola de la misma manera usarlo con Apache Spark y son versiones más nuevas. La diferencia, por supuesto, es que en lugar de un único servidor de base de datos monolítico, tiene un clúster completo haciendo esto potencialmente. Por lo que se puede ver que seleccionamos con éxito la columna de nombre y la mostramos. Por lo que tenemos este pequeño adelanto de las primeras entradas. Solo mostramos las 20 primeras filas por defecto, o de lo contrario, simplemente seguiría para siempre. Y nuestro siguiente experimento aquí fue filtrar a cualquier persona mayor de 21 años al pasar en este argumento filtrante de personas menores de 21 años. Y bastante seguro, los datos resultantes que obtuvimos de vuelta sólo mostrando a las personas que tienen edades de 19 o 20 ó 18 años, porque esas son todas las personas menores de 21 años en nuestro conjunto de datos. Por lo que ese trabajo a muy cool. Y también intentamos ese comando grupo por edad aquí otra vez, un poco más de fantasía aquí. Entonces de nuevo para recapitular, agrupamos a todos por números únicos de AGE y los
contábamos todos y los mostramos y parece que funcionó. Por lo que tenemos 831 años, 565 años, 753 años, etcétera, dentro de nuestro conjunto de datos. Entonces otra vez, una línea de código, muy simple, muy fácil de usar. Están altamente optimizados. Y es mucho más sencillo que la forma en que teníamos que hacer esto usando RDD. Por último, hicimos esto, hacemos que todos 10 años más viejo truco aquí donde seleccionamos la columna de nombres y también inventamos una nueva columna que se llama gente edad más 10. Entonces, veamos si eso funcionó. Y sí, se veía así que presumiblemente era originalmente 33, pero en la columna de edad más 10 que creamos aquí, ahora
tiene 43. Y en realidad funciona. Se puede pasar en expresiones matemáticas como esa y en
realidad se les evaluarán y se mostrarán de esta manera. Cuando terminamos, detenemos la sesión, y eso fue todo. Entonces ahí lo tienes. Conjuntos de datos que utilizan funciones en lugar de comandos SQL reales. Puedes hacerlo de cualquier manera, pero, sabes, depende de tu preferencia. Entonces ahí lo tienes. Dos formas diferentes de usar conjuntos de datos.
24. [Ejercicio] Implementar el ejemplo de "Amigos por la edad" utilizando DataSets: Está bien, ya me has escuchado hablar de conjuntos de datos el tiempo suficiente. Creo que es hora de ensuciarse las manos y tratar de usarlas ustedes mismos. Entonces déjame darte tu primer reto usando conjuntos de datos. ¿ Recuerdas a los amigos por ejemplo de edad que hicimos con RDDs? Bueno, quería volver allí y hacerlo de nuevo,
pero esta vez usando conjuntos de datos en lugar de RDD. Entonces solo para revisar de qué se trata ese ejemplo, hemos proporcionado un archivo de
valores separados por comas de amigos falsos que contiene datos en este formato. Es básicamente un ID de usuario, su nombre, su edad, y el número de amigos que tienen. Y tu tarea es darme el promedio de amigos por edad. Por lo que quiero saber en promedio, cuántos amigos como un joven de 33 años tienen, muchos amigos es un 55 años tienen y así sucesivamente y así sucesivamente por cada edad representada en mis falsos amigos dot archivo CSV. Y se llama falsos amigos porque todo son datos falsos. Todo se generó al azar. Entonces no son como, no
estoy haciendo un juicio de valor a tus amigos de aquí. En fin, algunas pistas sobre cómo superar esto. Por lo que hay un archivo csv de punto de amigos falsos en los materiales de tu curso que contiene una fila de encabezado. Y como has visto en nuestros ejemplos anteriores, uso de conjuntos de datos que va a ser importante para permitir vieira y chispa para el esquema correcto para esos datos. Y aquí algunos comandos que podrían ser de utilidad. Recuerde, podemos usar el comando select para extraer columnas
dadas de un conjunto de datos y obtener uno nuevo que solo tenga los datos que necesitamos. Podrían recordar que cuando hicimos esto con RDD, teníamos una función de mapa que realmente hizo eso por nosotros. Entonces esto va a ser mucho más sencillo usando una declaración selecta. Y necesitarás alguna otra función de conjunto de datos. Por lo que GroupBy hemos mirado antes que básicamente agregará cosas por edades únicas, algo así como una operación de reducción. Show mostrará los resultados finales y los recuperará. Y cuando no hablamos de AVG era de promedio. Entonces después de agrupar las cosas por edades, entonces
querrás obtener el promedio por edad. Y así siempre veo los nombres de las columnas que pongo aquí con fines ilustrativos, toca a ti poner ahí los correctos y ponerlos en el orden correcto y lo que no. Pero esas son las piezas que debes necesitar para hacer esto. Y es posible que desee volver al archivo de punto
de datos DataFrames DataFrames para obtener inspiración. Y tampoco tienes que hacerlo así. Podrías usar un comando SQL directo si también quieres. Entonces depende de ti en qué dirección quieres ir. Entonces ve y dale una oportunidad a eso. Y cuando volvamos a la siguiente conferencia, te
mostraré mi solución al mismo y también algunas formas de expandirlo para hacer algunas cosas más interesantes con esos datos también. Entonces ve a darle una oportunidad y a ver si puedes conseguir que funcione eso y luego regresa y te mostraré mi solución. No mires la solución. Está ahí y por supuesto materiales, así que asegúrate de crear un nuevo archivo que tenga algún nombre único y resistir la tentación de pico chicos y volver y repasaremos la respuesta.
25. Solución de ejercicio: amigos por la edad, con datasets.: Vale, Así que espero que hayas podido superar ese ejercicio e implementar la actividad de amigos por H usando conjuntos de datos sin demasiados problemas. Si quieres comparar tu acercamiento al mío. Aquí está mi solución. Si abres los amigos por edad script conjunto de datos aquí en los materiales del curso. Y de nuevo, hay muchas formas de hacer esto. Entonces si tu código no coincide exactamente con el mío, Eso está bien. Todo lo que realmente importa es que obtienes los mismos resultados finales. Así que spot checa algunos de los resultados promedio que obtuviste para diferentes edades y si coinciden con los míos, Estás bien. Entonces pasemos por lo que hice aquí. Por lo que mucho de esto se verá familiar. Creamos una clase de casos llamada Fake Friends en este caso en lugar de persona solo para mezclar un poco las cosas. Esto define el esquema explícito de nuestros datos procedentes del archivo CSV de punto de amigos falsos, cual consiste en un ID y nombre, edad y amigos. Ya hemos visto esto antes, sólo un nombre diferente. Lo primero que hacemos es establecer nuestro nivel de registro, crear una SparkSession, igual que antes. Y como lo hacíamos antes, cargamos la tira de datos de falsos amigos dot archivo
CSV usando esquema inferido del encabezado. Y luego forzamos a ese DataFrame a un conjunto de datos diciendo punto S y pasando, en ese caso clase amigos falsos para definir explícitamente cuál es su esquema. Ahora podemos en tiempo de compilación comprobar todos los tipos y qué no y hacer algunas optimizaciones en tiempo de compilación también. De acuerdo, entonces lo primero que hacemos es ir y seleccionar solo las columnas que necesitamos. Entonces como recordarán, las únicas cosas que realmente nos importan en este ejemplo son la edad y el número de amigos, los identificadores de usuario y los nombres son irrelevantes para este problema. Por lo que sólo vamos a seleccionar de ese conjunto de datos, las columnas de edad y amigos, y pasar eso a un nuevo conjunto de datos llamado Amigos por edad. Y ahora todo lo que tenemos que hacer es decir amigos por edad punto groupby sobre edad. Entonces eso va a agrupar todo por valores de edad únicos. Y luego una vez que tengamos eso, además
diremos dot AVG para obtener el promedio las columnas de
amigos agrupadas por edad y luego dot show para mostrar los resultados. Y eso es todo. En realidad estaríamos hechos en este punto. Hay algunos trucos más que quiero mostrarte aquí, así que hay más de que hablar. Pero para el reto como se afirma, eso es todo lo que necesitas. Entonces eso es bastante guay, ¿verdad? En dos líneas de código, básicamente hicimos lo que hicimos en todo
el ejemplo usando RDD antes. Volvamos atrás y miremos eso sólo con fines de comparación. Entonces aquí están los amigos por edad dot Scala script donde hicimos esto usando RDDs. Y verás que aquí es mucho más complicado. Entonces aquí atrás tuvimos que escribir esta función de línea de análisis para ir y analizar todo y dividir las cosas por comas y extraer los campos que queremos y devolver una nueva tupla. Eso es lo que los campos que queremos. tanto que con los conjuntos de datos, sólo podemos usar el cargador CSV que está integrado en nuestra sesión de Spark. Y utiliza la sentencia select para seleccionar los campos que queremos. Mucho más simple usando conjuntos de datos. Entonces usando RDD, tuvimos que hacer todo tipo de cosas
complicadas para computar ese promedio, ¿verdad? Teníamos que ir a mapear las cosas a x coma uno aquí. Por lo que solo podemos contar todo usando ReduceByKey. Y es una forma bastante retorcida de hacer lo que hicimos solo usando aquí en el ejemplo del conjunto de datos, agrupar por un promedio. Y después de eso ReduceByKey, tuvimos que computar el promedio a mano también mediante el uso de MapValues. Entonces este código, creo que tiene mucho más sentido. Es mucho más fácil de leer. Es mucho más sencillo. A diferencia de lo que teníamos que hacer aquí usando RDD para hacer lo mismo. Entonces ese es un buen ejemplo de donde los conjuntos de datos pueden ser mucho más fáciles de usar e incluso podría ser más rápido. Pero bajo el
capó, son RDDs a un nivel más bajo. Y así que a veces es bueno ir a ese nivel inferior si
realmente necesitas ajustar las cosas a ese nivel, sigamos adelante y llevemos esto al siguiente paso. Entonces, ¿y si quisiera ordenar esos datos? Resulta que eso también es fácil. Si quisiera ordenar estas cosas por edad, solo
podría meter un comando de clasificación de puntos ahí antes del show. Y eso tomará los resultados de mis promedios
por edad y sólo ordenarlos por la columna de edad antes de mostrarlo. Y además, podría formatear eso más bien. Nuestros promedios a veces tendrán muchos decimales para ellos y no tiene sentido tener tanta precisión. Podría decir AGG y luego promedio redondo. Esto requiere un poco de tener la cabeza alrededor. Entonces tenemos el promedio del número de amigos aquí que hicimos antes. Y entonces estamos diciendo que vamos a redondear eso a dos decimales de precisión. Entonces así funciona ahí el comando redondo. Y tenemos que usar esta función AGG porque estamos agregando todos los datos para esa edad dada por la que agrupamos, ¿no? Entonces agonías, vamos a computar ese promedio a través del agregado de todos los valores para esa edad que ahí seleccionamos. Después de que se haga ese redondeo, nuevamente
ordenamos los resultados por edad y los mostramos. Y también podemos personalizar nuestros nombres de columnas también. Y eso es lo que está haciendo este ejemplo de aquí. Entonces aquí estamos agregando un alias después de ese agregado de redondear todo. Y vamos a renombrar eso a amigos subrayan promedio. Y luego otra vez, lo ordenamos y lo mostramos. Entonces volvamos a caminar por esto. Después de ver la salida, podría tener un poco más de sentido. Vamos a hacer clic con el botón derecho en amigos por edad conjunto de datos y ejecutarlo. Y aquí vamos. De acuerdo, así que recorremos cada conjunto de resultados aquí desde arriba, desplácese hasta el principio aquí. De acuerdo, entonces nuestro primer ejemplo fue el simple donde
acabamos de hacer un grupo por edad y luego promedio de amigos y lo mostramos. Y eso funciona. Por lo que el grupo por edad agruparon todo por edades únicas, luego promediar la computadora de un amigo, el promedio de la columna de amigos para cada edad. Es sólo así de fácil y de hecho esto sí funciona. No obstante, notarás que los bordes no están ordenados, por lo que es un poco difícil buscar las cosas y obtener una respuesta específica de ello. También, la pantalla Aquí está un poco raro, ¿verdad? Tenemos todas estas locas cantidades de precisión en los promedios que probablemente no sean necesarias. Entonces en nuestro siguiente ejemplo, resolvemos el problema de clasificación. Todo lo que hicimos aquí fue agregar un tipo de puntos con un parámetro de edad allá al, a la mezcla ahí al final. Y eso sí funcionó. Entonces vemos que ahora las edades están ordenadas. Empezamos con 18, 19, 20, 21, etc. Y eso parece haber funcionado también. Y además, podemos hacerlo aún más bien. Entonces si bajamos a este tercer ejemplo aquí, en este, estamos redondeando los resultados a dos decimales de precisión aplicando una función redonda al promedio y usando Ag para aplicarlo a todos los resultados de edad para ese grupo. Entonces aquí tenemos la edad y la expresión ronda promedio amigos coma dos, que está redondeando ese promedio a dos decimales de precisión. Y se puede ver que en realidad funciona como se pretendía. Muy cool. Y por último, le dimos a eso un nombre de columna personalizado mediante el uso del comando alias dentro de ese agregado también. Entonces al decir alias de punto, cambiamos el nombre de esa columna de amigos promedio
redondo coma dos a algo más útil, los amigos subrayan promedio. Y si dijeras esto en un conjunto de datos resultante, eso haría más fácil referirse a esa nueva columna que calculamos por su nombre sin tener que escribir esos enormes resultados complicados. Entonces, cuando estás encadenando conjuntos de datos juntos de esa manera eso suele ser muy útil para tener una manera más fácil de referirse a esos resultados calculados en esa columna. Y ahí lo tienes en datasets con nuestros amigos por ejemplo de edad, hecho algunas maneras diferentes y extendido de algunas maneras diferentes para hacerlo, espero que hayas aprendido algunas cosas ahí. Pasemos a algunos ejemplos más y nos familiaricemos aún más con los conjuntos de datos.
26. [Actividad] ejemplo de contar Word con datos: Entonces sigamos aprendiendo sobre los conjuntos de datos a través de ejemplos. Y de nuevo, volveremos a nuestros ejemplos de RDD y adaptaremos nuestro ejercicio de
conteo de palabras para usar conjuntos de datos en lugar de RDD. Y iremos directamente a la versión más complicada que en realidad utiliza expresiones regulares y ordena los resultados. Ahora en este ejemplo, estaremos usando funciones SQL para lograr los resultados que queremos. Entonces en lugar de usar FlatMap, vamos a usar una función llamada explode que explotará columnas en filas. Entonces si cada columna representa una palabra explotable, pon cada palabra en su propia fila. Usaremos la función dividida para dividir las cosas por palabra. Utilizaremos la función inferior con el fin de convertir todo en minúsculas. Y unas cuantas notas aquí sobre sintaxis a tener en cuenta. Entonces cuando estás pasando un nombre de columna como parámetro en estas funciones SQL, la sintaxis es signo de dólar y luego el nombre de columna entre comillas. Entonces, por ejemplo, la coma del valor de la cita de signo de dólar dividido, y luego la expresión regular se dividiría cualquier texto que esté en la columna de valores basada en los delimitadores de palabras allí. De igual manera, filtro funcionaría de la misma manera si quisiéramos filtrar para eliminar cualquier palabra que tenga una cadena vacía, lo haríamos de esta manera. Filtra signo de dólar, y luego palabra entre comillas. Y ten en cuenta los extraños operadores de igualdad aquí cuando estás usando declaraciones de filtros aquí, no
va a ser un signo bancario igual, va a ser igual, bang sine igual. Tan poquito de una cosa rara. De igual manera operador de desigualdad aquí sería igual, igual, igual. Entonces solo algo para recordar, obtendrás un error en el compilador si no lo haces bien. Entonces eso te recordará si hay un problema, pero una especie de cosa extraña y peculiar ahí. Entonces, de nuevo, ese es un ejemplo de solo probar dónde es contra una cadena vacía, solo dos comillas sin nada entre ellas. Ahora bien, vale la pena señalar que los conjuntos de datos realmente funcionan mejor con datos estructurados. Y cuando sólo estamos tratando con líneas de textos, eso no es realmente datos estructurados. Así que estás ajustando una clavija cuadrada en un agujero redondo aquí mediante el uso de conjuntos de datos. En cierta medida. A veces los RDD son más simples y esto podría ser uno de esos, pero no solo tienes que usar conjuntos de datos o RDD. Podrás usarlos a ambos juntos y hablaremos más de eso en un segundo. Otra cosa a notar sin embargo, es que algo más Es raro usar conjuntos de datos en este sentido es que debido a que no tenemos datos estructurados entrando, tampoco
tenemos un esquema entrando. Por lo que el esquema que termina por inferirse es algo arbitrario. Acabamos con un DataFrame lleno de objetos de fila con una columna denominada valor por defecto para cada línea de texto porque no hay esquema. Cada, cada fila es sólo una línea de texto. Por lo que hay un nombre predeterminado para esa columna llamado valor que solo un poco tienes que saber. Y así nos referiremos a esos datos adelante en el guión. Pero de nuevo, puedes usar ambos y veremos una forma de hacerlo también. Entonces recuerda, puedes convertir RDD dos conjuntos de datos. Y así a veces tiene sentido revelar su carga, sus datos utilizando las interfaces RDD y luego convertirlos en un conjunto de datos para facilitar el procesamiento posterior más adelante. Entonces intentaremos eso también. Vamos a sumergirnos y ver cómo se ve. Así que abramos el recuento de palabras, mejor script de conjunto de datos surtido aquí y recorremos lo que está pasando aquí. Entonces vamos a hacer esto un par de maneras diferentes aquí. Empecemos como siempre hacemos solo importando todas las cosas que necesitamos, declarando nuestro paquete, declarando un objeto. Esta vez vamos a tener una clase de caso muy simple para cargar nuestro conjunto de datos inicial. Simplemente lo llamaremos libro. Y el único dato que tiene es una cadena que vamos a tener que llamar valor. Recuerda, volveremos a eso más adelante en cuanto a por qué eso tiene que nombrarse valor. Vamos a nuestra función principal, establecer el nivel de registro, crear una sesión de Spark igual que antes. Y de nuevo, vamos a importar inicialmente esto como DataFrame mediante el uso de readme.txt con texto de punto de libro de datos. Y para poder descifrar implícitamente ese esquema, necesitamos importar implícitos de punto chispa para hacerlo a nivel DataFrame. Entonces llamamos al punto como libro para forzar eso en un conjunto de datos que tenga un esquema definido que podamos conocer en tiempo de compilación. Lo que es raro aquí es que cuando inferimos ese esquema implícitamente con el DataFrame, no
había ningún esquema proporcionado. Entonces todo lo que sabemos es que tenemos líneas de texto entrando a través del texto de puntos de Spark. Y por defecto, cada fila de texto se va a llamar valor. Ese es el nombre de esa columna que tenemos. Y sólo tenemos que saber eso. Entonces, para que ese conjunto de datos coincida con el esquema de DataFrame inferido, necesitamos nombrar ese valor de línea. De acuerdo, Entonces no sólo escogimos ese nombre arbitrariamente. Si fuera otra cosa que el valor, esta línea no funcionaría. Entonces, de nuevo, nos estamos metiendo en cómo usar conjuntos de datos puede ser un poco torpe en algunas situaciones en no
estás tratando con fuentes de datos estructuradas reales vienen de una base de datos o algún formato de base de datos. Pero una vez que hayamos hecho esto, sólo
vamos a seguir adelante. Entonces ahora vamos a dividir eso usando una expresión regular como lo hicimos antes con el operador split, estamos usando RDD. Y luego en lugar de usar FlatMap para soplar eso en filas individuales para cada palabra, vamos a usar la función explode. Por lo tanto, mira esto con más cuidado. Vamos a decir input, que es nuestro conjunto de datos de entrada que contiene una fila de texto en cada línea. Y diremos seleccionar, explotar, dividir valor con un patrón de expresión regular para dividir las cosas en palabras individuales. De acuerdo, así que empecemos por el medio aquí. Por lo que empezamos diciendo dividir la columna de valor. Y de nuevo, ese es solo el nombre que asignamos automáticamente a esa columna de texto que hemos basado en la palabra delimitador. Entonces en este punto vamos a tener una serie de palabras. Vamos a llamar a explotar en eso para luego
dividirlo en una serie de filas individuales para cada palabra. Y luego además, le daremos a eso un alias llamado palabra porque lo contrario sería esta gran descripción enrevesada de esa columna que generamos. Entonces en este punto deberíamos tener un nuevo conjunto de datos que tenga una columna de palabras donde cada palabra esté en su propia fila. Ahora además, resulta que terminamos con un montón de cadenas vacías cuando lo hacemos de esta manera, y queremos filtrar esas para que no tengamos esta gran entrada en nuestros resultados finales sobre que las cadenas vacías son realmente comunes. Entonces para hacer eso, solo vamos a decir filtro de puntos. Y vamos a filtrar para donde la columna de palabras no es igual a una cadena vacía, solo dos comillas sin nada entre ellas. Entonces de nuevo, anote la sintaxis aquí, signo de
dólar y luego el nombre de la columna entre comillas. Y en este punto ya habíamos dado un alias a esa nueva columna de palabras llamada palabra, lo que podemos referirnos a ella por la palabra de nombre en la operación de filtro que viene después de ella. De acuerdo, así que ahora tenemos un nuevo conjunto de datos de palabras que tiene palabras individuales en cada fila. Hemos filtrado todas las palabras vacías. A continuación, vamos a convertir eso en minúsculas. Y de nuevo vamos a decir words.py seleccionar pasando en nuestra función inferior. Y vamos a aplicar esa función inferior a la columna de palabras. Y volveremos a darle a esto un nuevo alias y quedaremos con la palabra del nombre. Simplemente vamos a convertir eso en minúsculas en su lugar. A continuación, contaremos las ocurrencias de cada palabra usando el grupo por operador, y luego contaremos. Por lo que groupby juntará todas las palabras únicas juntas y luego contará, ¿contará esto todas las ocurrencias de cada una? Entonces ahora tenemos un nuevo conjunto de datos de conteos de palabras que contiene un recuento de cada palabra individual. Ya casi terminamos. Ahora solo necesitamos ordenar los resultados por la columna de conteo y mostrarlos. Y tenga en cuenta la sintaxis aquí. Entonces, ¿qué está pasando aquí exactamente cuando decimos show word count, ordenada dot count, dot t2 int, solo
estamos asegurándonos de que el comando show muestre aquí el conjunto completo de resultados. Por defecto, solo mostrará las primeras 20 filas. Queremos mostrar todos los resultados. Entonces la forma en que funciona este espectáculo es que le pases el número de filas que quieres mostrar. Y queremos todo el asunto. Entonces vamos a llamar a conteos de palabras ordenados conteo de puntos para obtener el recuento de cuántas filas están en conteos de palabras ordenados. Y entonces tenemos que convertir explícitamente eso a un entero para
asegurarnos de que show está obteniendo el tipo de datos que espera. Entonces, siempre que quieras mostrar todo
el contenido de un conjunto de datos, así es como lo harías. Simplemente dirías el dataset name.com dot t2 int, y pasarías eso como parámetro
al comando show para asegurarnos de que obtenemos cada fila mostrada. Entonces sigamos adelante y ejecutemos esto antes de seguir adelante y solo veamos cómo funciona eso. Así que haga clic derecho en ejecutar WordCount, conjunto de datos
mejor ordenados. Fuera va. Y ahí están nuestros resultados. Entonces, vamos a desplazarnos hacia arriba. Y se puede ver que funcionó. Entonces parece que tengo un tipografía ahí dentro. Usa tres. Estas son todas las palabras y sólo aparecieron una vez en todo mi libro. Y a medida que nos desplazamos hacia abajo, veremos más y más palabras comunes a medida que avanzamos. Entonces ahí está el fin de ello. Sí. Entonces la palabra que en realidad es la palabra más común seguida de la palabra, resultados
bastante poco sorprendentes y los mismos resultados que obtuvimos con RDD también. Ahora déjame mostrarte otra forma de hacerlo porque como dije, el proceso de cargar esos datos en un conjunto de datos era un poco torpe. A lo mejor un RDD es más adecuado para saquear esos datos brutos. Entonces como dije en las diapositivas, podemos mezclar y emparejar. Puedes conseguir lo mejor de ambos mundos. Entonces en este enfoque alternativo aquí, estamos cargando los datos usando la interfaz RDD. Entonces voy a sacar estos SparkContext de la SparkSession y llamar a la antigua función TextFile en eso. Entonces eso sólo va a cargar todos los datos de texto de punto de libro en un RDD donde cada línea es una línea de texto. Entonces ahora solo podemos llamar a FlatMap en el libro RDD y dividirlo usando una expresión regular como lo hicimos antes. Y eso es posiblemente un poco más simple que la forma en que lo hicimos usando un conjunto de datos. Tuvimos que hacer esta extraña cosa complicada con split y explotar un alias y un filtro para que eso funcione usando un conjunto de datos. Entonces aquí hay un ejemplo donde un RDD es en realidad más simple. Pero cuando se quiere hacer análisis, conjuntos de datos suelen ser la mejor opción, ¿no? Porque tienes todo el poder de SQL detrás de ti y la mejor optimización que, eso ofrece. Por lo que en este punto podemos convertir el RDD2 un conjunto de datos. Y eso es lo que está pasando aquí con dos ds. Y a partir de ese momento, el código es básicamente el mismo. La única diferencia es que nos estamos refiriendo a ese nombre de valor en lugar de palabra, porque en este punto, seguimos lidiando con el nombre de columna predeterminado del valor aquí que obtuvimos cuando convertimos el RDD a ds. Y eso también funciona. Por lo que ya corrimos esto. Si nos desplazamos hacia abajo, podemos ver esa segunda corrida donde
obtuvimos los mismos resultados exactos solo usando una forma diferente, empezando usando un RDD para cargar los datos y un conjunto de datos para analizarlos realmente. Entonces, a veces eso puede ser un truco útil, sobre todo si no estás tratando con una fuente de datos estructurada. Y se puede ver que al final tenemos la misma respuesta ahí. Entonces esas son dos formas de hacerlo usando conjuntos de datos y también usando un enfoque híbrido RDD y conjunto de datos. Por lo que tener estas herramientas en el bolsillo trasero a veces puede ser útil.
27. [Actividad] revisitar el ejemplo de la temperatura mínima, con datas.: Por lo que el uso de conjuntos de datos, en realidad es bastante simple como has visto, pero vamos a pasar rápidamente por unos ejemplos más aquí solo para volver atrás y
volver a implementar esos ejemplos de RDD con conjuntos de datos por el bien del ejemplo. Entonces volvamos a los ejercicios de temperatura mínima y máxima que
hicimos y echamos un vistazo a aquellos que usan conjuntos de datos en lugar de RDD. No mucho nuevo en este ejemplo. Uno sin embargo, es que vamos a estar proporcionando un esquema explícito a SparkSession dot read. Entonces en lugar de inferirlo de un archivo CSV, vamos a decirle explícitamente cuál es el esquema tal como está leyendo en el DataFrame. Todavía vamos a tener que convertir eso en un conjunto de datos con una clase de caso. Pero esta es otra forma de importar datos de un archivo de texto que veremos. Y también veremos el uso de la función de columna de ancho en un conjunto de datos para crear una nueva columna utilizando nuestra propia función personalizada. Entonces, sumémonos y veamos cómo funciona todo eso. Entonces echemos un vistazo a la versión original de RDD de esto. Ese es el guión Min temperature aquí. Y solo para refrescar tu memoria, cargamos un archivo CSV de 8800 puntos que contenía información meteorológica del año 8800. Después analizamos eso para extraer los campos que queríamos y lo convertimos a Fahrenheit conforme íbamos. Y luego recortamos cualquier cosa que no fuera una entrada T min para el tipo real de entrada de clima ahí con el comando de filtro. Mapeamos eso a la estación ID y tuplas de temperatura y lo reducimos por clave para realizar un seguimiento de la temperatura mínima encontrada para cada estación meteorológica única. Entonces veamos cómo hacemos esto con un conjunto de datos en lugar de un RDD. Haga clic en Conjunto de datos de temperaturas mínimas. Y aquí está nuestra nueva implementación aquí. Curiosamente, es más código, no menos. Entonces de nuevo, para cosas simples como esta que realmente no están tratando con tipos de problemas de base de datos. A veces un RDD podría ser en realidad más fácil. Pero echemos un vistazo. Entonces vamos a empezar con nuestra declaración de paquetes y estamos importando tipos SQL específicos que vamos a utilizar dentro de nuestro script, la función SparkSession y SQL. Entonces en lugar de importar todo, Normalmente
es una mejor práctica simplemente importar lo que necesitas, que es lo que estamos haciendo aquí. Empezamos declarando una clase de caso de temperatura. Este va a ser el formato que leemos de nuestro archivo de datos real. Tiene el formato de una ID de estación basada en cadena, una fecha, que podemos interpretar como un entero, un tipo de medida, que es una cadena, y una temperatura, que va a ser un valor de punto flotante. Establecemos nuestro nivel de registro, creamos nuestra sesión de Spark como lo hemos hecho antes. Y ahora vamos a hacer algo un poco nuevo aquí. Vamos a declarar un esquema específico para esos datos de entrada. Entonces en lugar de inferirlo de un encabezado, porque no tenemos un encabezado en este archivo CSV. Vamos a decirle explícitamente lo que significan esas columnas en que está leyendo. Ahora antes engañamos diciendo importar el encabezado e inferir el esquema del encabezado, pero no tenemos eso esta vez. Entonces aquí hay una forma alternativa de hacerlo. Por lo que estamos configurando un valor de esquema de temperatura que será un StructType. Y vamos a llamar a la función add en este StructType para agregar diferentes campos a esa estructura. Por lo que sólo decimos add station ID, que es un tipo de cadena, y puede ser móvil. fecha como un tipo de medida de tipo entero es un tipo de cadena, temperatura es un tipo de flotación C. Y esto todo coincide con los nombres que tenemos aquí en nuestra clase de casos también. Y los mismos tipos, los mismos nombres. Entonces ahora que tenemos eso, podemos importar implícitos de
punto chispa y leer nuestros datos desde el archivo CSV. Esta vez en lugar de decir 3D desde el encabezado, vamos a decir esquema de punto con esquema de temperatura. Entonces eso nos va a permitir construir nuestro DataFrame correctamente a partir de esos datos CSV. Y luego como antes, convertimos eso explícitamente a un conjunto de datos con una estructura de tiempo de compilación codificada que está viviendo en la clase de caso de temperatura. Entonces, de nuevo, se ve la diferencia aquí. En realidad estamos inferyendo el esquema en tiempo de ejecución todavía, porque estamos definiendo ese esquema como una estructura en tiempo de ejecución. tanto que al decir punto como temperatura en tiempo de compilación, sabemos qué es ese objeto de temperatura y Spark puede hacer más optimizaciones, nos
dan errores de tiempo de compilación en lugar de errores de tiempo de ejecución. Por lo que podría parecer un paso extra que podría no ser necesario, pero estamos obteniendo un beneficio de ello. Entonces ahora vamos a volver atrás y hacer lo mismo que hacíamos antes con RDD pero usando un conjunto de datos. Entonces lo primero que vamos a hacer es filtrar cualquier cosa que no sea un equipo en la entrada. Entonces, en lugar de usar filtro en un RDD, solo
usamos filtro en el conjunto de datos. Y usamos esta sintaxis aquí, signo de
dólar otra vez que precede al nombre de la columna. Por lo que queremos probar la columna de tipo de medida y ver si es igual a T min. Y de nuevo, en estas declaraciones de filtro, la sintaxis es un poco inusual para la igualdad. Se trata de tres signos iguales. Por lo que eso creará un nuevo conjunto de datos de carpas MR1 solo contiene el equipo en líneas. A continuación, queremos simplemente seleccionar las columnas que necesitamos. Hay un montón de cosas que no necesitamos como las fechas específicas porque solo estamos buscando el mínimo a lo largo de todo el año. realidad no nos importa cuándo sucedió eso. Por lo que sólo vamos a hacer un selecto con una lista de las columnas que queremos. Estación ID, temperatura coma. Eso es todo lo que necesitamos preservar. Ahora nos metemos en la carne de las cosas. Los agruparemos y encontraremos el mínimo. Por lo que grupo por ID de estación agrupará todas las entradas juntas para identificaciones de estación únicas. Y sólo deberían quedar dos de ellos en este conjunto de datos. Y luego una vez que tengamos esos grupos, además
llamaremos a Min para encontrar la entrada mínima dentro de cada grupo, mirando la columna de temperatura y encontrando el valor mínimo de temperatura para cada grupo de identificadores de estación. Lo tengo. Por lo que ahora tenemos un conjunto de datos de Estación Espacial de plazo Min que es solo ID de estación y temperatura mínima. Ya casi terminamos. El último que hay que hacer es convertir esas temperaturas dos grados Fahrenheit. Y bien podemos ordenar los resultados mientras estamos en ello. Entonces eso es lo que está pasando aquí. Vamos a hacer un nuevo conjunto de datos llamado Min tries por estación F porque estamos convirtiendo esto a Fahrenheit. Y eso será tomar nuestros tiempos Min por conjunto de datos de la
estación y aplicar esta función de columna de ancho en él. Por lo que esto va a crear una nueva temperatura de nombre de columna. Esto en realidad es diferente al que empezamos aquí. Por lo que con columna puede o bien reemplazar una columna existente o crear una nueva. En este caso, en realidad estamos creando uno nuevo porque con muchos intentos por estación, todo lo que obtenemos de ese grupo BY comando es el ID de la estación y una nueva columna que se llama Min a temperatura con temperatura entre paréntesis. Entonces nuestra columna de temperatura que teníamos originalmente, en realidad se ha ido al estado y la vamos a recrear ahora vamos a hacer una nueva columna de temperatura aquí con el comando width column. Entonces con columna, vamos a llamar a nuestra nueva temperatura de columna. Y se construirá usando esta función. Entonces vimos con columna antes cuando hablamos funciones
definidas por el usuario, mismo concepto aquí. Simplemente no estamos usando una función real que definimos. Estamos pasando en una expresión aquí explícitamente. Entonces empecemos por el medio. Empezamos con la columna de temperatura mínima, y eso es lo que se
nombró automáticamente a esta columna cuando la creamos con el comando grupo BY. Por lo que agrupa agrupando en la Temperatura Min creará una columna de temperatura Min. Y si hicieras un show en ese conjunto de datos mientras estás depurando cosas, habrías visto ese nombre de columna. De manera alterna, podríamos haber llamado alias a eso para darle un nombre más explícito al que pudiéramos referirnos más adelante, pero no lo hicimos. Por lo que sólo vamos a usar este nombre predeterminado aquí. Entonces vamos a tomar eso, multiplicarlo por 0.1. Eso va a convertir el formato de datos sin procesar en grados centígrados reales. Y luego convertimos eso a Fahrenheit multiplicándose por nueve quintas partes y sumando 32. Además, esto va a vivir dentro de la función redonda aquí. Parámetro de dos, lo que significa que queremos redondear eso a dos decimales de precisión. De acuerdo, entonces eso va a crear una nueva columna de temperatura otra vez, con nuestra temperatura convertida a Fahrenheit redondeada a dos decimales. Además, seleccionaremos los datos que necesitamos, por lo que ya no necesitamos esa columna de temperatura mínima. Simplemente queremos la columna Fahrenheit final convertida en su lugar. Entonces vamos a seleccionar
las columnas ID de estación y temperatura porque eso es todo lo que queremos mostrar al final. Y finalmente, lo ordenaremos por temperatura para que
obtengamos estos resultados ordenados por temperatura, la temperatura mínima que se observó en cada uno. Por último, recolectaremos esos resultados igual que lo habrías hecho con un RDD. Y en este punto todos nuestros datos están de vuelta dentro nuestro guión de conductores y estamos viviendo dentro del mundo de Scala de nuevo. Por lo que sólo pasamos por el código Scala aquí, iteramos a través de todos los resultados en nuestro conjunto de resultados. Extraer el primer, segundo elementos de la tupla, llámalo estación en temp. Y además lanzaremos explícitamente la temperatura como un valor de punto flotante. Entonces podemos formatear eso usando el operador de impresión F aquí. Y finalmente imprimir línea los resultados reales usando el operador de sustitución, como hablamos de camino atrás en nuestro curso de choque de Scala. Entonces vamos a ejecutarlo y convencernos de que funciona. Haga clic con el botón derecho, ejecute Conjunto de datos de temperaturas mínimas, y apagado va. Y funcionó. Genial. Por lo que tenemos nuestras dos estaciones meteorológicas ahí con sus temperaturas mínimas en Fahrenheit redondeadas a dos decimales de precisión. Wu funcionó. Está bien, así que sí, si quieres un poco de un reto extra, puedes seguir adelante y tratar de modificar esto para hacer temperaturas máximas y establecer unas temperaturas mínimas solo para ponerte en tus manos un poco más debería ser trivial. Entonces en realidad ni siquiera estoy ido a brindarte una solución para eso. Pero si quieres jugar un poco más con esto, sin duda
lo animo.
28. [Ejercicio] Implementar el problema de "Total Spent por el cliente" con Datasets: Por lo tanto, vamos a terminar esta sección introduciendo conjuntos de datos con otro ejercicio y otro reto práctico. Lo que vamos a hacer es volver al ejercicio desde la sección anterior,
donde calculamos el total gastado por el cliente en nuestro falso conjunto de datos de comercio electrónico. Y vamos a volver a visitar eso usando conjuntos de datos en lugar de RDD, probablemente vio que uno regresaba a casa. Entonces, para recapitular, lo que vamos a hacer es sumar la cantidad gastada por el cliente en nuestro conjunto de datos aquí, los datos brutos que entran, es formato CSV. Y contiene tres columnas, un ID de usuario y ID de artículo y un precio pagado por ese artículo. Lo que quiero hacer es sumar todo el monto total pagado por ID de usuario. lo que en este sencillo ejemplo de nuevo, el ID de usuario 44 gastó un total de $77.83. Userid 35 gastó 7897, y así sucesivamente y así sucesivamente. Por lo que nuestra estrategia va a ser algo similar a como lo hicimos con los RDD. Es solo que la técnica será un poco diferente. Por lo que estaremos cargando los datos pedidos de clientes dot archivo CSV como un marco de datos con ocho esquema explícito será la forma más fácil de hacerlo. Y puedes optar por convertir eso explícitamente en un conjunto de datos si lo deseas. Obviamente eso a veces conducirá a un mejor rendimiento, pero no tienes que hacerlo. Después de eso, vamos a agrupar ese conjunto de datos por ID de cliente. Lo resumiste por el monto gastado por ID de cliente. Y si quieres puntos de bonificación, no es que alguien realmente esté manteniendo la puntuación. Puedes redondear eso a dos decimales mientras estás en ello, ordenados por la cantidad total gastada. Para que podamos ver a nuestros principales gastadores y clientes más baratos también, luego mostrar los resultados. Y algunos fragmentos útiles si quieres algunas pistas más aquí, revisando los ejemplos anteriores de esta sección, sin duda
seremos de ayuda. Y hay una función SQL llamada suma que puedes usar para sumar cosas después de haberlas agrupado. Y específicamente la sintaxis para un redondeo que después de sumar se verá como AG,
redondear algunos, cualquiera que sea el nombre de la columna como él, estás sumando redondos de trompas comas a dos decimales. Tan poco, pequeño tramposo ahí. Y sí, esta solución está en los materiales del curso. Por favor, resistan la tentación de echar un vistazo y mirar hacia adelante. Prueba esto tú mismo y ve si puedes arreglarlo. Es una buena práctica. Y volveré y caminaré por mi solución en la próxima conferencia.
29. Solución de ejercicio: el tiempo total con el cliente con datas.: Espero que hayas tenido algún éxito en hacer ese ejercicio y recrear nuestra cantidad total gastada por la actividad del cliente usando conjuntos de datos. Echemos un vistazo a mi solución y puedes comparar mi enfoque con el tuyo. Abre el total gastado por los clientes ordenados script de conjunto de datos aquí. Y de nuevo, ya sabes tu, tu código no tiene que ser exactamente como el mío. Lo que cuenta es el resultado final realmente
ahí, hay muchas formas de hacerlo. Por lo que comenzamos importando las cosas que necesitamos y creamos un objeto llamado
conjunto de datos total gastado por los clientes ordenados y comenzamos con una clase de caso definiendo el esquema en el que nuestro conjunto de datos se verá forzado. Por lo que estamos diciendo explícitamente en tiempo de compilar que nuestro conjunto de datos de pedidos de clientes va a contener un ID de cliente entero y un ID de elemento entero y una cantidad de doble precisión gastada. Entonces entra en mi función principal aquí y configuramos nuestra sesión de Spark como siempre lo hacemos. Y crearemos un esquema para su uso con la lectura en el archivo CSV como DataFrame inicialmente. Entonces vamos a crear un esquema de pedidos de clientes, que es, ya sabes, se parece mucho a algún código anterior que miramos. Por lo que ojalá pudieras levantar eso, creara un nuevo StructType y agregara un id de cliente de tipo integer ítem ID de cantidad entera gastada de tipo tipo doble. Y entonces en realidad leemos eso delante
del archivo CSV aquí usando el esquema que proporcionamos. Y forzaremos eso en un conjunto de datos utilizando la clase de caso de pedidos de clientes como lo hicimos antes. Ahora nos metemos en la carne del ejercicio. Aquí, creamos un nuevo total por conjunto de datos del cliente que prácticamente hace todo. Empezamos agrupando por el campo ID de cliente. Y recuerda que definimos ese nombre aquí arriba en nuestra clase de casos, ese nombre tiene que coincidir con el de aquí arriba. Por lo que al agrupar por ID de cliente, agrupamos todas las diversas compras para cada cliente juntas. Y entonces esta siguiente línea es lo que en realidad resume a todos esos. Entonces, empecemos desde el medio y trabajemos nuestra salida. Empezamos sumando la cantidad de subrayado gastado columna. Por lo que por cada ID de cliente único, vamos a resumir todos los montos Spence asociados a ese ID de cliente. Y eso está aún más envuelto por una función redonda para redondear eso a dos decimales de precisión. Vamos a usar huevo de punto para agregar ese resultado en una sola columna en el resultado final. Y vamos a dar ese nuevo nombre de columna diciendo alias de punto, subrayado
total gastado para facilitar la referencia. Porque necesitamos darle un nombre para poder ordenarlo, ¿verdad? Entonces me doy cuenta de que esta función agg puede ser un poco confusa. Básicamente, lo que está haciendo es decir que vamos a agregar estas funciones juntas en una sola columna, ¿de acuerdo? Y también vamos a darle un nombre a esa columna usando alias de punto también. Por lo que en este punto, la estructura de nuestro conjunto de datos va a ser una columna de ID de cliente y una columna de subrayado total gastado. Ahora podemos ordenarlo solo diciendo dot sort con el total de subrayado gastado nombre de columna que especificamos en la línea anterior y volver a mostrar los resultados, razones poco truco para obtener el gran total de cuántas filas son en el total por conjunto de datos del cliente, convirtiendo eso a un entero y pasando eso como parámetro a la función show para asegurarnos de que mostramos explícitamente todo el conjunto de datos y no solo las primeras 20 filas. Entonces sigamos adelante y pateemos eso. Y ahí tenemos. Parece que funcionó. Parece que los resultados están ordenados por cantidad gastada. Por lo que nuestro mayor gastador fue UserID 68, gastando 6,375.45 dólares. Muy cool. Está bien. Espero que hayas disfrutado de eso y quizá hayas ido aún más lejos. Es decir, podría haber llevado esto un paso más allá forzando que sea un ejemplo de punto 24, estoy usando un formato de impresión f para realmente iterar a través cada fila individual que se devolvió y formatear la salida más a mi gusto. Pero sí, si lo hiciste, puntos de bonificación para ti. Pero oye, espero que hayas pasado por esto. Por lo que tenemos CAD introducción a los conjuntos de datos y cómo funcionan a nivel bastante alto, hay más por explorar, debo agregar. Hay mucho más a Apache Spark de lo que puedo cubrir en este curso. Entonces si alguna vez quieres referirte a la documentación para el conjunto completo de referencia sobre lo que puedes hacer. Puedes ir a spark dot apache.org slash docs slash latest para obtener la documentación más reciente. Si quieres profundizar en todo lo que puedes hacer con el conjunto de datos, por ejemplo, solo
puedes navegar a org. Apache Spark. Dataset Sql va a ser la ruta para ese nombre de clase. Y te contará todo al respecto en cada intrincado detalle. Si te desplazas hacia abajo, verás algunos ejemplos que son aún más útiles. Y se puede ver una lista de todos los métodos que están disponibles en el conjunto de datos. La mayoría de ellos se verán familiares. Nosotros sí cubrimos muchos de ellos. Por ejemplo, recolectar y contar para cada uno aplicando una función a cada fila. Head es una forma de obtener las primeras n filas del conjunto de datos muestran que hemos usado mucho eso, ¿verdad? Take también se puede usar para tomar un cierto número de filas del conjunto de datos. Aquí también hay algunas otras cosas que explorar. En realidad se puede hacer explicar, para explicar la forma real en que se va a ejecutar, lo cual es algo interesante para propósitos de depuración. Hay formas de persistir en un disco. Hay una forma de convertirlo en un RDD. Eso lo miramos un poco. Podemos imprimir el esquema. Ya lo hemos hecho antes. En realidad podemos convertirlo a un DataFrame también si queremos, así
como también una función adecuada para almacenarlo en disco. Y hablaremos de streaming más tarde, llegaremos a eso más adelante. Y hay otras cosas aquí como varias operaciones como distintas para obtener valores distintos en el conjunto de datos. Hemos mirado el filtro antes, hemos hablado de FlatMap. Se puede aplicar eso a un conjunto de datos así como un GroupByKey de la que hemos hablado intersecciones de unión. Se pueden hacer algunas operaciones booleanas ahí al mapeo. Eso se puede hacer en un conjunto de datos igual que en un RDD, aunque va a ser un poco más engorroso con un conjunto de datos. Y sí, solo sigue adelante y pesca a través de esto si alguna vez quieres conseguir un ejemplo más completo de lo que puedes hacer y lo que está disponible. Y si tiene alguna pregunta sobre la sintaxis y los parámetros que se soportan en estas funciones de conjunto de datos. Este es el lugar para acudir a ti para averiguarlo. Como puedes ver, hay una larga lista de lo que puedes hacer el conjunto de datos. Hemos tocado algunas de las cosas más comunes que puedes hacer. Pero como puedes ver, aquí
hay bastante menú. Por lo que seguiremos utilizando conjuntos de datos a lo largo del resto de este curso. Y también tenga en cuenta que en los materiales de su curso para cada ejercicio hay tanto una versión RDD como una versión de conjunto de datos. Entonces si alguna vez quieres comparar los dos, están todos ahí. No vamos a pasar por cada versión de cada guión individual. Como dije, nos vamos a centrar en conjuntos de datos de aquí en adelante. Pero si alguna vez tienes curiosidad, puedes mirar ambas versiones. Y hay algunas que no hemos tocado también. Por ejemplo, nuestro contador de calificación inicial ejemplo RDD. También es una versión de conjunto de datos de eso ahí si quieres jugar con él también. Entonces está todo ahí para tu referencia y alegría. Y pasemos a algunos ejemplos más complicados en nuestra siguiente sección.
30. [Actividad] encontrar la película más popular: Entonces hasta este punto del curso, te
hemos estado presentando a Spark y usando algunos ejemplos bastante sencillos. Pero quiero que veas que Spark tiene mucho poder más allá también. Entonces si incluso tienes un problema más complicado, a veces si piensas de manera creativa, desencadena problemas sin resolver que no habrías pensado que podría resolver. Y vamos a sumergirnos en algunos ejemplos como ese en la siguiente sección usando algunos ejemplos bastante divertidos usando datos de películas y datos de superhéroes. Entonces, sumémonos y veamos qué puedes hacer con Spark que quizá no hayas pensado que podrías hacer si solo piensas un poco creativamente en tus problemas. De acuerdo, Así que sé que el nombre de esta sección es ejemplos más avanzados de Apache Spark, pero necesitamos empezar con algo simple y trabajar nuestro camino hacia arriba desde él. Entonces para sentar las bases de este siguiente ejemplo, vamos a hacer algo fácil. Vamos a encontrar la película más popular en el conjunto de datos de MovieLens. Y para recapitular, en realidad hacer, Ya
hablamos de MovieLens. Hicimos brevemente de vuelta con el, el contraejemplo de calificaciones. Por lo que vamos a estar ingiriendo aquí el conjunto de datos de MovieLens 100 K. Y para recapitular el formato
, contiene estas cuatro columnas. Corresponden a un ID de usuario, ID de
película, una calificación, y una marca de tiempo. Y para encontrar la película más popular, todo lo que necesitamos hacer es encontrar las identificaciones de película que tengan más calificaciones, ¿verdad? Entonces si asumimos que alguien que calificó la película la vio, y definimos popular como la película más vista que por sólo encontrar la identificación de película que aparece con más frecuencia. En este conjunto de datos, encontraremos la película más popular de esa manera. Entonces vayamos al código y veamos cómo podemos hacer esto usando conjuntos de datos. Bastante sencillo, pero de nuevo, vamos a construir sobre esto para hacer algo un poco más complicado en la próxima conferencia. Así que vamos a explorar el popular script de dataset de películas en los materiales de su curso. Y caminaremos por esto. No es demasiado elegante aquí, pero de nuevo, vamos a construir encima de esto para hacer algo un poco más profundo y complejo en conferencias posteriores. Por lo que empezamos por sí mismo importante. Necesitamos, como de costumbre, llamaremos a eso nuestro objeto, popular dataset de películas. Somos clase de caso innecesaria llamada película. El conocimiento aquí es que todo lo que estamos haciendo es contar cuántas veces aparece cada ID de película en nuestro conjunto de datos. Y para hacer eso, todo lo que necesitamos es la columna de identificación de la película, ¿verdad? No nos importan las calificaciones. No nos importa cuándo fueron calificadas. No nos importa quién lo calificó. Todo lo que nos importa es que ese ID de película aparezca en cada fila individual. Entonces esos son los únicos datos que realmente tenemos que extraer, lo que hace las cosas un poco más simples. Al sumergirnos en nuestra función principal aquí, establecemos nuestro nivel de registro, mayor SparkSession, nada especial ahí. Creamos nuestro esquema de películas para cargar el DataFrame inicial desde el archivo CSV. A pesar de que en realidad es un archivo de datos de valor separado por tabulaciones aquí Pero eso está bien. Todavía podemos usar el cargador CSV hacia adelante como veremos. Y vamos a decirle que la estructura de esos datos es ID de usuario, ID de película, rating, y marca de tiempo con tres enteros y un largo para representar esos datos. Importar desató implícitos para cargar ese CSV mediante el uso de ese esquema implícito. Y vamos a cargar, nota la opción set backslash t Eso es decirle al cargador CSV que son un separador en realidad no es una coma,
sino un carácter de tabulador, que es lo que estos datos realmente se formatean a medida que pasamos en el ruta al archivo de datos, es
decir, el archivo de datos que contiene la información de calificaciones reales. Y luego lo forzaremos posteriormente en un conjunto de datos de películas. Y al hacer eso, lo estamos lanzando a esa sola primera columna ahí que sólo consiste en la identificación de la película y nada más. Tan pequeño truco interesante ahí. Su dataset no tiene que incluir todas las columnas, por lo que el DataFrame desde el que lo está construyendo. Y ahora la carne del mismo sucede en esta sola línea. Y es muy SQL like y cómo se acerca al problema. Por lo que empezamos agrupando por identificaciones de películas. Por lo que acabamos de agrupar todas las calificaciones de cada ID de película. Después los contamos todos. Y entonces ordenar por es básicamente cómo haces una clasificación en SQL para que haga lo mismo. Básicamente estamos diciendo orden POR la columna de conteo, que va a ser creada por esa función ahí. Y en orden descendente para que consigamos nuestras películas más populares en la parte superior de la lista y nuestras menos populares en la parte inferior de la lista. Después de eso, mostraremos los diez mejores resultados y eso nos debería dar nuestras 10 películas más populares. Entonces vamos a patear eso y a ver qué obtenemos. De acuerdo, ahí tenemos nuestros resultados y parece que funcionó. Por lo que aparentemente la película más popular es la película ID 550, con 583 calificaciones distintas asociadas a esa película. Pero eso no es terriblemente útil, ¿verdad? ¿ Cómo sabemos qué película es ID 50? Por lo que un siguiente paso obvio para extender este guión sería realmente importar
el nombre de la película asociado a cada ID de película para
que realmente podamos tener alguna idea de cuáles son estas películas. Es decir, podríamos hacerlo de la manera difícil que estos datos viven en el archivo de ítem en nuestro conjunto de datos. Entonces si abrimos eso para explorar lo que hay ahí dentro, puedes ver que esto contiene todo tipo de información extra sobre cada ID de película. Entonces por ejemplo, la película ID uno es la película Toy Story y te dice que el año fue lanzado, vinculado a datos del IMDB de ella. Y estos y ceros en realidad corresponden a los géneros en los que está esa película. Y si bajas a la película ID 50, veremos que nuestro ganador es en realidad Star Wars, el original de 1977. No demasiado sorprendente. Pero sí, no lo sabemos. No queremos tener que buscar esos a mano, ¿verdad? Entonces volvamos y hablemos de cómo unirnos realmente a eso con nuestros datos de nombres de películas. Y cómo hacerlo de una manera óptima para que podamos realmente distribuir esos datos a cada nodo de nuestro clúster.
31. [Actividad] las variables de transmisión para mostrar los nombres de la película: Por lo que necesitamos que esos resultados sean legibles por humanos. Esas identificaciones de películas no nos son realmente útiles como seres
humanos porque no sabemos qué decir película representa. Por lo que no hay intuición que ganar. Entonces vamos a ocuparnos ahora de ese problema. Por lo que queremos mostrar los nombres de las películas y no sólo los identificadores. Y para ello, necesitamos fusionar la información de ese archivo de elemento
u dot del conjunto de datos de MovieLens. Ahora hay muchas formas de hacer esto. El más sencillo sería simplemente configurar otro conjunto de datos que mapee los identificadores a los nombres después de analizar en ese archivo de elemento u dot. Y entonces podemos simplemente unirnos a ese conjunto de datos con nuestro conjunto de datos de calificaciones por los identificadores de películas y unirnos a esos nombres de películas de esa manera. Esa sería una especie de la forma más directa de hacerlo. Y desde el punto de vista SQL, así es como te acercarías a este problema también. Pero esa no es la única manera de hacerlo. No se puede hacer eso. De hecho, te animo a que le des una prueba si quieres un poco de ejercicio práctico con el que practicar. Pero lo vamos a hacer de una manera diferente. Porque hacer un join in como distribuir un conjunto de datos a través del clúster, esa es una operación bastante pesada. Y no es totalmente necesario para estos datos, ¿verdad? Porque no hay tantas películas en el mundo. El cuadro de identificadores de películas a nombres de películas no es en realidad tan grande. Podemos caber todo eso en la memoria con bastante facilidad en una sola computadora, Así que realmente no necesitamos distribuir eso a lo largo de un conjunto de datos. Por lo que podríamos simplemente mantener una tabla cargada en el programa de conductores y usar eso para mapear también los identificadores. Nombres de películas mientras los estamos imprimiendo. Eso va a estar bien. Pero hay otra forma de hacer un dos. Por lo que también podríamos dejar que Spark automáticamente para eso a cada ejecutor cuando fuera necesario. Entonces imagínense, si se quiere, que necesitábamos tener esos nombres de películas dentro del propio guión del conductor y no sólo para la etapa final de salida. En realidad podemos, hay una forma de usar lo que llamamos variables de
difusión para reenviar un objeto el cual puede incluir un mapa, que podría estar mapeando identificadores de película para mover los nombres, por ejemplo, y fordando eso automáticamente a cada ejecutor dentro nuestro cluster para ser utilizado según sea necesario. Y ya sabes, si la mesa es masiva, esto podría ser algo importante usar estas variables de transmisiones porque eso
asegurará que solo le transferimos lo quiere a cada ejecutor y lo mantengamos ahí. Contraste eso con un conjunto de datos donde podría estar siendo arrojado por todo el lugar. Es un poco más de una operación compleja. Por lo que al usar una variable de difusión, podemos asegurarnos de que esa tabla, ese mapa de información, que mapea identificadores a nombres solo se envíe a través quiere a cada ejecutor, y se quede ahí hasta que explícitamente nos deshagamos de él. Entonces con variables broadcast, podemos transmitir cualquier objeto a todos
los ejecutores de tal manera que siempre estén ahí cuando sea necesario. Solo tenemos que llamar a broadcast en el objeto de contexto Spark en nuestro script de conductor para enviar esos datos fuera de
lo que quisieras enviar a cada nodo ejecutor. Sólo tenemos que asegurarnos de que cabrá dentro de su memoria de obviamente. Y luego después de que eso haya sido transmitido, podemos usar el valor de punto en esa variable de difusión para recuperarlo y recuperar ese objeto y referirnos a él dentro del script que se está distribuyendo a lo largo de todo el clúster. Y podemos usar esos objetos difundidos como quieras. Puedes usarlos dentro de funciones de mapa en RDD o en nuestro caso, queremos aplicarlos a datasets, lo que significa que vamos a configurar una función definida por el usuario para que podamos usarla de una manera más SQL ESC. Entonces con eso, vamos a sumergirnos en el código y ver cómo funcionan las variables de difusión. Así que abramos las películas populares más bonito script de conjunto de datos aquí y veamos cómo se ve eso. Por lo que de nuevo, la forma más sencilla de manejar este problema sería cargar un conjunto
de datos de ID de películas a nombres de películas y unirse a eso en una especie de operación SQL. Pero lo vamos a hacer de una manera un poco diferente porque sabemos que este es un conjunto de datos relativamente pequeño y podemos salirnos con la suya simplemente enviando eso a cada ejecutor individual a medida que nuestro guión se inicia y simplemente referirnos a ello localmente dentro de cada nodo ejecutor. Entonces es sólo otra forma de hacerlo. En ocasiones las variables de difusión pueden ser útiles de esa manera
realmente no las ves usadas que muchas veces en la práctica para ser honestas, pero es una herramienta en tu cofre de herramientas que creo que debes saber. Y esto también nos da la oportunidad de ilustrar el uso de funciones definidas por el usuario en un conjunto de datos, lo cual también es algo bueno para conocer. Entonces, a pesar de que este es un ejemplo un poco
artificiado, ilustra un par de puntos importantes. Entonces vamos a sumergirnos en el código aquí. Importamos todas las cosas que necesitamos. Y vamos a configurar una clase de caso completo desde el tipo de datos de películas aquí que incluye el ID de usuario, calificación de ID de
película, y marca de tiempo que importará desde el archivo de datos u dot. A continuación crearemos una función de nombres de películas de carga. Y el propósito de esta función es solo crear un mapa de Scala que mapee identificadores de películas a nombres de películas. Entonces esto es solo código directo de Scala. No es código Spark. Todo lo que está haciendo es cargar esa carpeta de elementos u dot usando la codificación de caracteres correcta, por cierto, que es un poco oscura. Y regresamos un mapa de enteros a cadenas que mapea identificadores de películas a nombres de películas. Simplemente cargamos el archivo directamente del disco, iteramos a través de cada línea de ese archivo, lo
dividimos en base a ese carácter de tubería que lo delimita. Y hacemos un chequeo de cordura para asegurarnos de que sea una línea válida. Y si es así, agregamos a nuestros nombres de películas mapa y entrada que mapea ese primer campo, que es el ID de la película al segundo campo, que es el nombre de la película. Cierra el archivo cuando hayamos terminado y devuelve el mapa de nombres de películas resultante. Entonces de nuevo, esto no es código de Spark, esto es solo código directo de Scala, leyendo esos datos del disco local desde donde estemos, estamos ejecutando nuestro script de conductor desde. Entonces entrémonos en el propio guión real. Como de costumbre, comenzamos con nuestro nivel de registro y configuramos un objeto SparkSession. Y ahora vamos a llamar a esa
función de carga de nombres de películas para cargar ese mapa de identificadores de películas a nombres de películas. Y vamos a llamar a broadcast desde nuestra interfaz de contexto de Spark. Y vamos a llamar a esa variable de difusión resultante lo
llamó corto para diccionario de nombres, tiene sentido, ¿verdad? Entonces en este punto ese mapa se ha cargado y se ha enviado a todos los ejecutores que van a estar ejecutando aquí nuestra aplicación Spark. Por lo que estará disponible para todos los ejecutores localmente para hacer búsqueda rápida de identificadores de películas a nombres de películas. Muy bien, Ahora nos metemos en el propio código de Spark. Vamos a estar cargando los datos de nuestras películas con el siguiente esquema. Entonces vamos a cargar el archivo de datos especificando el separador de tabuladores. Nuevamente, este es el mismo código exacto
del ejemplo anterior y usando el esquema que estamos proporcionando. Y luego lo forzaremos a la clase de casos de películas para obtener el contenido completo de los datos de esa película definidos así. Muy bien, adelante, entonces obtendremos el número de críticas por,
por identificación de película, igual que lo hicimos antes con las declaraciones simples del grupo BY. Por lo que vamos a agrupar por la columna de ID de película y contar cada ID de película individual cuántas veces ocurre. Entonces en este punto tenemos lo que teníamos antes. Contamos con un conjunto de datos de conteos de películas que contiene ID de
película y recuento para cada ID de película individual. Muy bien, entonces ahora necesitamos una manera de
transformar realmente esos ID de películas en nombres de películas dentro de nuestro conjunto de datos. Entonces, de nuevo, este es un ejemplo artificiado. Podrías haber hecho esto con la misma facilidad en la etapa de salida, ¿verdad? Y podríamos haber repetido a través del conjunto de datos resultante que recuperamos y
buscar esos nombres de películas de nuevo en el guión del conductor localmente cuando realmente estamos imprimiendo los resultados. Pero sólo estamos tratando de ilustrar el uso de las UDF aquí y las variables de difusión. Por lo que realmente vamos a hacer esto distribuido dentro del propio clúster. Por lo que para cada ejecutor que esté manejando algún subconjunto de las películas, algún subconjunto de identificadores de películas para este problema, estarán individualmente mirando los títulos de películas para los ID de película. Ellos son responsables de tan poco más escalables, ¿verdad? Para ello, necesitamos configurar
primero unas funciones definidas por el usuario para que realmente podamos configurar un comando de conjunto de datos para crear una nueva columna usando esta función para generar los datos de esa columna. Ahora la sintaxis para esto es un poco rara, así que en realidad no hemos visto esto antes. Estamos declarando aquí lo que se llama una función anónima. Y en Scala, la sintaxis para eso se ve así. Entonces básicamente estamos definiendo una función en línea aquí. Vamos a llamarlo nombre de búsqueda. Ese es el nombre de nuestra, de nuestra función. Estamos diciendo que tomará un entero y devolverá una cadena. Y vamos a poner eso igual a esta siguiente función anónima. Por lo que toma un entero llamado ID de película y pasa a este bloque de código, que sólo devuelve la búsqueda del diccionario de nombres dado ese ID de película,
anote el valor de punto, así lo llamó de nuevo como una variable de difusión. No es el mapa real. Para recuperar el objeto de mapa tenemos que llamar valor de
punto quería recuperar el nombre objeto de Dick. Entonces otra vez, llamado dict es la variable broadcast. Para obtener su contenido, necesitamos llamar valor sobre él. Por lo que en este punto tenemos un mapa real de Scala para usar. Y entonces sólo podemos pasarle el ID de película para
buscar cuál es el nombre de la película asociado a esa identificación de película. A continuación, necesitamos envolver esa función con una UDF. Por lo que puede anotar en la parte superior aquí importamos explícitamente. Aquí está, o punto Apache dot Spark dot SQL dot functions.php UDF. Y eso nos permite realmente envolver esa función como una función definida por el usuario que luego podemos usar en una configuración SQL. Entonces ahora que tenemos nombre de búsqueda UDF, podemos usarlo. Y aquí es donde sucede la magia. Entonces diremos películas con nombres. Este va a ser nuestro nuevo conjunto de datos que tiene una columna adicional llamada título de película. Y para agregar esa columna, sólo diremos película cuenta columna de ancho de puntos. Para agregar esa nueva columna a ese conjunto de datos, llamaremos a esa nueva columna título de película. Y el contenido de esa columna se generará usando el nombre de búsqueda UDF, esa función definida por el usuario que acabamos de definir. Y los parámetros para eso vendrán de la columna id de película. Entonces la sintaxis aquí es utilizar la función de llamada que proviene de las funciones de
punto SQL para realmente pasar en el contenido de un nombre de columna dado, en este caso ID de película. Y debido a que envolvemos eso con una UDF, aceptará esa columna y transformará eso el entero que la función subyacente real espera para usted. Entonces aquí es donde todo sucede. Por lo que de manera distribuida en todo el clúster, va a utilizar nuestra función definida por el usuario usando nuestro mapa difundido para buscar identificadores de
películas a nombres de películas y generar un nuevo conjunto de datos llamado películas con nombres. En ese punto, entonces podemos ordenarlo de nuevo en todo el clúster basado en el campo de conteo. Y en ese punto sólo podemos recuperar los resultados y mostrarlos. En este caso, sólo vamos a mostrar todo
el asunto porque quizá queramos indagar en todos los detalles del mismo. Y así simplemente pasaremos como parámetro, toda
la lista, el recuento D2 y para obtener la cada fila de ese conjunto de datos. Y además, diremos truncar es falso para evitar que realmente trunque la longitud de cada fila individual. De lo contrario, cortaría algunos de esos nombres de películas para caber dentro de un ancho de fila dado. Entonces vamos a patear esto y a ver qué pasa. Y ahí lo tenemos. Entonces no hicimos un tipo descendente en este caso, realidad sólo s finales. Por lo que las películas más comunes, las más populares estarán al final en este caso. Y obtuvimos el mismo resultado. Star Wars es, se enseñan cine, seguido de contacto, seguido de Fargo, seguido de Retorno del Jedi. Se puede decir que esto definitivamente es un conjunto de datos fechado. Hay más actuales que puedes obtener de MovieLens si quieres experimentar con ellos. Entonces solo ten en cuenta que se trata de datos antiguos, así que no te sorprendas de que cerca de éxitos de taquilla favoritos y apareciendo aquí. Pero sí, funciona. Entonces de nuevo,
un ejemplo un poco artificiado, pero el punto era enseñarte sobre variables de difusión y funciones definidas por el usuario. Nuevamente, a menudo se puede lograr lo que necesitamos hacer con una variable de difusión mediante el uso de un conjunto de datos en su lugar. Pero a veces una variable de difusión será más eficiente. Entonces es otra herramienta en tu cofre de herramientas y ahora la tienes. Sigamos adelante.
32. [Actividad] el superhéroe más popular en un gráfico social: Muy bien, entonces en nuestras próximas conferencias vamos a estar viendo un conjunto de datos bastante divertido. En realidad está basado en el universo de cómics de Marvel es un Marvell o Marvell y todo el mundo sabía pronunciar eso. Pero de todos modos, estamos hablando de superhéroes como Spiderman y Thor y todos en ese mundo entero ahí. Y resulta que en realidad se puede pensar en el mundo de los superhéroes como un poco de una red social. El conjunto de datos con el que vamos a trabajar es algo interesante. Modela a los superhéroes como una red de superhéroes al mirar con
qué otros superhéroes aparecía cada héroe en un solo cómic. Entonces si tuvieras a Spiderman aparecer en el mismo cómic que Thor, entonces diríamos que hay una conexión entre Spider-Man y exhaustiva, por ejemplo. Y resulta que hay un montón de este tipo de co-ocurrencias de héroes dentro de un mismo cómic. Y lleva a esta estructura de red realmente interesante entre todos estos héroes en el universo Marvel. Entonces tenemos en realidad un conjunto de datos público bastante cool por ahí. Y contiene los dos archivos que nos interesan. uno se le llama Marvell texto de punto gráfico discontinua. Y lo que hemos hecho es que hemos asignado una identificación a cada personaje individual que aparece en estos cómics. Entonces el primer número que aparece en cada línea es el personaje del que estamos hablando, seguido de una lista de todos los identificadores de personajes con los que, ese personaje ha aparecido en otros cómics. Entonces no tengo ni idea de qué identificación de personaje para 395 es, pero finjamos que es Spider-Man. Entonces esto significaría que Spider-Man apareció con los personajes 22, 37, 17, 6, 7, 4, 7, 2, y así sucesivamente y así sucesivamente. Y luego podemos buscar qué nombres están asociados con identificadores de caracteres individuales. Los llamaremos identificadores de héroes si así lo deseas. En el archivo Dash Marvel nombra dot txt, eso es muy sencillo. Es sólo una identificación seguida de una comilla nombre entre comillas de eso, que corresponde a ese ID de héroe. Ahora una cosa que te puede tropezar aquí arriba es que un héroe puede abarcar múltiples líneas en el archivo de gráficos discontinuos de Marvel dot txt. Por lo que algunos superhéroes aparecen tan a menudo que tienen tantas co-ocurrencias con otros héroes que no pueden caberlos a todos en una sola línea. Entonces en ese caso, podríamos tener dos o más líneas que comenzarían con el mismo ID de héroe. Por lo que podemos ver cómo esto podría ser interesante desde el punto de vista del procesamiento de datos. Tenemos que combinar esos juntos ya que lo estamos procesando de alguna manera. Y bueno, hablemos de cómo hacer eso. Entonces nuestro reto es averiguar quién es el superhéroe más popular en el mundo de los cómics de Marvel. Y vamos a definir popular por quién aparece con más superhéroes en otros cómics? Quién es, quién se mueve más en el mundo de los cómics básicamente. Entonces aquí está nuestra estrategia para responder realmente a este problema. Entonces cargaremos nuestro conjunto de datos desde el archivo de datos de ahí. Y lo primero que haremos es dividir ese primer número en cada línea porque esa es la identificación de héroe de la que estamos hablando. Con esa línea. Entonces simplemente contaremos cuántos números separados por espacio están en esa línea. Realmente no nos importa quiénes son las conexiones. Solo los estamos contando, ¿verdad? Y así todo lo que nos importa es cuántas conexiones tiene Hero. Entonces tomando ese gran total de cuántas cosas hay en esa línea. Si sólo restamos uno para deshacernos de ese ID de héroe inicial que identifica de quién se trata, obtenemos el número de conexiones a ese ID de héroe que están representadas por esa línea de datos conmigo hasta ahora. Entonces sólo vamos a contar. Cuántos otros IDE están en esa línea para corresponder a ese ID de héroe para obtener un recuento de cuántas conexiones están representadas por esa línea de datos. Y como dijimos, podemos tener múltiples líneas para un determinado ID de héroe, lo que significa que necesitamos combinarlas de alguna manera. Entonces en SQL, podemos hacer un comando de grupo BY o en nuestro conjunto de datos que podemos hacer un comando de grupo BY para realmente combinar esos por completo. Y luego podemos sumar todas las conexiones juntas para diferentes identificaciones de héroe que se separaron. En ese punto, podemos simplemente ordenar por el total de conexiones y arrancar el resultado máximo para conseguir al superhéroe más popular. Y al mismo tiempo podemos tener otro conjunto de datos cargado desde el archivo de texto de nombres de Marvel y simplemente hacer un filtro sobre eso por el ID del año que nos interesa para obtener el nombre de nuestro ganador. Entonces con eso, vayamos al código y veamos cómo funciona. Entonces,
volvamos a nuestro proyecto aquí, abramos el script de conjunto de datos de superhéroes más popular y recorremos lo que está haciendo. Entonces vamos a hacer esa misma estrategia de la que hablamos aquí en las diapositivas. Empezaremos importando las cosas que necesitamos como siempre y declarando nuestro objeto. Tenemos dos clases de casos aquí, porque tenemos dos conjuntos de datos para cargar. Uno va a ser la base de datos de nombres de superhéroes que mapea identificadores de superhéroes, que son enteros, dos nombres que son cadenas. Y también sólo tenemos un conjunto de datos de superhéroes. Y esto sólo va a ser una cadena porque en realidad
no vamos a preocuparnos por estructurar esos datos. Simplemente nos vamos a preocupar por, bueno, cuál es la línea cruda real de los datos de entrada y cuántas cosas separadas por espacio hay en ella. Por lo que no necesitamos ponernos de lujo aquí. Simplemente vamos a importar en la cadena real de la línea misma en su forma cruda. Entonces, no realmente haciendo pleno uso de lo que los conjuntos de datos pueden hacer aquí, pero no necesitamos hacerlo. No somos como hacer análisis de fantasía aquí. Solo estamos contando cuántos campos hay en cada fila. Entonces con eso, arrancaremos las cosas. Por lo que nuestro nivel de registro definió nuestra sesión de Spark. Y empezaremos creando nuestro esquema de nombres de superhéroes. Esto nos permitirá cargar ese guión de Marvel nombra archivo dot txt porque no tiene un archivo de encabezado del que podamos inferir el esquema. Tenemos que decirle qué es explícitamente. Entonces vamos a decir que tenemos dos columnas en ese archivo. Uno es el DNI y otro es el nombre. Y estarán separados por un personaje espacial. Entonces, a pesar de que estamos usando el cargador CSV, podemos usar cualquier separador que queramos. Y en este caso va a ser el personaje espacial. Y se podría decir a estas alturas, pero Frank, ¿Y si tengo un espacio a mi nombre? Bueno, lo bueno del cargador CSV es que es inteligente con las comillas. Por lo que realmente manejará eso porque nuestros nombres están
entre comillas en ese archivo, lo cual es genial. Muy bien, entonces necesitamos cargar también el archivo de datos del gráfico de tablero de Marvel también. Y sólo vamos a cargar eso directamente como un tipo de datos de superhéroe. Entonces no hay necesidad de inferir un esquema ahí porque solo tenemos una línea, solo lo
estamos tomando, digamos, línea cruda de datos. Entonces no hay ninguna transformación pasando ahí en absoluto. Simplemente vamos a cargar eso justo arriba en el conjunto de datos de superhéroes, que estamos definiendo como solo una vieja cadena llana. Entonces aquí es donde ocurre la acción. Tomamos ese dataset de líneas allí que contiene los datos brutos, y agregamos una nueva columna llamada id Y todo lo que va a hacer es contener esa primera entrada en la línea. Entonces estamos usando split aquí. El split función en SQL en la columna de valor. Ese es el nombre predeterminado de la columna que fue importada por el DataFrame usando el separador de espacio. Y sólo vamos a extraer el primer elemento número 0 de esa operación dividida. Entonces todo esto está haciendo es decir dividir esa línea de datos
sin procesar y arrancar el primer resultado y llamar a eso el ID. Y vamos a poner eso en una nueva columna llamada id Y luego hacemos algo similar por todo lo demás. Entonces tenemos otra columna llamada conexiones, que es sólo tomar el tamaño de cuántas cosas existen en esa fila dividida por espacios. Entonces trabajemos desde adentro aquí. Estamos empezando con la columna de valor, que es el nombre predeterminado de esa columna que cargó el DataFrame. Eso es todo de los datos crudos. Eso lo dividimos en base al carácter espacial, y luego llamaríamos tamaño para contar cuántas de esas cosas existen. Entonces después de que dividimos todo por espacio, ¿cuántos campos tenemos? Entonces restamos uno para restar el ID de héroe al inicio de esa línea de datos. Y ese es nuestro recuento de cuántas conexiones se asocian a esta línea de datos. Y pondremos ese número en nuestra nueva columna de conexiones. Y luego agruparemos por identificación. Esto nos permitirá combinar múltiples líneas juntas para el mismo ID de héroe. Y usamos aquí se ensamblan agregación Trick, vamos a resumir todas las conexiones y cualquier entrada múltiple para un ID de héroe dado que las suma todas juntas. Y vamos a dar ese nuevo resultando en para Tidal, el alias de conexiones. Por lo que estamos introduciendo un nuevo total de suma para cada grupo juntos, héroe ID. Y vamos a llamar a eso conexiones. Entonces eso es básicamente todo. Ahora tenemos un conjunto de datos que contiene cada ID de héroe único porque hicimos un grupo BY y el número total de conexiones para eso aquí están IID bajo una columna de conexiones. Todo lo que tenemos que hacer ahora para encontrar a los superhéroes más populares para ordenarlos. Y eso es lo que estamos haciendo aquí, ordenando en orden descendente. Y además arrancaremos el primer resultado, obtienes el superhéroe más popular. Por lo que ahora nuestro conjunto de datos más popular contiene una fila, que es el superhéroe más popular, con una columna para el ID y para el número de conexiones que tiene Hero. A continuación, necesitamos buscar ahí el nombre del ganador. Entonces en realidad significa algo para nosotros. Por lo que podemos decir el nombre más popular. Vamos a tomar ese conjunto de datos de nombres que cargamos antes, filtrarlo en función del ID más popular. Por lo que el 0 más popular va a ser ese primer campo que es el héroe ID. Y lo usamos para filtrar nuestro conjunto de datos de nombres por esa ID que estamos buscando. Entonces eso nos va a devolver esa fila para la identificación que nos importa. Después seleccionaremos la columna de nombre de ese resultado y nuevamente arrancaremos el primer resultado en la improbable situación de
esta más de una fila para el mismo ID de héroe en ese conjunto de datos. Y en ese punto, sólo podemos imprimir los resultados. Entonces aquí arrancamos la primera y única columna de
nuestro conjunto de datos de nombres más popular allí e imprimimos nombre usando el formato de sustitución. Y decimos que es el héroe más popular con uno más popular que
va a arrancar el segundo campo del resultado más popular ahí que conseguimos, que será el número de conexiones que tuvo el héroe. Entonces vamos a patearlo y a ver qué pasa. Haga clic derecho. Corre. ¿Quién crees que el superhéroe más popular está en el universo Marvel? La respuesta podría sorprenderte. Resulta que es el Capitán América. Eso no lo vi venir. Pero resulta que de todos los superhéroes en el Universo Marvel, Capitán América aparece con mayor frecuencia en todos los cómics con otros personajes. Entonces se mete por ahí, ve figura, quién sabía. Entonces ahí está, Eso es usar conjuntos de datos para resolver este problema. Yo sí quiero dirigir su atención, sin embargo, a la versión RDD del guión también. Entonces te darás cuenta de que tuvimos que hacer algunas cosas complicadas aquí para analizar esos datos, ¿verdad? Por lo que tuvimos que gustarnos agregar estas nuevas columnas que hicieron alguna información bastante pesada allí. Teníamos un acarreo alrededor de esa línea original de datos en todo el camino. Entonces, aunque puedes hacer esto solo usando comandos de conjunto de datos, eso no siempre significa que sea lo correcto. De hecho, cuando miras muchos ejemplos en línea de análisis de datos como este, donde necesitas hacer alguna limpieza real y reordenamiento de los datos entrantes. A menudo verás que empiezan cargando cosas usando las interfaces RDD y luego convierten ese RDD en un conjunto de datos para hacer más análisis al respecto. Y si miras la versión RDD de esto, ese es el guión de superhéroes más popular aquí. Ya verás que en realidad es un poco más simple. Entonces, bueno, yo no diría más simple, pero es más sencillo de alguna manera, al
menos el análisis de los datos. Entonces, por ejemplo, veamos cómo analizamos ese archivo gráfico de puntos de Marvel aquí en el ejemplo de RDD. Aquí solo estamos llamando, recargando eso hasta en un RDD y luego usando una función de mapa para contar co-ocurrencias. Echemos un vistazo a lo que eso hace. Cosas bastante sencillas, ¿verdad? Entonces aquí solo estamos dividiendo la línea en base espacios y acabamos de devolver el primer elemento, el ID de héroe y los elementos longitud de punto menos 1. De muchas maneras eso es más simple y más sencillo que cómo lo hicimos con datasets, donde tuvimos que hacer este tipo de enrevesados con columna en realidad dos diferentes con comandos de llamada, con todas estas funciones SQL anidadas para obtener el mismo resultado. Por lo que podría decirse, esto en realidad podría ser más eficiente. Y una vez que tengamos eso, solo podemos hacer una ReduceByKey para conseguir el gran total de amigos por carácter. Entonces, de nuevo, ya sabes, a veces los RDD pueden ser más simples y incluso más rápidos a veces, pero los conjuntos de datos están ahí para ti también. Si no quisieras hacer análisis de datos más complicados sobre datos estructurados verdaderos, Ahí es donde realmente brillan los conjuntos de datos y su poder se vuelve atractivo. Pero recuerda, aunque los datasets en DataFrames son una especie de la forma moderna de usar Spark. No siempre es la mejor manera. A veces los RDD van a ser más sencillos. Entonces, así que aún debes sentirte libre de mezclar y emparejar los dos, porque a veces RDD es la respuesta correcta, a veces los datasets son la respuesta correcta. No siempre es un conjunto de datos. Pero ahí lo tienes. El superhéroe más popular, Capitán América, no lo vio venir a continuación, Hagamos algunas cosas más complicadas con este conjunto de datos y extraigamos de él alguna información más interesante.
33. [Ejercicio] encuentra los superhéroes más oscuros: Bueno, este parece un buen momento para que te vayas y escribas tu propio código por un rato aquí y obtienes algo de práctica. Entonces tu reto va a ser encontrar a los superhéroes más oscuros a diferencia del superhéroe más popular. Y me gusta encontrar imágenes de fotos de stock cursi. A veces este superhéroe se ve bastante oscuro. A lo mejor es un oficinista. No lo sé. De todos modos es un poco perturbador. Entonces el problema es que quiero que enumeren los nombres de todos los superhéroes en nuestro conjunto de datos que solo tienen una conexión. Y esto va a ser un poco más difícil de lo que parece que
podrías pensar que podrías simplemente tomar el guión existente que tienes para los superhéroes más populares y cambiar un máximo a un mínimo en alguna parte y terminarlo o ordenar por un orden diferente. Pero no es tan sencillo porque el código que te
acabo de dar supone que sólo hay una respuesta, un superhéroe más popular. No obstante, en este caso, en realidad hay muchos superhéroes en nuestro conjunto de datos que solo tienen una sola conexión. Y los vas a enumerar a todos junto con sus nombres. Entonces eso hace las cosas un poco más complicadas. Vas a tener que unirte a un conjunto de datos en algún momento con el
conjunto de datos de nombres para imprimir todos esos nombres juntos a la vez. Es decir, podrías hacerlo después del hecho y, ya sabes, poco hacer con la forma en que lo hicimos originalmente y buscar nombres individuales mientras los imprimes. Pero eso no va a ser tan eficiente como simplemente unirse a los nombres en algún momento para meterlos a todos, manera distribuida
en todo el clúster. Y para un crédito extra, Vea si puede computar el número más pequeño real de conexiones en lugar de simplemente asumir que es una. Si puede averiguar cómo hacer el comando min para realmente averiguar el número más pequeño de conexiones en todo el conjunto de datos, lugar de simplemente codificarlo duro a uno. Eso sería lo que más principios hay que hacer, ¿verdad? Pero resulta que la respuesta es una que es el menor número de conexiones. No hay ninguno que tenga 0 en el conjunto de datos. Fueron filtrados ya aparentemente. Y uno es el número mágico, pero sería mejor computar eso de alguna manera, ¿verdad? Entonces aquí está la estrategia general que querrás usar aquí. Empieza con una copia del script de conjunto de datos de superhéroes más popular que acabamos de ver. Y si solo haces una copia de ese guión e Intel J y luego lo pegas en el paquete. Eso te dará la oportunidad de cambiar el nombre de ese script a medida que lo copias. Así que solo llámalo algo así como superhéroes más oscuros o algo así. Y ese script puede estar en gran medida sin cambios hasta el punto en que construimos el conjunto de datos de conexiones. Eso te va a dar este conjunto de datos que tiene cada superhéroe y cuántas conexiones tienen. Y eso todavía va a ser útil para este ejercicio. Pero de ahí entonces en adelante, va a ser completamente diferente. Entonces en ese punto vas a querer filtrar eso hacia abajo para encontrar solo las filas que tienen una conexión. Y luego cuando filtra eso hacia abajo, quieres unir esos resultados con nuestro conjunto de datos de nombres para unirte a los nombres de cada superhéroe en ese filtro hacia abajo en dataset. Ahora nota aquí estamos pensando un poco en el rendimiento aquí, ¿no? Podría haberme unido a ese conjunto de datos de nombres antes filtrar todas esas conexiones que solo tienen una conexión. Pero eso obligaría a mi clúster a hacer mucho más trabajo del que tiene que hacer, ¿verdad? De qué sirve unirme a los nombres para todos estos superhéroes que tienen más de una conexión, no
voy a exhibir esos. Por lo que a veces a pesar de que Spark está optimizado y tiene mucha optimización automática, aún hay que pensar un poco en los resultados que desea y en el orden correcto para hacer las cosas. Muy bien, así que una vez que tengamos eso, solo
necesitamos seleccionar la columna de nombres y mostrarla. Y eso es más o menos. Y si quieres algunos consejos extra aquí, Aquí hay algunos fragmentos de código que podrían ayudarte. Nuevamente, si quieres filtrar un conjunto de datos para algún nombre de columna igual a algún valor, se vería algo así. Simplemente el nombre del conjunto de datos filtro punto. Recuerde que la sintaxis es el signo del dólar y luego el nombre de la columna de cotización. Y tres signos igual a cualquier valor contra el que quieras filtrar. También para unir un conjunto de datos con otro. Esto es igual que una operación de unión SQL. Podrías simplemente decir nombre del conjunto de datos, sea lo que sea, unir puntos, y luego especificar el nombre de otro conjunto de datos que comparte un nombre de columna común que puedes usar para unir esos conjuntos de datos juntos. Entonces en nuestro caso, esa será la columna de identificación. Y luego dices que usar columna es igual a lo que sea ese nombre de columnas comunes. Y eso se unirá en los campos del segundo conjunto de datos con el primer conjunto de datos donde coincida ese nombre de columna común. Y por último, si sí quieres el crédito extra, realidad no
estoy haciendo un seguimiento de tu puntuación aquí. Esto está totalmente en el sistema de honor. Pero si realmente quieres computar el número mínimo de conexiones que se encuentran en el conjunto de datos, se vería algo así. En el conjunto de datos, utilizaría el comando add y el uso para contener el comando minimum en el nombre de la columna que le interesa encontrar el mínimo de que devolverá un conjunto de datos. Pero si realmente quieres volver a meter ese valor real en tu script de conductor como un valor de Scala. Para convertir eso de nuevo, primero
debes llamar a punto primero para extraer esa primera fila de ese resultado. Y sólo habrá una fila. Y eso te devolverá un tipo de datos de fila. Y eso no va a ser útil en sí mismo. Entonces vamos a llamar a get long as 0 para extraer el primer número de esa fila, que será ese valor mínimo. Entonces la sintaxis hay un poco mal, pero eso es lo que tienes que hacer para realmente recuperar ese número
del conjunto de datos y en un valor real que luego puedes usar en tu operación de filtro. Así que buena suerte. Wow, si hubiera un Hombre de Brócoli, estoy bastante seguro de que estaría en esa lista final en tus resultados. Ese es un cuadro súper perturbador. Hagamos que esto desaparezca. Ve a escribir algún código y volveremos en la próxima conferencia y te mostraré mi solución.
34. Solución de ejercicio: encuentra los superhéroes más oscuros: Está bien, espero que hayas tenido un go en ese ejercicio y aquí está mi solución al problema. Nuevamente, hay muchas formas de hacer esto. Entonces, mientras obtienes los mismos resultados que yo hice, eso es lo que cuenta. Hay muchas formas de hacer esto. ¿ Piensas en lo eficiente que fue tu solución sin embargo? Y hablaremos un poco de eso. Entonces como sugerí, acabo de copiar el guión de superhéroes más popular. Y al hacer eso, acabo de hacer clic derecho en eso y dije copiar y copiar o simplemente Control C. Y luego si lo pegas en com dot sun dot software dot chispa, eso te dio la oportunidad de duplicar ese guión con un nuevo nombre. Y en mi caso, lo duplicé con el nombre de superhéroes más oscuros, dot Scala. Entonces sigamos adelante y echemos un vistazo a eso y caminemos por mis cambios. La mayor parte del guión no cambia. Todo lo que hice fue cambiar el nombre, como dije, y también cambié el nombre de la app porque ¿por qué no? Y como dije, va a ser lo mismo hasta
la construcción de ese conjunto de datos de conexiones. Entonces aquí es donde construimos el conjunto de datos de todos los identificadores de superhéroes y el número de conexiones que tienen. Y esa columna número de conexiones se llama conexiones. Entonces en este punto tenemos un conjunto de datos que tiene un ID y conexiones. Entonces eso no ha cambiado. Utilizamos esa misma información para encontrar al superhéroe más popular. Pero una vez que tenemos eso, necesitamos filtrar eso hasta los resultados que tuvieron el menor número de conexiones. Y resulta que sé que el número es uno, que el menor número de conexiones en mi conjunto de datos es uno. Pero si quisiera definir eso de manera algorítmica, podría hacer algo como esto. Podría decir val, Min recuento de conexiones. Y eso va a ser un valor escalar que sí sostiene algún número igual a conexiones dot agg. Solo necesitamos eso para envolver esa función SQL min ahí. Nombre de columna Hombres es igual a conexiones. Entonces en este punto, estamos diciendo conexiones AG Min, conexiones de nombre de columna, así nos devolverán un conjunto de datos que tiene una sola fila en ella, nuevamente contiene una columna que contiene el valor mínimo encontrado en la columna de conexiones. Ahora en este punto tenemos todavía un DataFrame. Y en realidad queríamos devolverlo a nuestro guión de conductor como valor, ¿verdad? Por lo que primero necesitamos llamar primero a punto para convertir ese conjunto de datos en una sola fila. Y luego una vez que tenemos ese objeto de fila, llamamos getline non-zero para extraer el primer y único campo de esa fila y convertirlo de nuevo a un entero largo. Entonces esta pequeña expresión complicada aquí computa ese valor mínimo y lo convierte de nuevo a un conjunto de datos, lo
trae de vuelta al script del controlador con el primer comando, y luego las llamadas se alargan para extraer el número de ese dataset de esa fila del conjunto de datos más específicamente. Por lo que ahora el conteo de conexiones principales será igual a uno. De acuerdo, entonces ahora que sabemos cuál es nuestro número mínimo de conexiones, podemos filtrar nuestro conjunto de datos de conexiones en él diciendo conexiones filtro de puntos, conexiones de signo de
dólar es igual, igual, igual, recordar tres iguales. Una especie de extraña peculiaridad de la sintaxis aquí, equivale al recuento de conexiones min, que será uno. Y si tuvieras aquí el enfoque más directo y asumas que era uno, podrías haber dicho que es igual, igual igual a 1. Y eso funcionaría también. Entonces estamos tomando ese dataset filtrado y llamándolo Conexiones Min. Por lo que el conjunto de datos de conexiones de hombres ahora solo contiene las ID de héroe. Que contienen una conexión. Por lo que todavía tenemos la columna de conexiones colgando por aquí. Ahora necesitamos unirnos a los nombres de esos superhéroes para poder mostrarlos realmente y tener resultados legibles por humanos. Y eso es lo que está pasando en esta línea aquí, estamos diciendo Min conexiones con nombres es igual a min conexiones dot join con el dataset de nombres usando ID de columna. Por lo que notarás que tanto las conexiones DataFrame como los nombres dataframe tienen un campo llamado ID. Y vamos a usar eso para unir estos dos conjuntos de datos juntos. Entonces, para cada fila en nuestro conjunto de datos de conexiones Min, básicamente
vamos a buscar el ID en esa fila y unirnos en el nombre del conjunto de datos de nombres que tiene esa misma ID. Al igual que un comando SQL join si estás familiarizado con eso. Entonces en este punto vamos a tener un conjunto de datos que contenga no sólo un ID y número de conexiones, sino también una columna de nombre a la que nos unimos desde ese nombre DataFrame. Por lo que ahora finalmente podemos imprimir nuestros resultados. Entonces, en primer lugar, imprimamos un poco de encabezado sólo porque queremos que los resultados se vean aseados. No tenías que hacer esto. Por supuesto, vamos a decir que los siguientes caracteres sólo tienen conexiones de recuento de conexiones Min. En ese caso seré 1. Y luego solo decimos Min conexiones con nombres, dot select name para simplemente seleccionar esa columna de nombre. No me importa nada más Para la salida final. Y los puntos muestran para mostrar eso como la salida de mi script de conductores. Tiene sentido. Bastante sencillo. Y de nuevo, hay más de una forma de hacerlo. Aunque haces una cosa sobre el rendimiento. Esta es una forma bastante buena de hacerlo. Podría haber una forma más eficiente de conseguir realmente ese valor mínimo allí sin
detener realmente mi guión aquí y básicamente detener al mundo aquí para averiguar cuál es ese valor mínimo en este momento. Porque ha vuelto a mi script de conductor y estoy usando ese valor en una sección posterior de mis scripts de conductor. Por lo que toda esta sección de arriba aquí tiene que correr es un paso. Se va a parar en el clúster, esperar a que ese resultado regrese para el valor mínimo, y luego arrancar las operaciones posteriores del conjunto de datos después de eso, eso podría no ser del todo óptimo. Pero hay una mejor manera de hacerlo. No lo he averiguado. Creo que eso es inevitable en este caso. Pero una cosa que sí hice, como dije en las diapositivas, fue asegurarme de que solo hice esa operación de unión una vez que
filtré las conexiones al conjunto final de resultados que quería, juntas son operaciones caras en Spark. Por lo que definitivamente quieres mantener esos tan pequeños y tan limitados como puedas. Entonces ese fue el método de mi locura para hacer en ese unir después de la operación del filtro en lugar de antes de ella. Y también ruido. Tenga en cuenta que no estoy iterando a través de los resultados finales en hacer una búsqueda de conjunto de datos en el dataset de nombres para cada nombre único y el script de controlador. Eso será aún peor. Entonces esto es bastante óptimo. Entonces sigamos adelante y corramos y veamos qué obtenemos. Superhéroes más oscuros corren ahí
va. Y aquí vienen héroes oscuros. Los siguientes caracteres tienen una sola conexión. Y es una lista bastante corta. Pero trabajador a Blair, Marvel muchacho. Seguimiento torpe. Si bien estas son, ya sabes, ha
habido muchas películas de superhéroes de Marvel de alguna manera. No creo que vayamos a ver uno sobre seguimiento torpe. Esa es una tarjeta bastante oscura. No he oído hablar de ninguno de estos tipos, si tiene usted si lo tiene, dilo en los comentarios, podría estar interesado en enterarse de ello. Entonces sí, cuando, cuando Marvel empieza a hacer películas sobre estos personajes, ya
sabes, realmente han tocado el fondo del barril. Está bien, bueno ese fue un ejemplo interesante ahí. Entonces espero que tuvieras algún éxito con ese ejercicio y obtuvieras los mismos resultados que yo. El orden obviamente no tiene que ser el mismo, pero debes tener la misma lista de resultados aquí en lo que hayas hecho. De no ser así, vuelve a bug lo que hiciste y sigue iterando en él hasta que obtengas la respuesta correcta. Y es una buena práctica. Y con eso, sigamos adelante.
35. Grados de superhéroes de la separación: introducción de la búsqueda de la primera búsqueda: Entonces el propósito de este próximo ejercicio es mostrarte que la chispa a menudo se
puede usar para paralelizar problemas que tal vez no hayas pensado que Spark podría hacer. Por lo que muchas veces la gente usa Spark para Data Analytics y específicamente para cosas que se pueden expresar como un comando SQL. Pero puede hacer mucho más si solo piensas creativamente al respecto. Entonces como ejemplo, averigüemos los grados de separación entre los superhéroes en nuestra red social de superhéroes aquí, para recapitular con la idea de grados de separación es si no lo estás familiarizado, bueno, de vuelta en Hollywood, solía
haber un concepto llamado tu número de tocino. Y así fue cuántos grados de separación y actor fue de Kevin Bacon. Había esta leyenda en la que Kevin Bacon estaba tan bien conectado, apareció en tantas películas diferentes que casi todos los actores podían rastrearse hasta Kevin Bacon de alguna manera. Y es verdad en realidad. Entonces, ¿cómo funciona eso? Pongamos eso en términos de nuestros datos de superhéroes, ¿verdad? Entonces digamos que por el bien de la discusión, Spider-Man apareció en el mismo cómic que el Incredible Hulk. Y el Increíble Hulk a su vez apareció en el mismo cómic que Thor. En ese caso, diríamos que Spider-Man y Thor son dos grados de separación, ¿verdad? Porque si miras las conexiones de Spider Man, el Hulk no está en ese conjunto inmediato de conexiones. Alguien con el que Spider-Man se conectó está conectado al Hulk. Entonces eso está a dos pasos de Spider-Man o a dos grados de separación. Entonces eso es algo interesante de mirar. Resulta que la gente está más conectada de lo que se podría pensar. Y resulta que eso también es cierto en el mundo de los cómics. Entonces, ¿cómo haríamos esto? Bueno, hay un algoritmo de ciencias de la computación llamado
búsqueda breadth-first que resuelve este tipo de problemas para nosotros. Y esto ciertamente no es algo donde simplemente escribirías un comando SQL y te harías con él para encontrar la respuesta, ¿verdad? Queremos descifrar para cualquier persona dada en cualquier nodo dado, en este caso, cualquier superhéroe dado en esta gráfica de conexiones. ¿ A cuántos pasos se encuentra un superhéroe dado de cualquier otro superhéroe? Entonces, ¿cómo haríamos esto usando Apache Spark? Bueno, antes de hablar de los detalles de implementación, hablemos del algoritmo. lo que para entender este ejemplo, es necesario entender la búsqueda de amplitud primero o BFS. Este es un problema de algoritmos de ciencias de la computación. Y si vas a estar entrevistando para puestos de ingeniero de software, es algo bueno saber, aunque no está directamente relacionado con chispa. Entonces si no sigues los detalles aquí, no te pongas demasiado colgado en ello. No es realmente relevante chispearse a sí misma. Solo soy relevante para entender este ejemplo de cómo se puede usar Spark para resolver problemas para los que quizás no hayas pensado que se puede usar Spark. Entonces imagínense esto representa nuestra red. Entonces cada círculo aquí representa a un superhéroe, y cada línea entre esos círculos representa una conexión entre superhéroes. Entonces eso significa que aparecieron juntos en el mismo cómic. Y algunos, ya sabes, a veces tienes muchas conexiones saliendo de un superhéroe y a veces hay muchas rutas entre dos superhéroes que mirar. Por lo que el número dentro de cada círculo representa la distancia de ese superhéroe de cualquier superhéroe del que estemos midiendo los grados de separación. Y inicialmente no conocemos la respuesta ya que estamos iniciando este algoritmo. Por lo que todo está puesto al infinito. Asumimos que están infinitamente lejos porque aún no lo hemos computado. Entonces para empezar, escogimos al superhéroe con el que queremos empezar y a quién queremos calcular los grados de separación. Entonces digamos eso Spider-Man, y llamaremos a esa S aquí en este ejemplo. Entonces el arranque, el algoritmo, coloreamos ese nodo inicial gris, lo que significa que necesitamos explorar ese NOAEL, queremos saber más sobre las conexiones de ese nodo. Y ponemos el número 0 porque esa es la distancia de la persona con la que estamos empezando 2, ese nodo. Spiderman es 0 grados de separación de Spider-Man porque Spider-Man es Spider-Man. Entonces, ¿qué hacemos en el algoritmo BFS es que vayamos buscando nodos grises en nuestra gráfica. Y por cada nodo gris que encontramos, exploramos las conexiones que salen de ese nodo gris. Y cuando lo hagamos si ese nodo que estamos explorando su blanco, lo que
significa que ha sido inexplorado previamente, lo
colorearemos de gris, que
significa que necesitamos explorar ese nodo más iterativamente. Y tomaremos el nodo que acabamos de explorar en color negro, lo que
indica que ya hemos explorado ese nodo. No necesitamos volver a ello. Incrementamos el conteo actual de distancia. Por lo que fue 0 más uno es uno. Entonces ahora sabemos que somos un grado de separación en R y W Tiene sentido. Por lo que empezamos a explorar ese nodo gris inicialmente color
S a negro porque ya terminamos con él. Y por todas sus conexiones, si fueran blancas, hacemos grises ahora y ponemos en el conteo actual de distancia desde ese nodo inicial. Entonces en el siguiente pase, nuevamente, buscamos las notas grises y exploramos sus conexiones. Entonces empecemos con w Ahí se romperán sus conexiones. Por lo que esos dos eran blancos originalmente y ahora los vamos a colorear de gris e incrementar de nuevo la distancia. Por lo que ahora estamos a dos grados de separación de S hará lo mismo para la conexión de S a R. Explora Es una conexión a v y colorela gris. Y de nuevo, pon un dos ahí porque actualmente estamos en la iteración de dos distancia de S. Ahora que hemos explorado están en W, vamos a llamarlo se vuelve negro, que
significa que no debemos volver a visitarlos en el futuro. A continuación, empezaremos con T. Nuevamente. Tenemos que pasar por todos los nodos grises y volver a explorar sus conexiones. Ahora T está conectada a u, que era blanco, por lo que ahora colorearemos ese gris e incrementaremos nuevamente el recuento de distancia a tres. Ahora. Ahora tenga en cuenta que t también está conectada a x y w, Pero esos no son blancos. Vamos a tratar de preservar el color más oscuro aquí a medida que pasamos. Entonces no nos vamos a molestar en volver a visitar x otra vez. Ya está marcado en gris. Definitivamente no vamos a volver a visitar a W porque eso está marcado de negro. Eso significa que ya hemos hecho esa. No necesitamos un proceso que uno en absoluto. Entonces podemos marcar x se está explorando ahora, tenemos, podemos marcar ese negro ahora porque ya hemos determinado que hemos terminado con él. Y seguir adelante. También necesitamos explorar si aún no hemos terminado esa. Por lo que iremos a revisar V como negro ahora también. Ese era un gris originalmente. Entonces ahora el siguiente paso es simplemente llamar a eso negro, lo que significa que ya terminamos de explorarlo. Ahora sólo tenemos dos nodos grises más por explorar aquí. Y no tienen ningún nodo recién inexplorado asociado a ellos. Por lo que sólo vamos a colorearlos de negro y terminar con ello. Entonces el algoritmo general aquí para recapitular, empezamos por colorear todo en blanco con una distancia desconocida. Nuestro nodo inicial es gris, y para cada iteración, buscamos nodos grises, exploramos sus conexiones. Y por cada nodo blanco que salga de ese nodo gris, lo
marcaremos como gris para futura exploración a menos que ya haya sido de color gris o negro, donde precisamente preservando el color más oscuro que hay a medida que vamos. Y además, estamos preservando la métrica de distancia más baja que vemos en estos nodos a medida que avanzamos. Entonces nunca vamos a hacer algo como ir de ti de vuelta a T y decir que t es ahora una distancia de cuatro porque retrocedimos, eso tendría sentido, ¿verdad? Por lo que siempre preservaríamos esa métrica de menor distancia ya que estamos atravesando la gráfica. Por lo que es algo difícil envolverte la cabeza. Y de nuevo, si no lo seguiste del todo, no te preocupes demasiado por ello. Este no es un curso sobre algoritmos, es un curso sobre Spark. Solo estoy tratando de transmitir cómo es posible usar Spark para resolver problemas que tal vez no pensarías Spark con adecuado para. En realidad se puede paralelizar bastante
bien este problema si lo pensamos de manera creativa. Entonces hablemos de esa implementación en Spark siguiente y hagamos que esto suceda en nuestro Clúster de Spark.
36. Gradas de superhéroes de la separación en : Accumulators, e implementar BFS en Spark: Entonces hablemos de cómo enmarcar esto como un problema de chispa y en realidad distribuyó la primera búsqueda de ancho a través de todo nuestro clúster potencialmente. Entonces lo primero que tenemos que hacer es representar nuestros datos entrando como estos nodos de los que hablamos en la conferencia anterior. Entonces por ejemplo, una línea de entrada podría estar en este formato, el primer número es algún ID de héroe, seguido de una lista de los otros héroes que Hero ha aparecido con otros cómics. Por lo que queremos estructurar eso de una manera que represente uno de estos nodos en la búsqueda de ancho primero. Entonces por ejemplo, podríamos estructurar esto como la siguiente tupla de tuplas, si se quiere. Donde el primer elemento es el ID de héroe del que estamos hablando. El que básicamente está representado por este nodo, seguido de una lista de todos los demás identificadores de héroes que están conectados a este héroe. Entonces imagínense una línea virtual entre 59, 83 y 11, sesenta y cinco, treinta y ocho, treinta y seis, etcétera, etcétera. Entonces estas son todas las conexiones que están conectadas a nuestro héroe. Y eso en sí está dentro de su propia tupla. Para mantener eso todo autónomo. El siguiente elemento en nuestra tupla representará la distancia asociada a este nodo del personaje del que estamos midiendo la distancia. A inicialmente, pusimos eso al infinito. No hay forma de representar realmente el infinito aquí, así que simplemente lo pondremos en un número realmente grande. En este caso, 99. El 99 será nuestro sustituto para el infinito como valor de distancia inicial. Y necesitamos asociar un color. Recuerda, nuestras notas podrían ser blancas, grises o negras, donde el blanco representa un nodo inexplorado. El gris representa un nodo que necesita ser explorado, y el negro es un no que ya se ha explorado. Por lo que inicialmente cada nodo es blanco. Entonces ese es un ejemplo de cómo podemos representar estas líneas en un formato que es consistente con nuestro concepto de nodos en una búsqueda de primer aliento. Por lo que ahora realmente pasar por ese algoritmo de búsqueda primero de amplitud se puede pensar como un mapa y reducir la operación. La función de mapeo se encargará de convertir esas líneas en el formato de nodo BFS del que acabamos de hablar. Y ese código podría verse así. Por lo que sólo necesitamos dividirlo por espacios, convertir los ID de héroe en enteros y las conexiones a enteros
acumulan una matriz de conexiones que son todas las conexiones asociadas a esa persona. Establezca el color inicial en blanco. Establezcamos la distancia inicial en 99, 99. Y si el ID de héroe es uno, estamos empezando con el caso inicial para el que estamos empezando. Color que uno gris con una distancia de 0, pero todo lo demás debe ser blanco con una distancia de infinito como nuestro caso inicial. Y acabamos de devolver nuestra estructura tuplada de la que hablamos con el ID de héroe. Y luego además, el array de conexiones y la distancia y el color. Ahora, tal vez sea una buena idea
hablar un poco de la historia de la computación distribuida aquí. Por lo tanto, tenga en cuenta que estamos usando un paradigma de MapReduce para especie de pensar en este problema. ¿ De dónde viene esa idea? Por lo tanto, cuando Google se ocupaba por primera vez analítica de datos a
gran escala y la necesidad procesar datos que no cabían en una sola máquina. Inventaron MapReduce. Y MapReduce estaba más o menos limitado a las funciones de mapa y reducir funciones. Eso fue lo que hizo, ¿verdad? Y hemos visto ejemplos de mapeadores y reductores en ejemplos anteriores de este curso, pero tiene que ser, Ese es más o menos el único truco que teníamos en nuestras mangas. Hadoop se construyó encima de los conceptos que se le ocurrió a Google. Y Hadoop, también tiene algo llamado MapReduce. En realidad se llama MapReduce, una palabra que es un componente esencial del propio Hadoop. El problema es que MapReduce no era muy inteligente en cuanto a la optimización, y ahí es donde entró Spark. Entonces Spark inicialmente solo era una especie de alternativa más rápida a MapReduce. Entonces de ahí salió la interfaz RDD inicial de chispa. Notarás que los RDD tienen una función de mapa y una función de reducción disponible para ellos. Y por eso, porque intentaban replicar la funcionalidad de Hadoop MapReduce. Ahora más tarde con el tiempo, cuando llegamos a Spark Versión 2, cuando se introdujeron DataFrames y DataFrames. Dataframes llegó primero en realidad. Y ahí fue cuando empezamos a decir, Hey, pensemos en esto en términos de operaciones SQL. Sql se estaba convirtiendo en el lenguaje común entre los paquetes de software de análisis de datos en ese momento. Entonces incluso para cosas que se distribuyeron y técnicamente no eran adecuadas para las operaciones de bases de datos relacionales. Sql todavía se estaba convirtiendo en la sintaxis común entre todas estas diferentes plataformas. Por lo que vimos esta evolución de MapReduce a chispa que fue una especie de construida como una extensión para hacer mejor MapReduce. Para chispear convirtiéndose más en una interfaz SQL SAL. Pero no todo es un problema SQL, ¿verdad? Por lo que aún tenemos esa funcionalidad de nivel más bajo de MapReduce disponible para nosotros que podemos usar para resolver problemas de propósito más general como este. No puedo escribir un comando SQL que diga computar la distancia en una gráfica entre dos nodos cualquiera. Pero puedo enmarcar eso como problemas de MapReduce. Entonces eso es lo que vamos a hacer aquí. Nuevamente, se trata de elegir la herramienta adecuada para el trabajo, pesar de que podemos hacer esto con un conjunto de datos. Y les mostraré que en este caso, uso de RDD y su
funcionalidad de mapeo y reducción de nivel inferior va a ser el enfoque más sencillo. De acuerdo, fuera de mi plataforma, hablemos un poco más de la implementación. Entonces al igual que caminamos en las diapositivas para la búsqueda de ancho primero, vamos a pasar por las cosas de manera iterativa. Y por cada paso, cada distancia, vamos a buscar todos los nodos grises y
expandir esos nodos grises hacia fuera. Colorea la nariz. Ya terminamos con su negro y solo seguimos incrementando las distancias a medida que avanzamos. Entonces vas a ver un gran bucle a que simplemente
pasa iterativamente por ese gráfico una y otra vez,
buscando nodos grises y procesando esos nodos grises consecuencia en base a las reglas que definimos en el BFS algoritmo. Está bien, así que de nuevo, sólo estamos enmarcando esto como un mapa y un trabajo de reducción. Por lo que cada vez que incrementamos a través de nuestro algoritmo, el mapeador incrementará la distancia en una. Y va a buscar notas grises. Si encuentra un nodo gris, va a mirar todas las conexiones de ese nodo gris, colorelas grises para futuras exploraciones. Y en un principio no tendrán conexiones porque
necesitan ser exploradas para construir esas conexiones. En la siguiente iteración, el grano de avena que simplemente procesa será entonces de color negro. Y copiará el propio nodo de nuevo en los resultados para asegurarnos de que no lo perdamos. El trabajo de los reductores será atender todos aquellos casos en los que tengamos múltiples caminos yendo al mismo nodo, muchas conexiones. Por lo que necesitamos combinar todos los nodos que existen para el mismo ID de héroe. Y si hay un caso donde hay múltiples conexiones, queremos preservar la conexión con la distancia más corta y el color más oscuro. Y como está reduciendo cosas que conservarán esa lista de conexiones desde el nodo original para asegurarnos de que no perdamos las de la siguiente iteración. Entonces Así funciona todo desde un punto de vista algorítmico. Pero, ¿cómo sabemos cuando terminamos? Entonces aquí es donde vamos a introducir un nuevo concepto llamado el acumulador en Spark. Por lo que un acumulador es básicamente un contador compartido a través de todos los ejecutores de tu clúster. Entonces si necesitas tener una especie de contador comúnmente sostenido, si quieres, o una bandera de algún tipo. Y acumulador puede hacer eso. Permite que muchos ejecutores incrementen alguna variable compartida en todo el clúster. Entonces aquí hay un ejemplo de esta sintaxis. Podría decir que el contador de golpes es un acumulador largo llamado contador de golpes. Y por defecto su valor inicial será 0. Por lo que a medida que estamos pasando por nuestro algoritmo, nuestras iteraciones se van a distribuir a lo largo de toda nuestra plataforma. Y cualquier ejecutor individual podría golpear al personaje que nos interesa. Entonces, cuando eso sucede, ese ejecutor necesita de alguna manera señal de vuelta
al guión del conductor en su conjunto, Hey, ya terminamos. En realidad nos dieron un golpe aquí. Por lo que podemos incrementar el acumulador de contador de golpes en ese caso para indicar
que realmente encontró al personaje que estamos tratando de encontrar la distancia de a nuestro personaje original. Entonces cuando terminemos con cada iteración, solo
comprobamos si el contador de hits es mayor que uno. Y si lo es, sabemos que ya terminamos y a veces conseguiremos un hit desde múltiples direcciones y ese contador de golpes de obstáculos podría ser más de uno. Uh, pero así es como sabemos que hemos terminado. Esos ejecutores pueden devolver la señal al guión, Hey, me dieron un golpe. Y puede hacer un seguimiento de cuántos hits al tener este acumulador compartido a través de todos los ejecutores. Entonces eso es mucho para envolverte la cabeza. Vayamos al código y veamos cómo se ve.
37. [Actividad] grados de superhéroes de separación: ¡revisa el código y correr!: Entonces vamos a sumergirnos en el código, abrimos grados de separación, aún
no el conjunto de datos uno, sólo grados de separación. Y caminaremos por este código. Ahora otra vez. El punto de este ejercicio es sólo para mostrarte que puedes hacer cosas
complejas con Spark que no solo se limitaba a las operaciones de estilo SQL. Entonces si quieres hacer como la analítica de datos tradicional, genial, usa comandos SQL. Pero para cosas como esta, es posible que necesites bajar al nivel más bajo de Spark y volver a la interfaz RDD. Y eso está bien, eso es, eso está disponible para ti también. Y ya sabes, eso es una especie de pensamiento creativo es realmente lo que empresas como Amazon y Google y Apple van a estar pagando a la gente los grandes dólares, ¿verdad? No se necesita alguien realmente especial para escribir un comando SQL y averiguar cuántos hits de sitio web tuviste en la última hora. Pero sí se necesita alguien especial para averiguar cómo puedo tomar un problema que nunca se ha resuelto antes de usar Apache Spark y resolverlo. Y aquí hay un ejemplo de hacer eso. Entonces si no sigues el código aquí, si no sigues el algoritmo, no te estreses demasiado por eso. Ese no es realmente el punto de esta actividad. El punto es sólo para mostrarte que es posible hacer cosas complicadas en Spark y paralelismo a través de un clúster que quizá no hayas pensado posible. En este caso, estamos pensando más en un paradigma MapReduce que en un paradigma SQL. Y eso está bien. Entonces buceando en, importamos todas las cosas que rezamos o grado de objeto. Ahora lo primero que hacemos es definir de
qué personaje partimos y qué personaje buscamos. Por lo que el propósito de este guión va a ser encontrar los grados de separación entre Spider-Man, que es el personaje ID 5306, resulta, y el átomo del personaje 3,031, que francamente es el personaje más oscuro I encontrar en el conjunto de datos, al menos nunca oí hablar de ellos. No tengo ni idea de quién es ese. Y su identificación de personaje es 14. Entonces lo que estamos tratando de hacer es encontrar los grados de separación entre Spider-Man y Adam, 3,031 aquí. Y hablamos de usar un acumulador llamado contador de golpes. Y así va a ser como nuestros ejecutivos hacen una señal para decir, Hey, en realidad
encontré átomo 3,031 mientras atravesaba la gráfica de Spider-Man. Entonces eso va a ser una especie de nuestro contador compartido que dice, oye, tengo una conexión aquí. A continuación configuramos nuestros tipos de datos aquí. Por lo que tenemos un tipo de datos BFS que es una matriz de enteros y un entero y una cadena que representará una lista de conexiones, la distancia y el color asociado al nodo. Y el propio nodo tendrá el ID de héroe asociado a ese nodo y los datos asociados a él. Por lo que un nodo BFS va a representar uno de esos círculos en nuestras diapositivas que representa cierto ID de héroe. Y las conexiones en ese Héroe tiene la distancia de Spider-Man. Y finalmente, el color de ese nodo, que va a ser blanco, gris, o negro. Saltemos a la función principal y trabajemos hacia atrás desde ahí. Por lo que aquí abajo en algún lugar, tenemos una función principal. Empieza diciendo el nivel de registro y configuramos un nuevo contexto de Spark. No estamos usando una sesión de Spark porque no estamos usando la interfaz de conjunto de datos en este ejemplo, solo
vamos a estar usando RDD. Y para eso sólo necesitamos Chispark contexto. Inicializamos nuestro acumulador y le damos un nombre. Y lo primero que hacemos es crear arrancando RDD. Entonces esto está creando esas condiciones iniciales de nuestra gráfica. Entonces veamos qué hace eso. ¿ Dónde está crear arrancando RDD? Muy sencillo, ¿verdad? Entonces todo lo que estamos haciendo aquí es cargar el texto de punto del gráfico de puntos de Marvel en un archivo de entrada sin procesar RDD. Y luego llamamos mapa con converge a BFS para convertir esos datos al formato de nodo BFS. Echemos un vistazo a Convertir a BFS. Divide la línea en campos individuales, arranca el primero hace que el ID de héroe arranque todos los campos subsiguientes aquí y rellena una matriz de enteros y que va a representar todo el conexiones de ese héroe con otros héroes. Estableceremos su color predeterminado en blanco y es la distancia por defecto en
99, 99, que es nuestra representación del infinito, a menos que seas Spider-Man. En cuyo caso te coloreamos gris con una distancia de 0. Significa que queremos empezar explorando el nodo Spiderman y los grados de separación del propio Spider-Man 2 es 0. Después regresamos esa estructura de notas BFS de la que hablamos, que es un ID de héroe y luego una tupla que contiene el array de conexiones, la distancia actual y el color actual asociado a cada nodo. Por lo que inicialmente todo va a tener un color blanco, una distancia de 99, 99. Y todas las conexiones asociadas a cada ID de héroe leídas desde ese archivo de texto, excepción de Spider-Man, quien va a estar gris con una distancia de 0. Muy bien, Así que hemos hecho ese caso inicial, están montados. ¿ Qué pasa después? Entonces ahora pasamos por esta iteración, como dijimos, y elegimos diez es un límite superior arbitrario. Resulta que nunca tienes a nadie. En realidad son diez grados de separación en este conjunto de datos en particular que es más que suficiente. Imprimimos cuántas iteraciones hemos ido. Por lo que esto representa la distancia que estamos viendo de Spider-Man a este paso. Y lo primero que hacemos es hacer una operación de mapa. Por lo que llamamos a FlatMap en BF usando la función de mapa BFS usando esa iteración RDD. Entonces empezamos yo sentado iteración RDD a ese estado inicial. Después llamamos a FlatMap en iteración RDD. Y FlatMap, como se puede recordar, tiene el potencial de crear nuevos nodos, ¿no? Entonces vamos a ver qué está pasando en el mapa de BFS. A hacer. Ahí está el mapa de BFS. Muy bien, Así que básicamente extraemos el ID de personaje
y los datos asociados, y soplamos esos datos también para extraer la matriz de conexiones, la distancia y el color del nodo que estamos viendo que estamos mapeando. Ahora como se trata de un FlatMap, podemos devolver una matriz de nodos BFS más de uno si queremos agregar a nuestro nuevo RDD. Y a medida que vamos, buscamos nodos grises cada vez, ¿verdad? Por lo que los nodos grises son los que hay que explorar. Entonces si nos encontramos con un nodo gris, lo procesamos. Exploramos todas sus conexiones y creamos un nuevo nodo para esa conexión. Por lo que podríamos tener un nuevo ID de personaje, una nueva distancia, que es la distancia más 1 de ellos. Sepa que partimos de, el nuevo color será gris. Y si ese es en realidad el personaje que buscamos, si éste resulta ser Adam 3000, 31 o lo que fuera, entonces vamos a incrementar nuestro contador de hits y decir:
Hey, encontramos al tipo, ya terminamos. En realidad encontramos un nodo donde esta persona está conectada con Spiderman. Después creamos un nuevo nodo basado en la nueva distancia en nuevo color que calculamos y agregamos eso a nuestra lista de resultados. Por lo que hemos creado todos estos nuevos nodos grises que necesitamos explorar desde las conexiones del gris saber que acabamos de encontrar. Y tomamos el gris saber que acabamos de explorar y colorearlo de negro, que
indica que ya terminamos con él. Está bien. Acabamos de devolver los resultados y ya terminamos. Entonces de nuevo, si no entiendes el algoritmo BFS, no te pongas demasiado colgado en él. Ese no es realmente el punto de este curso, pero solo quería mostrarte lo que puedes hacer. Muy bien, así que hemos hecho la operación del mapa. Después imprimimos nuestro proceso a medida que vamos y decimos que hemos procesado sin embargo muchos valores hasta el momento. Y si realmente nos dieron un hit, vamos a decir, Hey, encontramos al personaje que estamos buscando. Aquí está el total real de cuántos hits obtuvimos de esa iteración. Por lo que es posible que más de un ejecutor estuviera procesando ese personaje al mismo tiempo. Y podrían haberte dado múltiples hits viniendo de diferentes direcciones y eso está bien. Tenemos el gran total impreso aquí. En caso afirmativo. Ahora antes de iterar más, necesitamos combinar los datos juntos. Por lo que podríamos haber generado nuevos nodos para el mismo ID de personaje que fuimos. Entonces mientras exploramos todas esas conexiones, podríamos haber ramificado en múltiples direcciones diferentes y
regresar y sabe que ya procesamos, por ejemplo. Entonces para manejar ese caso, necesitábamos hacer una operación ReduceByKey. El ReduceByKey reunirá todas
las nuevas notas que podrían haber creado para el mismo ID de carácter. Y el trabajo de la función reducida de BFS en la vida es solo para preservar la distancia mínima y el color más oscuro en ese caso. Entonces eso es todo lo que está pasando aquí. No voy a pasar por el código aquí con mucho detalle porque no es importante. Pero ese es el propósito de esta función sólo para manejar aquellos casos en los que tenemos más de una conexión entrando en el mismo nodo. Y en ese caso, preservar la distancia mínima y el color más oscuro asociado a ese nodo en particular. Entonces sí, veamos si realmente funciona. Vamos a hacer clic derecho en grados de separación y ejecutarlo. Trabajo bastante complicado, ¿verdad? Pero Spark puede hacer un trabajo corto de ello. Aquí vamos. Ya hecho tan bien, en realidad
procesamos 218,067 conexiones ahí. Pero encontramos que incluso este oscuro personaje es sólo dos grados de separación de Spider-Man. Si bien resulta que incluso superhéroes ficticios en los cómics están muy bien conectados. Y esto en realidad es cierto en el mundo real. Resulta que si miras, ya sabes, red social
real como LinkedIn o IMDB es base de datos de conexiones de actores que lo actúan juntos en la misma película, obtienes resultados similares. La gente está mucho más conectada de lo que se podría pensar. Es un poco interesante. Entonces mira eso. Funcionó. Bastante cool de nuevo, esto es solo un ejemplo de cómo al usar las funcionalidades de nivel inferior de Spark, a veces
puedes resolver problemas para los que no pensarías que Spark fuera necesariamente adecuado. No se trata solo de resolver problemas SQL. Puedes hacer más cosas con él que eso. Entonces recuerda que tienes ese poder a tu disposición. Eso no quiere decir que no pudiera tener frame esto en términos de conjuntos de datos y operaciones SQL, se
puede, y eso hemos hecho. Por lo tanto, veamos brevemente la versión del conjunto de datos de este script. Y hace algunas cosas bastante raras. Entonces quiero decir, tratando de gustar hacer MapReduce sin usar MapReduce, Es posible. No va a ser eficiente. Entonces si miramos esto, no
voy a entrar en demasiado detalle el guión aquí, pero se puede ver que estamos haciendo algunas cosas bastante complicadas aquí para hacer las mismas cosas que hicimos en los scripts de RDD. Entonces incluso la creación de esas condiciones iniciales aquí, sólo una especie de construcción de esa estructura de nodo termina siendo esta complicada operación de columnas de ancho en funciones
SQL para tratar de replicar lo que hicimos con solo usar, ya sabes, directamente arriba código Scala en nuestro mapa y reducir funciones. Y tenemos todos estos casos especiales para nuestro personaje titular. Básicamente tenemos que gustarnos hacer estos filtros y buscar a través de todo el conjunto de datos buscando ese caso especial, en lugar de simplemente manejarlo en línea. A medida que exploramos cada nodo, buscando nodos grises, tenemos que hacer una operación de filtro y todo para extraer esos nodos grises. Seleccione la información que necesitamos. Filtra hacia fuera buscando el ID de personaje objetivo que buscamos y maneja eso, sobre todo. Por lo que hace lo mismo. Bueno, eso es código complicado que también preservo el color más oscuro, para ser justos, también
fue bastante complicado en nuestro código, pero no implicó hacer una operación de unión. Buen Señor. Y todo esto SQL realmente elegante
que probablemente va a ser operaciones bastante pesadas. Entonces, a pesar de que podemos, si pensamos en esto lo suficientemente duro, enmarcarlo como un problema SQL, no es la forma más eficiente de pensarlo. Y sólo para demostrar mi punto, vamos a correr esto. Y vamos a contar cuántos segundos
tarda en ejecutarse esta versión del guión una vez que Spark gira hacia arriba. Entonces aquí vamos. 1, 2, 3, 4, 5, 6, 7. Tardó alrededor de siete segundos en conseguir esa respuesta allí. Tenemos la misma respuesta. Entonces eso es bueno. Funcionó, pero tardó siete segundos en obtener esa respuesta. En contraste, ejecutemos la versión RDD de eso. uno a ni tres segundos, ¿verdad? Entonces eso fue en realidad más del doble de rápido que la versión del conjunto de datos. Entonces, de nuevo, se trata de elegir la herramienta adecuada para el trabajo. Los conjuntos de datos son impresionantes en el manejo de tipo de problemas tradicionales de análisis de datos. Si puede enmarcar su problema en términos de un comando SQL fácilmente, un conjunto de datos probablemente le dará el mejor rendimiento. Pero si te encuentras teniendo que estar realmente en la cabeza para tratar de enmarcar lo que estás tratando de hacer en términos de comandos SQL. No va a terminar bien, ¿verdad? Y a veces los RDD son la mejor herramienta. Entonces, en este caso, al ir a un nivel más bajo usando la interfaz RDD de nivel inferior de Spark, hemos conseguido un rendimiento mucho mejor que al usar la API del conjunto de datos. Pero si realmente estuviéramos haciendo algo que fuera muy adecuado para un comando de estilo SQL implementando eso usando conjuntos de datos. Y hay funciones que se parecen mucho a comandos SQL, permite más optimizaciones y en realidad sería más rápido para problemas como ese. Y en el mundo real, ya sabes, ese es probablemente el problema más común que te darán con Apache Spark. Por lo general, estás tratando de hacer cosas como responder preguntas sobre los datos registrados que entran. ¿ Cuántos errores obtuve en el último mes o lo que sea? Cosas así. Los conjuntos de datos son impresionantes. Pero si estás tratando de hacer algo en un nivel inferior, recuerda que los RDD también están ahí para ti, y tienes esa funcionalidad disponible para ti.
38. Filtración colaborativo en Spark, cache(), y persiste. ): Entonces como otro interesante ejemplo de cosas
complicadas puedes hacer con Spark que quizá no hayas pensado que podrías hacer con Spark. Hablemos de filtrado colaborativo basado en elementos. Esto es básicamente un algoritmo de motor de recomendación. Es la forma en que Amazon solía hacer cosas como las personas que compraban esto también compraban o te recomendaban cosas en función de tus compras pasadas. La idea de alto nivel es que podamos echar un vistazo a las cosas que has comprado en el pasado, buscar artículos similares a las cosas que compraste y luego recomendarnos esos artículos, cosas que podrían interesarte. Y lo vamos a hacer en el contexto de las películas utilizando el conjunto de datos de MovieLens. Por lo que lo fundamental que necesitamos es alguna medición de películas que sean similares entre sí en función de las calificaciones de los usuarios. Entonces eso es lo que vamos a hacer aquí. Y mientras estamos en ello, también vamos a introducir el concepto de almacenamiento en caché de sus conjuntos de datos para mejorar el rendimiento. Películas tan similares, esta es una pequeña captura de pantalla y una más antigua de los sitios web de GroupLens. Por lo que en realidad tienen una interfaz de usuario donde puedes calificar películas, decirles explícitamente los movimientos que la luz UV, y te recomendará nuevas películas basadas en esas calificaciones. Entonces una forma de hacerlo es echarle un vistazo a todas las películas que te han gustado. Y para todas esas películas, mira las películas similares a esas películas. Y esas similitudes se basarán en otros usuarios que les gusten las mismas películas que te gustan. ¿ De acuerdo? Entonces el algoritmo básico aquí es que vamos a empezar por encontrar cada par de películas que fueron vistas por la misma persona. Nuestro objetivo aquí es encontrar todas las películas que sean similares a cualquier otra película. ¿ De acuerdo? Para ello, primero vamos a descomponer cada par de películas que fueron lavadas por las mismas personas. Entonces si el usuario a y el usuario B ambos veían la película y le gustaba, eso sería un par de películas. Ahora podemos entonces reunir a todos los usuarios que gustan de esos pares de películas y medir la similitud de sus calificaciones a través de todos ellos que vieron ambas películas. Entonces en base a cada usuario que vio ese par de películas y le gustó, ¿qué tan similares son esas películas en cuanto a calificaciones? Entonces podemos agruparlos todos juntos por el ID de la película, ordenarlos en función de su fuerza de similitud. Eso es algo que calculamos en base a esas calificaciones. Y entonces tenemos una lista ordenada de películas que son similares a cualquier otra película sólo por ese simple algoritmo. Entonces esta es solo una forma de hacerlo. Téngase en cuenta. También hay muchas otras técnicas por ahí, pero ésta es simple y a veces simple como mejor. Produce buenos resultados si tienes suficientes datos. Déjame guiarte por el algoritmo y más de una manera gráfica aquí. Entonces imagina que N aquí vio tanto Star Wars como The Empire Strakes Back, que es el SQL to Star Wars, significaba que te gustaban ambos. Y luego aquí Bob, el tipo con un mohawk, también vio Star Wars y The Empire Strikes Back y como ellos también. Por lo que en base a esta información, podemos decir que aquí tenemos un par de películas, Star Wars y The Empire Strakes Back. Y ambos tenían en común a estos dos usuarios que les gustaban a ambos. Entonces para ese par, sabemos que tanto al usuario como al usuario Bob
les gustan e imaginemos que ambos les dieron cinco estrellas. Entonces en base a eso, podemos computar que estas son películas
muy similares basadas en ese comportamiento de calificación del usuario. De las tres personas en nuestro conjunto de datos. dos de ellos les encantó este par de películas, ¿verdad? Por lo que eso arrojaría una muy buena puntuación de similitud. No obstante, podríamos optar por medir eso. Ahora imaginemos a Ted aquí en el fondo viene y sólo vio The Empire Strakes Back. A lo mejor se acaba de mudar aquí y vino de un país donde Star Wars no es algo grande. Eso está bien. Pero de alguna manera no sabe que la primera película, Star Wars, una Nueva Esperanza existió realmente. Entonces, ¿cómo le recomendamos qué más le podría
interesar ver en base a la información que tenemos aquí. Bueno, podemos decir, vale, conocemos a Ted, te gustó Empire Strikes Back. Y sabemos por nuestro cómputo anterior que la película más similar,
The Empire Strikes Back es Star Wars a New Hope, ¿la primera película? Y de nuevo, esa es similitud se basó en el comportamiento de calificación de los demás usuarios en nuestro conjunto de datos. Entonces eso es todo a un alto nivel. Básicamente, podemos recomendar películas que sean similares a las películas que te han
encantado en función del comportamiento de calificación de las otras personas en nuestro conjunto de datos. Y eso es el filtrado colaborativo basado en objetos en pocas palabras. Entonces en última instancia eso le recomienda una buena película a Ted de la que tal vez no conocía antes. Ahora nos vamos a centrar aquí en esta actividad sólo
en la porción de similitud cinematográfica de la misma. Entonces, en realidad no vamos a estar haciendo recomendaciones completas para la gente, pero vamos a estar computando ese conjunto de datos de similitudes de películas. Qué películas son similares a otras películas basadas en el comportamiento del usuario. Esa es la parte difícil, ¿verdad? Porque una vez que tengas esos datos, puedes hacer recomendaciones a las personas muy rápidamente basadas en las cosas que antes les han gustado. Entonces podría decirse a sí mismo, ¿cómo diablos podemos hacer esto en Spark? Spark está un poco construido alrededor de un paradigma SQL en estos días, o tal vez un MapReduce en el mejor de los casos. ¿ Cómo enmarcan esto como un problema que encaja en ese marco y algo que pueda paralelizar. Bueno, se puede, sólo hay que pensar en ello de manera creativa. Y de nuevo, ya sabes, poder pensar en
estos problemas de manera creativa es por lo que te pagan los grandes dólares. lo que es un ejemplo de cómo puedes usar esta tecnología para resolver un problema para el que quizás no hubieras pensado que era adecuado. Aquí está el algoritmo general que vamos a utilizar en nuestro ejemplo de Spark. Por lo que comenzaremos seleccionando los identificadores de usuario, los identificadores de
películas, y las calificaciones. En este ejemplo, realmente no nos importan los tiempos, aunque podrías imaginar un mundo donde también utilizas esa información. Después encontramos cada par de películas que fue calificada por el mismo usuario. Y eso podría sonar como algo complicado de hacer, pero resulta con una operación autoadjoint, que es mucho un tipo de cosa que hacer en base de datos. Eso es exactamente lo que te dará. Básicamente tomas el conjunto de películas de usuario y columnas de calificación y te unes a eso en sí mismo basado en el ID de usuario. Y eso te dará cada par posible de películas que fueron calificadas por la misma persona. Entonces en ese punto podemos replantear nuestro conjunto de datos autounido para tener película uno, película a calificación uno y leer dos columnas que nos
dirán los pares de películas y las calificaciones asociadas a cada uno. Y de nuevo, en este punto, esto se hará por cada usuario único que calificó juntas esas dos películas. Podemos entonces pasar y filtrar mientras estamos en ello cualquier par duplicado, porque una calificación de película uno para mover los dos es lo mismo que película a película uno. Entonces tendremos algo heurístico ahí dentro para asegurarnos de que solo
capturamos una de esas dos variaciones. Una vez que tengamos eso, podemos pasar por cada usuario que calificó ese par de películas y computar la puntuación de similitud coseno en base a esa información. No quiero meterme en las matemáticas de eso porque no es realmente relevante para el desarrollo de Apache Spark. Pero si tienes curiosidad por cómo funciona la similitud del coseno, yo, hay otro curso que tengo sobre sistemas de
recomendación que se mete en más profundidad en él. Pero a un nivel alto, si se echa un vistazo a todas las calificaciones de los usuarios para una película, se
puede pensar en eso como una especie de vector multidimensional. Y una puntuación de similitud de coseno sería básicamente el ángulo entre dos vectores para dos películas diferentes basadas en las calificaciones de los usuarios que tienen en común. Entonces una vez que tengamos eso, podemos agrupar todo por la película uno, película dos pares y asegurarnos de que agregamos todo juntos para un par de películas dado, computando eso es similitud de coseno a través de todos los usuarios que calificaron ese par de películas. Entonces, en este punto, tenemos un conjunto de datos que contiene cada posible emparejamiento de películas y la puntuación de similitud entre esos pares de películas. Podemos entonces simplemente filtrar y ordenar y mostrar los resultados. Entonces podemos agrupar los juntos por cada ID individual de película, filtrar cosas que están por debajo algún tipo de umbral de puntuación de similitud para asegurarnos de que solo estamos capturando similitudes fuertes y ordenarlas por eso puntuación de similitud y mostrar los resultados finales. Y eso en última instancia nos dará la puntuación de similitud de cualquier película dada con cualquier otra película. Entonces, antes de sumergirnos en el código, permítanme introducir la idea de almacenar en caché conjuntos de datos porque esto va a surgir en este ejemplo. A veces cuando estás haciendo cosas complicadas como esta, terminas consultando o usando un conjunto de datos más de una vez. Y si te encuentras haciendo eso, deberías almacenarlo explícitamente en caché si puedes. De lo contrario, hay una posibilidad que desató podría terminar reevaluando todo
ese conjunto de datos una segunda vez, solo para hacer esa segunda operación en él. Y si quieres asegurarte de que eso no suceda, puedes usar dot cash en un conjunto de datos después de que hayas terminado calcularlo para asegurarte de que se quede en la memoria. Cualquier operación o análisis subsiguientes que
realice en ese conjunto de datos ocurre lo más rápido posible. También hay no persistir. Persist opcionalmente te permitirá atrapar eso no sólo una memoria sino también al disco. Entonces si un nodo falla o algo así, puedes recuperarte desde ese punto y solo retomar donde lo dejaste. Por lo que el efectivo estará en la memoria, persiste opcionalmente se puede persistir en disco también. Y con eso, saltemos al código y veamos cómo se ve.
39. [Actividad] cómo ejecutar el guiador de películas similares con el administrador de la clúster de Spark: Muy bien, saltemos al código aquí para computar similitudes de películas usando Spark. Así que abre el script de conjunto de datos de similitudes de película aquí. Y este es un caso en el que el uso de un conjunto de datos superará el uso de un RDD. La parte realmente más complicada de todo este algoritmo es esa operación de autounión, donde tratamos de encontrar cada par único de películas fueron calificadas por la misma persona. Y eso es un tipo de cosas muy SQL que hacer, ¿verdad? Una operación de autounión. Por lo que esto realmente encaja bien en las ideas de usar un conjunto de datos en Spark SQL. Es posible hacer esto también con RDD, pero en este caso, conjuntos de datos sí superan a los RDD, que suele ser el caso. Entonces nos vamos a centrar en conjuntos de datos para este. Si tienes mórbida curiosidad acerca de cómo hacer esto con RDD, hay un guión de similitud de película así aquí disponible que solo lo hace usando RDD en su lugar. Pero centrémonos en conjuntos de datos. Entonces, ¿qué tenemos aquí? Bueno, empezamos importando todas las cosas que necesitamos como de costumbre. Y declaramos un objeto de dataset de similitudes de película que contiene varias clases de caso. Estos definieron los diversos formatos de archivo que vamos a leer
y utilizar para los conjuntos de datos que utilizamos a lo largo del camino a lo largo de nuestro algoritmo. Entonces tenemos un conjunto de datos de películas que solo está reflejando el formato de los datos brutos en los que estamos leyendo. Consiste en un entero ID de usuario, un entero de ID de película, o entero de calificación, y una marca de tiempo larga. También vamos a cargar un conjunto de datos de nombres de películas para que podamos mostrar
muy fácilmente los nombres legibles por humanos del ID de película dado. Eso es sólo ir a mapear identificaciones de películas a títulos de películas. También tendremos un conjunto de datos de pares de películas en el camino, y esto encarna un par único de películas. Esta es una especie de salida de esa operación de autounión donde obtenemos cada set de película que fue calificada por la misma persona. Y eso consistirá tanto en los identificadores de película uno como de
película a película y en las calificaciones asociadas a cada una de esas películas de un determinado usuario. Por lo que una fila de pares de películas consistirá un par de películas y sus calificaciones por un solo usuario que las vio a ambas. Lo tengo. Y luego también tendremos un conjunto de datos de similitud de película Paris en algún momento que contiene un par de películas, película 1, una película a una puntuación de similitud en formato de doble precisión, y el número de pares que se asociaron en la computación que es puntuación de similitud. Entonces eso va a reflejar cuántos usuarios realmente vieron este par de películas y las calificaron juntos. Saltemos adelante a la función principal y trabajemos desde ahí. Empezamos estableciendo nuestro nivel de registro y creando un objeto SparkSession. Como de costumbre. Después creamos un esquema de nombres de películas, que se usará más adelante para estructurar nuestro conjunto de datos para buscar identificadores de películas a títulos de películas. Simplemente dice que nuestra ID de película será un entero, y tendrá un título de película para cada ID de película que sea una cadena. Entonces declararemos un esquema para los datos, los datos de las calificaciones de la película también. Eso va a tener ID de usuario, ID de película, calificación, y marca de tiempo en la estructura que hemos visto antes cargará entonces esos nombres de películas. Como primer paso, importamos desatado en implícitas porque estamos cargando un DataFrame inicialmente y luego convirtiendo eso en un conjunto de datos. Por lo que para inferir implícitamente el esquema de un DataFrame, pesar de que te estamos proporcionando uno, aún
necesitas usar los implícitos de punto de Spark para ese paso. Por lo que le decimos que archivo de datos en particular, que punto elemento está separado por un delimitadores de tubería. Está en el juego de caracteres ISO 8859 dash one. Y utiliza el esquema de nombre de la película que estamos proporcionando explícitamente porque no hay una fila de encabezado en este archivo que podamos usar para inferirla. Y cuando terminemos con eso, lo convertiremos explícitamente en un conjunto de datos utilizando la clase de caso de juegos en movimiento para un mejor rendimiento en Spark. Después miramos los datos de calificaciones de películas en sí, nuevo es un conjunto de datos. Misma idea aquí. De hecho, la pestaña de ésta se separa usando el esquema de película que definimos anteriormente. Y vamos a convertir eso también a un conjunto de datos usando la clase de caso de películas. Entonces en este punto tenemos un conjunto de datos de nombres de películas y tenemos un dataset de películas que representa todas las calificaciones individuales de los usuarios. Después seleccionaremos la información que nos importa solo para evitar que llevemos información que no necesitamos. Por lo que nuestro conjunto de datos de calificaciones ahora será solo el ID de usuario, ID de
película y calificación. Dejando de lado la, la columna de marca de tiempo, porque en realidad no necesitamos esa información para lo que estamos haciendo aquí. Ahora aquí es donde se pone interesante. Esta es esa operación de autounión de la que hablamos antes. Entonces vamos a tener un conjunto de datos de película de París. Aquí tiene la intención de contener cada par de películas calificadas por la misma persona. Entonces la forma en que estamos haciendo eso es antes que nada, vamos a tomar nuestro conjunto de datos de calificaciones. Vamos a darle un alias de calificaciones uno para que podamos referirlo fácilmente. Y nos uniremos a eso con otra copia
del conjunto de datos de radio al que se hace referencia como calificaciones. Entonces vamos a hacer una unión entre las calificaciones uno y las calificaciones a las que realmente son lo mismo. Ambos apuntan al conjunto de datos de calificaciones. Entonces por eso llamamos a esto un auto unirse. Nos estamos uniendo al conjunto de datos de calificaciones en sí mismo, y nos uniremos a él en función de la columna de ID de usuario. De acuerdo, Entonces estamos diciendo que nos vamos a unir sólo si un ID de usuario o un rating a uno coincide con el ID de usuario y las calificaciones con. Por lo que esto tendrá el efecto de
emparejar todas las películas que fueron calificadas por la misma persona. Lo tengo. Tienes que entender cómo funcionan las operaciones de unión en SQL. Y esto no es realmente una clase SQL, pero el resultado es, eso es lo que se obtiene de esta expresión aquí. Cada par de películas que fueron calificadas por la misma persona. Y además, mientras estamos en ello, vamos a hacer cumplir que la identificación de película para las clasificaciones uno sea menor que la identificación de película que viene de las clasificaciones a. Y lo estamos haciendo sólo para evitar duplicados. Entonces de nuevo, no queremos tener una entrada separada para las calificaciones uno emparejado con lecturas a, como lo haríamos para las calificaciones a con calificaciones uno. Entonces, al hacer esto, solo nos aseguramos de que solo estamos capturando un emparejamiento único allí. Una vez que tengamos eso, podemos entonces cambiar el nombre de las cosas para que sea más fácil de usar. Entonces vamos a cambiar el nombre de las calificaciones un punto de la película ID a la película uno, lecturas hoy en la película ID a la película dos, valoraciones cuando estoy leyendo a uno y clasificaciones a punto lectura 2, escribiendo 2, otra vez, solo para que sea más fácil trabajar con. Y además, haremos explícitamente esto un conjunto de datos utilizando la clase de caso de pares de películas que definimos anteriormente. Ahora, tenemos a nuestra disposición aquí ese conjunto de datos de pares de películas que puede doler pares de películas y sus clasificaciones para cada usuario único que calificó ese par de películas. Dado eso, ahora podemos llamar similitud de
coseno computo para construir nuestra película Paris similitudes dataset que
contendrá por cada par de películas lo similares que son entre
sí en base a todos los usuarios que calificaron esas películas juntos. Entonces, antes de ir más allá y hablar de esa operación de caché, veamos qué hace la similitud del coseno computarizado. Eso es aquí arriba, en alguna parte. Ahí está. Entonces aquí está pasando un poco de matemáticas de fantasía. Realmente no quiero meterme demasiado en la métrica
de similitud de coseno porque eso no tiene nada que ver realmente con la programación de Spark. Nuevamente, si quieres aprender más sobre eso, puedes consultar mi curso sobre sistemas de recomendación. Pero a un nivel alto, estamos creando tres nuevas columnas aquí. Xx y XY. Eso va a calcular x cuadrado, y cuadrado, y x,
y a partir del algoritmo que utilizamos para calcular la similitud del coseno. Nuevamente, es sólo básicamente un, un ángulo entre dos vectores virtuales en este espacio de cine del usuario. Podemos entonces calcular esa similitud puntajes. De esta manera, básicamente usamos ese nuevo conjunto de datos llamado partituras de París. Tiene esos términos extra, se le anexa. Y luego llamamos huevo para sumar todas las entradas para cada par de películas dado, están usando la siguiente expresión. Entonces para todos los pares de películas, para todos los usuarios en calificadas esas dos películas juntas. Vamos a cruzarlos todos con esa función agg. Y resumiremos las columnas X, Y y llamaremos a eso el numerador. Ese sólo va a ser el numerador de nuestra expresión para computar similitud de coseno. Y luego para el denominador que enrutándote ese el denominador más temprano que terminará siendo la raíz cuadrada de la suma de la columna XX y la raíz cuadrada de la suma de la columna
y, y sumado. Y finalmente, tendremos los non pairs, que sólo va a contar cuántos de la columna x y existe. Eso es sólo un atajo para averiguar cuántos usuarios calificaron en realidad este par de películas juntas. Y esa es información que necesitamos para calcular realmente el puntaje de similitud real, que es lo que va a aterrizar en este conjunto de datos de resultados aquí, solo
agregamos una nueva columna de puntuación a eso también. Y lo que hacemos es primero asegurarnos de que no vamos a estar dividiendo por 0. Verificamos explícitamente para asegurarnos de que el denominador no sea 0. De lo contrario sólo tenemos un resultado nulo ahí. Si no, entonces sólo dividimos el numerador por el denominador. Y en este punto tenemos nuestra puntuación de similitud real calculada en base a la métrica de similitud de coseno. Entonces simplemente le restamos esto a las columnas que nos importan, que va a ser la película uno y la película a la puntuación de similitud entre ellos y el número de pares que respaldan esa partitura. Y forzaremos eso en un conjunto de datos también usando la clase de caso de similitud de pares de películas arriba y devolveremos el conjunto de datos de resultados, que de nuevo en este punto solo contiene película una película para anotar y no pares que, acuerdo, volver a donde se llamó eso. Por lo que ahora tenemos este conjunto de datos de todas las puntuaciones de similitud entre cada par único de películas. Y probablemente vamos a usar eso más de una vez. Entonces sigamos adelante y caché eso para que tengamos eso en la memoria a mano para ir. No importa qué vamos a hacer con él más adelante. No sólo vamos a usar esto para mostrar nuestros resultados, sino que se podrían imaginar, realidad
podríamos hacer un sistema de filtrado colaborativo basado en artículos real de
esto manteniendo ese conjunto de datos de similitudes de par de películas en la memoria. Podemos entonces tomar el conjunto de todo lo que a cualquier nuevo usuario le
ha gustado o expresado interés ahí, o bien calificado, lo que quiera usar como indicación de interés y luego golpear esa película El estado de similitud de París se establece en muy rápidamente volver todas las películas similares a las películas AP persona luz. Por lo que de nuevo, esto sería muy importante cobrar si estuvieras construyendo aquí un verdadero sistema de recomendaciones. Pero todo lo que vamos a hacer aquí es sólo tratar de obtener los resultados de las mejores similitudes para una película determinada. Entonces vamos a comprobar que pasemos aquí una discusión. Entonces la idea aquí es que vamos a pasar como argumento a este guión, una identificación de película a la que nos interesa ver todas las similitudes. Y además, aquí vamos a establecer algunos umbrales. Entonces vamos a decir que a menos que haya una puntuación de similitud del 97% entre dos películas, no lo vamos a considerar lo suficientemente similar como para ser interesante. Y también diremos que se necesita tener al menos 50 usuarios en común que calificaran ambas cosas juntas. Entonces esa es una especie de apoyo mínimo que necesitamos para tener confianza en que este es un resultado confiable. No quieres estar haciendo una recomendación basada en lo que dijeron dos personas. Idealmente, quieres que muchas personas que estén de acuerdo entre sí te den un mejor resultado. Entonces estos umbrales y un ser importante para obtener resultados de
calidad y son bastante arbitrarios, pero volveremos a eso. Entonces aplicaremos esos filtros aquí. Filtraremos el conjunto de datos de similitudes de París de la película y filtraremos no solo para hacer cumplir esos umbrales de puntuación, asegurándonos de que la puntuación fuera mayor que nuestro umbral de puntuación escolar. Y ninguno de los pares es mayor que el umbral de inicio de co-ocurrencia. Pero también lo vamos a filtrar para la identificación de película que nos interesa. Entonces para la película que pasamos como argumento, Esa es la película que queremos ver, películas similares también. Por lo que hacemos cumplir que la película uno es igual a ID de película o la película dos es igual a ID de película. No sabemos realmente si va a estar en la película uno o la película a lado, podría
ser o dependiendo del orden de las identificaciones de película, ¿verdad? Entonces si alguna de las películas del par de películas es la que nos interesa. Vamos a levantar eso a través y
también comprobaremos que nuestros umbrales de calidad también se cumplan. Una vez que tengamos eso, vamos a ordenar ese descendente en base
a esa columna de partitura para conseguir las películas más similares a esa película y tomar el top 10. Por lo que llamaríamos a esto un top n recomender en lenguaje de sistema de recomendación porque estamos tomando los 10 mejores resultados en hacer que nuestras recomendaciones para esta película. Y luego lo imprimimos y sólo decimos conseguir las 10 mejores películas similares por lo que sea ese nombre de película para hacer que ese humano legible. Nuevamente, usando ese conjunto de datos de nombres de películas que cargamos hace
mucho tiempo para esa ID de película. Y por cada resultado único que recuperamos, iteramos a través de él y extraemos estas películas similares
basadas en la identificación de la película no es la que pasamos como parámetro. Imprime ese resultado junto con su puntuación y la fuerza en función del número de pares que apoyaron esa puntuación. ¿ Quién? Entonces oye, parece que esto debería funcionar. Ya sabes, era mucho de lo que hablar, pero si miras el código para todo,
lo hace, realmente no es tanto código, ¿verdad? En realidad no es tan malo. Es decir, hay algunas cosas funky pasando seguro. Ellos NED, envuelven tu cabeza con estas expresiones más complicadas aquí como este agregado aquí o la operación de autounión. Pero una vez que superas eso, no es tanto código. Entonces sigamos adelante y lo ejecutemos y veamos qué pasa antes de ejecutarlo sin embargo, necesitamos pasar ese parámetro de qué ID de película queremos volver, ¿verdad? Entonces para hacer eso, te
mostramos ese poco más complicado e inteligencia. Haga clic derecho en similitudes de película y vamos a decir Crear similitudes de película. Esto creará una configuración de ejecución que podemos configurar explícitamente. Y eso tiene una ranura aquí para argumentos de programa. Para que puedas poner cualquier identificación de película que quieras aquí para cualquier película que te interese, digamos 56, sea lo que pase a ser. Y diremos: Está bien. Y ahora aquí arriba tenemos las similitudes de película ejecutar configuración que acabamos de definir. Y podemos presionar el botón de reproducción para ejecutarlo. Entonces vamos a patear eso y a ver qué pasa. Fuera va. Cargamos nuestros nombres de películas y ahora está apagado realmente computar esas similitudes. Y ahí tenemos nuestros resultados. Entonces eso es bastante bueno. Esa fue una cantidad de tiempo razonablemente pequeña para una operación muy complicada. Y hacer una autounión en un gran conjunto de datos no es pequeña hazaña, ¿te importa? Y sí, recuperamos los mejores resultados para Pulp Fiction. Resulta que eso es lo que es la película ID 56, y es una especie de película codiciosa. Y eso volvió con películas más gruñitas. Por lo que en realidad parecía funcionar. Nunca había visto humo antes. En realidad no me gusta tirar de la fisión, así que no estoy seguro de que realmente quiera ir a ver eso yo mismo, pero Reservoir Dogs, Dani brass van. Verdadero Romance. Todos estos son resultados razonables para unas películas similares a Pulp Fiction basadas en otras calificaciones de usuarios. Entonces ahí lo tienes. Si ibas a construir gente a la que le gustó esta película también le gustó en Netflix o algo así. Ahora sabes cómo hacer eso y en realidad podrías escalar eso usando Apache Spark para manejar una cantidad masiva de calificaciones o un número masivo de películas. Porque en realidad se puede lanzar todo un clúster en esto ahora. Entonces ahí lo tienes. Ejemplo de hacer una película similitudes y filtrado colaborativo basado en artículos, al
menos la primera mitad de ella usando Apache Spark. Y como verás más adelante, En realidad
hay una función incorporada en la biblioteca de aprendizaje automático para Apache Spark que hace algo similar, pero en realidad no genera resultados tan buenos con el conjunto de datos MovieLens. Entonces a veces solo usar las herramientas listas para usar no es suficiente y necesitas volver atrás y una especie de ser inventivo e implementar nuevos algoritmos usando Spark que tal vez no se hayan visto antes en Spark, nuevo, que es lo que van a pagar los grandes pavos por los chicos. Pero ese es un buen ejemplo y vamos a terminar con ese. Antes de que lo hagamos sin embargo, te
voy a desafiar para que realmente haga esto mejor. Entonces hablemos de eso en nuestra próxima conferencia.
40. [Ejercicio] Mejorar la calidad de las películas similares: Por lo que resulta que las similitudes de cine son un poco cercanas y queridas para mi corazón por un par de razones. En primer lugar, la mayor parte de lo que hice durante mi tiempo trabajando en Amazon.com fue trabajar en el campo del filtrado colaborativo y sus sistemas de recomendación de usuarios. Pasé mucho tiempo tratando de mejorar esos sistemas ahí. Y fue cosas divertidas. Es, realmente es interesante trabajo también corrí IMDB por un tiempo. Entonces esa es una especie de esa intersección de filtrado colaborativo y películas que invade gran parte de mis cursos. Entonces mi reto para ti es mejorar los resultados. Y realmente no hay respuesta correcta o incorrecta a esto, bien. El asunto con las recomendaciones es que a menudo son de naturaleza bastante cualitativa. Es decir, puedes medirlos en base a cómo la gente reacciona ante ellos en el mundo real. Pero al final del día, un poco
tienes que juzgar por ti mismo si son buenos o no. Entonces mi recomendación ver qué hice ahí. Recomendación, mi recomendación para ti es ir a buscar una película que te
apasione y encontrar que en la búsqueda de MovieLens Dataset, es ID de película. Y si hay una película con la que realmente estás familiarizado, tendrás una buena sensación intuitiva de qué buenas películas similares a esa película podrían ser. Entonces empieza corriendo el guión que acabamos de tener para esa identificación de película que conoces y amas tan bien. Y juzga por ti mismo si esas son buenas recomendaciones y piensa en cómo podrían ser mejores esas? Entonces aquí hay algunas ideas de cosas que puedes hacer para modificar ese guión para mejorar aún más la calidad de esas recomendaciones, una idea sería simplemente descartar todas las malas calificaciones. Entonces si alguien escribe una película una o dos estrellas, ¿realmente queremos que eso influya en nuestra medida de lo similar que es la película? Una especie de escollo de este algoritmo es que las películas que son similares en términos de todo el mundo las odiaba seguirían apareciendo como películas similares. Entonces eso no es necesariamente algo bueno si estás tratando de recomendar buenas películas para ser sacadas que podrían querer ver. Entonces esa es una idea. Acaba de introducir otro filtro que se deshace de cualquier mala calificación desde el principio y ver qué diferencia tiene eso en el resultado. También podrías probar diferentes métricas de similitud. Tendrías que buscar estos ahora mismo, razón similitud coseno, pero hay métricas alternas por ahí así como el coeficiente de correlación de Pearson,
el coeficiente de Jaccard, o simplemente la probabilidad condicional recta arriba. Por lo que quizá quieras buscar esos hacia arriba y tratar de implementar eso en lugar de la métrica del coseno y ver si eso hace mejor o peor. También puedes jugar con esos umbrales y probablemente sea lo más fácil de hacer. A lo mejor deberías tener más curadores mínimos o un puntaje mínimo más alto por convertirlo en el corte final. Eso tendrá un compromiso o cobertura sin embargo, ya sabes, si tienes películas más oscuras, no
tengas suficientes datos para realmente hacer una recomendación si estableces esos umbrales demasiado altos. O podría inventar su propia nueva
métrica de similitud que tome en cuenta a una serie de cooperadores. Entonces tal vez el número de personas que vieron el par de películas es en sí mismo una indicación de lo buenas que son esas películas. A lo mejor sólo el hecho de que sean populares. Y mucha gente los ha visto a ambos es algo que debes tener en cuenta. Entonces tal vez puedas normalizar eso de alguna manera e introducir eso en tu métrica de similitud también. Y si realmente quieres llegar a ambicioso, incluso
podrías sacar información de género del archivo de datos de elementos de punto UE y
del conjunto de datos de MovieLens que contiene una matriz de ceros y unos que indica a qué géneros y película pertenecen. Y tal vez podrías filtrar películas que están en diferentes géneros o impulsar las puntuaciones de similitud de películas que tienen muchos géneros en común. Entonces algunas ideas generales ahí y cómo podrías mejorar los resultados. De nuevo, aquí no hay una respuesta correcta. No te puedo mostrar como la respuesta correcta a esta actividad. Yo solo quiero que vayas y juegues con él y veas si puedes mejorar los resultados. Y si lo haces, tendría mucha curiosidad por saber lo que hiciste, ya sea en los comentarios o en la Q y un mecanismo o lo que sea la plataforma en la que estás viendo este curso te da por proporcionar retroalimentación. Entonces ten en
ello, en realidad es una actividad divertida y una muy importante para mucho comercio electrónico depende de hacer recomendaciones. Entonces si puedes aprender a hacer eso, Es algo bueno. Vete y juega con eso. Y luego volveremos en la siguiente sección y hablaremos de escalar las cosas.
41. [Actividad] el uso de spark-submit para ejecutar guiones de conductor de Spark: En lo que va de este curso hemos estado desarrollando en tu PC de sobremesa local porque, bueno, eso es barato y fácil, ¿verdad? No quiero estar gastando un montón de dinero mientras aprendes estas cosas necesariamente, pero es hora de escalar las cosas. Por lo que en esta siguiente sección hablaremos de ejecutar Spark en un clúster B real que posee un clúster que su acompañante o un clúster que podría estar rentando en un servicio como Amazon Web Services. Hay algunas consideraciones especiales cuando estás escribiendo tus scripts de controladores para usarlos en un clúster. Y ciertas formas en que vas a estar implementando tu código y empaquetando tu código y ejecutando tu código cuando está en un clúster real. Así que vamos a entrar en esos detalles y esto debería armarte con los conocimientos que necesitas para usar realmente Spark en un entorno de producción real a gran escala. En lo que va de este curso, hemos estado ejecutando nuestras aplicaciones Spark en nuestro escritorio dentro del entorno de inteligencia. Y eso está todo bien y bueno para el desarrollo. Pero si realmente quieres ejecutar una aplicación Spark en el mundo real, probablemente la
estés implementando un clúster en algún lugar y no dentro de IntelliJ a, vas a querer poder disparar esto desde algún tipo de trabajo de Cron o algún tipo de sistema de
gestión que dará inicio tu aplicación de Scala en algún tipo de horario, ¿verdad? Entonces, ¿cómo hacemos eso? Bueno, comencemos hablando de cómo empaquetar e implementar
su aplicación y ejecutarla desde
fuera de la inteligencia y solo desde una línea de comandos en algún lugar. Entonces en el mundo real, en un clúster estarán ejecutando nuestros guiones con algo llamado Spark dash submit. Por lo que cuando instalas Apache Spark, viene con una aplicación llamada Spark submit. Y su trabajo es leer en un archivo jar que contenga su aplicación Spark compilada y distribuirla a todo su clúster para que se ejecute. Y puede hacer todo esto fuera de la inteligencia. Todo es completamente independiente. Ahora antes de hacer esto, hay algunas cosas de las que debes asegurarte. En primer lugar, asegúrate de no dejar ninguna ruta a tu sistema de archivos local dentro de tu script, ¿verdad? Entonces en nuestros ejemplos hasta ahora nos hemos estado refiriendo a archivos que existen en nuestro sistema de archivos local en una ruta relativa desde donde está nuestro proyecto. Ahora en el mundo real, quieres asegurarte de que tus archivos de datos sean accesibles para cualquier nodo en tu clúster que pueda estar ejecutando tu aplicación, ¿verdad? Por lo que en términos generales, sus datos se desplegarán como algún tipo de sistema de archivos compartido. A lo mejor es HDFS, a lo mejor es S3 de Amazon, algo, pero no va a ser el sistema de archivos local. Porque cuando estás distribuyendo este código, ese sistema de archivos local no necesariamente estará disponible para ti. Entonces lo primero es lo primero, asegúrate de que cualquier pasado a los archivos se esté utilizando a un sistema de archivos distribuido o al menos a algún archivo que sea accesible desde donde pueda estar ejecutándose tu script. Entonces vamos a empaquetar nuestro proyecto Scala en un archivo jar de alguna manera. Y hay un par de formas de hacer esto. Por ahora, vamos a empezar simplemente agregando un artefacto jar en inteligencia para realmente exportar nuestro propio código de aplicación a un archivo jar. Esto tiene limitaciones sin embargo, si sí tienes dependencias en tu script más allá de las bibliotecas de Spark stock, eso va a ser un tema que necesitamos pensar en cómo distribuir esas dependencias. Y más adelante hablaremos de usar SBT para hacer eso. En realidad hemos estado haciendo eso todo el tiempo. Simplemente no lo sabías. Y una vez que tengamos un archivo JAR, podemos usar Spark para pedir enviar para ejecutar ese script de controlador fuera del IDE. El formato de la misma es bastante sencillo. Simplemente tecleas Spark dashed, submit, dash, dash class, cualquiera que sea el nombre de tu clase que quieras ejecutar que tenga tu función principal. Si sí tiene dependencias para otros archivos JAR, puede usar dash, dash jar es especificar dónde se pueden encontrar esos. Y también puedes usar los archivos dash, dash para colocar automáticamente los archivos junto a tu aplicación. Por lo que para los archivos pequeños que podrían ser pequeños archivos de búsqueda o algo así, puedes salirte con la tuya usando los archivos dash para eso. Y por último, la ruta al propio archivo JAR que contiene el código que desea ejecutar. Entonces con eso, vamos a darle una oportunidad, en realidad ejecutaremos nuestro ejemplo hola mundo yendo camino de regreso
al inicio del curso usando Spark dash submit fuera de la inteligencia. Entonces te guiaré a través de cómo hacer eso. Entonces, antes de que podamos intentar ejecutar nuestra aplicación Spark fuera de la inteligencia, primero, necesitamos un entorno de Spark para ejecutarla dentro. Por lo que vamos a configurar aquí un entorno de Spark independiente en nuestro PC de escritorio, que simulará el mismo entorno que podríamos tener cuando estamos ejecutando esto en un servidor de la nube en algún lugar. Así que abramos nuestro navegador web y nos dirigimos a Spark dot apache.org. Y aquí es donde vas a descargar la última versión del propio Apache Spark. También vas a necesitar 7-Zip si estás en Windows o alguna utilidad que pueda descomprimir archivos tar.gz. Tan bien, entonces si estás en Windows y no tienes ya una utilidad que te permita descomprimir un archivo dot tar.gz. Te recomiendo instalar 7-Zip para cuidar eso primero. Por lo que de vuelta a Apache Spark. Bueno, ve a Descargar Spark, y estamos usando Spark 3 en este curso aquí. Por lo que elegiré esa chispa liberada por ahora. Y queremos la versión preconstruida para Apache Hadoop 2.7 o lo que sea. Y vamos a golpear Descargar Spark 3 usará el sitio de espejos sugerido y esperemos a que eso baje. Solo son unos 200 megabytes, por lo que sólo tomará unos segundos aquí. Una vez hecho eso, usaremos 7-Zip en Windows para descomprimirlo. O si estás en Mac o Linux, solo
puedes ir a tu línea de comandos y decir, ya sabes, el zip de GAN habitual y luego tar dash X, vf, cualquier comando que necesites para descomprimir eso. Seguro que ya estás familiarizado con los archivos T, G, C si estás en Mac o Linux. Está bien, parece que descargado. Entonces vamos a nuestra carpeta de descargas y echémosle un vistazo. Desde que instalé 7-Zip, solo
puedo hacer clic derecho en él e ir a 7 Zip y decir extracto. Y creo, uh, ¿cómo hacerlo de nuevo? Sí. Por lo que eso extrajo el archivo zip G a un archivo tar. Ese archivo tar y giro necesita ser descomprimido también. Y aquí dentro deberíamos tener la propia Spark. Voy a pre-compilar para nosotros. Está construido usando Java, por lo que en realidad es una plataforma independiente. Por lo que podemos salirnos con la suya frente a esto en Windows en su mayor parte. Como verás, hay algunos errores. Entonces sigamos adelante y Controlar un y copiar todo eso. Control C. Y voy a ir a mi disco C y crear una nueva carpeta llamada Spark y abrir eso y copiarlo y pegarlo allí más bien. Y si estás en Mac o Linux, claro que solo estarías haciendo esto usando make dir y el comando cp para copiar estos archivos donde los quieras. Tan solo asegúrate de recordar dónde las pusiste. Está bien, así que hemos desatado 3 instalados. Eso no fue duro, ¿verdad? Entonces vamos a crear realmente un archivo JAR y a ver si podemos ejecutarlo usando esta nueva versión de Spark que hemos instalado. Por lo que de vuelta a Intel J. Vamos a ver aquí. Entonces lo que vamos a hacer es ir a File y decir estructura del proyecto. Y vamos a ir a artefactos y hacer clic en el signo más. Y diremos tarro. Y empezaremos con un frasco vacío. En primer lugar, vamos a darle un nombre. Llamémoslo por supuesto desatado. Y tenemos que decirle qué queremos poner en este frasco. Entonces abrimos aquí este directorio de cursos de Scala desatado. Y se puede ver que están todas las dependencias que importamos de propia
Spark en registro para J y todo de lo que depende. Pero como ya tenemos instalado un entorno de Spark, no
necesitamos empaquetar todas esas dependencias. Sólo necesitamos el código para nuestro propio script. Y eso va a vivir en estas chispas curso de gala compilar salida. Por lo que este será el bytecode compilado de nuestro código, las cosas reales bajo el software com dot sun dot dot Spark. Entonces sigamos adelante y hagamos doble clic en eso. Y eso lo hemos agregado a nuestro archivo JAR. También hagamos clic en incluir y proyectar construido para asegurarnos de que realmente se crea. Y vamos a dar click Ok. Y volveremos a hacer clic en el icono Construir para forzarlo a construir eso. De acuerdo, así se puede ver por el camino que está construido, ver chispas, curso de
gala hacia fuera artefacts, Spark Core, Spark course dot jar. Entonces ese es nuestro archivo JAR que contiene nuestro código. Vamos a buscarlo. Si vamos a ver curso de gala chispas. Ahí está nuestro directorio OUT, artefactos, curso de
chispa, y hay jarra de punto de caballo chispa. Por lo que 399 kilobytes. Eso parece del tamaño correcto para todo lo compilado por código en todo nuestro proyecto aquí. Entonces eso incluye cada clase que tenemos aquí. Entonces sigamos adelante y echémoslo y veamos si podemos usarlo. Ahora, como dije, sí necesitas asegurarte de que cualquier ruta de archivo vaya a ser válida todavía. Por lo que verás en Hola mundo, sí
tenemos un camino relativo aquí a data slash m uno a través de k slash u dot data. Entonces para que esto funcione, necesito asegurarme de que estoy ejecutando esto desde la ubicación correcta donde será accesible ese camino. Nuevamente, si esta fuera una aplicación real en un clúster real, probablemente
quisiera asegurarme de que los datos estuvieran en algún tipo de sistema de archivos compartido en su lugar. Pero por el bien de la ilustración, corriendo en nuestro escritorio aquí, lo mantendremos así. Abramos un símbolo del sistema. Y de nuevo, en Mac o Linux, solo
usas un prompt de terminal. Navegemos a nuestra carpeta Materiales del curso. Entonces para mí ese C colon barra invertida chispa curso de Scala slash Spark Scala curso. Y desde aquí tenemos ese relativo datapath disponible para nosotros. Entonces eso es bueno. Entonces ahora ejecutemos en realidad estos desatados pedir comando enviar desde nuestro entorno independiente de Spark que instalamos. Entonces como recuerdas para mí, eso fue C colon barra invertida Spark slash bin slash Spark dashed, submit. Lo siguiente que necesitamos pasar es el nombre de clase que queremos ejecutar. Y así vamos a decir dash, dash class, com, Dotson dogs software, dot chispa dot hola, mundo. Y ahora necesitamos darle la ruta
al archivo JAR real que queremos enviar a Spark enviar. Y eso será para mí C colon barra invertida, chispa Scala corte corte corte Spark Scala corte corte. Fue artefactos absolutos, curso de
Spark, tarro de inicio de Spark Core. De acuerdo, Entonces esto debería funcionar. Lo que va a hacer de nuevo es tomar ese archivo JAR de mi compilado por código y en realidad pasar eso a la propia Spark usando Spark dash submit. Buscará ese nombre de clase que especifiqué e intentará ejecutarlo. Y de nuevo, si estuviéramos en un cúmulo real aquí, estimación
desatada lo echaría todo. Distribuiría ese código a lo largo de todo el clúster. Inicia a nuestro Cluster Manager, haz todo lo que necesite para distribuir eso y asegúrate de que realmente se ejecute con éxito. Entonces vamos a golpear Enter y ver qué pasa. Nuevamente, tenga en cuenta que estamos fuera de inteligente por completo aquí estamos utilizando un entorno de Spark independiente completamente diferente. Esto es bastante análogo a lo que estarías haciendo en el mundo real. De acuerdo, entonces tenemos algunos mensajes de error de aspecto aterrador, pero ignora eso por el momento. Si miras la parte superior aquí, sí
conseguimos nuestra salida. Por lo que dice Hola Mundo, el archivo de datos tiene 100 mil líneas. En realidad funcionó. Eso es impresionante. Ahora bien, no preste atención a estos mensajes de error. Sé que suena realmente ondulado a mano, pero este es en realidad un error específico de Windows en Scala misma que ha existido desde siempre. Hay un problema con
los permisos de archivo en realidad en los directorios temporales que Spark usa en Windows. Y de eso se está quejando. En el mundo real. Nadie realmente ejecuta trabajos de producción Spark en Windows, así que nadie se ha molestado en arreglar esto. Entonces, solo lo vamos a ignorar por ahora. Si haces esto en Linux, no verás que al agrandar, estarás ejecutando trabajos de Spark en Linux en el mundo real, pero el proceso será el mismo. Seguirás usando estimación chispeada para iniciarla, incluso si estás en un clúster gigante, la única diferencia es que se ejecutará y no recibirás estos mensajes de error raros sobre permisos de archivo cuando hayas terminado. Entonces ahí lo tienes realmente usando Spark dash enviar en una marca Chinas nalgando nuevo entorno de Spark usando Spark tres, usando nuestro bytecode compilado que generamos de Intel J. Pero en realidad no estamos corriendo dentro de la inteligencia ya. Entonces donde realmente hemos ido más allá de los límites de nuestro IDE, lo cual es importante para las implementaciones del mundo real.
42. [Actividad] el empaque guías guías del conductor con SBT: Entonces, ¿no sería genial si pudiéramos empaquetar todo lo que necesitamos, todas nuestras dependencias y todo en un solo archivo JAR y simplemente distribuir eso al nodo maestro de nuestro clúster y ponerlo en marcha. Bueno, eso es lo que SBT o la sencilla herramienta de construcción te permite hacer. Entonces hablemos de SBT con más profundidad y cómo podemos empaquetar tu script y todas sus dependencias juntas usándolo. Entonces si estás familiarizado con Java, podría estar familiarizado con Maven. Se puede pensar en SBT es como Maven para Scala. Y lo que hace es administrar tu árbol de dependencias de bibliotecas por ti. Entonces si tienes un script que depende de alguna biblioteca Scala o Java, algún archivo JAR, automáticamente saldrá y descubrirá no solo dónde
sacarlo de eso, cómo empaquetarlo en tu archivo JAR definitivo que estás compilando. Pero también cualquier dependencia en ese paquete tiene con
demasiada frecuencia tienes estos árboles complicados de dependencias y estos archivos JAR y cualquier paquete del que dependas a su vez depende de otros paquetes, que a su vez podría depender de otros paquetes. Por lo que hacer un seguimiento de todo lo que a mano es que se sale de las manos con bastante rapidez, pero SBT manejará esa complejidad por ti. Averigua automáticamente qué paquetes necesitas para que todo se ejecute
realmente y junte los para ti y empaquetarlos. Entonces eso es realmente lo que tiene SBT. Cuatro, hace la vida mucho más fácil si tienes muchas dependencias o si tienes una biblioteca que tiene muchas dependencias propias, es mucho más fácil que rastrear esas dependencias a mano. Y es mucho más fácil que pasarlo una tonelada de opciones al guión,
dash tarros parámetro de línea de comandos cuando estás ejecutando Spark submit. Entonces en lugar de pasar un montón de dependencias
específicas en la línea de comando con Spark submit. Podemos parchearlo todos en el archivo jar en sí para que no tengamos que recordar realmente cuáles son esos y realmente entrar eso en la línea de comandos. Para obtener SVT Es gratis, es de código abierto. Podemos conseguirlo de Scala dash SBT.org, y en breve te lo mostraremos. Usarlo es bastante sencillo. Solo tienes que configurar una estructura de directorios que se vea así. Por lo que en el nivel superior en algún lugar, tendrás un directorio de proyectos donde compilará cosas y un directorio fuente que como podrías adivinar, es donde irá tu fuente. Debajo de tu fuente, debería haber un directorio principal, y debajo principal debería haber un directorio vieiras. Y dentro de ese directorio de Scala es donde vas a poner los archivos reales de Scala que quieres que se compilen. Sbt coincidirá con compilar eso para usted y empaquetarlo en su archivo JAR junto con cualquier dependencia que especifique para usarlo. Como dije, acabas de poner tus archivos fuente y la carpeta fuente bastante sencilla. Ponlo en el lugar correcto. Y luego en tu carpeta de proyecto, vamos a crear un pequeño archivo SBT de punto de ensamblaje que contiene solo una línea que se veía así. Ahora 0.14.10 podría cambiar con el tiempo. Eso sigue siendo bastante actual. Ya hay un 15 0 por ahí, pero aún no está muy difundido. Entonces por ahora nos vamos a quedar con la versión 14 aquí del plugin de ensamblado SBT. Pero eso es todo lo que tienes que hacer. Eso solo le dice a SBT que vamos a estar usando este plug-in llamado ensamble SBT. Y su trabajo en la vida es crear ese archivo JAR autónomo que queremos. El verdadero corazón de la misma sin embargo es el archivo de compilación SBT. Y eso es construir un punto SBT que debe colocarse en la raíz de
su árbol de directorios SBT allí junto a los directorios de origen y proyecto. Entonces, aquí hay un ejemplo de cómo podría verse uno. Especificamos el nombre del Padre, estamos creando un número de versión, lo que quieras ser. La organización que está asociada a este paquete. El versión de Scala de la que depende, esto es importante para hacer bien. Recuerda que diferentes versiones de Spark requerirán diferentes versiones de Scala. Entonces en este ejemplo, estamos especificando una dependencia de biblioteca de org dot apache, Spark, spark dash core. De acuerdo, Entonces esto nos está diciendo que este popular guión de película que tenemos en Scala depende del paquete Spark Core. De Apache Spark. Y estamos especificando específicamente la versión 3 con Spark aquí. Entonces porque sabemos que desató tres requiere Scala versión 2.12. Por eso tenemos la versión 2.12.3 de Scala allá arriba o lo que sea, ya
sabes, la última versión podría ser que estás usando. Ahora esto es importante para ponerse bien. Por ejemplo, vamos a ir a la siguiente conferencia, subir nuestro archivo JAR al servicio Elastic MapReduce de Amazon, que a partir de esta grabación aún no soporta Spark tres, soportan la versión 2.4.5 de Spark, que requiere Scala versión 2.11. Entonces en ese ejemplo, vamos a especificar Spark Core versión 2.4.5 en lugar de 3 y Scala versión 2.11 algo. Entonces tienes que asegurarte de que esos coincidan o de lo contrario no va a funcionar bien? Tenga en cuenta que las dependencias de la biblioteca aquí en realidad es una secuencia, por lo que podemos tener más de una cosa ahí si solo
tenemos una lista separada por comas de líneas allí. Entonces además, podríamos haber desatado bibliotecas SQL o de terceros, incluso lo que sea que necesites para que se ejecute tu script, acabarías de enumerar aquí y luego SBT saldría y lo conseguiría y usaría africano apilando tu código y también para empaquetar eso en su archivo JAR final. Ahora de algo de lo que queremos hablar en particular aquí es de esa cláusula proporcionada allá. Por lo que siempre significa que podemos asumir
que ese paquete se preinstalará en donde sea que vamos a estar ejecutando esto. Entonces porque voy a estar desplegando esto en un cluster que ya tiene instalado Spark. No hay necesidad de que incluya núcleo chispeado dentro del
propio archivo JAR porque eso va a estar disponible para el sistema en su conjunto, todo listo. Entonces al decir provisto, eso significa que sí requiero este paquete para poder compilar mi código, pero no necesito empaquetarlo en mi archivo JAR final porque ya
estará presente dondequiera que vaya a estar ejecutando esto. Si realmente quisieras incluir smart core en el archivo jar en sí, dejaría fuera de lo proporcionado y eso lo agruparía todo en un archivo char verdaderamente autónomo. Pero como ya tengo instalado Spark desde donde voy a estar ejecutándolo. No necesitamos eso, Podemos dejar eso fuera con la bandera proporcionada. Entonces como otro ejemplo, digamos que necesito depender de Kafka. Eso en realidad no es parte de Spark. Podría tener otra línea ahí en las dependencias de
la biblioteca que dice o datos apache dot Spark,
chispa Streaming versión Kafka, cualquiera que sea la versión de esos paquetes que necesites. Ahora en ese caso, no diría siempre porque sé que eso no está preinstalado en mi sistema, entonces voy a estar ejecutándolo desde. Entonces eso empaquetaría ese jar de Spark Streaming Kafka en el archivo JAR definitivo que voy a estar desplegando y construyendo en mi archivo JAR final. Entonces una vez que tienes todo en su lugar, todo lo que tienes que hacer es ejecutar el ensamblado SBT desde la carpeta raíz. Y se apagará y trabajará su magia. Y se apagará y compilará tus, tus guiones. Lo parchará todo junto después de reunir todas las dependencias que necesita. Y encontrarás el archivo JAR final bajo objetivos last Scala dash sea cual sea la versión de Scala que le dijeras que construyera contra. Y luego tienes un archivo jar que puedes hacer lo que quieras. Y la belleza de nuevo es que es completamente autónoma. Siempre y cuando puedas obtener ese archivo JAR
al nodo maestro de tu clúster desde el que lo vas a ejecutar. Todo lo que tienes que hacer es decir desatado como ruta Summit a ese archivo jar y ya está hecho. No es necesario especificar la clase, no hay dependencias JAR, nada, eso es todo. Entonces vamos a probarlo. Muy bien, Así que primero revisemos ese guión que en realidad vamos a estar empaquetando aquí. Entonces si volvemos a IntelliJ y buscamos un dataset de similitudes de película 1M. Eso es lo que vamos a empaquetar aquí y finalmente enviarnos a Elastic MapReduce de
Amazon para que realmente se ejecute en un clúster real. Entonces vamos a caminar por lo que es diferente aquí. No mucho en realidad, pero aquí hay algunas cosas de las que hablar. En primer lugar, para el archivo DAT de las películas dot, tenga en cuenta que estamos pasando esto como un camino específico a las películas dot dat. Eso se va a esperar que esté al lado de nuestro donde estamos ejecutando Spark submit, su va a asumir que ese archivo está presente ahí en el sistema de archivos local. Ahora, como ya hablamos antes, ese no suele ser un gran plan. Al igual que si tienes un sistema de archivos distribuido donde puedes sacarlo de eso, eso va a ser mejor. Pero en nuestro caso, películas dot dat es un archivo bastante pequeño. Entonces podemos ponernos eso a nuestro alrededor sin un montón de problemas. No obstante, en términos generales, te gustaría
tener eso en algún tipo de sistema de archivos distribuido en su lugar, en lugar de confiar en que ese archivo esté presente en todas partes desde donde vas a ejecutar este script. Estamos sin embargo, asegurándonos de que tenemos el archivo
DAT puntuaciones dot en un sistema de archivos mucho más grande aquí. Entonces eso va a ser en Amazon tiene tres, eso se refiere el prefijo S3 n ahí. Entonces, um, así que tengo un cubo S3 llamado Sun dog hace chispa que contiene el archivo de datos de calificaciones dot dat allí. Y debido a que eso es realmente big data per se, bueno, realmente podríamos manejar eso en una sola máquina, pero para conjuntos de datos más grandes como ese, generalmente
quieres tener eso en algún tipo de sistema de archivos distribuido seguro. Entonces en ese caso, nos tomamos la molestia de asegurarnos de que está disponible en Amazon S3. Y no vamos a suponer que eso está en el sistema de archivos local. Ahora bien, este es un formato algo diferente que vimos antes para los conjuntos de datos de analítica 100 K. Entonces hablemos un poco de eso también. Vayamos a Grouplens.org. Y si vamos a conjuntos de datos, podemos aprender más sobre ese conjunto de datos específico de 1 millón o hay un dataset de mil millones ahora para, bueno, si realmente quieres big data, pero hay uno que estamos usando en este ejemplo. Entonces si vas al texto de punto Read
Me, te dice sobre el formato de archivo con más detalle. Desplazémonos hacia abajo. lo que la descripción del archivo de valoraciones, por ejemplo, te está diciendo que el formato es User ID, ID de película, rating, marca de tiempo, pero en este caso no está separado por tabulaciones. En realidad está separado por estos pares de Coleman. Entonces eso es importante darse cuenta. También la información del archivo de películas es importante saber demasiado también que está delimitada por el poco poco inusual de colon doble. Entonces debes asegurarte de entender el formato con el que estás tratando antes de escribir tu código. Si volvemos a la inteligencia, podemos ver que sí especificamos ese doble colon como el separador en ambos casos. Y estamos especificando el conjunto de caracteres para los nombres de las películas también. Eso también es ISO 8859 dash one. Entonces esa es una diferencia, solo el formato y la ruta que estamos usando para esos archivos de datos para el dataset de MovieLens 1 millón, estamos cambiando al conjunto de datos de 1 millón aquí solo para ilustrar realmente operando en big data. Por lo que esta es una mediana de tareas en hacerlo en una sola máquina podría ser un reto. Entonces estamos, estamos abordando eso ahora. En cuanto a qué otra cosa es diferente? Bueno, no mucho. resto del código es más o menos el mismo. Por lo que sólo tuvimos que asegurarnos de que estamos obteniendo nuestros datos del lugar correcto, que estén en el formato correcto. Y aparte de eso, es más o menos el mismo código que vimos de nuevo en el ejemplo de conjunto de datos de similitudes de la película anteriormente en el curso. Entonces vamos a cerrar esto ahora que ya terminamos de hablar de ello. Lo primero que tenemos que hacer es descargar el propio SBT. Entonces si te diriges a Scala dash Sbt.org. Deberías ver un botón de descarga en algún lugar. Estoy seguro de que este sitio web cambiará con el tiempo, pero ojalá lo puedas encontrar. Para Windows. Ahí hay un instalador de Windows, así que sigamos adelante y agarramos eso. Si estás en Linux o Mac OS, puedes obtener un paquete autónomo aquí
ya sea desde archivo zip o formato TGC, lo que prefieras. Y solo puedes descomprimir eso y terminarlo con él. Encontrarás el ejecutable SBT dentro de ahí. Si estás en Ubuntu y prefieres usar un gestor de paquetes, puedes dirigirte a la documentación para una Scala SBT y te dirá al respecto. Simplemente ve a este enlace aquí y eso te guiará a través de cómo asegurarte de que tienes el repositorio correcto en su lugar y cómo instalarlo usando app.get. Pero estoy en Windows, así que solo voy a ejecutar el instalador de Windows y terminar con él. Sí, sí, lo sé. Corre de todos modos. Esta caminata a través de ella. Y lo bonito es que deberían poner SBT en mi camino para
mí para que no tenga que preocuparme por donde Dios instale dos. De acuerdo, así que eso está fuera del camino. A continuación, en realidad obtengamos nuestros directorios SBT para que podamos agregar algo para empaquetar. Entonces si te diriges a medios http, perros Dotson, dash, soft.com slash Spark, Scala slash SPT dot zip. Está bien. Adelante y consigue eso y descomprimirlo. No obstante descomprimes cosas en tu sistema operativo. Y deberías tener una carpeta SBT que se vea así. Entonces, solo movamos eso a algún lugar donde no lo perdamos. Voy a cortar eso y vamos a ponerlo en mi disco C. Muy bien, entonces ahora tenemos una carpeta SBT y si miramos en el contenido de la misma, vemos lo que esperamos ver, justo ahí está ese directorio de proyectos. Y dentro del directorio del proyecto está ensamblado no SBT. Examinemos eso. Y sí contiene esa línea de la que hablamos antes, simplemente especificando que vamos a estar usando el plug-in de ensamblado
SBT con esa versión del mismo. Y bajo el directorio fuente, tenemos un directorio principal y un erudito el cual contiene las similitudes de la película. Un dataset m dot archivo Scala que acabamos de ver. Y finalmente en el directorio superior aquí tenemos nuestro mágico build dot SBT archivo. Y si examinamos eso, podemos ver que tenemos un nombre que coincide con nuestro ClassName, cualquiera que sea el número de versión que queramos darle, nombre de
nuestra organización, la versión de Scala de la que dependemos, y las versiones de Spark Core y Spark SQL de los que dependemos para este script. Ahora de nuevo, en este ejemplo en Amazon EMR actualmente están en la versión 2.4.5. Entonces eso es lo que he especificado aquí porque
ahí es donde voy a estar desplegando esto al final. Y sé que Spark 2.4 se basa en la versión 2.11 de Scala. Entonces ese es el método para toda esa locura. Y de nuevo, tenga en cuenta que estoy diciendo proporcionado porque sé que Spark Core en Spark SQL se van a preinstalar en mi clúster Amazon EMR. No necesito empaquetar la propia Spark en mi archivo JAR final. Ahora esto es una especie de ejemplo poco interesante porque no tengo ninguna dependencia de terceros aquí. Entonces, al final, todo lo que realmente voy a estar empaquetando es el archivo JAR para mi propio script. Pero esto viene de gran utilidad si tienes un árbol de dependencias más complicado, ¿verdad? Entonces por el bien de ejemplo aquí, no
estamos haciendo nada súper complicado, pero así es como administrarías tus dependencias si tuvieras un paquete de terceros que no estuviera preinstalado en tu sistema. Estarás corriendo desde. Acabas de enumerar esos aquí. Además, asegurándose de que esté separado por comas y no
dirías proporcionado en aquellas específicas en las que sí quieres que se agrupe. Entonces, veamos si funciona. Abramos un símbolo del sistema, y lo haré con permisos de administrador solo para estar a salvo. Entonces si bajo y windows, eso sería bajo el símbolo del sistema de Windows, haré clic con el botón derecho en eso, digamos más ejecutar como administrador. Y vayamos a esa carpeta SBT. Ahí está. Ahora solo podemos teclear en ensamble SBT. Y fuera debería ir. Y en realidad necesitaremos salir y recuperar un entorno de Scala y Apache Spark y todo lo que necesita para realmente compilar eso. Por lo que es un poco mágico cómo SBT puede tener todo
este entorno autónomo que construye desde cero. Y ahí lo tenemos. Por lo que parece que ha tenido éxito. Echemos un vistazo y veamos qué tenemos aquí. Entonces si vamos y aquí ahora tenemos un directorio objetivo. Veamos qué tenemos ahí dentro. Y hay un directorio esquelético 11 y dentro está nuestro archivo JAR. Muy cool. Entonces es como si funcionara similitudes de película cuando soy dataset dash assembly, dash 1 dot jar, solo sentado ahí esperando a que lo usemos. Entonces en nuestra próxima conferencia, Vamos a usarla.
43. [Ejercicio] Combar un guion con SBT y cortarlo localmente con la presentación con chispa-: De acuerdo, Entonces en este punto te he enseñado a usar Spark submit en una instalación local de Apache Spark para ejecutar tus scripts. Y también te he mostrado cómo usar sbt para agrupar tu script en un archivo JAR autónomo. Entonces tu reto es juntar estas dos cosas. Quiero que uses sbt para agrupar un archivo JAR y luego ejecutarlo localmente usando Spark das submit en tu escritorio local. Y la estrategia aquí, elige cualquier guión que quieras. Realmente no me importa, pero voy a elegir el script de conjunto de datos de temperaturas Min. Realmente no importa con cuál quieras jugar. Y lo que vas a tener que hacer es modificar el archivo build SBT en tu árbol de directorios SPT y asegurarte de que estás usando la misma versión de Spark que instalaste localmente para usar Spark submit. Y también necesitamos asegurarnos de que estamos usando una versión compatible de Scala para esa versión de Spark. Por lo que esto va a implicar hacer un poco de investigación en línea. Vas a tener que averiguar qué versión de Spark estás usando y qué versión de Scala es compatible con esa versión de Spark. Y una vez que hayas hecho eso, además, debes averiguar cuál
es el lanzamiento actual de Scala para esa revisión importante de Scala. Entonces no quiero darte demasiada orientación aquí porque ser desarrollador en el mundo real a menudo
se trata principalmente de hacer este tipo de investigación tú mismo y descubrir nuevos problemas tú mismo. No vas a poder ir con tu jefe o tus compañeros a resolver esto por ti. Es decir, puedes, pero van a encontrar eso bastante molesto y probablemente no durarás mucho si haces eso todo el tiempo. Entonces quiero que te hagas un poco de práctica y hagas una figuración de estas cosas tú mismo. Una vez que tengas sin embargo, is solo debería ser cuestión de
asegurarte de que tu script esté en el lugar correcto en el árbol de compilación para sbt. Y también asegurándose de que tengas el Bill dot SBT correcto armado para la versión correcta de Spark y Spark Submit. En ese punto, podemos simplemente usar el ensamblado de Spark para construirlo y asegurarnos de que ejecutamos Spark submit desde el directorio que asume el script. Como recuerdan, la mayoría de nuestros scripts asumen que existe un directorio de datos local que contendrá los datos que queremos en el sistema de archivos local. Por lo que necesitamos asegurarnos de ejecutar ese script desde el lugar correcto donde exista ese subdirectorio de datos. Y con eso, apártate y dale una oportunidad. Y en el siguiente video, te
guiaré por cómo lo hice.
44. Solución de ejercicio: con SBT y la presentación de: Así que déjame guiarte por cómo me he ocupado empaquetar el script de dataset de temperaturas Min usando SBT y ejecutándolo localmente usando Spark submit fuera de la inteligencia. Entonces lo primero que siempre quieres hacer es echar un vistazo
al script antes de empaquetarlo y asegurarte de que nada
ahí dentro que necesites cambiar antes de ejecutarlo en un entorno diferente, ¿verdad? Entonces, antes que nada, ten en cuenta que estamos usando estrella local. Ahora si en realidad me estaba ejecutando en un clúster real, probablemente
quiero sacar eso porque en un clúster quiero estar usando cada núcleo y cada máquina de mi clúster,
no solo la máquina local en la que estoy ejecutando el script de controlador, pero ya que mi intención es seguir ejecutando esto solo en mi PC local que puede permanecer sin cambios en este caso. También presta atención a las rutas de archivo. Esto supone que vamos a la barra de datos 8800 puntos CSV para nuestro archivo de datos allí. Y eso implica que voy a tener que tener una carpeta de datos en mi sistema de archivos local que esté junto a la misma ubicación donde estoy invocando este script de usar Spark submit. Por lo que podría cambiar eso por un camino absoluto si quisiera. Podría cambiarlo a algún sistema de archivos compartido si quisiera. Pero de nuevo, ya que solo estoy ejecutando en mi sistema de archivos local, solo
me aseguraré de que recuerdo ejecutar esto desde
junto a esa carpeta de datos donde ya lo tengo instalado. Entonces no voy a cambiar nada aquí en realidad, pero siempre quieres estar al tanto de ese tipo de
temas antes de empaquetar un guión con el que has estado jugando localmente y enviártelo fuera para ti a otro lugar, sería realmente horrible si olvidara sacar esa línea maestra ahí,
cierto, y en realidad enviarla a un cúmulo. Había tenido este enorme cúmulo y no lo estaría aprovechando para nada en ese caso. Por lo que siempre ten cuidado con ese tipo de cosas. Entonces, empecemos con la parte fácil. Copiemos ese guión en sí y lo pongamos en SBT. Entonces minimicemos eso en mi curso de Spark Scala, encontremos ese archivo. Está bajo fuente, principal scala com, software de
algunos perros, una chispa. ¿Y qué fue? Conjunto de datos de temperatura mínima, puntos vieiras, voy a seguir adelante y copiar eso. Y ve a mi directorio SBT y entra en la fuente principal Scala. Y lo pegaré aquí y
eliminaré las similitudes de película 1 millón de archivo de conjunto de datos que utilizamos en la actividad anterior. Entonces ahora necesito asegurarme de que estoy usando la versión correcta de Spark y la versión correcta de Scala para que esto pueda ejecutarse localmente en mi entorno local de Spark. Entonces volvamos a la parte superior de SBT aquí y voy a editar ese proyecto de ley no archivo SBT, usa lo que sea editor que quieras. Para mí, tengo instalado algo llamado Notepad Plus, Plus. Algo funciona, ¿verdad? Cualquier editor de texto hará el trabajo aquí. Por lo que necesitamos especificar qué versión de Spark estamos usando y qué versión de Scala. Y estos necesitan ser compatibles, no solo entre sí, sino también con lo que tienes instalado para Spark en tu sistema local. Tenga en cuenta que estamos diciendo que se proporciona chispa en sí, por lo que no va a empaquetar la propia Spark en nuestro archivo jar resultante. Se va a usar cualquier versión de Spark presente en mi sistema de archivos aquí. Por lo que necesito asegurarme de que esto se está construyendo contra la versión correcta de Spark. Empecemos con eso. Entonces volvamos a mi instalación de chispa y solo comprobemos dos veces. Por lo que instalé Spark en ver Spark. Y si miro el lanzamiento TextFile ahí, me dice
que estoy usando Spark 3. De acuerdo, así que esa es una pieza del rompecabezas. Volvamos a mi archivo Bill dot SBT bajo SBT. Y cambiaremos Spark Core a 3. Y como estoy usando conjuntos de datos, sí
necesito el paquete Spark SQL también. Entonces dejaremos eso ahí también. Y también quieres pensar en qué otras dependencias
tienes dentro de la misma Spark en este punto o fuera de una chispa. Y en este caso ya no hay. Pero si estaba empaquetando, digamos, un script de machine learning, podría querer incluir Spark ML, archivos de streaming de
Spark haciendo algún script de streaming de pantalla. Así que asegúrate de tener alguna dependencia que necesites ahí. Muy bien, ahora tenemos que averiguar qué versión de Scala es compatible con esa versión de Spark. Entonces para hacer eso se requiere un poco de investigación. Vamos a encender un navegador web. Y traeré aquí una ventana de nucleón. Entonces vamos a chispa punto apache.org. Y si miramos a Spark de tres puntos, Oh, ve al área de Download Spark aquí, y podemos ver que aquí nos dice con qué versión de Scala compatible, qué versión de Spark. Entonces dice que no, esa chispa a punto x está preconstruida con 2.11 excepto la versión 2.4.2, que está construida con esqueleto 12. Pero Spark de tres puntos Oh, eso somos nosotros está pre-construido con Scala a 0.12. De acuerdo, así que sé que necesito Spark versión 2.12. ¿ Eso es lo suficientemente específico? Bueno, veamos. Yo también quiero una versión menor. Está bien. Bueno, cambiaremos el 11 a 12, pero ¿qué viene después del 12? No lo sé. Hagamos un poco más de investigación. Entonces, de nuevo, tienes que ser ingenioso a veces. Entonces, solo busquemos Scala a 0.12 y veamos si podemos averiguar cuál es el lanzamiento actual de eso. Parece que eso señalándome a escalar una línea discontinua.org, que es la casa oficial de Scala. Y aunque no quiero, parece que 2.13 está realmente fuera, pero de nuevo, necesito usar 2.12 para esa versión de Spark. A ver si las notas de lanzamiento me dicen algo. Está bien. Por lo que al parecer el último lanzamiento de 2.12 es 2.12.12. Está bien, vamos con eso. Por lo que de vuelta a mi archivo SBT build out, vamos a especificar 2.12.12 y voy a guardar esto. En este punto, deberíamos estar listos para empaquetar esto. Adelante y abramos un símbolo del sistema. Limpia un poco las cosas aquí. Entonces vamos a ver. Iré al menú Inicio. Por supuesto, en Mac o un Linux, simplemente
abrirías una terminal. No es gran cosa. Esto va a ser bajo el símbolo del sistema de Windows y queremos ejecutar eso como administrador sólo para estar seguros. Muy bien, así que vamos a navegar a esa carpeta SBT. Y acabaremos de escribir en ensamble SBT. Y ojalá haga lo correcto. De acuerdo, ¿algo se ve como un construido contra esqueleto 0.12. Entonces eso suena bien. Sigamos adelante y veamos si tenemos ese archivo jar resultante. Vamos a entrar en objetivos esqueleto 12. Ah, me olvidé de cambiarle el nombre. Está bien, bien. Bueno, volvamos a sbt y editamos de nuevo ese archivo SBT de Bill dot. Ver Olvidé cambiar el nombre. Entonces realmente esto debería ser lo que era esta cosa otra vez, conjunto de datos de temperatura Min. Muy bien, hagámoslo otra vez. Debería ser más rápido ahora que se descarga todas esas dependencias. De acuerdo, veamos qué tenemos ahora. Destina a Scala a 12. Ahí está, min temperature dataset assembly dash 1 O. Así que vamos a copiar eso y ponerlo junto a ese directorio de datos desde donde quiero ejecutarlo. Entonces Control C, obviamente podrías usar el comando cp desde un símbolo del sistema si lo quisieras también. Y entraremos a ver curso de gala chispas. Y dentro de ahí, está el directorio de datos que asume es local relativo al script. Adelante y peguemos eso aquí. Y ahora debería poder navegar hasta ahí y lo ejecutas con Spark submit. Entonces vamos a cambiar nuestro directorio para ver chispas curso de gala slash Spark Scala. Y vamos a empezar con Spark somete y a ver qué pasa. Por lo que chispas envía camino estaba bajo C chispa bin, escritorio de chispa enviar. Asegúrate de que esté ahí, de acuerdo. Y deberíamos poder pasar en Min temperature dataset dash assembly dash dash 1 dot char. Solo estoy usando la tecla Tab para autocompletar eso. Y debería funcionar. Y sí nos dieron un montón de errores en el apagado. Pero de nuevo, eso es normal. Eso es algo de Windows. En realidad sí obtuvimos nuestra salida sin embargo. Entonces mira, funcionó genial. Conseguimos nuestra temperatura mínima para esas dos estaciones meteorológicas. Y tenemos un packaging exitoso de eso es bueno con SBT y lo ejecutamos localmente usando Spark desk enviar cuidando la versión de Spark que teníamos instalada y la versión de Scala que, esa versión de De la chispa depende. Por lo que ojalá tuvieras algún éxito con esto también. Si no, creo que ver este video probablemente te mostró dónde salieron mal las cosas. Así que regresa y vuelve a intentarlo si es necesario. Y con eso, sigamos.
45. Introducción a Amazon Elastic Map: Entonces, en el momento que hemos estado esperando, realmente
vamos a ejecutar nuestro guión de calificación de 1 millón de películas en un clúster real usando la superficie Elastic MapReduce de Amazon y Hadoop. Hay muchas palabras de zumbido ahí. Hablemos de un poco más antes de que realmente lo hagamos. Hablemos de cómo funciona realmente Spark distribuido. Por lo que los mismos scripts que has estado usando para ejecutar estos trabajos de Spark localmente en tu propio PC se pueden usar en un clúster sin mucha modificación. Por lo que es algo que toca a Spark enviar y a Spark sí mismo averiguar en qué gestor de clústeres estás corriendo encima. Y eso podría ser chispas incorporado administrador de clústeres. Podría ser el hilo de Hadoop, podría ser Mesos. E intégrate con eso para distribuir realmente el trabajo de todos tus mapeadores y reductores así como un CAN a través del cluster que tienes disponible para ti. Entonces, básicamente, el script del conductor de Spark se está ejecutando en tu nodo maestro, tu conductor, ¿de acuerdo? Y eso se comunica con tu administrador de clústeres para distribuir realmente el trabajo que está en el script de ese conductor a diferentes trabajadores de nodos ejecutores, ¿de acuerdo? Y el administrador de clústeres es responsable de lidiar con fallas de nodos
individuales y hacer clic de
nuevo en los resultados juntos para volver a su script de controlador cuando esté terminado. Ahora algunos otros parámetros de Spark Summit deberíamos hablar. Y primero debo señalar que en muchos clústeres, muchos
de estos ajustes van a estar preconfigurados para ti automáticamente. Entonces si no especificas nada en tu script explícitamente para lo que va a ser el maestro o si no se está especificando en la línea de comandos. También hay un archivo de configuración dentro de chispa que se
puede configurar para configurar todas estas cosas para usted automáticamente. Y por ejemplo, si configura un clúster en Amazon, Elastic MapReduce, muchas de estas cosas estarán configuradas para usted y no de manera óptima ya. Pero a veces te encuentras con temas donde las cosas no se completan. Te quedas sin recursos, las cosas empiezan a agotarse y necesitas ajustar un poco estas cosas para que las
cosas funcionen de manera más confiable por lo que necesitas saber que existen. La primera opción de la que no queremos hablar es dash, dash master. Y eso no es algo que puedas retocar. Es solo prueba que se establezca en lo correcto para qué tipo de clúster tienes. Entonces si estás corriendo en un cluster de Hadoop y quieres
aprovechar el Gestor de Cluster de hilados de Hadoop que se establecerá en hilado. Si desea usar el clúster independiente de Spark, lo establecería en el nombre de host y el puerto de su nodo maestro en su clúster de Spark. Mesos trabaja de manera similar. Y de nuevo, si tienes una chispa conf o algo en tu propio guión que anula eso. Ignorará lo que hay en la línea de comando. Entonces la jerarquía es lo que hay en tu guión, aguas en la línea de comando y ganadores en los archivos de configuración para chispas. Así que nunca olvides volver a revisar tus guiones para asegurarte de que no eres difícil codificar a un maestro dado. Por ejemplo, si tienes esa estrella de paréntesis locales, eso anulará la opción maestra aquí. Y si ejecutara ese script en un clúster, no
aprovecharían el clúster completo. En cuanto a administrar el uso de los recursos en su clúster, también
hay opciones para eso. Los ejecutores Num especificarán cuántos nodos ejecutores quieres usar. Por defecto, eso son sólo dos. Por lo tanto, si estás ejecutando en un clúster más grande que tiene más de dos nodos, querrás aumentar esa configuración. Nuevamente, por lo general eso te lo fijará otra persona, por la administración, pero algo de lo que estar al tanto y asegurarte de que eso esté en algún lugar. El ejecutor memoria maneja cuánta memoria está disponible para cada ejecutor. Y por supuesto quieres asegurarte de que eso no exceda la memoria física disponible para cada nodo ejecutor individual. Si estás ejecutando en un clúster en la Nube, esas son a menudo máquinas virtuales que tienen menos memoria de la que podrías pensar. Por lo tanto, asegúrese de estar al tanto de la memoria disponible para su script en cada ejecutor. Y también puedes mirar los núcleos ejecutores totales. Si tienes multinúcleos en tus nodos virtuales, entonces es posible que quieras ajustar eso para poner realmente un límite superior en cuántos, cuántos núcleos puede consumir tu script. De acuerdo, Amazon Elastic MapReduce, así que eso es lo que vamos a usar en este curso. Es una forma rápida y fácil de hacer girar un clúster de Hadoop y
en realidad puedes decirle que preinstale Spark en él como para ti también, con todo configurado automáticamente. Así que manera muy fácil de empezar y ejecutar tu script en un clúster real donde solo rentas tiempo y pagas por lo que necesitas. Y esa es toda la premisa de Amazon Web Services. Simplemente escribes tiempo y pagas por los recursos informáticos que realmente necesitas para lo que estés haciendo. Entonces se te cobra básicamente por la instancia de hora, cuánto tiempo estás gastando en cuántas computadoras de un tipo determinado. Y también se te cobra por cualquier IO de red y cualquier espacio de almacenamiento y cualquier IO de almacenamiento también. Por lo que pagas por lo que usas. Y por lo general no es mucho. Creo que gasté unos 30 dólares y en realidad
juntando este curso en términos de cargos de AWS. Pero ten cuidado. Yo sí recomiendo sólo verme hacer esto por ahora a menos que
tengas alguna cuenta corporativa o algo donde no sea tu dinero en la línea. Porque si te equivocas, es muy fácil
olvidarte de terminar tu clúster cuando termines. Y si haces eso, tu clúster
solo seguirá funcionando para siempre aunque no lo estés usando. Y te van a construir durante todo ese tiempo cuando tal vez ni siquiera te des cuenta hasta
que veas un cargo de tarjeta de crédito por 1000 dólares. No quiero que eso te pase. No quiero ser responsable de eso. Entonces, um, ya sabes, si sí quieres juguetear con el MR, Acuérdate de terminar tus clústeres cuando termines. Si no te vas a gustar a tus cuentas bancarias y no te voy a gustar yo, así que simplemente no vayas ahí. Está bien. Entonces con eso, hablemos de correr realmente en un clúster, hablando de algunos de estos puntos ya. Pero de nuevo, lo que EMR configura para ti es un clúster de Hadoop y puedes ejecutar Spark encima del componente de hilo de Hadoop. Por lo que la gente tipo de conflar Hadoop y Hadoop hilo. A veces escucho hablar de mucha gente sobre cómo Spark es más rápido que Hadoop, pero en realidad no es uno u otro. ¿ De acuerdo? Lo que realmente quieren decir es que Spark es más rápido que MapReduce, que es una forma de ejecutar trabajos distribuidos en Hadoop. Pero Hadoop en sí es sólo una tecnología para administrar un clúster. Y un componente de Hadoop es el hilado, el Cluster Manager, que chispa puede correr encima de simplemente bien. De acuerdo, así que recuerda las diferentes piezas ya que un conductor de Spark es un gestor de clústeres y luego está el hardware real en sí. Hadoop solo está llenando esa pequeña pieza del medio para ti. Por lo que Hadoop y Spark no son mutuamente excluyentes, lo cual es un error común. ¿De acuerdo? Otra cosa a la que quiero señalar en cuanto a las mejores prácticas, porque correr en un clúster real es caro. Estos son recursos costosos con los que estás lidiando aquí potencialmente, siempre
quieres asegurarte de que estás haciendo tu desarrollo y pruebas localmente en tu propia PC primero, de acuerdo. O alguna computadora de escritorio o alguna computadora única que tienes acceso a ti que no cuesta mucho dinero. Y una forma de hacerlo a menudo es usar un subconjunto de tus datos solo para desarrollarse con. Entonces, si estás lidiando con un conjunto de big data que solo puedes administrar en un clúster, considera usar solo una pieza de ese conjunto de datos para desarrollar y probar el ancho. Y de esa manera tienes más probabilidades de tener una carrera exitosa cuando realmente estás rentando tiempo en el clúster mismo, realmente
quieres minimizar la cantidad de tiempo que estás trabajando en el clúster si es posible. De acuerdo, Entonces en cuanto a conseguir la configuración, necesitas comenzar creando una cuenta de servicios web de Amazon. Y yo solo asumiré que puedes averiguar cómo hacer eso. Desde otra vez, sólo quiero que me veas hacer esto ahora mismo. El siguiente paso será crear un par de claves EC2 para que tengas la capacidad de iniciar sesión en tu clúster una vez que lo hayas girado de manera segura. Y necesitarás una forma de iniciar sesión en esa máquina virtual real en algún momento usando algo como masilla en Windows, necesitas algún tipo de terminal para poder conectarte a estas máquinas y realmente ejecutar tu script y descargar las cosas que necesitas para ellos. Entonces empecemos y realmente veamos cómo funciona.
46. Crear películas similares con un millón de un billón en EMR: Entonces hagámoslo. Generemos en realidad similitudes de películas basadas en 1 millón de calificaciones de películas de usuarios y lo hagamos de verdad. Entonces solo sigue aquí y te mostraré cómo funciona usando el servicio Elastic MapReduce de Amazon. Ahora para configurar las cosas, ya
he cargado algunas cosas en el servicio S3 de Amazon, que es básicamente un almacén de archivos distribuido en el que rentas espacio. Muy bien, Así que un poco como HDFS, pero es la versión de Amazon del mismo. Una forma de pensarlo. Por lo que ya he creado lo que se llama un cubo en S3 llamado Sunday August Spark. Y he subido algunas cosas que voy a necesitar. Una es las similitudes de película, una M Jar, archivo Jar. Y esto es lo mismo que generé usando SBT antes en el curso. Acabo de darle un nombre de archivo ligeramente diferente. Por lo que tiene mi script de controlador Spark autónomo empaquetado en un archivo jar. De acuerdo, así que eso va a ser en S3. Por lo que puedo copiarlo rápidamente en mi clúster una vez que haya dividido mi clúster para ejecutarlo. La otra cosa que he hecho es que he movido aquí
el conjunto de datos de calificación de 1 millón de MovieLens también. Así que he creado una carpeta MNL dash 1M aquí en mi hijo murió inteligente S3 cubo. Y eso va a asegurar que este sistema de archivos distribuido de S3 que contiene mis calificaciones de 1 millón de películas también sea accesible para todo mi clúster. Y dentro de eso tenemos los diferentes archivos que conforman las calificaciones del conjunto de datos. Dot dat es las propias calificaciones de película y películas dot dat es todos los metadatos asociados con las películas reales. Entonces nuestra estrategia, si recuerdan, va a ser ejecutar ese archivo JAR desde el nodo maestro de nuestro clúster. Y va a tener películas dot dat ubicadas a su lado. Por lo que en realidad puede construir esa tabla de búsqueda de identificadores de películas a nombres de películas cuando está dando salida a los resultados. Pero todo lo que necesita el clúster son los datos de gradaciones. Entonces vamos a armar las cosas y hacer un cúmulo. Por lo que tenemos nuestro bonito y brillante archivo MovieLens 1 millón JAR listo para desplegar en nuestro clúster. Pero primero necesitamos un clúster para desplegar un dos y crear uno. Voy a utilizar el servicio AWS Elastic MapReduce para hacer eso. Ahora esto sí cuesta dinero. Entonces si no te gusta gastar dinero o no tienes una cuenta de AWS, probablemente solo quieras ver aquí y en realidad no seguirte. ¿ De acuerdo? Pero ya tengo una cuenta de AWS y un poco de presupuesto con el que jugar. Entonces voy a seguir adelante y dar clic en EMR aquí o simplemente teclear Elastic MapReduce y encontrar servicios. Y adelante y agita aquí un nuevo clúster. Entonces vamos a crear un nuevo clúster y llamémoslo chispa diversión de Scala. No lo sé, llama a lo que quieras. Y vamos a decir aquí que estamos usando la última versión de EMR. Eso no es una beta al menos. Y esto va a ser usando Spark. Queremos seleccionar aquí la aplicación de Spark. Y puedes ver que ahora mismo están ofreciendo Spark 2.4.4. Todavía no han tenido las agallas para crear una chispa tres. Pero para cuando estés viendo este video, tal vez esa sea una opción también. Pero por eso empaquetamos nuestros archivos JAR específicamente para Spark 2.4.4 y Scala a 0.11. Porque sabíamos que eso es lo que este cluster va a tener instalado en él. Para la configuración de hardware, podemos atenernos a los predeterminados aquí. Esto en realidad va a hacer girar un clúster de Spark de tres nodos. Por lo general es Spark corriendo encima de Hadoop, y eso va a ser todo m5 siguiente Grandes Instancias. Las cosas no son baratas, no
son Frigyes. Entonces aunque seas como una cuenta totalmente nueva en la que estás hablando de nivel gratuito. Esto no es hardware de nivel gratuito. Entonces de nuevo, esto costó dinero real para dar vueltas, me
costó unos 30 dólares para hacer esto cuando estaba poniendo todos estos ejercicios juntos. Entonces otra vez, si eso te hace chillar, no
hagas esto, solo mira. También es necesario especificar un par de claves EC2. Ya tengo uno creado que se llama Sun dog EC2. Y si necesitas crear uno nuevo, solo
puedes seguir ese enlace para aprender a crear tu propio par de claves EC2 totalmente nuevo. Por lo que obtienes una clave pública y una privada que puedes usar para conectarte
realmente a este clúster más adelante, necesitarás eso para iniciar sesión en el nodo maestro y realmente arrancar el script. Los permisos predeterminados están bien. Adelante y golpeemos Crear Cluster. Y fuera va. Entonces eso se va a apagar y aprovisionar todo el hardware que lo necesitamos. Nos tomaremos unos minutos para realmente conseguir ese hardware y conseguir todo configurado y bootstraped en él. Entonces volveremos cuando eso haya terminado de conseguir la configuración. De acuerdo, Entonces después de unos cinco o diez minutos, vemos que ahora tenemos nuestras maquinas maestras y core en estado en marcha aquí. Y mi clúster sólo está esperando a que haga algo. Tan cool, mi clúster está listo. Entonces hagamos algo con él. Para hacer eso primero, necesito conectarme a él de alguna manera. Por lo que puedes ver aquí bajo el maestro público DNS SEC me
da la dirección externamente disponible del nodo maestro. Entonces voy a ejecutar mi guión desde. Y si hago clic en este enlace SSH, te dirá exactamente cómo conectarte a él. Por lo que para Windows puedes usar algo llamado como masilla para un programa terminal. Eso es lo que estoy usando. Y si necesitas instalarlo, Hay un práctico dandy descarga el link ahí para ti. Y te dice exactamente cómo conectarte. Usando eso. Si estás en Mac o Linux, también
tienen instrucciones para ti. Pero estoy en Windows. Entonces lo que vamos a hacer es copiar esa dirección para que rápidamente
pueda meterla ahí y abrir masilla. Escriba eso en para el nombre del host. Y luego necesito especificar mi archivo APK, mi clave privada para realmente iniciar sesión en eso. Entonces recuerda, especifico mientras estaba configurando un clúster que
iba a usar la llave Sun dog EC2. Y ahí es donde guardo ese archivo ahí. Por lo que ahora debería poder simplemente golpear Open. Y ahí estamos logueados en nuestro nodo maestro. Ahora, dependiendo de su configuración de seguridad, realidad podría obtener un tiempo de espera en este punto. Entonces si estás tratando de averiguar por qué no puedes conectarte sin importar lo que intentes con tu configuración de firewall o siempre que aún no puedas pasar. Azar está bloqueado en el lado del servidor. Entonces si te encuentras con ese consejo rápido,
puedes hacer click en el grupo de seguridad aquí para el nodo maestro. Y una vez que estés ahí, puedes hacer clic en las reglas de entrada aquí y asegurarte de tener un puerto SSH abierto. Entonces en este caso, tuve que agregar manualmente un puerto SSH TCP al puerto 22 a la dirección IP desde la que me estoy conectando. Entonces si estás teniendo problemas para conectarte, Eso es probablemente lo que necesitas hacer. Pero volvamos a donde estábamos, vuelta a la consola EMR. Y de todos modos, ya estamos logueados. Entonces ahora podemos empezar a hacer algunas cosas divertidas. Entonces primero lo primero, veamos dónde estamos. Deberíamos tener un pequeño directorio de inicio aquí bajo el usuario de Hadoop. Primero que voy a hacer es copiar sobre nuestro script de controlador real en el archivo jar que creamos usando SBT anteriormente. Así que sigamos adelante y copiemos eso desde S3, EMR y AWS EC2 nodo tiene un conjunto de utilidades integradas llamadas AWS que puedes usar para copiar realmente cosas desde S3. Y esas cosas. Por lo que puedo escribir en AWS, S3 ,
CP, Veamos, s3 colon slash slash, Sun dog. No se lo puede decir a algún parque de perros. ¿ Y cómo llamé nuevamente al expediente? Películas similitud es un m dot jar. Las similitudes de un m dot char aquí. Está bien, y se puede ver que funcionó. El otro cosa que necesito es el archivo DAT de las películas dot. Por lo que realmente puedo hacer el construir la tabla de búsqueda que ID de película a nombres de películas. Y de nuevo, puse eso en la sub carpeta ML dash one m. Entonces vamos a copiar eso también. Aws S3 copia s3 colon slash slash, Spark slash ML dash 1M slash películas consiguieron adaptarse al directorio local. Por lo que ahí lo tenemos. De acuerdo, he ampliado un poco la ventana aquí para que podamos ver mejor nuestros resultados. Y todo lo que necesito hacer ahora es escribir en Spark dash, enviar el nombre del archivo jar, similitudes de
película, un m dot jar. Y si recuerdas bien, esta escritura requiere un parámetro de línea de comandos de la ID de película para la que nos interesa encontrar similitudes. Por lo que resulta que sé que Star Wars es 260 en el conjunto de datos de 1 millón. Vamos a patearlo. Muy bien, entonces vemos algunos mensajes introductorios de info aquí. Y una de las primeras cosas que hace el script es apagar cualquier cosa menos mensajes de error. Por lo que no deberíamos ver otra cosa que los mensajes de progreso ya que en realidad rompe esto y lo extiende al clúster. Entonces básicamente estamos esperando a que obtenga ese primer comando de acción y cree el DAG. Apenas cargó los nombres de las películas y ahora la está difundiendo. Entonces en este momento, mientras hablamos, en realidad
estamos computando películas similares para Star Wars usando 1 millón de calificaciones en un pequeño clúster de tres máquinas. bastante cool. Ya estamos en la etapa 2 y recuerdo que las etapas están divididas por áreas del DAG que están divididas por operaciones aleatorias de datos. Y esas etapas a su vez se dividen en tareas. Por lo que puedes ver ahora mismo aquí en la etapa dos donde atravesando 32 tareas, habrá otra etapa después de esto con un 100 para el, un 100 particiones que montamos. Y en unos cinco minutos o así se hará esto. No toma tanto tiempo, especie del poder de un clúster chupando a través un millón de calificaciones y cada posible permutación de cada posible par de películas luego filtrar los resultados queremos estudiante un mucho trabajo, pero lo hará con bastante rapidez. Entonces volvamos en cinco minutos aquí y te mostraré los resultados. Está bien, ya casi terminamos aquí. Ahí está. Impresionante. Por lo que tenemos las mejores películas similares para Star Wars Episodio 4 y nueva esperanza basada en 1 millón de calificaciones de películas reales. Y en estos días eso es un poco más nuevo a partir del 2003. Entonces de nuevo, no vamos a ver ninguna película actual, pero los resultados se ven bastante razonables. Tenemos un episodio 5 de Star Wars y el poder ataca a los apoyadores del Arca Perdida. Retorno del Jedi, especie de conseguir esa razón el Arca Perdida fue calificado más alto Retorno del Jedi. Pero para ser honesto, creo que podría haber disfrutado más Raiders of the Lost Ark que Retorno of the Jedi. Entonces eso tal vez no es tan loco como suena. Y la película original de Indiana Jones, muy buenas recomendaciones para alguien que disfruta de Star Wars. Y entonces empezamos a meternos en otras grandes películas que eran buenas. El terminador matriz, hay algunos, algunos bastante buenos aquí, de vuelta al futuro Princesa Novia todo apela a una especie de ese demográfico geeky. Muy cool. Hey miel Python y el Santo Grial, incluso estas son en realidad recomendaciones bastante malditas razonables. Enfriar, y ahí lo tienes. Entonces eso son recomendaciones de películas, películas
similares y Star Wars usando 1 millón de calificaciones de películas se ejecutan en un clúster real usando hilo Hadoop y ApachesPark. Es de lo que se trata. Ahora, último paso, no te olvides de terminar el clúster cuando hayas terminado. Entonces voy a salir de esto, pero eso no es suficiente. Y necesito volver al panel de control de EMR. Y en mi cluster hit terminar. Sí, seguro que ya terminé con ello. Ahora, si no haces eso, el proyecto de ley va a seguir corriendo por ti. Ese clúster sigue funcionando y a pesar de que no estás haciendo nada con él, todavía
te van a construir por el tiempo en ese clúster, para eso las tres de esas computadoras o incluso más si configuras más. Entonces, de nuevo, si estás haciendo esto a tu propio centavo y en realidad siguiéndote, por favor recuerda, determinate tu clúster cuando hayas terminado. De verdad no quiero oírme hablar de ello. Si recibes una factura de 1000 dólares al final del mes de Amazon, se supone que a 10, que es sobre lo que este costo. Está bien. Asegúrese de que eso termine con éxito y luego sea seguro cerrarlo. Pero con eso, woo hoo, felicitaciones, esa es una especie de culminación de lo que hemos estado haciendo aquí. En realidad ejecutamos una verdadera gran chispa, trabajo de
big data en un clúster real con éxito y sacamos algunos resultados realmente útiles de, fuera de él. tan cool. Hablemos con un poco más de profundidad sobre problemas de los trabajos de Spark y algunos de los puntos más finos de correr en las cosas de afinación.
47. Partición: Entonces una cosa que realmente pasé por alto fue esta línea aquí en estas películas similitud es un dataset m punto archivo Scala aquí del que no hablamos. Esto es diferente de nuestro script de conjunto de datos de similitudes de película original. Esta línea aquí, repartición num particiones es igual a 100. Entonces aplicamos eso a nuestro yo unimos a un DataFrame antes de convertir eso en un conjunto de datos. Entonces, ¿de qué se trata todo eso? ¿ De qué se trata el reparticionamiento? ¿ Por qué tengo que hacer eso? Bueno, esta es una operación
realmente, realmente pesada aquí yo haciendo esa auto-unión a través un millón de calificaciones va a explotar muy rápido y eso es más de lo que realmente puedes hacer en una sola máquina. Entonces en este caso tenemos que decirle a Spark, oye, realmente quieres dividir esta operación. Y ese parámetro de repartición le dice por
cuántas formas quieres dividir esa operación hacia arriba. Entonces hablemos de eso en un poco más de profundidad. Por lo que Spark suele ser bastante mágico. Hará automáticamente lo correcto para distribuir tu trabajo en todo un clúster. Pero a veces tienes que darle algunas pistas y a veces necesitas pensar un poco cómo se particionarán tus datos a través de los diferentes ejecutores de tu clúster. Ahora ejecutar ese guión de similitud de película como lo era sin esa llamada de repartición podría no funcionar en absoluto por sí mismo. Eso es auto-unirse es una operación realmente, realmente cara, y Spark no siempre es lo suficientemente inteligente como para distribuir eso por sí solo de la manera correcta. Esa es realmente la parte más exigente de este guión. Y tenemos que dar chispas algunas pistas para asegurarnos de que no nos quedamos sin recursos pidiendo a un solo ejecutor que haga más de lo que puede hacer. Entonces llamando explícitamente a repartición en ese DataFrame. Y si estuvieras usando RDD, hay una función de partición BY que hace lo mismo en RDD. Si usas eso antes de ejecutar una operación grande que se beneficia de la partición, se asegurará de que las cosas estén divididas de una manera que tenga sentido. Ahora algunas operaciones que se benefician del particionamiento incluyen join, que es lo que estamos haciendo en este ejemplo. También grupo COGROUP con esa unión, unión externa izquierda, Bisk, cualquier tipo de unión o grupoPor operación o reducida por operación o combinada por operación. También lookup puede beneficiarse de ello también. Por lo tanto, si estás llamando a alguno de estos métodos en un conjunto de datos muy grande, posible que quieras pensar en particionarlo explícitamente usando la función de repartición. Y cuando hagas eso, las operaciones conservarán ese particionamiento y los resultados también. Por lo que también obtendrás tus resultados rotos por esas particiones. Por lo tanto, ten eso en cuenta. ¿ Cómo se elige un tamaño de partición sin embargo? ¿ De dónde salió ese número 100? Bueno, si tienes muy pocas particiones, eso no va a aprovechar al máximo tu cluster, ¿verdad? Entonces si tengo menos particiones, entonces tengo ejecutores. Eso va a dejar a algunos ejecutores ociosos en esta tarea. Por lo que definitivamente quiero al menos tantas particiones como tengo ejecutores en mi clúster. De lo contrario solo estoy desperdiciando recursos, ¿verdad? Entonces para que eso sea real, si estoy tomando la operación de autounión que estamos usando en este guión. Y estoy diciendo repartición dos. Y tengo cinco nodos en mi clúster que tres de esos nodos van a quedar sin usar. Eso no tiene sentido porque sólo voy a estar distribuyendo esa obra entre dos particiones. Pero si tienes demasiados, eso da como resultado demasiada sobrecarga al barajar todos los datos alrededor. Por lo que mover datos alrededor de su clúster también es una operación costosa. Tampoco quieres estar haciendo eso demasiado. Entonces tienes que golpear este punto dulce donde estás aprovechando al máximo cúmulos y los ejecutores que tienes en tu, en tu clúster. Pero no tener una ridícula cantidad de particiones donde la sobrecarga de administrarlo todo se vuelve prohibitiva. Entonces, en general, quieres al menos tantas particiones como tengas núcleos o ejecutores que encajen dentro de tu memoria disponible para tu clúster, 100 suele ser un lugar razonable para comenzar para operaciones grandes. Eso es lo que estamos usando aquí funciona. No es un número alocado que va a tener una tonelada de gastos generales. Y es probablemente un número que es más que el número de ejecutores que tienes en un cúmulos típicos. Entonces ese suele ser un buen punto de partida. Pero si tuvieras más de 100 ejecutores, obviamente querrías usar un número aún mayor ahí. Entonces de eso se trata el particionamiento. Nuevamente, si estás usando una operación de unión muy grande o grupo por o reducido por, eso puede beneficiarse de la partición explícita. En ocasiones eso puede marcar la diferencia entre tu trabajo triunfar o quedarte sin memoria. Entonces si te encuentras con problemas extraños donde tu script está fallando y se está quedando sin recursos a pesar de que tienes un enorme clúster disponible. Esta podría ser la razón por la que podría necesitar volver atrás y pensar en, ¿necesito particionar explícitamente estas operaciones usando el comando repartición?
48. Las mejores prácticas para operar en un clúster: Vamos a entrar en algunos detalles más tontos de correr en un clúster. En primer lugar, asegúrese de evitar siempre especificar una configuración para Spark en el propio script del controlador. Eso incluiría especificar su configuración maestra. Recuerda, normalmente ponemos en masters set a estrella
local para decir que quieres correr localmente en tu máquina. Obviamente, no querrías hacer eso en un clúster real. Se desea utilizar todo el clúster, no solo un núcleo de CPU, incluso varios núcleos de CPU en un solo sistema. Sin embargo, lo que quieres hacer es usar los predeterminados que Elastic MapReduce configura en su lugar si estás ejecutando en Elastic MapReduce y esto va a ser cierto en mayoría de los clústeres que podrías estar ejecutando en donde Spark está preinstalado, probabilidades son sparkle ya se configuran fuera de la caja en su clúster para tener el derecho a caer configuración. Y también quieres tener cuidado con
cualquier opción de línea de comandos que pases a Spark desk enviar desde tu nodo maestro, puedes anular esas. De esa manera. El modo en que funciona es que una cosa en tu script de conductor tiene prioridad. Después de eso. Cualquier cosa que pases como argumento
de línea de comandos para enviar el escritorio de chispa tomaría prioridad. Y por último, los archivos de configuración en el propio clúster tendrían la última palabra en la cadena de mando ahí, si se quiere. Por lo que en términos generales, de nuevo, su clúster se configurará con la configuración correcta fuera de la caja. Y esto es cierto también para Elastic MapReduce. Por lo que generalmente no quieres estar especificando configuraciones en el script del controlador en sí o en la línea de comandos. Por lo general estás mejor solo dejar que la configuración haga su magia por ti. Obviamente, si eres administrador de sistemas y es tu trabajo configurar esa configuración, entonces sí tienes que pensar en eso. Pero como desarrollador de aplicaciones generalmente no lo harás. No obstante, hay situaciones en las que necesitas ajustar las cosas si encuentras que tus ejecutores están fallando y un gran trabajo, tal vez necesites ajustar la memoria que tiene cada ejecutor. Entonces si estás viendo mensajes de error que sugieran que te estás quedando sin memoria en tus nodos ejecutores. Bueno, tienes que hacer algo al respecto. Una forma es simplemente aumentar la cantidad de memoria que cada ejecutor le ha asignado. Entonces por ejemplo, se podría decir estimación desatada, dash, dash executor memoria uno G. Y eso asignaría explícitamente un gigabyte de RAM a cada ejecutor. Por supuesto, eso supone que tienes suficiente RAM disponible en cada nodo de tu clúster para sacar eso. Pero, ya sabes, eso es una especie de enfoque de fuerza bruta, ¿verdad? Y como tal vez lo que realmente deberías estar haciendo es pensar más en particionar y dividir tus datos de una manera más eficiente. Además, puede especificar un administrador de clústeres en la línea de comandos. Por ejemplo, se puede decir dash, dash master hilado. Si quería ejecutar explícitamente usando el hilo, un gestor de clúster en un clúster de Hadoop. Pero de nuevo, esto probablemente se va a configurar para ti por defecto. Y en Elastic MapReduce lo es, simplemente inferirá automáticamente que el maestro predeterminado es
el gestor de cluster de hilados porque Elastic MapReduce se está ejecutando en Hadoop, que tiene el hilado Cluster Manager. Por lo que realmente no necesitas hacer nada ahí, pero puedes especificar un maestro desde la línea de comandos si quieres tener esa flexibilidad. Y algunas mejores prácticas aquí, especie de recordatorio. Nuevamente, es muy importante asegurarse de que sus scripts en sus datos o en algún lugar donde EMR o cualquier clúster en el que se esté ejecutando puedan acceder a ellos. Si está en EMR, probablemente vaya a utilizar el servicio AWS S3. Ese es un sencillo servicio de almacenamiento. Y si haces eso, solo puedes usar el prefijo S3, AN URL para especificar la ruta a tu bucket S3. Y solo tienes que asegurarte de que tus permisos de archivo sean accesibles para tu clúster EMR. Eso a veces puede ser algo complicado con AWS en general, esos permisos, quiero decir, lo más fácil de hacer es simplemente hacer que tu cubo sea accesible públicamente. Pero si son datos sensibles ahí dentro,
entonces necesitas pensar en permisos más explícitos donde empates las cosas específicamente a donde se está ejecutando tu clúster EMR. Y no quiero entrar en los detalles de la seguridad de AWS en este curso, ese es un tema totalmente distinto, pero es posible una vez que tengas todo donde necesita estar, entonces
puedes girar tu clúster usando el AWS consola o si quieres usar la API, eso también está bien. Y en cuanto giras ese cúmulo, ahí es cuando arranca el reloj. Y recuerda que tan pronto como hagas girar ese clúster, el reloj empieza en la facturación, no importa que no lo estés usando, te van a facturar por hora ahí. Y para un cluster que contiene máquinas grandes y muchas de ellas que pueden llegar a ser extremadamente caras, extremadamente rápidamente. Así que asegúrate de saber lo que haces ahí dentro. Una vez que tienes ese cúmulo girado hacia arriba, tienes que, tienes que correr porque el tiempo es dinero, ¿verdad? Entonces tienes que conseguir el nombre DNS externo para ese nodo maestro. Accede a él usando la cuenta de Hadoop y tu archivo de clave privada que usaste al configurar el clúster. Una vez que esté en copia sobre su archivo de programa jar drivers y cualquier archivo que necesite en el controlador del script en sí. Puede usar el comando de AWS S3 cp para copiar cosas que lo subas en S3 con anticipación, y luego ejecutar estimación chispeada, y ojalá funcione. Y de nuevo, recuerda terminar tu clúster cuando hayas terminado. Si olvidas cerrar tu clúster una vez hecho tu trabajo, vas a conseguir una sorpresa muy, muy, muy desagradable en la factura de tu tarjeta de crédito a fin de mes. Y es posible por cierto, con EMR configurar las cosas para ejecutar automáticamente un script en cuanto se gira y se apaga automáticamente en cuanto se hace. Por lo que una vez que tengas los errores resueltos de tu script y puedes ejecutarlo de manera confiable. Puedes configurar las cosas para que tan pronto como gires
ese clúster te dé inicio automáticamente a tu trabajo. Y es girar ese clúster hacia abajo cuando termines con él. En algunas situaciones eso tiene sentido. En otras situaciones, su empresa podría tener suficiente dinero para simplemente mantener ese clúster funcionando todo el tiempo y mantenerlo accesible para su desarrollador es 24, 7. Pero para la mayoría de nosotros, no
tenemos ese tipo de lujo disponible para nosotros. Por lo que sí necesitas pensar en asegurarte de que estás viendo cuánto tiempo se ejecuta tu clúster 4. Y la mejor manera de minimizar este costo es
depurar y resolver los retornos en su script localmente. Primero antes de intentar ejecutarlo en un clúster real. Eso es lo que hemos estado haciendo a lo largo de este curso. Por lo tanto, si tiene un conjunto de datos grande que no puede ejecutar en una máquina utiliza un subconjunto de esos datos inicialmente para resolver los retornos en su aplicación. Y de nuevo, solo asegúrate de que cualquier archivo de datos que necesites va a ser accesible para cada nota de ejecutor en cada máquina que pudiera estar en tu clúster. Cualquier cosa que realmente pueda ser referenciada o leída desde un ejecutor distribuido necesita ser accesible más allá de donde se está ejecutando su script de controladores. Entonces, siempre y cuando tengas cuidado con esas cosas y vuelvas a tener cuidado de no especificar una configuración que sea específica para ejecutarte en una sola computadora en tu script de controlador final, deberías poder acercarte bastante a funcionando de manera confiable antes de comenzar a experimentar en el clúster en sí.
49. Resolución de problemas y gestionar las dependencias: Así que vamos a entrar un poco más de profundidad sobre la
solución de problemas de sus trabajos una vez que se estén ejecutando en un clúster. Desafortunadamente, es un poco de arte oscuro. Puede ser muy difícil rastrear este tipo de errores cuando se ejecutan dentro de la complejidad
de la propia Spark y además en la complejidad de ser distribuidos a través de múltiples nodos. Ahora tu maestro estará ejecutando una consola en el puerto 4040 que te permitirá ver alguna información sobre lo que está pasando en que a
veces puede llevar a algunas ideas sobre por qué tu trabajo está fallando. Pero si ves mensajes de error en tus registros, va a ser un poco difícil rastrearlos por una cosa. En primer lugar, vas a ver esta pila de llamadas profundas en tus archivos de registro si tienes un error, porque recuerda que estás ejecutando tu código Scala que se compila hasta código Java. Y a través de todas esas capas de compilación, es fácil perderse un poco en donde se ejecutan las cosas. Por lo que típicamente verás las cosas muriendo como profundas dentro del marco de la propia Spark. Y si miras lo suficientemente duro aunque eventualmente deberías ver un mensaje de error o algún tipo de excepción que te lleve al problema real en tu guión, pero no siempre tienes tanta suerte. No obstante, echemos un vistazo a la consola maestra aquí para ver qué información nos da ahora. Y de nuevo, esto es, esto en sí mismo puede ser difícil porque un Elastic MapReduce, es virtualmente imposible conectarse a eso desde fuera de tu clúster. Entonces si quieres conectarte a esa consola desde tu escritorio que se está ejecutando fuera de tu entorno EMR. Eso es algo difícil de configurar. A se puede hacer a través de cosas como hosts proxy y cosas así. Pero es duro. Sin embargo, si tienes tu propio clúster, corriendo en tu propia red, la vida va a ser mucho más fácil en ese respecto a tu oído, esos temas de seguridad deberían ser algo por lo que puedas trabajar un poco más fácilmente. Entonces echemos un vistazo a la consola que se ejecuta en nuestra propia máquina local como una forma de empezar. Y vamos a especie de explorar la información que te da. Está bien, así que vamos a explorar esa consola de Spark de la que hablé. Ahora desafortunadamente, sólo va a estar disponible mientras la propia Spark está funcionando. Entonces si en realidad no estoy ejecutando una interfaz de base de datos constante para chispear o algo así. Sólo voy a poder llegar a ella mientras mi guión de chispa se está ejecutando en realidad. Entonces, por el bien de la ilustración, iniciemos aquí un guión de chispa realmente carnoso que se ejecutará por unos minutos, así que tendremos tiempo para explorarlo en los materiales del curso. Hay un conjunto de datos de recomendaciones de películas, guión local. Y esto está configurado para usar el conjunto de datos ML 1 millón localmente en su máquina aquí. Entonces no tienes que ejecutar esto junto conmigo necesariamente, pero si quieres, verás que instalé el dataset ML dash 1M aquí en la carpeta de datos de mis materiales del curso. Y este guión está destinado a ir a usar eso. Entonces una vez que despido esto, eso correrá por un par de minutos tratando de descifrar las películas más similares a Star Wars. Y mientras está haciendo eso, podemos explorar la consola. Y tengo un navegador web aquí listo para ir por eso. Configurar hasta 127 punto 0, eso es 0 punto uno colon 4040, 127, 100, 000 punto uno es la dirección IP de nuestro host local. Y como estoy ejecutando Spark localmente en mi escritorio aquí, esa va a ser la dirección IP que golpearé para la consola de Spark. Y 40, 40 es el puerto en el que se ejecuta. Entonces voy a patear eso. Y en cuanto Spark esté funcionando, recargaré esta página y deberíamos ver una consola. Entonces volvamos a IntelliJ y vamos a patear eso. Y le daré un poco de tiempo para dar vueltas. Queremos asegurarnos de que en realidad haya tenido tiempo de encenderse. Se trata de ejecutores. Creo que estamos ahí. Entonces volvamos a nuestro tablero aquí y lo recarguemos. Y voy a seguir adelante y abrir cada uno de estos en una nueva pestaña para que podamos explorarlos. Y si vas a trabajos, puedes ver que aquí podemos perforar cualquier identificación de trabajo individual. Y puedes hacer cosas como visualizar la gráfica acíclica dirigida. Eso es bastante guay. Se puede hacer lo mismo desde etapas. Nuevamente, indaga en cualquier etapa que quieras. Éste, Tomémoslo por el bien del ejemplo, que en realidad no ha comenzado todavía. Entonces probemos el primero. Y puedes ver esto nos da mucha más información también. De nuevo, también hay una visualización DAG disponible aquí. Por lo que esto solo puede seguir corriendo y haciendo lo suyo mientras exploramos esto en este punto. Entonces volvamos a la pestaña de empleos aquí. Se puede ver que le da una especie de representación gráfica de la línea de tiempo del evento. Por lo que lanzamos al conductor en este punto y se ha
intentado ejecutar esa acción final y averiguar qué hay que hacer para cumplir esa acción final que tenemos en el guión de conductor para conseguir que las diez mejores películas similitudes a Star Wars. Para que eso te muestre el progreso ya que está pasando por todas las tareas para lograr eso. Y si vas a la pestaña de etapas aquí, puedes ver que te muestra tu progreso en esa línea. Y recuerda, las etapas están representando cada punto dentro de la ejecución donde necesita barajar los datos. Por lo que es bueno conseguir alguna visualización en cuántas etapas
realmente están involucradas en cumplir con el trabajo que quieres. Porque más etapas es malo. Cada vez que tienes una etapa, tiene que barajar datos en todo el clúster. Y esa es una operación muy cara. Entonces si ves menos etapas, Eso es algo bueno. Y de nuevo, se puede perforar en una etapa individual. Creo que en realidad terminó, así que en realidad podemos ver eso. Adelante y pateemos de nuevo ese guión. De acuerdo, tenemos algunos resultados para marcar una curiosidad. Oye, eso funcionó bastante bien. Por lo que nuestro algoritmo de filtrado colaborativo de similitud funcionó bastante bien. Dijo el máximo resultado para episodio para Star Wars, Episodio 5, Star Wars, Es como si tuviéramos en nuestras diapositivas. Entonces eso es genial ver. Rayos del Arca Perdida, Star Wars Episodio 6, Indiana Jones. Todas grandes recomendaciones para Star Wars, pero vamos a empezar eso otra vez para que podamos jugar con la consola un poco más. De acuerdo, así que de vuelta a la pestaña de etapas. Creo que ahí es donde jugábamos. Nuevamente, puedes hacer click en un escenario individual. Debería recargar esto para saber más sobre lo que está pasando en él. Y te dice todo tipo de cosas. Cuánto tiempo tarda en barajar esos datos. Recuerde, las etapas están asociadas con la barajación de datos. Podemos visualizar la gráfica acíclica dirigida que se le ocurrió. Entonces eso es bastante guay de ver. Entonces si estás tratando de optimizar el desempeño de tu trabajo, viendo, esto puede darte alguna idea de
cómo en realidad está desglosando lo que le has pedido que haga. Y a veces eso puede llevar a una mejor forma de estructurar tu script de conductor para ser más eficiente. ¿Qué más podemos mirar? El almacenamiento probablemente va a estar vacío. No estoy almacenando nada. Environment te da cierta información sobre el entorno de tiempo de ejecución. Vamos a refrescar eso también. Y se puede ver que estamos corriendo bajo el JDK, corriendo bajo JDK 14 en mi unidad C. Usando esa versión de Java, esa versión de Scala, solo algo de información general. También podemos mirar las propiedades del sistema. Entonces si quieres obtener más información sobre el entorno en el que se está ejecutando tu script, puedes hacerlo. Están bajo ejecutores. Esto te muestra cuántos ejecutores se están ejecutando, y esto en sí es interesante. Por lo que sólo un solo ejecutor está funcionando en este momento. Entonces eso me dice, por ejemplo, que a pesar de que tengo múltiples núcleos de CPU en mi máquina aquí, realidad no
lo está usando. Entonces esa podría ser la forma de la naturaleza de decirme que no he escrito las cosas de tal manera en que se pueda paralelizar o podría haber algo mal en mi configuración que esté llevando a ese tema. Si estuviera ejecutando esto en un clúster real y solo vi a un ejecutor corriendo a lo largo de todo el funcionamiento de esto. Eso probablemente me daría una pista bastante fuerte de que algo está realmente mal con la configuración en mi clúster que debería ir a descifrar. Entonces eso es una especie de resumen de las cosas que puedes ver usando la consola de Spark. Con eso, hablemos de un poco más de profundidad sobre la solución de problemas una vez que lo tengas. Ahora, cuando las cosas van mal, tus registros en modo independiente también estarán disponibles en esa interfaz de usuario web. Pero si estás corriendo encima del gestor de cluster de hilados como lo estamos haciendo con EMR. Esos registros se van a distribuir a lo largo de cada nodo individual de su clúster. Ahora puedes recogerlos después del hecho usando registros de hilados dash, dash ID de aplicación. Puedes descifrar el ID de aplicación de tu trabajo que se está ejecutando ahí. Por lo tanto, si estás corriendo en el autónomo Spark Cluster Manager la vida puede ser un poco más fácil. Ahí habrá en la UI para ti. Pero si estás corriendo encima de Hadoop, las cosas se complican por encontrar realmente esos troncos. Nuevamente, simplemente vuelve a enfatizar la importancia de depurar estos problemas localmente en su propia máquina antes de intentar
depurarlos en un clúster donde es más difícil obtener esa información. Ahora, mientras tu script de controlador se está ejecutando, él mismo registrará errores como ejecutores que no pueden emitir latidos de corazón. Entonces esa es una buena señal de que tu ejecutor está fallando y estrellándose por alguna razón en algún nodo remoto. Por lo que a veces tu salida de guiones de conductor te puede dar algunas pistas sobre lo que está sucediendo. Si estás viendo errores así, probablemente
significa que estás pidiendo demasiado a cada ejecutor. A lo mejor necesitas más de ellos, tal vez solo necesitas más máquinas en tu clúster para manejar el trabajo que estás haciendo. A lo mejor necesitas darle más memoria a cada ejecutor. Eso lo cubrimos en la lección anterior. ¿Cómo hacer eso? Eso sólo puede ser un parámetro de línea de comandos extra en Spark submit. O tal vez necesites usar PartitionBy o reparticionar para exigir menos trabajo a tus ejecutores individuales mediante el uso de particiones más pequeñas. Por lo que lanzar más máquinas editor o más memoria es una especie de solución de fuerza bruta a problemas como este. Pero a veces si simplemente utilizas explícitamente repartición para romper el trabajo en piezas más pequeñas, puedes arreglarte con menos hardware o menos memoria. Simplemente tomará más tiempo terminar el trabajo. Tan a menudo eso es realmente lo correcto. Entonces no veas que no vayas lanzando más hardware al problema si no necesitas. Si está realizando operaciones conjuntas grandes en su script o grupo grandePor operaciones o reducir operaciones. Probablemente puedas resolver estos problemas solo con el uso juicioso
del comando de repartición para romper las cosas en trozos más pequeños. Y también recuerda de nuevo, tus ejecutores no necesariamente se ejecutan en la misma caja que tu script de conductores. Por lo que no se puede suponer que los datos en memoria van a ser accesibles a través de todo el clúster. Necesitas asegurarte de que ese sea el caso. Si sí necesitas compartir datos fuera de tus RDD son conjuntos de datos, vas a tener que usar variables de difusión para hacer eso. No puedes simplemente almacenar eso localmente dentro de tu script de conductor y esperar que funcione. Si necesitas algún tipo de paquete Java o Scala que no esté precargado en tu clúster, asegúrate de que los estés agrupando en tu jar que estás ejecutando usando el ensamblado SBT. O puedes usar dash, dash tarros con Spark submit para agregar bibliotecas
individuales que están en el nodo maestro y que las distribuirán automáticamente a los ejecutores de ER. Pero eso se puede complicar realmente rápido porque a menudo los frascos que quieres incluir
tienen dependencias JAR y hay que especificar todas esas dependencias junto con él también. Mucho más fácil de usar sbt para empaquetarlo todo junto en el frasco mismo. Y ya sabes, realmente solo tratar de evitar usar paquetes
oscuros que realmente no necesitas en primer lugar es probablemente el mejor consejo. Recuerda, el tiempo es dinero en tu clúster y si no estás perdiendo el tiempo jugueteando con los problemas de distribuir esos paquetes jar a través de tus ejecutores. Bueno, tanto mejor. Entonces si puedes conseguir solo usando los paquetes core Spark y poco más, esa probablemente va a ser la mejor estrategia para simplificar las cosas. Recuerde, un simple es bueno cuando se trata de ingeniería de software en general. Y con eso, creo que hemos hablado de correr en profundidad en un clúster. Entonces pasemos a nuestra siguiente sección.
50. Introducción a la MLLib: Esta siguiente sección es bastante emocionante para mí porque me gusta mucho el aprendizaje automático. Esa es una gran parte de lo que he hecho en el pasado. Y vamos a hablar de cómo usar el aprendizaje automático en Spark. Y esto es súper emocionante porque el poder de los algoritmos de
aprendizaje automático generalmente se limita a una sola máquina. Muchas veces la gente simplemente desarrolla estos en un solo PC ejecutando un cuaderno en algún lugar, ¿verdad? Pero si tienes un conjunto de datos masivo, ¿qué haces? Bueno, Spark en realidad tiene una solución para muchos algoritmos populares de aprendizaje automático. Así que vamos a sumergirnos en y ver cómo la biblioteca Sparks ML permite aplicar DataFrames en todo un clúster en Spark para resolver problemas complicados de aprendizaje automático. Cosas bastante poderosas. Vamos a sumergirnos. Hablemos de Sparks Machine Learning Library, que es sorprendentemente suficiente llamada biblioteca Sparks ML, nombre creativo. Es realmente genial porque te permite distribuir el procesamiento de conjuntos de datos
masivos y aplicarles sofisticados algoritmos de aprendizaje automático a escala masiva. Por lo que hay formas más fáciles de aplicar estos algoritmos y técnicas a los datos en una sola máquina solo usando código Python y Cuadernos Júpiter. Pero cuando llega el momento de distribuir realmente estas cosas a través todo
un clúster porque tienes un conjunto de datos verdaderamente masivo. Bueno, esas herramientas que tan comúnmente se usan se desmoronan y necesitamos convertirlo algo así como Spark ML para poder manejar este tipo de tareas a gran escala. Tiene que ser un poco difícil hablar de lo que
hace ML sin tener algo de experiencia en aprendizaje automático. Y si tienes curiosidad por estos algoritmos, definitivamente
te animo a ir a tomar una clase dedicada de aprendizaje automático para aprender de qué se trata. Te daré una visión general de muy alto nivel de ellas aquí y
como, lo mejor que pueda hacer en una sola diapositiva al menos. Por lo que las capacidades básicas de Sparks ML paquete o extracción de características que incluye algo llamado TF-IDF, ese es el término frecuencia de documento inverso frecuencia. Y esos son analíticas que se utilizan en su mayoría para la búsqueda. Por lo que permite averiguar qué términos son más relevantes para un documento. Forma muy fácil de hacer eso. También tiene algunas estadísticas básicas cosas incorporadas. Si lo quisieras, como simplemente computar coeficientes de
correlación o pruebas chi-cuadradas y cosas así. Eso puede hacer a escala. Y luego nos metemos en los propios
algoritmos de aprendizaje automático reales , que son más interesantes. Por lo que puede hacer regresión lineal y regresión logística. regresión lineal simplemente está ajustando básicamente una línea a un conjunto de datos. Entonces, por ejemplo, podrías imaginar que tienes un conjunto de datos que mapea las alturas de las personas a sus edades. Y al ajustar una línea a los datos que has observado, realidad
puedes ajustar nuevos puntos de datos a esa línea para predecir su valor real. Entonces si tengo una línea que define la edad como una función de la altura, realidad
puedo perforar nuevas alturas en ese modelo nunca antes había visto y predecir su edad solo extrapolándola a través de esa línea. Eso es regresión lineal. regresión logística es una especie de la misma idea bajo el capó, pero es para fines de clasificación. Entonces, entonces si quiero predecir si alguien es demócrata o republicano, por ejemplo, podría usar la regresión logística para hacer eso. Si quiero predecir si un auto es un deportivo o un sedán basado en algunos atributos. Ese podría ser otro ejemplo de regresión logística. Estamos de nuevo, estamos aplicando una función matemática muy simple para predecir clasificaciones en contraposición a valores reales, lo cual estarás haciendo con regresión lineal. También puede hacer máquinas vectoriales de soporte. Esas son otra forma de hacer clasificación que es un poco más sofisticada, si se quiere. Funciona en estos espacios de mayor dimensión y puede encontrar divisiones
más complejas entre clasificaciones que no son necesariamente lineales. También puede hacer clasificación Naive Bayes. El niño de cartel de una solicitud para un Naive Bayes es clasificación de spam. Entonces un ejemplo muy común de Bayes ingenuo es alimentarle un corpus de correos electrónicos y tener un conjunto de entrenamiento que esté etiquetado como spam y no spam. Y puedes entrenar a ese clasificador Naive Bayes para que tome nuevos correos electrónicos que nunca antes se había visto y predecir si su spam o no basado en ese modelo ingenuo de Bayes. También puede hacer árboles de decisión distribuidos en todo un clúster, lo cual es realmente genial. A mí me gustan los árboles de decisión son sólo divertidos de mirar su, como suenan. Básicamente es este árbol de decisiones. Entonces básicamente empezarás con alguna decisión como, no sé, es esta la temperatura exterior por encima de 72 grados o por debajo de 72 grados. Si está por encima de los 72 grados, tal vez se baja a otro bloque de decisión. Y tal vez esta próxima decisión. Y el árbol de decisiones es, ¿está lloviendo o no? Y tal vez esto podría finalmente llevarte a una decisión sobre si
deberías salir afuera y jugar hoy si es un buen día o no, ¿verdad? Ese es un ejemplo muy sencillo de un árbol de decisiones. Obviamente, se puede complicar mucho más y puede funcionar en situaciones
arbitrarias donde se tienen muchas características que son numéricas, que se pueden comparar con algunos valores establecidos. Y al tomar decisiones en secuencia entre esas diferentes características de tus datos, puedes llegar a una decisión con un árbol de decisiones. K-significa clustering, solo una forma de agrupar datos juntos en función de sus atributos, basado en lo similares que son las cosas entre sí. En un medio muy sencillo. Esto es lo que llamamos aprendizaje no supervisado, donde en realidad no estamos entrenando un modelo basado en valores conocidos. Estamos intentando simplemente agrupar cosas en función sus propiedades naturales y de lo similares que son las cosas entre sí. Y también puede hacer análisis de componentes principales, conocido como PCA para la descomposición de valor corto y singular, SVD para abreviar. Estas son las que llamamos técnicas de reducción de dimensionalidad. Por lo que a veces tendrás este problema donde
tienes datos que tienen muchas características diferentes a la misma. Ya sabes, cosas diferentes que estamos midiendo para diferentes objetos. Y se vuelve, causa lo que llamamos la dimensionalidad cursiva. Este es básicamente un problema de datos escaso donde tienes demasiadas características. Estas son formas de reducir esas a las características más sobresalientes. A lo mejor son rasgos sintéticos que ni siquiera existían en el mundo real. Pero es una forma de hervir los datos de entidades de dimensiones superiores hasta los datos entidades de dimensiones
inferiores que hace que sea un poco más fácil trabajar con ellos. Y por último, puede hacer recomendaciones utilizando una técnica llamada Minimos Cuadrados Alternantes. Y vamos a cavar en eso con algo más de profundidad muy pronto. Als es genial. En realidad hubo una competencia hace mucho tiempo que fue patrocinada por Netflix para desarrollar un mejor sistema de recomendación que el propio. Y una de las anotaciones ganadoras que forman parte de su solución fue el uso de ALS. Entonces, para que eso también esté disponible para ti dentro de Spark ML. Ahora es una especie de lista limitada de lo que puedes hacer. Es decir, hay innumerables más algoritmos de aprendizaje automático por ahí, pero no todos ellos realmente se prestan bien a ser distribuidos a través de un clúster. Por lo que aún hasta el día de hoy, hay muchos algoritmos de aprendizaje automático por ahí donde simplemente los estamos escalando verticalmente. Sólo podemos ejecutarlos en una sola máquina. Y estamos un poco de vuelta a los viejos tiempos de las grandes bases de datos monolíticas donde la única manera de hacer estas cosas es tener una máquina realmente grande para
ejecutarlas con muchas GPU y mucha memoria y todas esas cosas buenas. Pero escaso tipo de allanar el camino a hacer escalado horizontal del aprendizaje automático. Y es realmente emocionante. Ahora había una API anterior que existía en Spark uno y en Spark a llamada ML Lib. Y esa fue una API de menor nivel que utilizó RDD y alguna estructura de datos especializada es realizar estos algoritmos. Ahora en Spark tres, eso ha sido obsoleto y partes de ella ya no funcionan en absoluto. Y francamente, a los mantenedores de Spark no les importa porque solo está en modo de mantenimiento en este punto. Por lo que realmente quieren que te muevas a la nueva biblioteca ML. La diferencia es principalmente que utiliza DataFrames para todo. Entonces, en lugar de pasar por los RDD y estas estructuras de datos especializadas, vas a estar usando dataframes y datasets, que es realmente la API a la que quieren estar empujando a todos hacia. El beneficio de esto es que al usar DataFrames en todos los diferentes componentes de Spark, puede pasar esos DataFrames de un componente a otro sin problemas. Entonces eso es un poco que son visión más grande. Quieren poder tomar un DataFrame que salga de Spark ML y tal vez, ya
sabes, alimentarlo a Spark SQL y tal vez a GraphX. ¿ Quién sabe bien? Esa interoperabilidad, eso se vuelve emocionante al tener este DataFrame de propósito general. Esa es una especie de la lingua franca de todos estos componentes de Spark incluido el aprendizaje automático. Si quieres más profundidad, Hay un libro llamado Advanced Analytics with Spark publicado por O'Reilly, probablemente un poco desactualizado en este momento, no
sé si tienen una versión actualizada para la nueva biblioteca ML, pero es un recurso bastante bueno. Cualquier cosa de O'Reilly suele ser una buena lectura. Los ejemplos más oportunos o siempre van a estar en el propio SDK chispa. Hay un directorio de ejemplos en el SDK. Y si te sumerges ahí, encontrarás un ejemplo de cada uno de esos algoritmos que se están utilizando realmente. Y de nuevo, para más profundidad sobre los algoritmos reales y cómo usarlos y cómo funcionan. Te referiré a un curso diferente, no éste sobre machine learning en general. Con eso, pongámoslo en práctica. En nuestra próxima conferencia, en realidad vamos a generar recomendaciones de películas utilizando ese módulo de ALS del que hablamos en Spark ML. Y es realmente emocionante porque es realmente, realmente fácil de usar. Por lo que los sistemas de recomendación son cosas realmente complicadas y Alternando Mínimos Cuadrados está usando este método de factorización de matriz. Aquí se trata de unas matemáticas muy hardcore bajo el capó. Pero para usarlo realmente en Spark y en realidad distribuido a través de todo un clúster, este es todo el código que necesitas hacer. Like ¿No es eso impresionante? Entonces pasemos un poco por esto. Todo lo que estamos haciendo aquí es cargar un archivo de datos que va a ser nuestro conjunto de datos de calificaciones de MovieLens a partir de datos de u dot. Entonces mapeamos eso en un RDD de calificaciones usando las API de nivel inferior porque estamos haciendo transformaciones un poco simples aquí. Y luego convertimos eso en un DataFrame para que sea compatible con Spark ML. Después solo creamos un nuevo objeto ALS desde la biblioteca ML. Establecemos lo que se llama un par de hiperparámetros. Poco secreto sucio del aprendizaje automático es que muchos de estos algoritmos son sólo tan buenos como los hiperparámetros que estableces en ellos. Por lo que el número máximo de iteraciones, el parámetro de regularización. Estos son dos ejemplos de hiperparámetros con el algoritmo ALS. Y la mayoría de los algoritmos de aprendizaje automático tienen varios de ellos. Y lo bien que funcionan depende de esos parámetros. Y la poca verdad sucia es que en gran medida sigue siendo cuestión de prueba y error encontrar los valores de parámetros que funcionen mejor para un problema dado. Por lo que nos gusta pensar que entendemos muy profundamente estos modelos, pero en realidad, muchas de ellas siguen siendo conjeturas. Pero una vez que tengamos esos valores ahí para empezar, al
menos podemos crear un nuevo objeto ALS. Nosotros le decimos dónde se encuentra la información de ID de usuario, ID de
película e calificación en nuestro DataFrame. Y entonces solo podemos llamar a fit en ese modelo de ALS. Y eso se apagará y entrenará a un modelo usando todos esos datos de MovieLens. Y en ese punto sólo podemos usar ese modelo para hacer predicciones para nuevos usuarios que nunca habíamos visto antes. Entonces es solo así de fácil. Vamos a jugar con él. Vamos a ejecutarlo.
51. [Actividad] con MLLib para producir recomendaciones de la película: Entonces vamos a ir a usar el algoritmo de recomendación de mínimos cuadrados alternos que está integrado en el ML Lib, eso es parte de Spark. Y vamos a ver las recomendaciones de película El script del conjunto de datos de ALS para este. Ahora antes de meternos en esto, lo que hemos hecho para probar esto es crear
una especie de persona falsa de un usuario cuyos gustos
al menos puedo entender un poquito que me va a dar algún sentido cualitativo en cuanto a si el las recomendaciones son buenas o no. Entonces para hacer eso, en realidad he entrado en mi conjunto de datos MO 100 K y editado el archivo de datos u dot. Y lo que he hecho se agrega en tres líneas para un usuario falso 0, usuario 0 no existía previamente en este conjunto de datos. Y esta es una persona muy sencilla aquí. Básicamente, he dicho que a este ID de usuario le gustan los ítems 50, ID de película 50 y ID de película 172 mucho. Les dio a ambos cinco estrellas. Y esos corresponden a la película Star Wars Episodio 4 y Star Wars Episodio 5. Una nueva esperanza en el imperio ataca de nuevo. Por lo que hemos establecido que esta persona tiene un gran fan de la ciencia ficción de Star Wars. Y en contraste, también he dicho que para la película 133, que es Gone With the Wind, Eso fue sólo una estrella. Por lo que he creado aquí una persona muy sencilla. Alguien que ama Star Wars y la ciencia ficción presumiblemente, pero realmente no es fan de los viejos dramas románticos, ¿verdad? Y así es alguien que puedo relacionarme conmigo misma. Entonces eso me da una especie de sensación
o sentido personal en cuanto a si estos resultados van a ser buenos o no. Ahora hay formas de medir objetivamente lo bueno que es un conjunto de recomendaciones. Pero a menudo es una especie de cosa cualitativa. Puedes intentar predecir si tu algoritmo puede sentir o no si a alguien
realmente le hubiera gustado una película que irradia previamente. Pero al final del día, las recomendaciones son sobre tratar de recomendar cosas que una persona no ha visto antes. Y eso es algo difícil de medir en cuanto a si ese es o no un buen resultado o no. Entonces por el bien de la demostración, sólo
vamos a mantener esta evaluación cualitativa. Voy a ver si las recomendaciones que saco de esto tienen sentido para alguien que ama Star Wars y odia Lo que se llevó el viento. Entonces, recorremos el código en sí y veamos cómo se ve. Bastante fácil de usar en realidad. Entonces estamos importando recomendación de puntos ML, todo debajo de eso y las cosas habituales también. Configuramos nuestro objeto y aquí tenemos dos clases de casos. Uno para la búsqueda de nombres de películas que solo vamos a estar usando para buscar nombres de
películas para identificadores de películas para obtener resultados legibles por humanos al final. Y también tenemos nuestro pequeño conjunto de datos para clasificaciones que incluye un ID de usuario es ID de películas y clasificaciones, tenga en cuenta que estamos emitiendo las marcas de tiempo porque en realidad no
importa para este algoritmo. Bajemos a la función principal aquí. Comience estableciendo nuestro nivel de registro. Entonces creo que con la sesión de Spark como siempre lo hacemos, y empezamos cargando ese conjunto de datos de nombres de películas. Proporcionamos un esquema que dice que tiene identificadores de película enteros y títulos de película de cadena. Y mientras estamos en ello, dijimos el esquema de la película también para los datos de calificaciones reales que vamos a leer también, importamos implícitos de punto chispa porque vamos a estar cargando DataFrames inicialmente y no un conjunto de datos. Leemos en la carpeta de elementos de punto de la UE que contiene esos nombres de películas utilizando el esquema de nombre de la película. Y lanzamos eso al conjunto de datos de nombres de películas usando la clase de caso de nombres de películas. Glossing sobre eso porque lo hemos hecho un millón de veces ya antes en el curso, ¿verdad? Entonces realmente recogimos eso de nuevo en Scala en un objeto de lista de nombres. Entonces en este punto, en realidad hemos usado Spark solo para cargar esos datos y analizarlos. En realidad copia eso de nuevo en nuestro script de conductor en sí. Ahora podemos salirnos con la suya porque simplemente
no hay tantas películas en el mundo, ¿verdad? Podemos encajar eso de forma segura en la memoria dentro de nuestros scripts de conductor. Entonces eso no es una locura para hacer en realidad por lo que sólo vamos a volcar eso de nuevo en un mapa de Scala aquí para buscar aquellos cuando estamos mostrando estos al final. No obstante, los datos de calificaciones de películas que sí queremos mantener distribuidos y mantener eso en nuestro clúster como conjunto de datos. Y eso es lo que estamos haciendo aquí es cargar eso usando el esquema que proporcionamos, el delimitador de tabuladores. Y vamos a lanzar eso como un dataset de calificación usando la clase de caso de calificación que definimos anteriormente. Y de nuevo, esto sólo va a extraer esas primeras tres columnas, el ID de usuario, ID de película, y una propia calificación. Vamos a dejar apagada esa marca de tiempo. Después de eso, echa un vistazo a lo fácil que es usar ML Lib. Por lo que configuramos aquí nuestro modelo. Por lo que solo decimos nuevas ALS para Alternando Mínimos Cuadrados como saliendo de la biblioteca de algoritmos de recomendación ML Lib allí. Y dijimos algunos hiperparámetros. Por lo que fijamos nuestras iteraciones máximas en cinco. Establecemos nuestro parámetro de regularización en 0.01. Y quizá quieras hasta donde sacamos estos números. Bueno, yo sólo un poco los arranco del aire inicialmente basado en ejemplos que vi en línea, encontrarás que en la práctica, una especie de sucio secreto del aprendizaje automático en general es que todo se trata de optimización de hiperparámetros. Y esa es una forma muy elegante de decir que solo vamos a adivinar cuál es el número correcto hasta que lo hagamos bien. Por lo que es una práctica muy común sólo tener estos enormes trabajos que prueban muchos, muchos, muchos valores diferentes de estos hiperparámetros como iteraciones max y parámetro de regularización, y solo ver cuáles dan los mejores resultados experimentalmente. A menudo no hay orientación real sobre cuál se debe perdonar
el mejor valor conjunto de datos y variará salvajemente del conjunto de datos, el conjunto de datos. Entonces ese problema de averiguar los parámetros correctos aquí está realmente en el núcleo de obtener buenos resultados de aprendizaje automático en la práctica. La otra cosa que el núcleo es solo limpiar tus datos, pero esto no es un curso de aprendizaje automático, así que no voy a meterme demasiado en eso. Nosotros le decimos cuáles son los nombres de las columnas para el ID de usuario, el ID de elemento, y la calificación. Eso es todo lo que necesita el algoritmo. Por lo que sólo tenemos que apuntarlo a lo que realmente se nombran esas columnas de conjunto de datos, para
que sepa de dónde recuperar esa información. En ese punto, todo lo que tenemos que hacer es decir punto ajuste en ese modelo pasando en ese conjunto de datos de calificaciones. Y eso es todo lo que realmente ejecutará ese modelo en nuestros datos y construirá un modelo que pueda predecir recomendaciones para nuevos usuarios de películas que les puedan gustar. Y es una especie de caja negra en ese punto, ¿verdad? Por lo que el algoritmo ALS está apagado haciendo algo. Sabemos que está usando Mínimos Cuadrados Alternados eso se trata. Crear un modelo que pueda tomar un nuevo ID de usuario y recomendar películas que a ese usuario le pueda gustar en función de lo que ha calificado. Entonces hagámoslo. Adelante y saquemos del argumento de la línea de comando. El ID de usuario es alguien para quien queremos obtener recomendaciones. En nuestro caso, pasaremos el ID de usuario desde la línea de comandos. Entonces solo creamos un DataFrame realmente simple que no contiene nada más que ese ID de usuario. Y pasamos eso a los modelos recomendados para usuarios método de
subconjunto pasando en ese falso usuario DataFrame de un solo usuario del que no éramos resultados. Y en realidad podríamos pasar múltiples usuarios y
recuperar recomendaciones para muchas personas a la vez si quisieras. Y estamos diciendo que solo queremos las 10 recomendaciones principales para cada usuario que estamos pasando a ese usuario DataFrame. En ese punto, tenemos nuestros resultados, sólo
tenemos que mostrarlos. Y extrañamente, esa es en realidad la parte más difícil de todo esto, averiguar cómo extraer esa información. Las recomendaciones DataFrame que nos dieron de vuelta. Entonces eso es lo que estamos haciendo aquí y este pequeño bucle Aquí, pasamos por cada recomendación en las recomendaciones DataFrame que recuperamos de recomiendo subconjunto freezer, extraemos el ID de usuario y las propias recomendaciones. En realidad tenemos que decirle a Scala qué es esta cosa. Entonces tenemos que lanzar explícitamente ese resultado como una matriz envuelta mutable de tipo de fila, que es lo que estamos recuperando cuando un DataFrame. Después podemos iterar a través de cada uno de los resultados de recomendación individual, extraer la película, extraer la calificación. Y luego podemos traducir esa identificación de película a un nombre de película usando nuestra función get movie name e imprimir los resultados. Por último, detenemos la sesión cuando terminemos y vemos qué pasa. Mirada rápida a la función get movie nombrada. Simplemente ejecuta una información de filtro sobre la matriz de nombres de películas que pasamos y trata encontrar el ID de película que coincida con el que estamos
buscando y devuelve el título de película asociado a ella. De nuevo, esto no es realmente usar un conjunto de datos. Esto en realidad es sólo una matriz que recuperamos del conjunto
de datos a través de la operación colectiva. Entonces, corrámoslo y veamos qué pasa. Haga clic derecho en eso. Tenemos que armar un perímetro para ello sin embargo. Entonces vamos a decir Editar recomendaciones de película y sentarse en un argumento de programa es 0 porque quiero recomendaciones de usuario ID ceros. Ahora puedo golpear Ok, y debería poder seleccionar eso ahora y ejecutarlo. Está bien, Está fuera de entrenamiento ese modelo ahora
basado en esas 100 mil calificaciones y ahí están nuestros 10 mejores resultados. Entonces sí, estos resultados son un poco raros. Es decir que para alguien que ama a Star Wars y no le gusta Gone With the Wind. Mi máximo resultado con alguna película de 1994, nunca
he oído hablar, pero se llama The Endless Summer 2. Estoy pensando que esa no es una película de ciencia ficción. Bastante seguro que sea o no ser a partir de 1942 tampoco lo es, ni lo es ball2. Es decir, hay algunas cosas aquí que algo tiene sentido Lost in Space. Transformadores. Supongo que eso tiene sentido para un fan de Star Wars, pero podrían, acabo de tener suerte. Estas me parecen recomendaciones aleatorias. Entonces los resultados aquí realmente no tienen sentido para mí. Bueno, vamos a explorar por qué eso podría ser. Por lo que como mencionamos antes, estos algoritmos tienden a ser muy sensibles a los hiper parámetros que usted elija. Tan a menudo se necesita mucho trabajo encontrar el conjunto óptimo de parámetros para el conjunto de datos que estás utilizando para obtener buenas recomendaciones de él. Entonces una técnica es usar algo llamado test de tren, donde reservamos una parte de nuestros datos de calificaciones y usamos eso con fines de prueba. Por lo que sostenemos a algunos usuarios de nuestro conjunto de datos y utilizamos el modelo capacitado en los usuarios restantes y vemos si nuestro modelo resultante puede
predecir con éxito qué películas disfrutaron realmente las personas en el set de pruebas, qué les gustó, lo que calificaban bien. Y se puede usar eso para obtener una especie de medida cuantitativa cuanto a lo buenas que son las recomendaciones. Y una vez que tengas eso, puedes probar diferentes combinaciones de hiperparámetros y ver qué combinación produce los mejores resultados e intentar afinar las cosas de esa manera. Pero esto se pone dudoso con recomendaciones. Es decir, ¿una buena recomendación se mide realmente por tu habilidad para predecir cosas que alguien ya veía? O es una buena recomendación si es algo que aún no han visto en el uso de datos históricos, no
hay forma de saberlo, ¿verdad? Así que recomiendo, los sistemas de recomendación es una especie de este extraño caso donde es difícil medir los resultados realmente aparte de hacer como experimentos en vivo con gente real. Pero pasé algún tiempo haciendo eso. Así que sí probé diferentes valores de parámetros. No pude sacar mejores resultados de esta cosa sin importar lo que hiciera. Entonces estoy pensando que esto no está funcionando de la manera que debería. Por lo que ni siquiera estoy convencido de que esta cosa esté funcionando correctamente internamente. Al menos para este conjunto de datos, este algoritmo simplemente llano no funciona bien. Y la lección que hay que aprender aquí es que poner tu fe en una caja negra como esta puede ser una proposición dudosa. Necesitas entender lo que está pasando en el algoritmo y entender si se ajusta o no a los datos que lo estás obteniendo. Puede ser que nuestro conjunto de datos sea demasiado pequeño. Puede ser que haya algo al respecto que
no sea particularmente adecuado para este algoritmo. Intenté algunas cosas obvias como normalizar las calificaciones a 0 a uno. Eso tampoco ayudó. A veces eso es lo que tienes que hacer, pero en realidad conseguimos resultados mucho mejores solo usando nuestro ejemplo de similitud de película antes en el curso, ¿verdad? Si solo usamos el filtrado colaborativo basado en artículos usando métricas de similitud de coseno como lo hicimos antes, habríamos obtenido recomendaciones mucho mejores con un enfoque mucho más simple. Y eso funcionó. Entonces ALS es un algoritmo más complicado, pero a veces complicado no siempre es mejor. Este es un buen ejemplo de eso. Y así, ya sabes, siempre mide los resultados, asegúrate de que estás obteniendo los resultados que esperas. Dice Joe, no solo confíes ciegamente en los resultados cuando intentes hacer análisis de datos en grandes conjuntos de datos. Porque los pequeños problemas en los algoritmos pueden convertirse en grandes a medida que le arrojas más datos. Y muy a menudo, el verdadero problema es la calidad de sus datos de entrada. Ahora en nuestro caso, ese no es el tema. El dato que estamos poniendo ya ha sido limpiado en fregado. Por lo que son datos de alta calidad. Pero a menudo el dicho Basura adentro, basura afuera aplica aquí, ¿verdad? Entonces si estás pasando datos sin filtrar que contengan un montón de información espuria de robots y cosas así, o personas que no son personas reales o personas que intentan jugar con el sistema. Eso también va a estropear tus resultados. Pero esto es entrar más en la práctica del aprendizaje automático que cualquier otra cosa. La lección aquí sin embargo, es, pesar de
que chispa contiene algunos algoritmos emocionantes, no siempre van a ser los adecuados para tus datos. Entonces, no solo pongas ciegamente tu confianza en lo que ofrece chispa en ML Lib. No obstante, ML Lib sigue siendo realmente útil en general. poco comenzó con un mal ejemplo ahí porque ALS es una
especie de cosa dudosa con ella para el conjunto de datos de MovieLens de todos modos. Pero el resto de los algoritmos son más sencillos y harán lo que esperes. Entonces vamos a cortar un turno a una nota más alta usando Sparks ML Lib y mostrarle algo para lo que sea más adecuado.
52. Regression lineal con MLLib: Entonces cambiemos las marchas a un algoritmo más confiable en la biblioteca Spark ML, el algoritmo de regresión lineal, es algo bastante simple. ¿ Qué es la regresión lineal? Bueno, si eres nuevo en el mundo del machine learning, ese podría ser un nuevo término para ti. En pocas palabras, la regresión lineal simplemente está ajustando una línea a un conjunto de datos. Y una vez que tienes esa línea, esa es una especie de línea de mejor ajuste para un conjunto de observaciones. Puedes usar esa línea para predecir nuevos valores para cosas que nunca habías visto antes. Por ejemplo, en esta pequeña ilustración aquí tenemos medidas de los pesos de las personas y sus alturas trazadas entre sí. Por lo que te puedes imaginar tratando de predecir la altura de
alguien en función de su peso una vez que realmente tengas esta línea, esa línea roja que está ajustada a esos datos observacionales. Básicamente tomas todos los puntos de datos observados de lo que estás tratando de predecir. En este caso, altura basada en algún atributo, que en este caso sería peso. Y si trazas todos esos juntos y encuentras la línea que tipo de ajuste a esos datos lo mejor. Después puedes usar la ecuación de esa línea para predecir las alturas de las personas nuevas solo en función de su peso. Entonces esto termina con alguna especie de fórmula punto-pendiente aquí para la línea, ¿verdad? Entonces básicamente estamos diciendo que tenemos una pendiente de 0.60 más una intercepción y de 1.23. Y podemos usar esos atributos para hacer predicciones en el futuro. ¿ Por qué lo llamaron Regresión? Es un poco confuso ser honesto. tipo de regresión implica que vas hacia atrás en el tiempo, pero de eso no se trata realmente de lo que se trata. Hay algo de historia detrás de ese término, pero trata de no colgarte demasiado en eso. Básicamente, la regresión lineal sólo está ajustando una línea a los datos históricos. A lo mejor puedes pensar en eso como la parte de regresión y usar esa línea para predecir nuevos puntos de datos para cosas nuevas que no habías visto antes. ¿Cómo funciona? Bueno, por lo general utiliza algo llamado mínimos cuadrados. Se trata de una técnica matemática para un minimizando el error cuadrado entre cada punto y la línea. Entonces cuando ajustemos una línea a esos puntos de datos observados, por cada punto, va a
haber algún error entre donde realmente está
ese punto y donde la línea dice que debería estar. Y nuestro objetivo al crear esa línea es
minimizar el error cuadrado entre cada punto y esa línea. Está al cuadrado porque de esa manera el error positivo o negativo no hace diferencia. Es todo lo mismo. Entonces es un poco interesante matemáticamente cuando estás pensando en cómo funciona esto en dos dimensiones en realidad. Entonces si recuerdas la ecuación de pendiente de interceptación de una línea que es y es igual a mx más b, donde m es la pendiente y b es la intercepción y. Volviendo de regreso a la preparatoria ahí para muchos de ustedes, resulta que la pendiente se puede expresar como la correlación entre las dos variables veces la desviación estándar en y dividida por la desviación estándar en x. Y eso es un montón de mumbo jumbo estadístico para muchos de ustedes. Pero solo creo que es un poco interesante cómo algunos de estos conceptos estadísticos como la desviación estándar, tienen un significado matemático real que se puede usar para algo tan simple como un ajuste de una línea a los datos. Entonces no es que la desviación estándar sea algún corte arbitrario que se le ocurrió a alguien. En realidad tiene un verdadero significado matemático, que para mí es interesante al menos. Y también puedes calcular la intercepción como justo la media de y menos la pendiente por la media de x Entonces esa es otra forma de calcular eso. Por lo tanto,
dadas esas ideas matemáticas es bastante sencillo ajustar realmente una línea a un conjunto de datos en dos dimensiones. Si solo estás lidiando con x e y, las cosas se vuelven un poco más complicadas cuando agregas más dimensiones a la mezcla sin embargo. Por lo que es una especie de ejemplo fabricado simplemente estar prediciendo algún atributo basado en algún otro atributo como la altura basada en el peso. el mundo real, normalmente estás tratando con múltiples atributos. Entonces podrías estar tratando de predecir la altura de alguien en función de su peso, dónde vive, qué edad tiene, sea lo que sea, ¿verdad? Entonces esto usualmente más de una cosa. Y eso entra como toda esta rareza multidimensional. Y una forma de lidiar con eso es el descenso gradiente estocástico. Es otro algoritmo que se ve mucho en el mundo del machine learning y también en deep learning. Y básicamente no quiero entrar en los detalles de cómo funciona, pero tipo de, busca estos contornos en dimensiones superiores, si se quiere. Por lo que de manera iterativa encuentra el tipo de líneas de mejor ajuste a través de este espacio multidimensional para ti. Tan mismo concepto, sólo un poco más complicado. Pero usando Spark dot HTML, No es complicado en absoluto. No tienes que preocuparte por cómo funciona porque todo lo hace por ti. Todo lo que tienes que hacer es decir Val y establecer algún valor a un nuevo modelo de regresión lineal, establecer un montón de hiperparámetros como el parámetro de regularización o el parámetro de red elástica, el número máximo de iteraciones, la tolerancia de convergencia . Y como siempre, el aprendizaje automático es sucio pequeño secreto es que no
siempre hay una buena manera de adivinar cuál debe ser este valor para un conjunto de datos dado. A menudo se llega a los valores correctos justo a través de ensayo y error. Pero una vez que tienes un modelo de regresión lineal configurado y configurado, solo entrenas al modelo y haces predicciones usando tuplas que
consisten en una etiqueta y un vector de las entidades que están usando para predecir esa etiqueta. Entonces en este caso, la etiqueta sería el valor que estás tratando de predecir. Normalmente enmarcamos ese es nuestro eje y. Una característica está en tu eje x o en los otros ejes. Esas son las cosas que estás usando para tratar de hacer esa predicción. Entonces básicamente entrenas a la modelo con un montón de puntos conocidos. Y luego intentas predecir nuevos valores de etiqueta y para Xs
dados o valores de entidad usando esa línea al modelo creado. Y no tienes que preocuparte por qué es esa línea. Puedes conseguirlo si quieres, pero ya sabes, es como cualquier otro modelo, solo
creas el modelo y una vez que está entrenado, lo usas para hacer predicciones. Todo es muy sencillo. Y puede, como dijimos, trabajar con más de dos dimensiones si tienes múltiples características y ahí es donde realmente entra el poder de la misma. Ahora hay algunos gotchas usando regresión lineal SGD, que es lo que esto está usando. Una es que no entorpece bien el escalado de entidades, por lo que asume que sus datos son similares a una distribución normal y cómo se presentan. Entonces, si no lo es, normalmente deberían escalar esos datos hacia abajo para que
encajen dentro de un rango que sea más comparable a tu curva de campana estándar aquí. Y quieres asegurarte de que todas tus características también tengan una escala similar. Entonces si tienes una característica que es enorme y otra característica que es un valor pequeño. Necesitas escalar todo a esta escala similar en el rango similar para que el algoritmo funcione bien. Entonces eso significa que vas a necesitar reducir tus datos y luego volver a subir cuando hayas terminado. Por lo que entrenarás a tu modelo en función de estos datos de características a escala. Y luego hay que recordar para escalarlo de nuevo usando lo que sean los inversos de esa relación cuando realmente estás mostrando los valores finales que este modelo predice. Además, el algoritmo asume que su y-intercept es 0 a menos que llame ajuste intercept true en él. Si estás lidiando con una situación en la que no crees que tu línea de mejor ajuste pasará por el origen
0, 0, necesitas llamar a fit intercept true para obtener buenos resultados. Entonces vamos a probarlo. Lo que vamos a hacer es fabricar algunos datos falsos para
velocidades medias de página e ingresos generados a partir de datos de sesión en una tienda en línea. Esto es algo que realmente teníamos que hacer en Amazon. Había una hipótesis hace muchos,
muchos, muchos, muchos, muchos años, ese tiempo de carga de páginas tenía una relación muy directa sobre cuánto dinero gastó el cliente. Y ahora sabemos que eso es cierto y eso es una especie de sabiduría común en toda la industria ahora. Pero entonces teníamos que averiguarlo. Entonces vamos a averiguarlo recientemente, datos falsos. Entonces vamos a saber que ahí hay una relación por cómo la fabricamos. Pero dado que vamos a tratar de construir un modelo de regresión lineal usando Spark ML y ver si podemos predecir ingresos basados en Page Speed usando este modelo lineal. Entonces vamos a sumergirnos y darle una oportunidad.
53. [Actividad] cómo dirigir una Regression lineal con Spark: Entonces recorremos nuestro ejemplo de usar regresión
lineal en Spark y veamos si funciona, abrimos el script de dataset de regresión lineal. Y antes de sumergirnos en el código, veamos los datos con los que estamos tratando primero, ese siempre es un buen primer paso, ¿verdad? Entonces si entramos en nuestros materiales del curso y vamos a la carpeta Data, archivo de
regresión dot txt aquí. Sólo familiaricémonos con lo que hay en él. Ahora como recuerdan, lo que estamos tratando de hacer es predecir cuánto gasta la
gente en base a PageSpeed. Entonces lo que estamos tratando de predecir se anuncia gastado y la cantidad que somos, nuestra característica que estamos tratando de predecir eso en es PageSpeed. Entonces en esta primera columna, estos números representan la cantidad gastada, pero se normaliza y se escala hacia abajo. Por lo que esto se normaliza para caber en una distribución de curva de campana. Por eso estás viendo cosas como valores negativos aquí. A pesar de que en realidad no verías cantidad negativa
gastada a menos que alguien recibiera un reembolso o algo así, ¿verdad? Entonces, como dijimos en las diapositivas, debes asegurarte de que estás escalando tus datos a ese rango consistente. Y luego recordando escalar eso de nuevo cuando termines. Esa segunda columna va a corresponder a nuestros datos de características. Entonces en ese caso esas van a ser las velocidades de página. Nuevamente, hemos normalizado esto y
reducirlo a lo que cabría en una distribución de curva de campana. Por lo que estos números por sí mismos no son valores crudos. Habían sido reducidos y esa es una especie de ingeniería de características que la llamamos en el mundo del machine learning es un paso muy importante y obtener buenos resultados. Muchos modelos de aprendizaje automático sí requieren que tus características y tus etiquetas estén reducidas a rangos similares, y a veces incluso más específicamente, centrados alrededor de 0 o entre 01. Es algo que hay que leer la documentación del algoritmo que estás usando para asegurarte de que tus datos estén en el formato correcto. De lo contrario, no funcionará. Obtendrás resultados realmente raros y se estará preguntando por qué. Entonces no olvides eso. Muy bien, así que vamos a sumergirnos en el código. Por lo que nuestro esquema de regresión va a corresponder a nuestras dos columnas de información de doble precisión. Ahí tenemos la etiqueta, que nuevamente corresponde a nuestra cantidad gastada y nuestras características subrayan RA, que corresponde a nuestras velocidades de página. Y de nuevo, estos se escalan hacia abajo a una distribución normal. Está bien, encendemos nuestra configuración de registrador, hablamos nuestra SparkSession, nada nuevo ahí. Y definimos un esquema de regresión que coincida con esa clase de casos de la que acabamos de hablar. Por lo que podemos importar eso desde el disco usando una interfaz DataFrame. Por lo que solo decimos chispa lectura con un separador de comas usando ese esquema. Y cargamos desde el archivo txt punto de regresión de data slash que acabamos de mirar y luego lo
lanzamos dataset usando la clase de caso esquema de regresión. Ahora las cosas se ponen interesantes. Por lo que el formato que espera este algoritmo en la biblioteca ML es muy específico y muchas veces necesitas referirte
al código de muestra que viene con Spark para averiguar exactamente qué quiere. Es así como fui a conseguir este código para ser honesto. Entonces lo que espera es que crearás un objeto VectorAssembler, que también forma parte de las bibliotecas de aprendizaje automático. Y desea establecer en sus columnas de entrada como una matriz de sus columnas de entidades. Ahora en nuestro caso, sólo tenemos una columna de características, se nombra entidades bajo puntuación raw. Por lo que sólo pasamos en una matriz con ese nombre de columna características subrayado raw. Si tuvieras más de una característica, si tuvieras un problema multidimensional, pasarías las características adicionales aquí también. Y entonces ese ensamblador vectorial dará salida a una nueva columna, algo llamado características. Y eso es en realidad lo que vamos a estar pasando a nuestro modelo. Entonces una vez que tengamos este ensamblador, Ese es este objeto ensamblador vectorial, vamos a llamar a transformarse en él alimentándose en ese conjunto de datos de nuestros datos brutos. Y transformará eso en esa columna de salida de características. Seleccionaremos de ella la columna de etiquetas y la columna de características que se producen. Entonces ahora tenemos un DataFrame llamado df que solo contiene etiquetas y características. Y las etiquetas corresponderán nuevamente a nuestra cantidad gastada y columnas a la PageSpeed. Entonces otra vez, bajaré a una escala uniforme. De acuerdo, entonces ahora que tenemos eso, lo que vamos a hacer para medir el rendimiento de este algoritmo es dividir esos datos en dos conjuntos. Vamos a dejar de lado la mitad de esos datos para capacitar a nuestro modelo. Y dejaremos de lado la otra mitad para probar el modelo. Entonces la idea aquí es que entrenaremos a este modelo usando sólo la mitad de los datos que tenemos. Y luego usando ese modelo entrenado, veremos qué tan bien puede predecir los valores correctos conocidos en la otra mitad de los datos. Y mediremos ese error para tener una idea de lo bueno que
es realmente nuestro modelo que nos puede informar en cuanto a si necesitamos probar diferentes hiperparámetros o no, por ejemplo, o limpiar mejor nuestros datos, ¿verdad? Por lo que extraemos la primera división de eso de divisiones aleatorias y llamamos a eso el DataFrame de entrenamiento. Y el segundo bloque de prueba ahí va a ser la prueba DataFrame. Por lo que la división aleatoria solo divide un DataFrame usando una matriz de porcentajes que le das. En este caso 5050. Tomamos ese primer DataFrame resultante y lo llamamos entrenamiento Tf y el segundo DataFrame resultante y lo llamamos prueba df. Y eso solo se basa en asignar aleatoriamente cada fila de d f a uno o dos de estos DataFrames. Entonces ahora lo tenemos todo. Necesitamos realmente crear nuestro modelo de regresión lineal. Y vamos a seguir adelante y crearlo. Y la regresión lineal, lo llamaremos LIR. Y dijimos todos los hiperparámetros. De nuevo, creo que acabo de arrancar estos de la documentación para lugares de donde podría querer empezar desde las muestras. Nuevamente, en el mundo real, querrías iterar sobre estos y encontrar qué combinación de parámetros arroja los mejores resultados. Una vez que tenemos nuestro objeto, llamamos fit on it pasando en nuestro entrenamiento DataFrame ese camino que reservamos para capacitar al modelo. Y luego tomamos ese modelo entrenado y hacemos predicciones al respecto. Por lo que tomamos nuestro modelo y llamamos a transformarse en él, pasando en nuestra prueba DataFrame. Y eso creará una nueva predicciones completas DataFrame que contendrá cantidad
prevista gastada basada en el PageSpeed visto en el conjunto de prueba DataFrame. Ahora lo interesante aquí es que entonces podemos comparar nuestra cantidad prevista gastada con
la cantidad real gastada que está viviendo en nuestros valores de prueba DataFrame en las etiquetas que tenemos ahí. Tenga en cuenta que lo estoy atrapando aquí. No estrictamente necesario para este simple ejemplo, pero si fueras a hacer cosas usando ese conjunto de datos completo de predicciones repetidamente, te gustaría almacenar eso en caché para acelerar eso, ¿verdad? Entonces, una vez que tengas un modelo entrenado y un conjunto de predicciones basadas en él, en términos generales, probablemente
querrás almacenar en caché esos resultados para poder usarlos repetidamente, ¿verdad? En este caso, sólo vamos a arrancar las predicciones y etiquetas después de volver a hacer clic en eso de las predicciones completas DataFrame. Y llamaremos a esa predicción y etiqueta. Y luego simplemente conectamos eso de nuevo al guión e imprimimos todos. Por lo que sólo podemos echar un vistazo a cuáles son los valores reales pronosticados y reales donde para cada punto, probablemente
puedas adivinar qué buen ejercicio para el lector aquí sería en que sería realmente hacer el trabajo de comparando esos valores pronosticados con los valores reales y realmente midiendo ese error desde el DataFrame de prueba. Pero por ahora sólo vamos a ver los resultados porque esto no es realmente un aprendizaje automático correspondiente. Por supuesto se trata de usar Spark. Por lo tanto, hagamos clic derecho en el dataset del marco de datos de regresión lineal y vuelva a
ejecutarlo . Y funcionó. Nuevamente, no tenemos una o al menos no hicimos el trabajo para saber si estas son predicciones razonables o no. Pero estas son predicciones. Por lo que se puede ver la salida aquí. Nuevamente, estos se escalan a cualquier factor de escalado que utilicemos cuando preprocesamos los datos. Por lo que para poder hacer buen uso de esto, tendríamos que volver a escalarlo. Pero parece que funcionó. Estos parecen valores reales y dentro de un rango razonable de valores. Entonces ahí lo tienes. Regresión lineal en un conjunto de datos usando Apache Spark. Entonces de nuevo, el poder de eso es que puedes tomar un dataset verdaderamente masivo y realizar regresión lineal sobre él y crear un modelo utilizando toda la potencia de todo el clúster. Entonces el cielo es el límite aquí, casi literalmente. Está bien, entonces eso es aprendizaje automático en Spark. En pocas palabras, encontrarás que la mayoría de los modelos funcionan de manera similar. Simplemente crea un objeto modelo con un montón de hiperparámetros. Encajas ese modelo a algunos datos de entrenamiento. Y luego puedes transformar ese modelo con datos para los que quieres hacer predicciones. Y es bastante fácil de usar. Entonces eso es todo. Sigamos adelante.
54. [Ejercicio] prepara valores reales con valores de bienes raíces en la opción en Spark en: Entonces para tu próximo reto, vamos a usar Spark con algunos datos del mundo real aquí vamos a tratar de predecir unos valores inmobiliarios usando árboles de decisión, que es otra técnica de aprendizaje automático similar a la regresión. También se puede utilizar con fines de regresión. Y Apache Spark para poder escalarlo si tuviéramos que hacerlo. Por lo que estamos obteniendo nuestro conjunto de datos en un conjunto de datos que tiene el precio por unidad de área. Lo llaman pings en donde viene esto, basado en un montón de atributos de casas. Y esto viene de Taiwán, de New Taipei City. Se trata de datos reales y aquí está el crédito necesario para quién se le ocurrió ese conjunto de datos. Y si quieres explorar más sobre el conjunto de datos en sí y leer más sobre su formato. Sigue ese segundo enlace ahí que viene del repositorio de datos de la UCI. Ese es un repositorio muy útil de conjuntos de datos de aprendizaje automático para que
puedas usar para experimentar y meterte con y aprender con. Entonces ese es un buen recurso ahí, velas y otro también, si estás buscando más fuentes de conjuntos de datos con datos del mundo real. Entonces así es como se ven los datos. En realidad lo he limpiado un poco para ti solo para darle nombres de columna
más razonables y convertirlo a formato
CSV para hacer tu vida un poco más simple para este ejercicio, consta de varias columnas de datos en formato CSV. A la primera columna se le acaba de llamar número es el número asociado a esa casa. Y luego para cada casa tenemos la fecha de transacción cuando se vendió, la edad de la casa, la distancia a MRT, esa es en realidad la distancia al sistema de transporte público local. El número de tiendas de conveniencia cercanas, que supongo que es una gran cosa en Taiwán parece, y la latitud y longitud de la propia casa. Y por último, lo que estamos tratando de predecir, el precio del área unitaria. Y por supuesto esa es una moneda local. Entonces, no leas demasiado en lo que eso realmente significa. Tu reto es predecir el precio por unidad de área en función de la edad de la casa, la
distancia al transporte público, y el número de tiendas de conveniencia cercanas. Sólo para que esto sea un poco más fácil, voy a tirar a la basura algunos de los datos que serían más difíciles de analizar como la ubicación real y cosas así. Obviamente, el número real de la transacción, eso realmente no importa, ni la fecha para nuestros propósitos. Entonces vamos a mantenerlo simple y sólo tratar aquí los datos numéricos. Tu estrategia será usar un
regresor de árbol de decisión en lugar de un objeto de regresión lineal de Spark dot SML, funcionaron mucho de la misma manera. Si lo desea, puede ir a ver la documentación en la documentación de Spark en línea, pero es más o menos la misma sintaxis, solo un nombre diferente. tanto que la regresión lineal funciona computando estas pendientes e intercepta para líneas, un árbol de decisión funciona con una estrategia diferente. Básicamente, es construir este árbol de decisiones que toma donde en cada punto del árbol dice, este atributo
es menor o mayor que algún valor? Y se abre camino abajo tomando estas decisiones basadas en estas decisiones binarias para tratar de llegar a una predicción final de cuál será tu sello predicho final. Entonces sólo una forma diferente de obtener el mismo tipo de resultado al final del día, la razón por la que vamos con árboles de decisión es doble. Uno, solo para exponerte a otro algoritmo ML que está disponible en Spark. Y también porque los árboles de decisión son menos sensibles a tener datos que están en diferentes escalas. En realidad no tenemos que preocuparnos por escalar todos nuestros datos para ser normalizados y en el mismo rango para obtener los mejores resultados con un árbol de decisiones, puede manejar eso mucho mejor. Entonces para empezar, comience con una copia del dataset de regresión lineal Dataframe clase Scala que miramos antes. Y ese será un punto de partida muy útil solo modificando eso un poco, deberías poder sacar esto adelante. Y también tenga en cuenta que tenemos una fila de encabezado en ese archivo CSV, por
lo que no hay necesidad de que usted codifique es esquema para leer eso en, solo
podemos tener el lector de chispas para hacerlo automáticamente si le decimos que el encabezado existe, algunos fragmentos útiles estamos pasando por esto. En primer lugar, en nuestro ejemplo anterior, sólo
teníamos una columna de una sola característica de pecado y no tienes que tener solo una. En realidad puede tener múltiples columnas de entrada en un ensamblador vectorial. Así que recuerda también puedes decir set input calls array, y luego una lista de columnas, no solo una sola columna si tienes múltiples características como lo hacemos aquí. Y recuerda al leer el archivo en, en lugar de especificar un esquema real, solo
puedes decir header true e inferir el esquema true. Y lo leeremos todo en tanto esos nombres de columna de encabezado coincidan con lo que tienes en tu clase de caso, todo saldrá bien. Lo único que tiene el regresor del árbol de decisión, no
vas a necesitar todos esos hiperparámetros extra que especificamos en los árboles de decisión de regresión lineal tienen un conjunto diferente de hiperparámetros, pero está bien simplemente no especificar ellos e ir con los valores por defecto. Eso está bien. Para que puedas despojar todo ese código extra en el ejemplo de regresión lineal. Y también tenga en cuenta que hay una función col de etiqueta set. Y eso te permitirá especificar una columna de etiqueta que no tenga nombre etiqueta. En nuestro caso no se nombra etiqueta. Se llama precio de área unitaria o algo así. Entonces eso debería ser todo lo que necesites. Así que vete y dale una oportunidad. Y en la próxima conferencia, te
guiaré por mi solución y veré lo cerca que te acercas.
55. Solución de ejercicio: predecir bienes raíces con bienes raíces con bienes raíces en la opción en Spark: Muy bien, paseemos por mi solución para predecir el valor de una casa por área basado en algunos atributos bastante inusuales de esas casas en Taiwán. Como siempre con el aprendizaje automático, debes empezar por estudiar la naturaleza de los datos que te dan. Y para nuestros propósitos ya que el estatus ya fue limpiado, principalmente solo queremos esto alrededor por tener una referencia práctica a esos nombres de columna. Porque igualar esos exactamente va a ser muy importante ya que escribimos aquí
nuestro pequeño script para cargar eso y convertirlo al formato que espera nuestro algoritmo. Y ya sabes, siempre es una buena idea, para simplemente volver
a comprobar los datos, asegurarse de que no haya nada inesperado en ello. Estamos asumiendo que todos son números. Entonces un escaneo rápido solo para asegurarse de que todos estos números parezcan estar en más o menos el mismo rango y no tengan ningún extraño como valores
faltantes o valles en el formato incorrecto, como valores aleatorios de cadena aquí y allá. Eso te ahorrará algunos problemas al pasar. Este conjunto de datos, sin embargo, ya se ha limpiado para usted. Por lo que ya se cuida la parte dura del machine learning en este caso, con esa lista, vaya al código. Así que acabo de empezar por copiar el dataset de regresión lineal dataframe puntos archivo Scala y lo llamo gala de puntos inmobiliarios en su lugar. Cambio principal aquí. En primer lugar, estamos usando un algoritmo diferente para la regresión. Estamos importando o dot apache dot chispa dot HTML dot regresión dot decision tree regressor esta vez, igual que te dimos una pista en las diapositivas, si quisieras usar una regresión lineal todavía podrías, lo haría en realidad todavía funcionan. Pero de nuevo, solo queremos exponerte a uno nuevo. Y los árboles de decisión son menos sensibles a tener diferentes rangos de valores en las características y las etiquetas. Por lo que declaramos aquí un nuevo esquema de regresión. Y como puedes ver, es mucho más complicado. Todas nuestras características tienen nombres diferentes y ahora hay más de uno de ellos. Por lo que en realidad tenemos cada una de las columnas en esos datos de entrada que está entrando. Y lo hemos mapeado así. Por lo que tenemos el nombre de columna NO, que significa número. Estamos asumiendo esta fecha de transacción entera. Vamos a llamar a esa casa doble, edad de doble, y etcétera, etcétera. Estos nombres simplemente todos se correlacionan con esos nombres de columna en el propio encabezado CSV. Muy bien, adelante. hay nada diferente. Cuando realmente cargamos en el archivo y vamos a decir opción cabecera true y opción en primer Esquema true, lugar de darle un esquema codificado duro que permitirá aprovechar esa fila de encabezado en el archivo CSV. Entonces eso hace la vida un poco más simple ahí. No tenemos que codificar ese esquema dos veces, lo cual es un poco molesto cuando eso sucede. A continuación, construimos nuestro VectorAsambleador como lo hicimos antes. Y la diferencia aquí es que en lugar de un solo rasgos, o creo que lo llamamos características crudas o características Ron, creo que originalmente en realidad tenemos tres características diferentes y este ejemplo, edad de la
casa, la distancia a MRT y el número tiendas de conveniencia. De nuevo, estamos haciendo coincidir eso hasta esos nombres de clase de casos como aquí. Por lo que la declaración del problema fue predecir el precio del área unitaria en función de la edad de la casa, distancia a MRT un número de tiendas de conveniencia. Entonces estamos tirando las columnas adicionales, no las necesitas. Simplemente estamos configurando las columnas de entrada a las que nos
importan que realmente queremos usar como características para hacer una predicción. Y llamaremos a la columna de salida de características cuando terminemos, eso está bien. Y además seleccionaremos el precio de columna de área
unitaria porque esas van a ser nuestras etiquetas. Entonces en este punto, con lo que vamos a terminar es una columna llamada precio de área unitaria. Eso será lo que estamos tratando de predecir, las etiquetas. Y una columna de características que solo contiene una lista de características. Por lo que esa columna contendrá en formato de lista, la edad de la casa, la distancia a MRT, y número de tiendas de conveniencia. Y ese es solo el formato que espera nuestro modelo. Entonces tenemos que conformarnos a eso. Al igual que antes, dividimos esto en un conjunto de capacitación y un conjunto de datos de pruebas. Y ahora vamos a construir nuestro modelo que se llama regresor de árbol de decisión. Supongo que debería haber cambiado el nombre de la variable a otra
cosa entonces LIR, supongo que debería haber sido. Pero lo que sea, lo que quieras hacer está bien. Establecimos explícitamente los nombres de columna de características y de columna de etiquetas aquí. Características es el predeterminado, así que técnicamente no tuve que hacer eso, pero el valor predeterminado para etiqueta está etiquetado no precio de área unitaria. Por lo que sí tuve que decirle explícitamente a mi modelo el nombre de mi columna de etiqueta es precio de área unitaria para que eso funcione. Después de eso todo funciona de la misma manera. Por lo que sólo decimos ajuste, pasando en nuestro entrenamiento DataFrame. Y hacemos un conjunto de predicciones transformando eso con nuestros datos de prueba. Y como antes, solo pasamos y lo seleccionamos. Sí cambiamos el nombre de columna de las etiquetas aquí otra vez y recogimos eso atrás e iteramos a través de ella e imprimimos todos. Y lo que esto hará como dice un comentario, es imprimir el valor predicho y el valor real para cada casa en nuestro conjunto de datos de prueba. Entonces, veamos si funciona. Haga clic con el botón derecho en bienes raíces y ejecute. Y tenemos salida. Enfriar. Así que sólo pulgar a través de ella fuera de juego, muchos de estos se ven bastante razonables. Predijimos que tenía 50 a lo que sea por lo que sea, y en realidad es 55. Y en su mayor parte, el modelo funcionó bastante bien. Es decir, obviamente hay formas de cuantificar qué tan bueno es el modelo usando métricas como RMSC. Pero esto no es un curso de ciencia de datos o aprendizaje automático. Entonces no voy a meterme en eso. Aunque sí me equivoqué a algunos de ellos salvajemente. Entonces para
éste, predijo un valor de 36, pero el valor real fue un 117. Por lo que claramente hay más de lo que establece el valor de un lugar además de lo cerca de una tienda de conveniencia en la que estás. Cosas como lo cerca que estás de la estación de tren más cercana. Entonces no es demasiado sorprendente que no sea un modelo impresionante porque no le dimos muchos datos impresionantes, pero funciona sorprendentemente bien en realidad en, por agrandar, se acercaba bastante a la mayoría de estos resultados tan interesantes. Entonces ahí lo tienes, espero que lo superes. Nuevamente, esta es sólo una forma de hacerlo. Si tomaste un enfoque diferente, eso también está bien. Tan solo asegúrate de tener una salida similar y lo llamaremos bueno.
56. La API de DStream para la transmisión de spark: Y casos de uso cada vez más comunes Spark está lidiando con datos de streaming. Entonces a este punto del curso, hemos hablado de analizar conjuntos de datos fuera de línea de manera por lotes. Por lo que tenemos estos datos piloto y queremos analizarlos o procesarlos de alguna manera. Pero en el mundo real, los datos nunca dejan de entrar, ¿verdad? Entonces aquí es donde entra Spark Streaming. Permite ingerir flujos de datos en tiempo real. Por ejemplo, podría tener una flota de servidores generando información de registro, recibiendo canalizado en su clúster de Spark, siendo analizado a medida que entra. A lo mejor estás transformando esos datos y almacenándolos en algún otro lugar de alguna otra base de datos. A lo mejor lo estás agregando con el tiempo y
buscando cosas de las que quieres que te alerten a medida que suceden. De cualquier manera, el streaming es un caso de uso muy importante en el mundo de los negocios en estos días. Entonces, sumémonos y veamos cómo se puede usar Spark Streaming para analizar los datos a medida que se crean y tomar medidas al respecto según sea necesario. Por lo que en esta sección, te presentaremos a Spark Streaming. Este es un caso de uso muy común para Apache Spark en estos días, donde estamos tratando con fuentes de transmisión de datos y no solo transformando un montón de datos todos a la vez en un proceso por lotes, sino monitoreando continuamente los datos entrantes y haciéndole algo en tiempo real como se recibe. lo que un ejemplo común de eso sería el procesamiento datos
registrados procedentes de un sitio web o de un servidor, o tal vez toda una flota de servidores que alimentan un sitio web. Esos datos nunca dejan de entrar, ¿verdad? Por lo que no hay como un conjunto realmente simple de archivos de registro. Entonces puedes apuntar y decir: Oye, ve a analizar este trozo de datos de registro. Siempre está entrando, siempre hay nueva información que se está recopilando todo el tiempo. Y tal vez quieras agregar y analizar eso en algún intervalo dado o ventana de información, ¿verdad? A lo mejor quieres configurar algún tipo de alarma donde si estás viendo un montón de errores en tu página web, algo se notifica automáticamente, ¿verdad? Entonces en lugar de sólo esperar un análisis nocturno de esos datos, estamos analizando esos datos continuamente a medida que entran y haciendo algo con ellos. Esos datos no tienen que venir de un archivo sin procesar que puede venir de algún puerto que está recibiendo datos TCP. Puede provenir del servicio Amazon Kinesis. Puede venir de un HDFS o algún sistema de archivos distribuido que puede venir de Kafka, venir de Flume y todo tipo de otras fuentes de datos para así Spark Streaming se puede integrar con un montón de diferentes sistemas, no solo archivos de texto y analizar que los datos a medida que entra. Y tal vez no se trate sólo de analizar y agregar datos. Podría tratarse de transformarlo y simplemente enviarlo a otro lugar a. Quizás todo lo que Spark Streaming está haciendo en tu caso es tomar los datos de registro entrantes, extraer la información que te importa, estructurar esos datos y luego almacenarlos en una base de datos en algún lugar. Ese es un caso de uso perfectamente válido para Spark streaming también. Y lo bonito de Spark streaming, en cambio, tiene unas características de checkpoint. Entonces, si tu stream sí baja, si tu clúster baja por alguna razón, tiene una manera fácil de retomar automáticamente desde donde lo dejó automáticamente. Entonces Esa es una bonita característica segura. Entonces, empecemos a hablar de la antigua API DStream para Spark Streaming. Básicamente, Spark Streaming tiene un historial histórico, si se quiere,
la interfaz original donde se llamaba DStreamds , y se basaba en la antigua interfaz RDD. Y debido a que se basaba en RDD, se centraba en torno a lo que llamamos micro lotes. Por lo que sólo se ocupaba de estos trozos de datos que se representaban como RDD. Y procesó esos pequeños trozos por completo. Entonces técnicamente hablando, no era cierto streaming. En realidad no estaba operando sobre datos sobre una base de campo o fila por fila. Fue fragmentando las cosas en lo que llamamos un micro lotes. Ahora en el mundo real, eso no suele ser realmente un problema si tienes una latencia de unos segundos a diferencia del procesamiento inmediato para la mayoría de las aplicaciones, eso en realidad no importa. Pero esa fue una de las principales cosas que
hacen que se alejen de esta interfaz a lo largo del tiempo. Y bueno, coberturas por razones históricas aquí. Pero pasaremos a la API de Streaming Estructurado más moderna después de esto. En fin, aquí hay un ejemplo de cómo podría verse de Streaming. Por lo que configurarías un contexto de streaming en contraposición a un SparkContext. Y eso son segundos uno ahí significa que va a procesar las cosas 1 segundo a la vez. Por lo que tendrás estos micro lotes contienen 1 segundo de datos nuevos que vamos a procesar como parte de nuestro script. Entonces podemos decir stream dot socket text stream. Y eso le va a decir que escuche el puerto 8888 para que se envíen datos de texto en ese puerto TCP. Y entonces todo lo que va a hacer es filtrar esas líneas entrantes por líneas que contienen la palabra error. Y si ve una línea que contiene la palabra error, la imprimirá. Una vez que hayas configurado eso, solo tienes que llamar a stream dot start para realmente patearlo y retransmitido una terminación de semana para esperar a que alguien lo detenga. Entonces es un poco mágico, poco raro envolver tu cabeza alrededor de este paradigma, ¿verdad? Por lo que hay que recordar que no estamos procesando ni un solo trozo de datos. Esta gráfica acíclica dirigida que estamos construyendo aquí para procesar estos datos en datos tomados y filtrarlos e imprimirlos si así, si pasa ese filtro, esto se va a aplicar repetidamente por cada 1 segundo valor de datos que se reciben automáticamente. No tenemos que escribir un bucle en algún lugar que diga seguir haciendo esto cada 1 segundo repetidamente. Spark Streaming hace eso por ti. Entonces esa sintaxis aquí puede parecer un poco extraña y mágica al principio porque un poco funciona en el arroyo. No tienes que pensar demasiado en esa parte, pero sí funciona. Entonces a un alto nivel, así funciona. Algunos gotchas. Entonces recuerda que tus RDD solo van a contener un pequeño trozo de datos entrantes. Ahora lo que puedes hacer son operaciones en ventana. Con una operación en ventana, puede combinar resultados de múltiples lotes en alguna ventana de tiempo deslizante automáticamente. Por lo que hay funciones como ventana o reducido por ventana o reduceByKey y ventana. Por lo que esas funciones de ventana te permiten
hacer una reducción a lo largo de algún tiempo retrocediendo en el pasado. Por lo que podría decir retroceder por el último minuto, retroceder por la última hora, volver por el día pasado, sea lo que sea, y reducir mi información en base a esa ventana de información. que esa ventana no tenga que corresponder al tamaño de tu lote que puede ser mucho más grande y automáticamente hará un seguimiento de esos resultados de RDD, esos micro lotes, y aplicará tu operación sobre esa ventana de tiempo que has definido. Por lo que automáticamente mantiene esa información alrededor para que puedas analizarla a medida que avanzas. Además, algo de lo que vale la pena hablar es actualizar estado por clave. Esto permite mantener un estado a que se extiende a través de muchos lotes a medida que pasa el tiempo. Por lo tanto, si necesita realizar un seguimiento de algún tipo de estado de ejecución medida que procesa esta información a través de Windows o a través de lotes, puede hacerlo con actualizaciones estado por clave. Un buen ejemplo de eso sería ejecutar algún tipo de contador y conteo
continuo de algún evento a lo largo del tiempo desde que iniciaste el script. Entonces si necesitas hacer un seguimiento de algo ya que el script se ejecuta como un todo en oposición a lo largo de alguna ventana de tiempo. Actualizar estado por clave, te permite hacer eso. Así que vamos a sumergirnos en un ejemplo simple aquí. Vamos a ejecutarlo un script de streaming de Spark que solo monitorea tweets en vivo desde Twitter. Y haremos un seguimiento de los hashtags más populares a medida que recibamos nuevos tweets. Y para ello, primero necesitamos configurar una cuenta de desarrollador de Twitter. Ahora, algunas personas tienen problemas para hacer esto depende de qué país o de cómo llenes el formulario. En qué tipo de humor está Twitter con bastante honestidad, Así que no estoy seguro de que realmente quieras pasar por esto tú mismo. Puedes, si quieres simplemente ir a apps dot twitter.com y solicitar una cuenta de desarrollador ahí si quieres seguir. Honestamente, creo que solo debes verme hacer esta próxima actividad porque como dije, DStreams están un poco anticuados. Ahora bien, si solo estás tomando esta clase con el propósito de obtener una certificación, te
puedo prometer que no va a estar en el examen de certificación, así que tal vez solo quieras verme hacer esta siguiente actividad en lugar de seguir. Pero si lo haces, solo puedes ir a apps dot twitter.com inicio de sesión para cuenta de desarrollador. Y luego puedes crear las claves API y los tokens de acceso que
necesitas realmente para consultar Twitter y canalizar eso a Spark streaming. Por lo que para almacenar esa información, sus credenciales, necesitarás crear un archivo txt de twitter dot. Y te mostraré dónde es eso cuando caminemos por
él, solo va a tener un nombre de tu clave de consumidor e información de token de
acceso en cada línea y nuestro script de conductor, lo
leeremos y usaremos eso para autenticarnos con Twitter. Nuestra estrategia general aquí, una vez que tengamos establecida esa corriente de Twitter, sólo
vamos a extraer los mensajes ellos mismos. También hay un montón de metadatos que Twitter te da como. Pero vamos a crear un Twitter utils dot create stream que va a estar usando una biblioteca de terceros que he incluido con el curso para conectar
realmente Twitter y hacer que parezca un DStream. Y luego llamaremos a tweets dot map para extraer el campo de texto en eso llamando status dot getText. Por lo que en este punto tendremos un nuevo RDD, un micro lote, si se quiere, que no contiene más los mensajes de estado de cada tuit que se recibe. Entonces por ejemplo, tal vez un tuit dice Votar por hashtag boldface bulímico. Y alguien podría decir un libro porque me gustan las botas grandes y no
puedo mentir y no votar por hashtag. ¿ Qué iceberg? Y alguien más podría decir, ¿qué estás loco? Hashtag, Bodhi MAC, atrevido todo el camino. Y si te preguntas de qué diablos estoy hablando aquí, esto fue un mal hace varios años. Básicamente un, me olvido de qué marina era, pero corrieron un concurso en línea para dejar que Internet nombrara su nuevo barco. Y por supuesto esa fue una idea horrible. El ganador, por supuesto fue podium mic boldface, que no usaron. Pero creo que lo pegaron en algunos como poco resumen en o algo que estaba en el barco o algo así. En fin, este ejemplo estamos tratando de hacer un seguimiento de los hashtags más populares, ¿verdad? Entonces en este caso tendríamos hashtag Boolean con ambas caras apareciendo como número, el resultado número uno con dos apariencias y hashtag, lo que iceberg sería el segundo resultado con una sola apariencia. Por lo que hemos establecido nuestra corriente de mensajes de estado. A continuación, podemos usar flatmap para dividir eso en sus palabras individuales. Por lo que al llamar a FlatMap en ese estado micro batch, entonces
volaremos eso hacia fuera en un RDD más grande que tenga una fila por cada palabra que aparezca. Entonces, por ejemplo, el voto del mensaje para su hashtag buddy macrophase, simplemente se
dividiría en tres filas separadas. Votar por hashtag fondo de buffets. Y como todo lo que nos importa son los hashtags, eso es lo único que estamos midiendo. Después podemos llamar a filtro para filtrar las filas que no comiencen con el símbolo hashtag. Entonces eso reducirá las cosas a solo los hashtags que están apareciendo. Y en ese punto podemos hacer nuestro viejo truco desde mucho tiempo atrás en la sección uno o sección hasta lo que fuera, donde podemos convertir esos a un RDD de pares de valor clave, donde la clave es el hashtag real y el valor es el número uno. Eso nos permitirá luego hacer una
operación de reducción para contarlos todos con justo lo que está pasando aquí. Y lo vamos a hacer sobre una ventana corrediza para que las cosas sean interesantes. Por lo que la operación de reducción sumará todos esos juntos y nos
dará un conteo total por cuántas veces aparece ese hashtag. Pero estamos usando un arroyo aquí, así que no vamos a decir reducir por clave. Tenemos que decir sobre qué periodo de tiempo. Y para hacer eso diremos ReduceByKey y window para realizar esa operación de reducción sobre una ventana dada e intervalo de deslizamiento. Entonces vamos a decir ReduceByKey y window, básicamente sumando todo. Y cuándo pasas esto, necesitas darle explícitamente una función para agregar y eliminar elementos a medida que va. Eso es lo que está pasando aquí en esta sintaxis de aquí. Y vamos a decir que vamos a aplicar esto sobre una ventana de 300 segundos. Esos son los últimos cinco minutos con una diapositiva de 1 segundo. Entonces vamos a deslizar nuestra ventana sobre una cada 1 segundo y mirar los últimos cinco minutos de datos. Entonces lo que esto va a hacer es recomputar esa reducción que los hashtags de COUNTIF cada segundo, retrocediendo durante cinco minutos. Y deberíamos obtener un resultado que se vea así si esos fueron nuestros datos de muestra reales. Entonces, por último, sólo necesitamos ordenar y dar salida a los resultados. Llamaremos a una transformación para ordenar ese RDD basado en el segundo campo, que es el conteo, e imprimirlos. Y eso debería ser más o menos. Entonces vamos a verlo en acción. Tenga en cuenta que sí tenemos algunas bibliotecas extra que estamos usando, algunas bibliotecas de terceros. Te mostraré cómo se configura eso. Y sí, vamos a sumergirnos en el código y ver si funciona. Podría ser interesante.
57. [Actividad] Monitorización en tiempo de los hashtags más populares en Twitter: Muy bien, Así que recorremos ese ejemplo de usar la antigua API DStream y usar eso para descubrir los hashtags más populares en Twitter ahora mismo. Y si sí quieres seguir adelante, puedes probar si
te diriges a apps dot twitter.com o desarrollador dot twitter.com, aterrizarás en el portal de desarrolladores para Twitter. Y si aún no tienes una cuenta de desarrollador, te
guiará por el proceso de solicitar una. Y de nuevo, no estoy realmente seguro Vale la pena tu tiempo para pasar por eso. En primer lugar, están haciendo cada vez más difícil conseguir una cuenta de desarrollador en estos días porque tanta gente las está usando para hacer cosas malas con bots y todo eso. Pero si sí quieres pasarlo, si solo dices que lo estás haciendo con fines
educativos para un curso en línea y enumerar el nombre de este curso. Probablemente te den uno bastante rápido. Entonces si sí quieres hacer eso, adelante y solicita una cuenta. Una vez que tengas eso, podrás crear tanto un conjunto de claves de acceso. Entonces veamos cómo se ve esto. Entonces si haces clic en claves y tokens, eso te llevará a un lugar donde podrás obtener tanto tus claves de acceso de consumidor, la pública y secreta, también un conjunto de tokens para una aplicación. Y una vez que tengas esos, vas a abrir tu archivo twitter dot txt en los materiales de tu curso y ponerlos ahí. Entonces el mío se ve así. Obviamente he difuminado las claves reales porque no quiero usar las mías. Pero simplemente pega en su clave de consumidor y secreto de consumidor y su token de acceso y token de acceso secreto aquí para su propia cuenta si lo está siguiendo. Y luego el código, sólo lo tomaremos y lo usaremos para autenticarnos con Twitter. Ten cuidado sin embargo, asegúrate de no tener líneas extra, no tengas espacios extra antes o después de estas cosas que estropearán las cosas. Número uno que la gente tiene con este. Una vez que tengas eso, volvamos a la inteligencia y abrimos hashtags populares. Y pasemos por lo que está pasando aquí. Entonces de nuevo, esto está usando algunas API más antiguas aquí, DStream y RDD. Por lo que tenemos aquí unas funciones separadas para manejar nuestro nivel de registro, para hacerlo de una manera un poco más verbosa. Habrá trato. Nosotros llamamos a nuestra función principal. Lo primero que hacemos es llamar configuración Twitter. Todo lo que hace es abrir ese archivo txt de twitter dot y extraer todas esas claves de autenticación. Por lo que solo establece las propiedades del sistema que el cliente de
Twitter necesitará para permitirte conectarte a Twitter. Y bajo el capó, esto es usar bibliotecas
de terceros que he incluido con los materiales del curso. Este es probablemente un buen momento para mencionar que todo
esto está construido usando SBT bajo el capó en inteligencia. Si realmente vas a construir sobre SBT aquí, puedes ver los paquetes que realmente estamos incluyendo para los materiales del curso en sí. Entonces aquí estamos diciendo explícitamente, estamos usando Scala versión 2.12, Spark versión 3. Estamos importando Spark Core Spark SQL, Spark, MLLib, Spark Streaming. Es así como todo se ha trabajado mágicamente en lo que va del curso. Así es como en realidad hemos tenido a Spark disponible para nosotros. A pesar de que en realidad no instalamos Spark explícitamente. Sbt salió y nos consiguió eso automáticamente. Y también estamos consiguiendo los paquetes Twitter para J core y Twitter para J stream. Estos son solo archivos JAR de Twitter que te permiten transmitir en Twitter datos desde la API de Twitter. Una vez que hayas establecido esas variables de entorno en una viñeta, se autentica por ti. Por lo que al establecer esto en nuestras dependencias bibliotecarias, es recuperar automáticamente la versión correcta de las bibliotecas de Twitter para
permitirnos conectar y transmitir esos datos para la versión dada que queremos aquí. También hay una biblioteca separada que vamos a convertir
ese stream de Twitter de la API de Twitter en un flujo D para la transmisión de Spark. Y acabamos de incluir eso en la lib. Y sólo incluimos eso en las bibliotecas incluidas en el proyecto aquí. Si subes aquí y vas a la carpeta lib, eso es lo que también está ahí ese archivo DStream dash Twitter Jar. Se ha construido explícitamente contra la versión específica de Spark y Scala y Twitter que estamos especificando en ese archivo SBT. Y la forma en que funciona SBT es que si hay algo en la carpeta lib, simplemente
lo pone automáticamente como una especie de dependencia local. Entonces así funciona todo bajo el capó. Volver al código sin embargo. Entonces en lugar de Twitter ha configurado toda la autenticación que necesitará para conectarse. Y una vez que tengamos eso, podemos configurar nuestro contexto de streaming con un tamaño de lote de 1 segundo de datos entrando. Configuraremos nuestro registro para establecer el nivel de registro. Y luego llamamos utils de Twitter. Eso es llamar a esa biblioteca local que incluimos ahí. Y vamos a llamar a crear stream en él para crear un DStream desde Twitter usando esa biblioteca de terceros, simplemente
pasamos en nuestro contexto de streaming y un parámetro opcional que no necesitamos. Una vez que tengamos eso, podemos simplemente llamar status to
status dot getText y usar eso como nuestra función de mapa en ese DStream. Entonces todo lo que está haciendo es extraer el campo de texto de cada tuit. Entonces no nos importa quién lo tuiteó. No nos importa a qué hora lo tuitearon. Todo lo que nos importa es el propio tweet. Y eso es lo que entra en nuestros nuevos estados, D-string. Y aquí, una vez que tenemos eso, usamos flatmap para soplar eso en palabras
individuales después de dividirlas en función del carácter espacial, filtramos cualquier cosa que no comience con un hashtag. Por lo que ahora nos acaban de quedar con hashtags que aparecieron dentro de nuestros tweets que están llegando a través de esa transmisión. Entonces mapeamos eso a estas tuplas del hashtag real en sí y del número 1. Y luego podemos usar ReduceByKey y window para revisar cada 1 segundo, retrocediendo cinco minutos para sumar todos esos por cada hashtag individual y reducirlo por esa clave hashtag. Nuevamente, este es un formato que no hemos visto antes con ReduceByKey. En ocasiones quieren tener ambos en operación por agregar algo en una operación por sacar algo. Entonces en este caso, si agregas algo en, queremos agregarlo. Si quieres sacar algo, lo restamos. Por lo general ese va a ser el caso, pero hay casos de uso raros donde se quiere hacer algo más complicado. Una vez que tenemos eso, solo lo ordenamos y mostramos los resultados, imprimimos el top 10. Está bien, para iniciarlo, dijimos un directorio de puntos de control. No hablamos mucho de eso en las diapositivas. Pero esto en realidad es establecer una carpeta de punto de control en mi unidad C. Si estás en algún otro sistema operativo, probablemente
querrás cambiarlo a una ruta que tenga sentido en tu sistema operativo que no funcionaría en Linux o Mac por supuesto, pero podrías cambiarlo para barra inclinada a los usuarios sea cual sea tu nombre de usuario es, su directorio de inicio si quería inclinar Check Point. Y eso funcionaría también. Ahí es donde almacenará una tienda los datos que necesita para recoger donde lo dejó. Si algo malo le sucede a este script de forma inesperada mientras se está ejecutando, por lo que puede reanudarse desde ese punto de control. Una vez que tenemos esa configuración, simplemente iniciamos nuestro contexto de streaming y dejamos que haga lo suyo. Simplemente va a hacer continuamente lo que le dijimos que hiciera. Reduciendo cada 1 segundo durante los últimos cinco minutos cuál es el hashtag más popular, y seguiremos haciendo eso hasta que alguien termine explícitamente el guión. Entonces veamos si funciona. Haga clic en hashtags populares, haga clic derecho y ejecute. Y aquí viene. Y cada vez que ejecuto esto, me recuerdan que Twitter es una plataforma global. Vemos un montón de cosas de lengua extranjera y referencias culturales que no significan nada para mí. En todo el mundo. Estamos viendo cada tuit que sale públicamente
al menos y sumando los hashtags que aparecen con mayor frecuencia. Entonces, dejemos que esto funcione un rato y veamos qué resultados interesantes obtenemos. Vamos a ampliar un poco esto para que podamos ver más de él. Ahí vamos. Por lo que en este momento BTS es tendencia como el hashtag superior. No tengo ni idea de lo que eso significa. Tendré que ir a buscar eso más tarde. Es sinónimo de algo culturalmente significativo en este momento por lo que la gente está entusiasmada. En cambio, la gente está sobre el helado. El helado se hace cargo. Helado acaba de ponerse al día para el número uno, muy emocionante. Oye, a quien no le gusta el helado justo arriba IP3, lo que sea que demonios, eso es. Todavía juntos. Muy dinámico, ¿verdad? Helado sin embargo, sostenga por su cuenta. Al igual que una guerra entre helado y BTS. Bts está sondeando adelante. De todos modos, podrías correr esto todo el día si quieres, y te garantizo que verás algo diferente si estás manejando esto tú mismo porque cambia cada día, cada momento dice lo que sea que el mundo esté hablando ahora mismo. Y afortunadamente, no creo que veamos nada ofensivo aquí. Por lo general lo haces. Si bien para ser justos, no sé qué es BTS ni cuál es esa lengua extranjera donde es que sigue apareciendo ya sea aún juntos. No sé a qué se refiere eso. Hombre, tengo que salir más. Pero de todos modos, ahí lo tienes. Podemos seguir adelante y simplemente cancelar esto. Pulsa el botón rojo aquí para parar. Eso. Parece que después de ese tiempo, el ganador fue lo que eso signifique en cualquier idioma que sea, tal vez alguien en los comentarios me pueda decir. No lo sé. A lo mejor no quiero saber. Debería ser, podría ser algo desagradable. Pero es un ejemplo bastante guay, divertido, ¿verdad? Por lo que en realidad hemos utilizado aquí la API DStream para ir y conectarnos a
fuentes reales de Twitter y hacer un seguimiento del hashtag más popular a medida que avanzamos con el tiempo. Y si tuviera que ejecutar esto por cinco minutos completos, obtenemos un total de cinco minutos de datos. Y entonces tendríamos una ventana deslizante de los últimos cinco minutos adelante mientras seguimos ejecutando este guión. Por lo que podría ser algo divertido correr por un tiempo y sólo ver lo que hace. Entonces ahí lo tienes una especie de ejemplo del mundo real usando datos del mundo real. Esa es la parte divertida, pero como dijimos, DStreams son una especie de la antigua forma de hacerlo. Entonces vamos a sumergirnos en la nueva forma de hacer las cosas con streaming estructurado a continuación.
58. Streaming estructurado: Entonces como mencioné, DStream fueron la API de streaming original para Apache Spark. En estos días, la gente usa algo más. A veces se llama Streaming Estructurado. Por lo que aún te encuentras con bibliotecas que esperan DStream como esa biblioteca de Twitter que solo estaba usando. Por lo que sigue siendo útil saber que está ahí fuera y cómo funciona. Pero encontrarás que el streaming estructurado es la API más moderna para streaming y Spark. Y también es más fácil usar sus ideas de que use datasets ya que su API principal en lugar de RDD son DStream que se parecen a RDD. Y como dije antes, gran parte de Spark va por el camino de usar datasets y en Scala o DataFrames en Python como su API primaria. Y la belleza de esto es que es bastante elegante para streaming porque puedes imaginar un conjunto de datos que simplemente se sigue anexando para siempre y solo lo consultas cuando quieras, al igual que cualquier otro conjunto de datos. Entonces la parte de streaming es solo que seguimos agregando más y más filas a ese conjunto de datos en tiempo real a medida que se recibe nueva información. Y eso hace las cosas mucho más fáciles. Significa que puedes usar estos conjuntos de datos deben ser muy parecidos a cualquier otro conjunto de datos. Entonces, en realidad no es mucho de lo que podamos hablar en esta conferencia. Una vez que hayas configurado las cosas, solo
usas esto como cualquier otro conjunto de datos. Todas las demás cosas que hemos aprendido en el curso se aplican exactamente de la misma manera a un dataset de streaming que a un conjunto de datos que se lee de un proceso por lotes. Y lo otro bonito es que al hacer esto, transmisión ahora es verdaderamente en tiempo real. Este fue un verdadero punto pegajoso con mucha gente. Y por un tiempo la gente decía que el streaming de Spark era inferior a otras plataformas de streaming por eso. Bueno, ahora ya no pueden decir eso porque con Streaming Estructurado, Streaming ahora es verdaderamente tiempo real. A medida que se reciban nuevos datos, se anexarán inmediatamente a ese conjunto de datos y obtendrás acceso a él de inmediato. Por lo que ya no estamos basados en estos micro lotes de como diminutos pequeños RDD contienen 1 segundo de datos. No tenemos que pensar en eso. Ese nivel de pensamiento ya no es requerido en nuestro código. Configurándolo, es súper fácil. Todo lo que necesitamos hacer es decir chispa punto read stream en lugar de Spark dot read, cuando estamos configurando un DataFrame o un dataset. ¿ Y se puede decir qué? Por ejemplo, si solo quisieras leerlo en archivos JSON desde un bucket de logs en Amazon S3, solo
podrías decir que se activó dot-dot-dot stream dot registros JSON S3 y eso simplemente se sentaría ahí y monitorearía que logs bucket en S3 todo el día, 24 , 7, buscando nuevos archivos JSON para leer y analizar. Y simplemente seguiría agregando cada nueva línea en cada nuevo registro JSON que se encontró allí en ese DataFrame de entrada. Y entonces puedes hacer lo que quieras. Puedes agruparlo por, ya sabes, alguna acción. Se puede hacer una ventana igual que vimos en DStream. Entonces si sí quieres especificar una ventana de tiempo, solo
puedes pasar ese parámetro de ventana extra ahí para especificar el, el periodo de tiempo sobre el que quieres ir. Y puedes contarlo hasta arriba, Correcto, el arroyo hacia fuera donde quieras. En este caso, lo vamos a dar formato a una conexión JDBC y simplemente escribirlo en una base de datos MySQL en algún lugar de vuelta y pegarlo en una base de datos. Entonces eso es realmente todo el código específico de streaming que
verías solo el activo realmente especificando esa ventana, estableciendo el stream y donde estás escribiendo el stream. Aparte de eso, es solo un marco de datos antiguo o conjunto de datos regular, dependiendo de cómo lo estés usando y todo lo que normalmente
harías con el DataFrame donde el dataset se aplica aquí también. Entonces vamos a hacer un pequeño ejemplo aquí de streaming de archivos de registro. Por lo que incluí un archivo de registro de acceso Apache en los materiales de su curso. Y lo que vamos a hacer es simplemente configurar un pequeño directorio en nuestros materiales del curso y copiaremos ese archivo de registro y veremos si nuestra aplicación de streaming lo recoge y lo procesa. Entonces para hacer eso, solo vamos a decir chispa punto read stream
dot txt porque estos son solo archivos de texto plano, archivos registro con una ruta de directorio a la carpeta logs dentro de mis materiales de curso. En ese punto, solo puedo usar operaciones SQL para analizar los datos de esas líneas de registro usando expresiones regulares. Eso podría usar con una operación de mapa si lo quisieras también. Y luego solo usa el grupo BY para
agrupar las cosas sobre alguna ventana si quieres transmitir la salida, en este caso a nuestra consola, pero con la misma facilidad podría ir a una base de datos o cualquier cosa que quieras. Así que vamos a sumergirnos y transmitir algunos troncos. No ese tipo de registro.
59. [Actividad] utilizando la transmisión estructurada para el análisis de archivos en tiempo real: Muy bien, Así que juguemos con streaming estructurado otra vez, un poco la forma moderna de hacer streaming en estos días y Spark. Vamos a abrir aquí el script de streaming estructurado y ver cómo funciona. En primer lugar, ves que esto es en realidad bastante simple. Es decir, aparte de las expresiones regulares reales de analizar esos datos de registro, el código de Spark en sí no es mucho. Es bastante conciso. Entonces pasémoslo por aquí. Muy bien, entonces nosotros cosas importantes. Necesitamos un objeto cráter aquí, establecer el nivel de registro, crear una sesión de Spark. Hasta ahora nada es diferente. Lo primero que es diferente sin embargo es que en lugar de decir chispa
punto, texto de punto, vamos a decir chispa punto leer stream dot txt. Eso es todo. Eso dice que vamos a hacer de esto un flujo de
información nada continuo en lugar de sólo leer en un bloque de información de un archivo de texto estático. Y el camino que pasamos aquí es en realidad una ruta de directorio. Y en este caso va a estar en nuestro sistema de archivos local. Pero podrías monitorizar con la misma facilidad un bucket S3 o algún sistema de archivos distribuido si así lo quisieras. Entonces solo se va a sentar aquí viendo mi directorio de registro de barra de datos para nuevos archivos de texto. Y a medida
que se descubran nuevos archivos de texto allí, añadirá cada línea de ese archivo de texto a las líneas del eje DataFrame. De acuerdo, es así de sencillo. Ahora el resto de este complicado código aquí realmente solo está analizando esos datos. Por lo que los registros de acceso de Apache son un formato bastante extraño y se necesitan algunas expresiones regulares bastante complicadas para extraer la información de ella y convertir esos datos de archivo de registro
no estructurado en información estructurada. Entonces no voy a entrar en los detalles de cómo funcionan estas expresiones regulares, pero están destinados a extraer la información que necesitamos de cada campo de ese registro de acceso de Apache. Y aplicamos esas expresiones regulares aquí dentro de esta gran declaración selecta vieja. Por lo que tomamos ese eje líneas DataFrame y llamamos a seleccionar en él. Ahora por defecto, cada nueva línea de textos que entren en líneas de eje estará en una columna llamada valor. Entonces por cada uno de estos ejemplos, estamos haciendo un extracto reg ex en la columna de valor. Eso significa que va a tomar la línea cruda de datos, sí le aplican una expresión regular. En este caso, la expresión host, que se supone para extraer el nombre del host. Y íbamos a darle a eso un alias de anfitriones. Por lo que esto básicamente creará una nueva columna de host que contenga el host extraído de esa línea. Y hacemos lo mismo para la marca de tiempo para el método, el endpoint
para el protocolo,
para el código de estado y el tamaño del contenido. En este punto, puedes hacer lo que quieras, ¿verdad? Entonces en nuestro sencillo ejemplo aquí, todo lo que vamos a hacer es agrupar POR el estatus y contar a lo largo del tiempo. Por lo que vamos a mantener un conteo continuo a lo largo del tiempo de cuántas veces aparece cada código de estado en estos archivos de registro. Entonces eso es que se va a sentar ahí otra vez a la espera de que los nuevos archivos de registro sean dejados caer en el directorio de registro de la slash de datos. Y se agrupará por con el tiempo, cuántas veces aparece cada código de estado. Tenemos que decirle dónde poner esa información. Entonces construimos lo que se llama una consulta. Y solo decimos cuenta de estado DataFrame, Ese es nuestro recuento final DataFrame allí. Vamos a escribir esa corriente con el siguiente modo de salida. Vamos a decir que queríamos completar la salida formateada yendo a la consola. Y le daremos a esa consulta un nombre llamado cuenta. Y solo llamaremos a almidón para que realmente inicie esa corriente de salida. Está bien. Por lo que definimos nuestro flujo de entrada aquí arriba con Spark dot read stream dot txt. Eso es lo que va a monitorear. Definimos una serie de operaciones que llevaron en última instancia a los
conteos de estado DataFrame que se está computando a partir de ese flujo de entrada. Y luego creamos un flujo de salida aquí llamado consulta. Entonces sólo esperamos la terminación. Simplemente correrá eso para siempre hasta que lo detengamos explícitamente. Y cuando alguien hace eso, llamamos a parar en la sesión para terminar las cosas. Entonces vamos a patearlo y a ver si funciona. En primer lugar sólo lo ejecutará. Nos damos el lujo de hacer girar un inicialmente
no hay nada en ese directorio y así que necesitamos poner cosas ahí para que realmente haga algo interesante, ¿verdad? Entonces hagámoslo. Vayamos a nuestros materiales del curso aquí y pasemos a los datos. Y verás que aquí hay un archivo de registro de acceso que contiene un registro de acceso de Apache real de uno de mis sitios web. Vamos a copiar eso y abrir el directorio de Registros y pegarlo ahí. Y lo que debería pasar es que nuestro guión debería recoger eso. Puedo escuchar mi ventilador de CPU funcionando, está haciendo algo. Y funcionó. Por lo que recogió ese nuevo archivo y contó todo el código aéreo. Entonces podemos ver que en realidad sí parece tener un error de 500 código de error aquí están apareciendo un montón horrible. Entonces esto me estaría alertando un problema real en mi página web si esta fuera una aplicación real, ¿verdad? A lo mejor podría tener algún tipo de umbral en el número de 500 errores y alertarme si eso supera algún umbral con el tiempo. Veamos si funciona con a medida que se le arrojan más datos. Entonces volvamos a los datos y hagamos una copia de nuestro archivo de registro de acceso. Yo sólo voy a copiar y pegar. Por lo que ahora tenemos acceso log dash copy. Copiemos eso también en nuestros registros. Y lo que deberíamos ver son todos estos números, doble lote uno, tenemos otro lote de información que entró. Y bastante seguro, todos estos números se han duplicado porque acabo de copiar ese mismo archivo de registro. Y otra vez, así que ahí lo tienes. Pongamos el botón X aquí para detener el arroyo. Y sí, eso es Spark streaming y acción, Cosas bastante cool. Por lo que como puedes ver, Streaming Estructurado es realmente fácil de usar. Si puedes usar un conjunto de datos, puedes usar streaming estructurado y ya no estás limitado a procesar datos de manera por lotes. Puedes procesarlo como entra,
en tiempo real, lo cual es muy emocionante. Está bien, Eso es Spark streaming en pocas palabras. Sigamos adelante.
60. [Ejercicio] Operaciones Windowed con transmisión estructurada con la transmisión estructurada: Por lo que este próximo ejercicio realmente interesante. Quiero que hagas un seguimiento de las principales URL vistas en mis registros de eventos allí para mis registros de acceso Apache. Y hacer un seguimiento de eso. Entonces, en lugar de mostrar el recuento de códigos de estado a lo largo del tiempo, quiero que muestre el recuento de las URL principales que se vieron desde los datos de registro en su lugar. Y para que sea aún más interesante, no
quiero que midas esto desde el principio de los tiempos. Yo sólo quiero que miren hacia atrás en los últimos 30 segundos y sólo me digan cuáles fueron los mejores resultados dentro del intervalo de 30 segundos pasado. Ahora para hacer esto, necesitas introducir el concepto de operaciones de ventana en Spark streaming. Entonces permítanme presentarles eso de verdad rápidamente. Una operación con ventana solo está mirando hacia atrás durante algún periodo de tiempo. Entonces, por ejemplo, si sólo quiero considerar eventos que sucedieron en los últimos 10 minutos, tendría una ventana de 10 minutos. Y el intervalo de diapositivas define con qué frecuencia evaluamos esa ventana. Por lo que tenemos una ventana de 10 minutos, digamos desde las 12 en punto hasta las 12 diez. Si tuviéramos un intervalo de deslizamiento de cinco minutos, eso significa que evaluaríamos esa ventana en 1205121012151220. Cada vez mirando la ventana de 10 minutos más reciente en la que estamos dentro. Para que eso sea un poco más concreto, permítanme mostrarles un diagrama que viene directamente de la documentación de Spark aquí. Y aquí dentro tenemos una ventana de 10 minutos con un intervalo de diapositivas de cinco minutos. Entonces estamos iniciando esto a las 12 en punto en este ejemplo hipotético. Por lo que tenemos ventanas que van de las 12 en punto a las 12 diez, de 1205 a 1215, de 1210 a 12, 20 y así sucesivamente y demás. Por lo que cada cinco minutos tenemos una nueva ventana de 10 minutos siendo definida. Y con el tiempo agregamos los resultados sin a lo largo de estas ventanas. Y seguimos agregando los resultados de esas ventanas a nuestra tabla de resultados a medida que avanzamos. Entonces en este ejemplo, tenemos una corriente de nombres de animales entrando aparentemente. Por lo que un 1202 y 12 03, tenemos gato perro y perro entran. Por lo que un 12 05, tenemos un ligero intervalo que se golpea. Entonces eso va a mirar la ventana de las 12 en punto a las 1210 porque esa es solo nuestra primera ventana que sucede que tenemos desde que empezamos a correr. Y lo que tenemos hasta ahora es un gato y tres perros que se han recibido. Al 1207, obtenemos un búho y un gato. Entonces cuando corremos nuestro siguiente intervalo de diapositivas a las 1210, ahora también vamos a mirar las 12 en punto a las 12 10 y las ventanas 1205 a 1215. Ahora resulta que nuestro gato realmente se le agregó a eso de las 12 en punto a las 12, 10 ventanas. Entonces vamos a agregar eso a nuestra tabla de resultados y actualizarlo. Y también vamos a crear una nueva ventana en nuestra tabla de resultados para 1205 a 1215 que vamos a hacer un seguimiento. Y simplemente sigue adelante y sigue, ¿verdad? Entonces un 1215, ahora vamos a conseguir otra ventana nueva de 1210 a 1220 que vamos a mirar. Y volveremos atrás y actualizaremos cualquier ventana anterior según sea necesario para dar cuenta de los nuevos datos. Entonces tenemos otro perro y otra hora que entró entre ahí. Y si miras de cerca, puedes averiguarlo. Pero básicamente la idea es que la ventana es el periodo de tiempo sobre el cual estás agregando cosas. Y el intervalo de diapositivas es la frecuencia con la que estás evaluando eso. El codificado para hacer esto es bastante sencillo. Simplemente dices grupo BY si querías hacer algún tipo de agregación en una columna, en este caso, la columna que estamos agrupando por el nombre de esa columna. Y sintácticamente diría ventana. Y luego especificar una llamada con el nombre de la columna que representa la marca de tiempo está definiendo cuándo sucedió esto, ¿verdad? Por lo que el código de ventana en la
transmisión de Spark no está realizando automáticamente un seguimiento de cuándo se recibieron los eventos. Va a estar mirando una columna específica en tus datos que se está ingiriendo. De acuerdo, así que ten eso en cuenta. Ya sabes, vas a estar ventanas definidas en datos que están en la propia corriente, no en cuando eso fue realmente recibido por Spark streaming. Diferencia tan sutil pero importante, sobre todo en nuestro ejemplo aquí, porque estamos usando registros de Apache muy antiguos que tienen marca de tiempo de años y años atrás. Entonces eso va a afectar cómo nos acercamos realmente a este problema. Entonces dices que la duración de la ventana de coma es igual a la duración de la ventana que quieras. Y eso se acaba de especificar en inglés llano como 10 minutos, 30 segundos, lo que quieras ahí. Creo que hay un límite de un mes en eso sin embargo. Y la duración de la diapositiva también se especificó en inglés llano también. Entonces sintácticamente, eso es lo que necesitas saber sobre cómo hacer agregaciones en ventana. Entonces tu reto otra vez, modifica estos scripts de streaming estructurados en los que acabamos de
trabajar para hacer un seguimiento de las URL más vistas. Y eso en realidad se llama endpoints en este script en particular. Lo mismo. Y quería computar eso con una ventana de 30 segundos y asistir a segunda diapositiva. Ahora estás en necesita algunos pequeños fragmentos de código para poder hacer esto. En primer lugar, de nuevo, sólo
voy a reiterar ese fragmento de código sobre cómo realmente especificar sintácticamente esa ventana. Entonces así sería ese código. Esa no es toda la línea que necesitarás en el guión real, pero es una buena parte de ella. Estoy agrupando por no es suficiente. También necesitas contar cuantos hay en ese grupo, ¿verdad? Por lo que ya has visto cómo hacerlo en ejemplos anteriores. Además, como dije, vas a tener un problema porque los registros de muestra Apache que te di son muy viejos, tienen años. Y eso no va a funcionar con una tensa, una ventana de 30 segundos, ¿verdad? Entonces si estás mirando atrás 30 segundos en un registro que estaba capturando datos de hace tres años, eso no va a funcionar tan bien. Entonces lo que puedes hacer es fabricar una nueva columna en tu conjunto de datos que es la hora actual en la que se ingirió. Y la sintaxis para eso es ese segundo bloque, su columna logs df punto ancho agregará una columna llamada tiempo de
evento como igual a la marca de tiempo actual. Por lo que eso te dará una nueva columna que podrás utilizar para la hora actual. Eso será un poco más útil para este ejercicio. Y por último, vas a querer asegurarte de que estás ordenando los conteos en orden descendente. Entonces en algún momento tendrás que decir orden por contador de llamadas, sea que llames a esa columna de conteo DESC para especificar que quieres que en orden
descendente para que veas los mejores resultados primero y no viceversa. Así que vete y ten en ello, esto es un poco más desafiante, podría requerir que hagas un poco más de pensamiento creativo o buscar cosas en línea. Pero oye, así funciona el mundo real. Entonces dale una oportunidad. Y cuando regresemos, te mostraré cómo lo hice.
61. Solución de ejercicio: la parte en la URL en una ventana de 30 segundos: Muy bien, así que hagamos algo un poco más elegante con transmisión
estructurada y echemos un vistazo a mi solución para hacer un
seguimiento de las principales URL vistas desde nuestros registros de acceso Apache usando una ventana deslizante de 30 segundos, en lugar de apenas desde el principio de los tiempos. Así que acabo de empezar con una copia de estos script Scala de punto de streaming estructurado como te aconsejé que hicieras. Y no cambia mucho hasta que bajemos a esta línea aquí en la línea 42. Ahora, como mencioné, esta es una ley de acceso apache muy antigua que les he dado dentro de los materiales del curso. Y si vamos a estar haciendo ventanas corredizas del tiempo desde los últimos 30 segundos. Bueno, necesitamos fabricar algunos nuevos tiempos de eventos que sean más actuales, ¿verdad? Entonces eso es todo lo que esta línea aquí está haciendo, es tomar nuestros logs df dataframe y anexar una nueva columna usando con columna llamada
tiempo de evento que se envía a la marca de tiempo actual cada vez que esos datos se ingieren realmente. Y vamos a dar la vuelta y llamar a los registros DataFrame resultantes df2. Está bien, ahora las cosas se ponen interesantes. Entonces mantengamos un conteo corrido de esos puntos finales. Entonces en, en nuestra nomenclatura aquí, y punto final es básicamente lo mismo que una URL. Por lo que tenemos un método GET seguido del punto final, que va a ser la URL en nuestra página web que alguien ha golpeado. Entonces para ello, vamos a usar esa misma sintaxis de la que hablamos en las diapositivas para establecer esa ventana de 30 segundos con una duración de diapositiva de 10 segundos. Simplemente decimos logs df2, groupby window call. El nombre de la columna aquí es hora del evento. Esa es la, esa es la marca de tiempo que vamos a estar ventanando. ¿ De acuerdo? Especificamos una duración de ventana de treinta segundos y registramos, actualizamos esas ventanas cada 10 segundos. Y el segundo parámetro para el comando group BY se va a llamar endpoint. Entonces vamos a estar agrupando por los puntos finales, agrupando todos esos extremos comunes juntos. Y luego una vez que tengas los agrupados dentro esa ventana y en esa duración de la diapositiva, los vamos a contar. Entonces, lo que esta sola línea de código está haciendo es contar cuántas de cada URL se encontró cada 10 segundos, mirando la ventana actual de 30 segundos que estamos en lo correcto? Ahora, eso no es suficiente. También quiero ordenar estos, así que veo las URL más populares. Simplemente no quiero ver una lista desordenada. Entonces además voy a tomar esos puntos finales, cuenta DataFrame y ordenarlo diciendo dot OrderBy call cout name igual a count, va a ser el nombre de la columna de conteo que se crea por ese comando Cal dot DSC, para decir que yo buscado en orden descendente. Por lo que las URL más populares están en la parte superior, y eso es todo. El resto del código es básicamente el mismo. Dimos salida a la consola ahí y la pateamos básicamente. Y un poco aparte aquí, una última nota, si quisieras escribir esto en una base de datos o en un archivo o algo así, simplemente establecerías el modo de salida es otra cosa y el formato es otra cosa. Entonces si buscas la documentación ahí, puedes ver cómo podemos escribir a una base de datos o a
un texto o a un archivo de parquet o lo que quieras. No tiene que ser a la consola. Va a ser mucho más práctico almacenar estos datos en algún lugar, ¿verdad? Y lo que estamos almacenando es esa tabla de resultados. Entonces vamos a conseguir estos, esta tabla de resultados para cada ventana actualizada, para cada duración de diapositiva. Entonces el resultado que vamos a ver es una tabla que hace un seguimiento de los resultados que vemos dentro de cada ventana, cada ventana de 30 segundos que tenemos. Entonces, veamos si realmente te estoy mintiendo o no. Vamos a ejecutar esto y a ver qué pasa. Por lo que las URL superiores corren
permitirán que eso se ponga en marcha y voy a hacer que esa ventana sea grande para que podamos ver qué está pasando. Está bien, así que está sentado ahí esperando datos. Voy a volver a mis registros aquí en mis materiales del curso. Y puedes ver en realidad tengo tres copias de mi tronco de eje aquí para jugar. Empecemos con uno. Tenemos que copiar eso y tirarlo en mi carpeta de registros aquí. Entonces como estamos en streaming en tiempo real, debería recoger la existencia de esos nuevos datos y seguir adelante y actualizar todo. Se está escapando ahora mismo. Se puede escuchar mi ventilador de CPU yendo. Y ahí lo tenemos. Entonces podemos ver que esos intervalos de deslizamiento de 10 segundos, estamos calculando ese valor de ventana cada vez y estamos obteniendo un resultado consistente porque
en realidad no hemos estado funcionando por más de 30 segundos todavía. Entonces sigamos adelante y arrojemos algunos datos más
ahí solo para asegurarnos de que funcione como se esperaba. Entonces nota aquí estamos viendo que 0, ahora debería ver Lote 1. Y hay lote uno. Curiosamente, es el mismo número que antes, ¿no? Porque han transcurrido más de 30 segundos desde ese primer lote. Por lo que ese primer lote de información realmente expiró. Se cayó del extremo de mi ventana. Entonces si no estuviéramos haciendo ventanas, habríamos visto todos esos números duplicados, verdad. Pero no lo hicieron porque esos treinta segundos de datos expiraron. No creo que hayan pasado ya 30 segundos, así que vamos a ver si realmente puedo conseguir un número más grande allí. Si soy lo suficientemente rápido, lo pondremos en una tercera copia ahí. Y aquí vemos un parche a yo no era lo suficientemente rápido, se cayó del extremo allá de la ventana de 30 segundos. Pero si tienes tu propia versión de esta corriendo, siéntete libre de jugar con ella o ajustar esos tiempos de Window para ser un poco más amigable contigo y cómo estás trabajando. Y una buena manera de tener una sensación de cómo funcionan Windows y los intervalos de diapositivas es experimentar con él y simplemente jugar con él como lo estamos haciendo ahora mismo. Por lo que ya has aprendido sobre Spark Streaming y cómo manejar los datos en tiempo real a medida que llegan.
62. GraphX, Pregel y Breadth-First-Search con Pregel .: Por lo que en esta sección presentaremos Graphx, que es una API para tratar con gráficas de información tipo como nuestra red de superhéroes antes del curso. Gráficos es una especie de hijastro descuidado de inteligente, para ser honesto, no ha visto mucho desarrollo últimamente y todavía está atascado en la antigua API RDD. Hay una versión más reciente de la misma en desarrollo llamada frames de grafo, pero aún no está lista para prime time. Entonces por ahora, solo por completitud, voy a hablar del gráfico x y su forma actual, que sí usa la interfaz RDD, pero verás que sigue siendo bastante potente. Y usarlo sí se siente un poco más como SQL a la vez. Entonces, sumémonos y veamos cómo los gráficos pueden ayudarte a resolver problemas distribuidos masivos usando gráficos de información. Vamos a sumergirnos brevemente en el mundo de GraphX, el último componente central de la propia Spark. Y cuando hablamos de gráficos, no
estamos hablando de gráficos de líneas o gráficos ni nada por el estilo. Estamos hablando de gráficos en el sentido de la informática. Entonces por ejemplo, nuestra red social de superhéroes que vimos antes en el curso. Ese es un ejemplo de la gráfica de la que estamos hablando, donde tenemos vértices que en ese caso representan superhéroes
individuales y bordes entre esos vértices que representan relaciones entre ellos. Los gráficos son un poco geniales, pero en realidad solo son útiles para alguna cosa específica. Entonces por sí mismo, en realidad no puede responder a las preguntas que
estábamos respondiendo en el código que escribimos para analizar nuestra red de superhéroes. Pero puede hacer cosas como medir la conectividad, la distribución de grados, la longitud
promedio de la ruta, el recuento de triángulo, especie de estas medidas de alto nivel de la gráfica en su conjunto. Puede hacer cosas como contar todos los triángulos en la gráfica
y aplicar el algoritmo PageRank a lo desigual. Entonces, entonces creo que esa es realmente la fuerza motriz detrás del propio GraphX. Es más útil para implementar algo como PageRank, que obviamente es un caso de uso importante. Y ese es también un problema que implica escala masiva, por
supuesto, donde el poder de Spark resulta muy útil. Entonces está un poco hecho para eso más que cualquier otra cosa. También puedes hacer cosas como unir gráficas y transformar esas gráficas muy rápidamente de manera distribuida. Pero para cosas como nuestros grados de separación ejemplo donde estamos tratando de
averiguar cuántos grados de separación como superhéroe es de Spider-Man. No vas a encontrar soporte incorporado para operaciones como esa. No obstante, sí soporta la API de Pregel para atravesar una gráfica. Y eso te permite escribir tu propio código y desarrollar tus propios algoritmos que tipo de vivir dentro de los gráficos. Y eso te da la flexibilidad para hacer esas cosas más complicadas que podrías soñar. Simplemente no salen de la caja. Hay que pensar a través de ello y pensar de manera creativa como teníamos que hacer cuando hacemos esto usando dataframes o usando RDD. Por lo que los gráficos introducen un par de nuevos tipos de datos, el vértice RDD y el borde RDD, así
como el tipo de datos de borde. Y así es como representamos los vértices y los bordes entre ellos que conforman una gráfica. Ahora Graphics es un poco de retraso. Todavía está escrito en la API de RDD, pesar de que la propia Spark ha estado tratando de
migrar cada vez más hacia los dataframes y datasets. Con toda sinceridad, GraphX ha caído un poco por el camino. Realmente no ha visto mucho desarrollo activo todavía. Sigue siendo una pieza central de Spark en sí, así que lo estoy cubriendo aquí. Pero lo estás viendo cada vez más siendo reemplazado por otras cosas simplemente no se
están utilizando mucho en el mundo real. Resulta, realmente no tiene tanto uso para gráficos. Y como resultado, se ha descuidado con toda honestidad. Por lo que GraphX todavía está construido en RDD. Sin embargo, otra razón para aprender RDD, existe un paquete alternativo llamado
marcos de gráficos que se basa en la nueva API de DataFrame. Pero en realidad no se ha lanzado todavía. Es versión set como 0.8 la última vez que revisé. Entonces en algún momento podríamos ver los marcos gráficos reemplazados por gráficos y chispa, pero por ahora tenemos los gráficos basados en RDD para trabajar. Y encontrarás que el código gráfico se parece mucho cualquier otro código de chispa RDD en su mayor parte. Y en realidad una vez que tienes un gráfico construido, tratar con él se ve un montón horrible como Spark SQL de todos modos, así que no es tan malo como suena. Crear un vértice RDD es bastante sencillo, en realidad. Solo tienes que devolver una tupla que incluya un ID de vértice, algún identificador numérico único como su primer campo. Y cualquier dato que quieras asociar con eso en este pequeño fragmento de código aquí que estamos tomando de nuestro ejemplo. Estás viendo que en realidad estamos envolviendo eso en una opción. Y así es como tratamos los valores nulos en Scala. Realmente no hablábamos de eso antes, pero ves que estamos definiendo una opción de un ID de vértice y una cadena, y eso significa que tenemos la opción de devolver nada. Entonces verás que en el caso en que tengamos un resultado válido, estamos devolviendo algunas con una tupla que consiste en un ID de vértice y los datos asociados a ese vértice. Si tenemos una entrada inválida ahí, no devolvemos ninguna. Y eso sólo significa que no hay resultados. Es básicamente el equivalente de Scala de null. Y esto es útil porque si estás llamando a FlatMap en un RDD y tu función devuelve ninguna, eso solo se descarta y eso está bien. Entonces esa es una forma de lidiar con el caso de no devolver nada de una operación de FlatMap. En el caso de nuestros datos, tuvimos que tener algunas líneas de datos que no son válidas. Resulta que cualquier ID de héroe por encima de 6486 no es un personaje real, por lo que necesitamos descartar esos. Y ese es el caso donde no devolvimos ninguno en este caso. Crear un borde también es bastante sencillo. Todo lo que haces es crear un objeto de borde que contenga una lista de los nodos que conecta. Entonces en este ejemplo aquí puedes ver que estamos creando un borde entre
un ID de héroe dado que inicia el inicio de
una línea en nuestro archivo de datos para el conjunto de datos de superhéroes de Marvel. Y construimos una nueva arista entre eso en cada superhéroe que,
ese Héroe está conectado, definimos por esa línea de texto. Entonces un filo, muy sencillo. Es solo un objeto de borde que consta de dos identificadores de vértices y alguna información adicional que quizás quieras asociar con eso también. Bastante sencillo otra vez. Y construir una gráfica, de nuevo, eso es sencillo. Simplemente construyen un objeto gráfico y lo construyen con la lista de vértices que se quiere tener en él, esos dos bordes entre esos vértices. Y eso es más o menos. Probablemente querrás guardar en caché esa gráfica porque probablemente
vas a querer hacer un montón de operaciones en ella. Y al almacenarlo en caché eso asegura que permanecerá en la memoria, lo que puede ayudar a generar cosas optimizadas cuando haces cosas con ese gráfico más adelante. Por lo tanto, hacer cosas con un gráfico también es bastante sencillo una vez que lo tienes construido, aunque a veces es útil ver algún código de muestra para empezar. Por ejemplo, si quieres llevarte a los 10 héroes más conectados, podríamos llamar al doctor gráfico acepta para obtener esos grados de conectividad y unirte a los que tienen los propios vértices. Ordenar los resultados dados por el campo que corresponde al número de conexiones que tienen en orden descendente. Toma el top 10 y listo. Entonces esa es una manera fácil de averiguar quiénes
son los superhéroes más conectados en solo una línea de código una vez que hayas construido esos objetos de gráfico, tan poco más fácil. La sintaxis es un poco más difícil de seguir aquí, así que es un poco fuera del jurado, creo, sobre si esa es en realidad una forma más directa de codificarla, pero funciona. Entonces esa es una forma de usar GraphX. Pero como dijimos antes, es mucho más flexible cuando
presentamos la API de Pregel encima de GraphX. Entonces hablemos de eso a continuación y cómo podemos realmente extender la gráfica x para
duplicar los resultados que obtuvimos en nuestro ejemplo de grados de separación antes en el curso.
63. Cómo usar la API de Pregel con Spark GraphX: Entonces, vamos a explorar con más profundidad cómo la API de Pregel nos da más flexibilidad. Además de los gráficos, en realidad
podemos recrear lo que hicimos con el algoritmo de
búsqueda primero de amplitud en encontrar los grados de separación entre dos superhéroes cualquiera en nuestra gráfica de superhéroes de Marvel que aparecen juntos y cómics. Y la forma en que Pegel trabaja a un nivel alto es básicamente cada vértice tiene la capacidad de enviar mensajes a todos sus vértices vecinos. Y cada gráfica se procesa entonces en una iteración llamada superpaso. Y en cada superpaso, suceden tres cosas. Los mensajes de la iteración anterior van a ser recibidos por cada vértice. A continuación, cada vértice ejecutará un programa para transformarse en base a esos mensajes. Y entonces cada vértice enviará mensajes a otros vértices si quiere ser recogido en el siguiente paso. Y si recuerdas cómo implementamos el algoritmo de búsqueda primero de amplitud, probablemente ya
estés pensando, Hey, eso mapea bastante bien a cómo funciona ese algoritmo. Y de hecho lo hace. Entonces podemos inicializar nuestra gráfica de manera bastante simple aquí, si recuerdas bien, solo
empezamos estableciendo todas las distancias al infinito excepto el punto de partida desde el que estamos midiendo las distancias. Y para eso vamos a fijar la distancia a 0, claro, porque la distancia entre algo y sí es 0. Podemos hacer eso con una sola línea de código y gráficos. Podemos decir simplemente los vértices del mapa de puntos del gráfico y comprobar si el ID es igual a la idea del héroe que queremos empezar desde el lugar desde el que estamos midiendo. Si es así, establecemos la distancia inicial en 0. De lo contrario establecemos ese vértice atributos a infinito positivo. Y luego aprovechamos
esa capacidad de mensajería para abanicarnos de esas notas iniciales. Por lo que partimos desde nuestro punto de partida inicial ahí. Y tenemos retro agregar un poco de código para definir lo que sucede mientras enviamos esos mensajes durante ese paso de mensajería. Entonces en este caso, estamos buscando nodos que no sean infinito positivo, uno que acabamos de procesar. Y para esos, vamos a abanicarnos a sus ID de destino, sus vecinos, pasando por el atributo de ese nodo inicial más 1. Entonces eso va a aumentar el conteo de distancia a medida vamos y mandar esa siguiente ronda y mensajes para ese superpaso. Por lo que esencialmente, Pregel se abrirá paso a través de esta gráfica, abanizando su salida. Y en el camino se busca nodos que no son infinitos. Y sigue adelante y los aficiona más allá, incrementando la distancia a medida que encuentra su salida. Entonces Pregel maneja un poco muchas de ellas mecánicas de atravesar el gráfico para nosotros, lo cual es útil para algo como esto. Ahora no te pongas demasiado colgado si no estás siguiendo esto, probablemente nunca vas a tener que hacer exactamente
este mismo algoritmo y el mundo real, ¿verdad? El punto más grande aquí sin embargo es que si tienes un gráfico de información que necesitas procesar en Spark, y las capacidades integradas de los gráficos no hacen lo que quieres. En ocasiones la API de Pregel te permitirá
hacerlo si solo piensas un poco más creativamente en profundidad al respecto,
es solo otra herramienta para tener en tu cofre de herramientas. La otra cosa que tenemos que hacer en BFS se conserva la distancia mínima en cada paso. Por lo que queremos asegurarnos de que no estamos retrocediendo sobre nosotros mismos y obteniendo estas distancias erróneamente altas entre nodos porque encontramos estos caminos más largos para llegar allí. Por lo que podemos escribir un programa de vértices que comprobará por eso. Y preservará la distancia mínima entre el que recibe y lo que tiene. Entonces a medida que recibe esos mensajes de sus nodos vecinos, si está consiguiendo una distancia que en realidad es más grande que la que ya hay ahí dentro, preservará la más pequeña de esas dos distancias. Y además, hacemos una operación de reducción también. Entonces si realmente tenemos múltiples mensajes recibidos para el mismo vértice en el mismo pase, eso también atrapará ese caso y preservará la distancia mínima en ese caso también. Por lo que ponerlo todo en conjunto es bastante sencillo. No es un montón de código en realidad. Por lo que podemos decir simplemente definir nuestro gráfico inicial y gráficos con la distancia establecida en 0 donde estamos empezando con lo contrario es infinito. A continuación llamamos gráfico inicial punto Pregel. Y esa llamada de función nos permite
definir todos los atributos de partícula que necesitamos. Por lo que pasamos en ese programa de vértices que mantiene que
siempre conservamos el valor mínimo recibido para la distancia ahí. Configuramos ese sistema de mensajería donde decimos que vamos a buscar nodos
no infinitos y fan son formas de salir de ellos incrementando esa distancia a medida que avanzamos. Y por último, tenemos esa operación de reducción que dice si tienes más de un mensaje entrando a la vez, nuevo, vamos a preservar la distancia mínima que está entrando. Por lo que esos tres componentes de regular pasaron como una sola función llaman a la API de Pregel ahí. De nuevo, tenemos el programa de vértices. En primer lugar, tenemos la función de mensajería, y después tenemos la operación de reducir. Y eso es todo lo que necesitas hacer. Entonces salgamos y realmente veamos si funciona.
64. [Actividad] los grados de superhéroes de la separación con GraphX: Entonces, sumémonos y usemos el poder de los gráficos y Pregel para resolver nuestro problema de grados de separación usando gráficos. Entonces abre el guión gráfico aquí y echaremos un vistazo. Veamos qué está pasando aquí. Es un poco más simple que la implementación basada en RDD, pero todavía hay una cantidad justa de código de que hablar aquí, ¿verdad? Entonces vamos a pasar por ello. Entonces saltemos a la función principal y empecemos por ahí. Nosotros montamos nuestro contexto Spark es el tiempo. Recuerda, GraphX todavía está construido en la API RDD, por lo que no estamos usando una SparkSession aquí. Estamos usando un SparkContext en su lugar. Nuevamente, hay una nueva versión llamada frames de grafo en desarrollo, pero aún no se ha lanzado oficialmente. Por lo que de nuevo, los gráficos un poco descuidados, pero los marcos de gráficos esperemos que esté en camino. No obstante, los gráficos siguen siendo útiles y como puedes ver, no
es tan difícil de usar. Entonces empezamos leyendo aquí en el archivo de nombres de tablero de Marvel,
y llamamos aquí a la función de nombres de análisis con un FlatMap. Se puede ver que todo está pasando aquí. Entonces devolviendo una tupla del id del vértice, que es nuestro ID de superhéroe, y una cadena que corresponde al nombre de esa ID. Nada de fantasía. Acabamos de dividirlo en base al carácter de cita ahí para extraer el nombre. Y si tenemos más de un campo, solo
hacemos un pequeño chequeo de cordura en los datos ahí. Recortamos ese campo inicial hacia abajo para despojar cualquier espacio extraño convertido en un entero largo. Y comprueba que sea una identificación válida. Si es así, devolvemos ese entero junto con el nombre de ese héroe que está asociado a ese ID. Y de nuevo, estamos usando el formato de opción aquí para decir que ninguno es un resultado válido. Entonces al decir suma, eso significa que esta función devuelve un resultado válido, pero también podemos devolver ninguno. Podría ser que esta línea represente un ID de héroe inválido o datos formateados incorrectamente. Y en ese caso al devolver el valor ninguno como parte de nuestra opción ahí, eso le dice a FlatMap que solo queremos ignorar esa línea y
no agregar nada al RDD resultante. A continuación, ¿qué hacemos? Construimos nuestros bordes. Entonces ahora vamos a analizar el archivo de Marvel dash graph dot txt. Y como recuerdan, eso es sólo una lista de líneas que tienen una identificación aquí seguida de una lista de todas las identificaciones en ese Héroe se ha visto con en el mismo cómic. Entonces hacer bordes se encarga de eso. Aquí tampoco está pasando mucho. Básicamente tomamos esa línea de entrada entera es una cadena y devuelve una lista de bordes que consta de enteros que corresponden a identificadores de vértices reales para cada héroe. Entonces vamos a construir aquí un búfer de lista y poblar esa lista con objetos de borde. Entonces este es básicamente el formato que el gráfico x va a esperar de nosotros. Dividimos esa línea de entrada sin procesar en campos individuales. Y por cada campo que
tenemos, extraemos el primero que va a ser nuestro origen, el del que estamos hablando. Y luego para cada campo posterior, creamos un nuevo objeto de borde que consiste el ID de vértice del superhéroe del que estamos empezando,
y el ID de vértice de cada conexión que tiene ese Héroe. Luego regresamos la lista de bordes resultante de vuelta a nuestro guión principal aquí. Entonces ahora podemos construir el gráfico en sí, lo cual es bastante sencillo. Simplemente construimos un nuevo objeto gráfico, dándole la lista de vértices y aristas que especificamos. Y sólo estamos pasando en esos vértices como tuplas básicamente donde el primer valor es el ID de vértice. Eso es algo válido para hacer aquí. Eso sólo funciona. Y cobramos la gráfica resultante porque presumiblemente vamos a hacer mucho trabajo con esa gráfica y queremos mantener eso en la memoria. Como vimos en las diapositivas, podemos calcular rápidamente los 10 superhéroes más conectados con esta única línea de código que acabamos de llamar a doctor gráfico acuerdo y uniéndonos a toda la lista de vértices, lo que significa que queremos obtener las conexiones para cada vértice que conocemos y ordenar los resultados resultantes por el campo que corresponde al número de conexiones. Toma el top 10, imprímelos, eso es todo. Y ahora en realidad podemos hacer búsqueda de ancho primero usando Pregel, que en realidad no es tan difícil. Entonces empezamos definiendo aquí el ID de nuestro vértice raíz. Por lo que resulta que sabemos que el vértice ID 5306 corresponde a Spider-Man. Y podemos iterar a través de la computación de las distancias si todos a Spiderman. Ahora, empezamos inicializando la gráfica. De nuevo, sólo hacemos una operación de vértices de mapa aquí, comprobando cada vértice y viendo si el ID es igual a Spiderman. Si es así, establecemos la distancia inicial en 0, lo contrario la establecemos en infinito. Y ahora en este solo mando, montamos todo el mundo Pregel, si se quiere. Llamamos gráfica inicial punto Pregel y pasamos en esta función que contiene, primer lugar, nuestro programa de vértices. Entonces nuevamente, su propósito en la vida es solo mantener la distancia mínima a medida que se reciben mensajes entre el mensaje entrante y el valor actual de un nodo dado. También definimos nuestro SendMessage, como ya hablamos antes. Eso se va a propagar a todos los vecinos con la distancia incrementada en uno. Entonces para cualquier nodo que sí tenga una distancia actual asociada a ella, nos
encontramos incrementando esa distancia a medida que avanzamos. Y por último, definimos una operación de reducción que preservará el valor mínimo de esos mensajes recibidos por un vértice si se reciben
múltiples mensajes por un vértice en el mismo paso. Por lo que tenemos aquí dos bits diferentes que pueden contener que siempre mantenemos esta distancia más corta que encontramos al atravesar la gráfica. Y este pequeño fragmento aquí define cómo atravesamos la gráfica e incrementamos esa distancia por una con cada pasada. En ese punto, podemos salir y simplemente imprimir los 100 primeros resultados ahí. Podemos decir vértices de punto BFS, punto unir verts otra vez, sólo diciendo que queremos evaluar esa gráfica en todos nuestros superhéroes. Toma el top 100 e imprímelos y ya veremos cómo se ve. Y si queremos recrear específicamente los resultados de nuestros grados de ejercicio de separación que usamos para usar RDD sin gráficos, solo
podemos hacer una pequeña operación de filtro ahí para arrancar el resultado para superhéroe ID 14, que es el átomo del personaje 3,031 e imprime esa línea específicamente. Entonces vamos a patear esto y a ver si funciona. Gráficos corren. Y lo que es genial es que también es bastante rápido. Entonces una vez que se ponga en marcha, no deberíamos tener que esperar demasiado. Fuera va. Y tenemos nuestro top 10 más conectado y tenemos nuestros grados de separación. Entonces si recuerdo bien, eso es mucho más rápido que en realidad nuestra implementación solo usando RDD directo. Por lo que GraphX obviamente está haciendo algunas optimizaciones bastante geniales. También están bajo el capó. Comprobemos nuestros resultados, asegurémonos de que tengan sentido. Entonces me voy a desplazar hacia arriba. Top 10 más conectado al máximo resultado sigue siendo Capitán América. Eso es lo que vimos antes en el curso. Para que cheques y grados de separación de Spiderman para todos. Curiosamente, es uno o dos para todos. Yo creo. Sabes que la leyenda de que todos están conectados con Kevin Bacon es probablemente cierta, ¿verdad? Ah, parece que boom es en realidad bastante lejos tenía tres. Él es más oscuro. Aún más oscuro que Adán, 3.031, que vuelve de nuevo como dos grados de separación de Spiderman. También el mismo resultado que obtuvimos antes. Entonces eso es bastante emocionante. En realidad obtuvimos el mismo resultado. Funciona. Y esto es un poco más de una forma de calcular con principios y directa esa operación gráfica para grados de separación usando GraphX y la API de Pregel. Y con eso, hemos cubierto todos los componentes centrales de Spark. Entonces felicitaciones, con GraphX, estamos envolviendo las cosas. Entonces hablemos de dónde ir desde aquí.