Apache Spark 3 com Scala: pratique com Big data! | Frank Kane | Skillshare

Velocidade de reprodução


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Apache Spark 3 com Scala: pratique com Big data!

teacher avatar Frank Kane, Machine Learning & Big Data, ex-Amazon

Assista a este curso e milhares de outros

Tenha acesso ilimitado a todos os cursos
Oferecidos por líderes do setor e profissionais do mercado
Os temas incluem ilustração, design, fotografia e muito mais

Assista a este curso e milhares de outros

Tenha acesso ilimitado a todos os cursos
Oferecidos por líderes do setor e profissionais do mercado
Os temas incluem ilustração, design, fotografia e muito mais

Aulas neste curso

    • 1.

      Introdução

      1:28

    • 2.

      Instalando os materiais do curso

      13:54

    • 3.

      Introdução ao Apache Spark

      14:26

    • 4.

      [de idade

      25:58

    • 5.

      Controle de fluxo no Scala

      9:28

    • 6.

      Funções no Scala

      9:08

    • 7.

      Estruturas de dados no Scala

      22:28

    • 8.

      A data de Resilient e Resilient

      11:30

    • 9.

      Exemplo de histograma

      11:27

    • 10.

      Internals internais

      1:59

    • 11.

      Exemplo de de amigos média por época

      10:42

    • 12.

      Exemplo de [a atividade] de qual de amigos médias por idade

      4:51

    • 13.

      Como filtragem

      5:54

    • 14.

      [de atividade] tendo o exemplo de temperatura mínima e modificá-lo para o máximo

      11:35

    • 15.

      [de atividade] contando as Occurrences de palavra usando Flatmap()

      5:46

    • 16.

      [de atividade] melhorando o script de contagem de palavras com expressões regulares

      3:44

    • 17.

      [de idade

      6:35

    • 18.

      [Exercício de ano

      4:30

    • 19.

      [Exercício de exercício de a sua consulta e Sort por o valor total de o tempo de visita

      5:09

    • 20.

      Confira seus resultados e implementação em

      3:00

    • 21.

      Introdução ao SparkSQL

      9:44

    • 22.

      [de atividade

      7:05

    • 23.

      [de qual pessoa [Activity]

      8:33

    • 24.

      [Exercício de vocês

      2:40

    • 25.

      Solução de exercício: amigos por idade, com o conjunto de dados

      7:22

    • 26.

      Exemplo de contagem de de de em Word

      10:37

    • 27.

      [de atividade, Revisando o exemplo de mínimo de temperatura, com o Datasets

      9:00

    • 28.

      [Exercício para Implement no problema de "gasto de cliente " com Datasets

      2:10

    • 29.

      Solução de exercício: total de pasto por cliente com datasets

      6:28

    • 30.

      [de idade

      5:24

    • 31.

      [de atividade] use variáveis de transmissão para exibição de nomes de cinema

      11:19

    • 32.

      [de atividade, encontre o superherói mais popular em um gráfico social

      12:18

    • 33.

      [de exercício ] encontre os Superheroes mais obde

      5:14

    • 34.

      Solução de exercício: encontre os Superheroes mais obde

      6:44

    • 35.

      Graus de separação de heróis: introduz a primeira pesquisa

      7:14

    • 36.

      Graus de separação de superherói

      7:59

    • 37.

      [de atividade] de superheróis de separação: revise o código e run o !

      12:55

    • 38.

      Filtração colaborativo com a origem em Spark, cache() e persiste ()

      7:59

    • 39.

      [de idade de televisão semelhante usando o cluster de Spark.

      14:48

    • 40.

      [Exercício de exercício de a qualidade dos filmes semelhantes

      3:54

    • 41.

      [de ação] use o de spark-submit para executar scripts de Spark

      11:43

    • 42.

      [de atividade em atação

      15:06

    • 43.

      [Exercício em uma Script com SBT e de o execute de o de o seu de presente

      2:04

    • 44.

      Solução de exercício: usando o SBT e o de spark-submit

      9:04

    • 45.

      Introduzindo o Amazon Elastic

      7:11

    • 46.

      Crie filmes semelhantes de um milhão de classificações no EMR

      11:33

    • 47.

      Partição

      4:18

    • 48.

      Best Práticas para a execução em um cluster

      6:25

    • 49.

      Solução, como resolver os problemas e gerenciar as dependências

      10:59

    • 50.

      Introduz o MLLib

      9:55

    • 51.

      [de atividade] usando o MLlib para produzir recomendações de cinema

      12:42

    • 52.

      Regression linear com MLLib

      6:58

    • 53.

      [de ação] tendo um efeito linear com o Spark

      7:47

    • 54.

      Prede valores com o início com o Decreto no Spark

      4:56

    • 55.

      Solução de exercício: prevendo uma propriedade com as árvores de decisão com centel

      5:47

    • 56.

      A API DStream para transmissão de Spark Streaming

      11:28

    • 57.

      Monitoramento em tempo real das Hashtags mais populares no Twitter

      8:51

    • 58.

      Streaming estruturado

      4:03

    • 59.

      [de idade estruturado

      5:33

    • 60.

      [de exercício compartilhado com o Streamer estruturado

      6:04

    • 61.

      Solução de exercício: uma URL de top em uma janela de 30 segundos

      5:44

    • 62.

      GraphX, Pregel, e primeiro primeiro pesquisa com Pregel.

      6:51

    • 63.

      Usando a API de pregel com o Spark GraphX

      4:29

    • 64.

      [de superherói de separação usando GraphX

      7:07

  • --
  • Nível iniciante
  • Nível intermediário
  • Nível avançado
  • Todos os níveis

Gerado pela comunidade

O nível é determinado pela opinião da maioria dos estudantes que avaliaram este curso. Mostramos a recomendação do professor até que sejam coletadas as respostas de pelo menos 5 estudantes.

617

Estudantes

--

Projetos

Sobre este curso

Novas! Atualização para o Spark 3!

A análise de grande dados é uma habilidade quente e altamente valiosa — e este curso vai ensinar a tecnologia mais quente em grande dados: Apache Spark. Empregadores, incluindo o Amazonas de EBay, NASa JPL, e Yas a ferramenta use a ferramenta de gravação e o Yahoo, use o Spark de is a Você vai aprender essas mesmas técnicas, usando o sistema do de Windows de É mais fácil do que você de pensamento, e vai aprender com um ex-engenheiro e gerente de alta os profissionais da Amazon e IMDb.

Spark funciona de melhor ao usar a linguagem de programação do Scala e este curso inclui um curso de crash-course no Scala para fazer você a velocidade Para para quem de python está disponível em python em python neste curso também está disponível: "de Onea e em eles há quem de

Aprenda e a a arte de criar como estruturar os problemas de análise como o Spark em mais de 20 exemplos de mãos na a cada dia e escame para a medida para serem criados em serviços de computação em nuvem neste curso.

  • Aprenda os conceitos de as de data resilientes

  • Obtenha um curso de colagem na linguagem de programação de Scala

  • Desenvolva e execute no Spark rapidamente usando a Scala

  • Traduzir problemas de análise em iterativo ou em vários a etapa de Spark

  • Esporte para conjuntos de dados maiores usando o serviço de elástic MapReduce

  • Entenda como Hadoop YARN distribuem o Spark em clusters de computação

  • Pratique o uso de outras tecnologias de fade de Spark SQL, DataFrames , DataFrames , like Spark Streaming e GraphX

Ao final deste curso, você vai executar o código que analisa a de gigabytes de informação na nuvem - em alguns minutos.

Vamos passar algum divertimento ao caminho. Você vai se aquecer com alguns exemplos simples de usar do Spark para analisar dados de rating de cinema e texto em um livro. Depois que você tiver os conceitos básicos em sua cinto, vamos passar para algumas tarefas mais mais básicas e interessantes. Vamos usar um milhão de classificações de filmes para encontrar filmes que são de um ano de em a si de outro, e pode até que ele possa descobrir um novo de filmes que você possa gostar no processo! Analisaremos um gráfico de superheróis e aprenda que o superherói mais "de popular é , e desenvolver um sistema para encontrar "graus de separação! entre os superheroes, entre o superheroes. heres. Todos os superheróis de marvel em alguns graus em de se conectar com SpiderMan? Você vai encontrar a resposta.

Este curso é de mãos isto; você vai passar a maior tempo em seguindo com o instrutor enquanto escrevemos , analisamos e analisamos o código real em conjunto. 7,5 horas de conteúdo em vídeo é incluído com mais de 20 exemplos de crescente de sua crescente complexidade que você pode criar, executar e estudar. MovEste de eles no seu próprio ritmo, em seu próprio calendário. O curso de course de outras tecnologias baseadas no Spark, incluindo o Spark SQL, Spark Streaming e Graph.

Insira agora e aproveite o curso!

"estudei o Spark pela primeira vez usando o curso de Frank's "Apache Spark 2 com Scala - Hands on com Big Data!!". Foi um ótimo ponto de partida para mim , adquira conhecimento no Scala e exemplos de aplicação de Spark Estrelas de marca Em alguns meses de conclusão, usamos o conhecimento adquirido do curso para propor na minha empresa atual para trabalhar principalmente em aplicações do Spark. Desde a partir de então eu continuo a trabalhar com o Spark. Recomendo qualquer um de cursos de Franks como ele simplifica os conceitos e o seu método de ensino é fácil de seguir e continuar! " - Joey Faherty

Conheça seu professor

Teacher Profile Image

Frank Kane

Machine Learning & Big Data, ex-Amazon

Professor

Frank spent 9 years at Amazon and IMDb, developing and managing the technology that automatically delivers product and movie recommendations to hundreds of millions of customers, all the time. Frank holds 17 issued patents in the fields of distributed computing, data mining, and machine learning. In 2012, Frank left to start his own successful company, Sundog Software, which focuses on virtual reality environment technology, and teaching others about big data analysis.

Visualizar o perfil completo

Level: Beginner

Nota do curso

As expectativas foram atingidas?
    Superou!
  • 0%
  • Sim
  • 0%
  • Um pouco
  • 0%
  • Não
  • 0%

Por que fazer parte da Skillshare?

Faça cursos premiados Skillshare Original

Cada curso possui aulas curtas e projetos práticos

Sua assinatura apoia os professores da Skillshare

Aprenda em qualquer lugar

Faça cursos em qualquer lugar com o aplicativo da Skillshare. Assista no avião, no metrô ou em qualquer lugar que funcione melhor para você, por streaming ou download.

Transcrições

1. Introdução: E eu passei mais de nove anos na Amazon.com e IMDB.com fazendo sentido de seus conjuntos de dados maciços. E quero ensiná-los sobre a tecnologia mais poderosa que conheço para disputar Big Data na Nuvem hoje. Esse é o Apache Spark, usando a linguagem de programação Scala faísca e corre para cluster Hadoop para distribuir tarefas massivas de análise de dados e aprendizado de máquina na nuvem. E saber como fazer isso é uma habilidade muito quente para ter agora, vamos começar com um curso intensivo na linguagem de programação Scala. Não se preocupe, é muito fácil pegar desde que você tenha feito alguma programação ou script antes. Vamos começar com alguns exemplos simples, mas trabalhar nosso caminho até exemplos mais complicados e interessantes usando conjuntos de dados maciços reais. No final deste curso, você terá ido práticos com mais de 15 exemplos reais. E você ficará confortável em escrever, depurar e executar seus próprios aplicativos Spark usando Scala. E alguns deles são muito divertidos. Vamos olhar para uma rede social de super-heróis e usar esses dados para descobrir quem é o Kevin Bacon do universo de super-heróis. Também analisaremos um milhão de classificações de filmes de pessoas reais e construiremos um mecanismo de recomendação de filmes real que é executado em um cluster do Spark na nuvem usando o serviço Elastic MapReduce da Amazon. Também faremos algumas grandes tarefas de aprendizado de máquina usando a biblioteca Sparks ML Lib. E vamos fazer alguma análise de gráficos usando a biblioteca Spark GraphX. Então tente comigo. Eu acho que você vai se surpreender com a forma como apenas algumas linhas de código podem iniciar um trabalho de análise de dados complexo massivo em um cluster usando o Spark. Então vamos começar. A primeira coisa que precisamos fazer é instalar o software que precisamos. Então vamos tirar isso do caminho agora. 2. Instalando os materiais do curso: Então vamos configurar tudo, incluindo Java e inteligência e todos os materiais de curso que precisamos para todo o curso. O que vamos fazer é começar acessando nosso próprio site aqui, que irá direcioná-lo para os materiais do curso onde você pode baixar todos os arquivos do projeto e os dados que você precisa para este curso. Iremos em frente e instalaremos isso no seu sistema. Em seguida, instalaremos um Java Development Kit se você ainda não tiver um, só precisamos ter certeza de que temos um JDK entre as versões oito e 14 instalado no seu sistema. As probabilidades são que se você é um desenvolvedor, você já faz. Depois disso, vamos instalar a ideia IntelliJ Community Edition. É um ambiente de desenvolvimento livre que pode, podemos usar para Scala e para Spark. E a beleza disso é que ele também integra algo chamado SBT. Então obteve uma alça todo o trabalho sujo de realmente instalar o Apache Spark para nós no Windows, nós temos um passo extra. Precisamos fingir janelas para pensar que ele está executando o Hadoop e eu vou te mostrar como fazer isso. Não é muito difícil. E finalmente, vamos montar nosso projeto na inteligência. Execute um pequeno problema helloworld simples no Apache Spark. Certifica-te de que está tudo a funcionar. Vamos mergulhar e eu vou te guiar por tudo isso. Então vamos começar por ter tudo configurado que você precisa para este curso. Dirija-se à mídia Dotson dog, um traço soft.com barra Spark scala dot HTML. Preste atenção à maiúscula e cada letra conta. E você deve chegar a esta página aqui que contém tudo o que você precisa para começar. Mas o mais importante, vamos instalar os materiais do curso, todos os scripts que você precisa para realmente passar por este curso prático. Vá em frente e clique neste link aqui para imediato Dotson cão traço, soft.com barra faísca Scala slash faísca curso Scala zip ponto. Se você estiver digitando isso à mão por algum motivo, certifique-se de prestar atenção à capitalização. Uma vez que descarrega. Vamos em frente e descompactá-la. E no Windows eu posso simplesmente ir em frente e clicar com o botão direito do mouse que e dizer extrair tudo. Em um Mac ou Linux, é claro, você iria a um prompt de terminal e usaria o comando unzip. E devemos obter é uma pasta curso Scala faísca dentro de uma pasta curso Scala faísca, Isso está correto. Isso é o que queremos. E dentro desse segundo nível de pasta está todos os materiais em si, todo o projeto para este curso. Então, primeiro, vamos levar isso para um lugar onde não vamos perdê-lo. Então eu estou pegando aquela pasta de curso de gala Sparks de nível superior e eu vou movê-la para um lugar seguro. Vamos colocar na minha unidade C. Tudo bem, então agora na minha unidade C eu tenho uma pasta de curso Scala faísca. E dentro disso há outra pasta de curso de gala faíscas. E no Mac ou Linux, é claro que você não teria um diretório C. Você colocaria no seu diretório pessoal, algum lugar onde você não vai perdê-lo. Certo, então a seguir precisamos obter alguns dados de teste aqui. E, infelizmente, os termos de licença dos dados que eu gosto de usar não me permitem incluí-los eu mesmo. Então você vai ter que ir e fazer o download você mesmo. Esse é o conjunto de dados MovieLens aqui. Para criar 100 mil classificações de filmes lá que vamos usar para jogar ao longo deste curso. Então você pode usar este link dandy útil para obtê-lo arquivos doc Grouplens.org barra dados barra barra MovieLens barra ML traço 100, k dot zip. Vá em frente e baixe isso. E se por algum motivo o site do Grouplens.org estiver inativo, isso acontece de tempos em tempos. Você geralmente pode encontrar o arquivo M L dash 100 K no Kaggle se você precisar. Vamos em frente e descomprimir isso também. Clique com o botão direito do mouse Mais uma vez, basta usar o comando unzip no Mac ou Linux. E a pasta MLH1 100 K resultante deve conter esse material. Vamos tomar esse nível aqui e vamos copiar isso. E eu vou voltar para a minha pasta de materiais do curso que eu acabei de criar, que para mim foi ver faíscas curso Scala. E no diretório do curso de gala de outras faíscas sob o qual há uma pasta de dados. Vá para a pasta de dados e é aí que eu quero colocar minha pasta AML traço 100 K. Tudo bem, então é assim que as coisas devem olhar neste ponto, se você é qualquer sistema operacional em que você está, você quer uma pasta de curso Scala faísca. Dentro disso, deve haver outra pasta de curso Spark Scala. Dentro disso deve ser uma pasta de dados. E dentro disso deve ser uma pasta ML traço 100 K. E dentro disso devem estar todos esses dados de teste. Ok, então certifique-se de que tudo parece certo ou então você vai ter problemas estranhos e você não vai saber o que está acontecendo. Assim que tiver certeza de que está tudo bem, vamos voltar para nossas instruções aqui. próximo passo é instalar IntelliJ a, que será nosso IDE para desenvolvimento neste curso. Agora eu costumava dizer às pessoas para instalar o Eclipse e o Scala IDE, mas parece que inteligente está ganhando a batalha que eles estão contra o eclipse. Então, vou ter que instalar o IntelliJ J agora. Agora, a fim de executar o código Scala, primeiro você precisa de um JDK e qualquer coisa entre as versões auxiliar e 14 vamos fazer para este curso. Mas se precisares de um JDK, há uma ligação aqui para o fazer. Você pode simplesmente ir para Oracle.com barra Java e ir em frente e obter o download do JDK 14 para o seu sistema operacional. Para mim, isso vai ser o Windows 64. Você precisará aceitar os termos deles. E espere que isso seja baixado. Parece que há um pequeno aviso de segurança aqui. Está tudo bem. Eu confio nele. E vamos isso descer. Vamos em frente e instalá-lo. Obviamente no Linux ou Mac você provavelmente usará um meio alternativo de obter Java. Na verdade, você provavelmente já tem Java instalado se estiver no Linux ou Mac. Então isso é provavelmente alguém que coisa específica. Vamos em frente e passar pelo instalador aqui. E uma coisa no Windows é que quando você executa código Linux como o Apache Spark no Windows, às vezes ele fica confuso quando você tem espaços em seu caminho. Então, esse espaço entre o programa e os arquivos pode realmente ser um problema. Vamos mudar isso só por segurança. E eu vou dizer isso em vez disso em um diretório C dois-pontos JDK 14. Bem, deixe isso fazer a sua coisa. Não deve demorar muito. E nós terminamos. Tudo bem, terminamos com esse site, volta às nossas instruções. Então agora podemos instalar a idéia IntelliJ Community Edition. Essa vai ser a nossa identidade real. Vamos em frente e clicar nesse link. E queremos a edição comunitária, a gratuita, a de código aberto. Não precisamos do último. Então vá em frente e baixe isso para qualquer que seja o seu sistema operacional. Você vê a oferta que para Windows, Mac e Linux. E isso é cerca de meio show. E então vamos demorar alguns segundos para descer. Volte quando isso acabar. Certo, o instalador baixou e vamos começar. E instalador bastante padrão aqui. Vamos em frente e apenas passar por ele. E se você quiser atalhos da área de trabalho ou como associações de arquivos, você pode fazer isso totalmente com você. Vou deixar estes como estão. E isso é bom também. Demora cerca de um minuto para instalar, então voltarei quando estiver feito. Tudo bem, bom. Vamos em frente e apertar o botão Executar para realmente iniciá-lo. Não quero importar nenhuma configuração existente. E preferência pessoal, se você gosta de um tema escuro ou um tema claro, eu gosto de um tema leve. Então eu vou selecionar isso, fazer o que você quiser embora. E agora vamos instalar plugins. Talvez o único plugin que realmente precisamos é o plugin Scala. E infelizmente eu não estou vendo isso oferecido aqui, então eu vou apenas seguir em frente. Eu não estou vendo isso oferecido aqui também. Então, se você ver o plug-in Scala embora, vá em frente e aproveite a oportunidade para instalá-lo. Mas eu não fiz. Então eu tenho a ver com a maneira difícil, que não é tão difícil. Vou apenas clicar no botão Configurar aqui na tela de boas-vindas e selecionar Plugins. E de lá eu posso encontrar o plugin Scala. Vamos em frente e instalar isso. - Tudo bem. Tudo bem, e podemos reiniciar o IDE para pegar isso. E agora mais uma coisa precisamos dizer qual JDK usar. Então volte para o menu de configuração aqui e vá para a estrutura para novos projetos. E se você precisar selecionar um JDK aqui, selecione o que acabamos de instalar, que será 14 para nós e clique em Ok. Agora, há mais um passo que precisamos fazer que é apenas para o Windows. Então, se você está no Mac ou Linux, você pode, você pode ignorar este próximo passo, precisamos tipo de janelas de truque para pensar que o Hadoop está sendo executado nele. E para fazer isso, bem, é um pouco desajeitado. As instruções estão na página de materiais do seu curso aqui na seção Somente Windows aqui, basta seguir as instruções. Vá em frente e crie um diretório bin C Hadoop. Então eu vou para o meu “C drive”. Vou criar uma nova pasta chamada Hadoop. E dentro dessa pasta do Hadoop, vou criar outra pasta chamada bin. Agora vou voltar ao meu material de curso, que está em curso de gala Sparks. E você verá um arquivo EXE quando utils dot lá. Vou copiar isso e colar no C. Hadoop. Em seguida, eu preciso configurar um par de variáveis de ambiente. Então, a maneira mais fácil de fazer isso é simplesmente ir para a barra de pesquisa do Windows aqui e digitar variáveis de ambiente. Apenas ENV é provavelmente suficiente. E selecione editar as variáveis de ambiente do sistema que o levará para o painel de controle do sistema. A partir daqui, você pode pressionar o botão de variáveis de ambiente. E nós vamos criar um novo chamado Hadoop sublinhar home all caps. E o valor será C dois pontos barra invertida, Hadoop. Também precisamos editar nossa variável de ambiente de caminho. Se você não tem um, você pode fazer um, mas você provavelmente já tem um. Então eu vou apenas editar o que eu tenho um adicionar um caminho adicional para ele clicando duas vezes aqui e digitando no sinal de porcentagem, Hadoop sublinhado home percentual sinal, Isso é barra bin. Aperte OK e OK novamente e Ok novamente. Tudo bem, então agora estamos prontos, prontos para realmente tentar importar o projeto para o curso em si. Vamos voltar para o IntelliJ. Agora, antes de carregar esse projeto, é sempre uma boa idéia reiniciar seus aplicativos depois de alterar variáveis de ambiente. Então, se você estiver no Windows, vá em frente e feche fora da idéia IntelliJ e reiniciado. Deve estar no menu Iniciar. E agora vamos clicar em Abrir ou Importar. E nós queremos navegar para a pasta Materiais do Curso, faísca curso Scala e a pasta do curso Scala faísca dentro disso, esse é o nosso projeto real para o curso em si. Acerte Ok. E deixe-o fazer a sua coisa. Ele vai tentar automaticamente fazer sentido fora do que está naquela pasta. Não quero dar gorjeta. E se tivermos sorte, tudo funcionará. Está bem. Veja qualquer coisa muito alarmante, vamos bater no ícone de compilação apenas para ter certeza que ele foi construído com sucesso. É este pequeno ícone de martelo aqui em cima. Você também o encontrará no menu Construir, se preferir. E parece que funcionou. Então, vamos tentar. Vamos em frente e abrir a pasta do curso Spark Scala aqui para o projeto e, em seguida, abrir a pasta de origem. E sob isso abrir principal, e então Scala e com ponto sol ponto ponto ponto ponto faísca. Estes são todos os roteiros para o curso aqui. Então tudo o que temos que fazer é escolher um e ver se funciona. Incluí um roteiro muito simples do Helloworld. Então vamos clicar duas vezes sobre isso. E você pode ver aqui ele não está fazendo muito, mas ele está realmente usando o Apache Spark. Então ele vai realmente verificar se você tem tudo configurado corretamente e configurar o caminho certo aqui. Ele só vai configurar um SparkContext e carregar arquivo de dados dentro do nosso conjunto de dados MovieLens que instalamos anteriormente. Então isso também irá garantir que você tenha isso no lugar certo também. Tudo o que ele vai fazer é gerar um trabalho do Apache Spark para contar o número de linhas nesse arquivo. Então, uma maneira muito complicada de fazer isso, mas vai verificar se funciona. E então, quando terminar, ele vai imprimir Hello World. O arquivo de dados tem esperançosamente um 100 mil linhas porque esse é um conjunto de dados 100 mil. Então vamos ver se funciona. Basta clicar com o botão direito do mouse em HelloWorld e dizer executar hello-mundo. E neste ponto há uma boa chance de que você vai ter um erro de classe não encontrado se você fizer isso, é apenas um bug e inteligência. Se você parar de ser inteligente e reiniciá-lo, ele deve esclarecê-lo. E isso deve começar o Spark. Você verá que alguns avisos são seguros para ignorar. E agora está funcionando e funcionou. Então, aí está. Helloworld, o arquivo de dados tem 100 mil linhas. Então, se você ver isso, parabéns, você configurar Spark e Scala e inteligência em Java tudo com sucesso. E tudo está funcionando. E agora tudo o que temos que fazer é passar por todo o resto desses scripts ao longo do resto do curso e falar sobre o que eles fazem e aprender ao longo do caminho. Se você não viu essa saída embora, volte, você provavelmente perdeu alguns pontos em algum lugar. Há sempre alguma coisa pequena e sinta-se livre para postar no Q e um ou comentários deste curso para obter ajuda se você precisar dele. Mas espero que isso funcione para você e podemos seguir em frente e começar a aprender. 3. Introdução ao Apache Spark: Então deixe-me apresentá-los ao Apache Spark em um nível alto e apenas falar sobre como ele funciona e o que é para realmente rápido. Portanto, a descrição oficial do Spark é que ele é um motor rápido e geral para processamento de dados em grande escala. E bem, essa é uma descrição muito boa. Basicamente, a idéia é que você pode escrever um script muito simples potencialmente que descreve como você deseja transformar uma enorme quantidade de dados ou analisar uma enorme quantidade de dados e sparkle descobrir como distribuir esse trabalho em todo um cluster de computadores para você. Então, é um mecanismo para descobrir como paralelizar o processamento de seus dados. Você ainda pode dizer o que quer. Você sabe? Eu quero tomar em um monte de arquivos de log e extrair algumas informações e colocá-lo em outro lugar. - Tudo bem. O Spark irá descobrir como fazer isso em todo o cluster e fazer isso acontecer o mais rápido possível usando os recursos de dezenas ou mesmo centenas de máquinas individuais para fazê-lo. Portanto, a chave para isso é sua escalabilidade. Então, novamente, você apenas escreve um único programa de driver, nós o chamamos. É apenas um script simples escrito em Scala ou Python ou Java. Isso indica ao Spark o que você deseja fazer com seus dados. É então o problema do Sparks descobrir como paralelizar isso e fazê-lo escalar quase uma frota inteira de computadores. Então, a principal visão aqui é que você não está limitado ao poder de computação de uma máquina aqui com o Apache Spark, você pode pegar um, um conjunto de dados massivo que você não poderia esperar processar em um único PC e realmente distribuir esse processamento em toda uma frota de computadores em paralelo ao mesmo tempo. Esse tipo de abordagem de divisão e conquista é como podemos processar conjuntos de dados maciços e lidar com o que chamamos de big data. Do ponto de vista da arquitetura, seu programa de driver é apenas algo que você escreve. Como eu disse, é um script variado, potencialmente muito simples. E isso é entregue a um gerente de cluster de alguma loja. Você precisa de algum tipo de sistema que orquestre todo o seu cluster de computadores. E isso pode ser um cluster Hadoop, caso em que o gerenciador de cluster de fios do Hadoop estaria entrando em jogo lá. E isso vai ser preocupante sobre como gerar os recursos que você precisa, como distribuir esse trabalho e onde colocar os diferentes empregos no lugar mais ideal. Pensa em coisas como como executar o código no local onde os dados são mais acessíveis? Então, se meus dados, por exemplo, são divididos em um sistema de arquivos distribuído, o gerenciador de cluster pode dizer, ok, eu vou executar os dados que processa essa parte dos dados na mesma máquina para torná-lo executado mesmo Mais rápido. No entanto, você não precisa usar o Hadoop. O Spark também tem o seu próprio Gestor de Cluster incorporado. Portanto, se você quiser apenas executar o Spark em um ambiente autônomo, você pode fazer isso apenas para instalar o Spark e todas as máquinas em seu cluster e configurá-lo corretamente. E ele só vai funcionar assim faísca e correr por conta própria. Ele não precisa necessariamente ser executado em cima do Hadoop, embora possa. Às vezes, você desejará executar outros aplicativos do Hadoop no mesmo cluster e defini-lo pipelines de operações mais complexos. Portanto, pode haver vantagens em executar em cima do Hadoop, mas você não precisa. Então, uma máquina individual, existem diferentes nós que lhes chamamos. E estes estarão executando executores diferentes. E cada processo executivo que pode ser distribuído por todo o cluster tem seu próprio cache e tem sua própria tarefa que está tentando operar em seus dados. E você pode ver com todas as flechas aqui que praticamente tudo está falando um com o outro. Seu programa de driver envia comandos para o gerenciador de cluster e também diretamente para os executores quando necessário. E os executores estão conversando uns com os outros e sincronizando entre si. E, claro, um gerenciador de cluster também está falando com todos esses processos executores, tentando orquestrar. O que é executado onde e, em seguida, colidindo esses resultados volta juntos para obter ver o seu resultado final quando tudo estiver feito. Então essa é a arquitetura sparc em um nível muito alto. Porque é que o Spark é tão popular? Bem, o Spark está praticamente substituído. Hadoop MapReduce porque pode ser até 100 vezes mais rápido se for baseado na execução na memória. Então, se você tem memória suficiente em seu cluster, isso é uma aproximação realista. Se você estiver realmente lendo dados diretamente do disco, ele será ainda ser cerca de 10 vezes mais rápido. Por que é tão mais rápido que MapReduce? Bem, é por causa do que chamamos de um motor gráfico acíclico direcionado ou de um motor DAG. Basicamente, ele vai olhar para o fluxo de trabalho que você descreveu em seu script de driver e ele irá otimizá-lo para você automaticamente. Em contraste, no MapReduce, você está meio que preso em uma única maneira de pensar em processar dados. Você tem que mapear explicitamente todos os seus dados em paralelo e, em seguida, definir alguma maneira de reduzir esses dados de volta para uma resposta final. Com o motor DAG, porém, pode ser um pouco mais flexível. Ele pode organizar esse fluxo de trabalho de uma maneira mais complexa e potencialmente mais otimizada também. E porque o Spark é baseado em memória, isso também lhe dá uma grande vantagem. Por isso, é rápido e também é muito fácil de usar. Também é quente, é muito utilizado. Esta é, na verdade, uma lista muito antiga de pessoas usando o Spark e há muitas, muitas, muitas, muitas mais pessoas usando agora. Mas o objetivo deste slide é mostrar que é tecnologia comprovada. Está sendo usado por grandes corporações. É uma tecnologia muito madura. Está apagado há algum tempo. Você sabe, os novos recursos no Spark ou tipo de abrandar um pouco, pelo menos no mundo de código aberto. E tudo bem, porque ele faz tudo o que você precisa fazer e faz isso de forma bastante confiável neste momento. Assim, para o processamento de dados distribuídos, Spark é uma tecnologia madura e é amplamente adotada. Também não é tão difícil. Então você tem a sua escolha de escrever seu código em Python ou Java ou Scala. Obviamente, neste curso vamos nos concentrar em Scala e vamos falar sobre o porquê em um momento. Mas é fácil de usar se você conhece SQL Structured Query Language, que é a mesma linguagem que você usa para fazer interface com qualquer banco de dados relacional. Você vai se sentir em casa porque o Spark tem recursos chamados conjuntos de dados de faísca e DataFrames do Spark que operam de forma muito semelhante às instruções SQL. E você pode até dar comandos SQL diretamente por meio de um recurso chamado Spark SQL. Então, se você conhece SQL, você pode usar o Spark. É tão fácil assim. Mas nem tudo é um problema SQL. Nem todas as análises ou transformações de dados podem ser definidas por meio de um comando SQL. E se você quiser chegar a uma API de nível inferior disponível para a API original do Spark é chamada Resilient Distributed Dataset ou RDD para abreviar. Nós vamos entrar em muito mais profundidade sobre como isso funciona em um, em um momento aqui. Mas com a API RDD, você pode obter um nível mais baixo e às vezes eu posso lhe dar um desempenho ainda melhor. E também lhe dá mais flexibilidade no que você pode fazer. Mas para a maioria das tarefas comuns de transformação de dados ou análise, você provavelmente pode definir isso como um comando SQL. E, na maioria das vezes, você estará usando conjuntos de dados, dataframes ou a API do Spark SQL. Do ponto de vista da arquitetura de software, é assim que o Spark é definido, e isso remonta à arquitetura original do Sparks. As linhas têm um pouco desfocado em alguns destes nos últimos anos. Mas no seu núcleo é, bem, Spark Core e é aí que os RDD vivem, certo? Então isso é como o motor subjacente do próprio Spark. E você pode ir diretamente para a faísca Core. Veremos isso em ação. Mas há essas outras APIs de nível superior criadas sobre Spark Core também para facilitar sua vida para tarefas específicas. Quando seu Spark Streaming, isto é, é obviamente uma tecnologia muito poderosa para ingerir dados em tempo real ou quase em tempo real. Você poderia imaginar, por exemplo, ter uma frota de servidores lá fora executando seu site que estão alimentando dados para o Spark através de streaming do Spark de seus arquivos de log continuamente. E em tempo real, o Spark pode monitorar esses dados, olhar para uma janela desses dados ao longo do tempo, fornecer análises sobre essa janela de tempo e tomar alguma ação com base nela. Exemplo simples, digamos que você queira ter algum tipo de alarme em 500 erros em seu site. Você pode ter uma configuração do sistema de streaming do Spark para que os logs estejam sendo transmitidos para o Apache Spark. E em tempo real está contando quantos 500 erros existem no passado, nosso minuto passado, o que quer que você queira monitorar e tomar alguma ação se exceder algum limite. E, obviamente, operações muito mais complexas também estão disponíveis. Talvez uma aplicação mais comum seria transformar esses dados de log e colocá-los em outro lugar. Então eu poderia ter um processo de streaming do Spark que ingeriu dados de meus logs, transforma-os em algum formato que talvez o Elastic Search queira ver ou algo assim. Também temos o Spark SQL e que existem para permitir que você integre com comandos SQL do faísca para que você possa tratar faísca como um banco de dados gigante distribuído na natureza. Então, se você pode definir seus dados em termos de uma estrutura de tabela, que você geralmente pode, e você pode definir o problema que você deseja resolver em termos de um comando SQL que você provavelmente pode. Você pode apenas usar o Spark SQL para definir o que você deseja que ele faça. E Sparkle descobrir como paralelizar isso em toda uma frota de computadores. Então isso é muito excitante, certo? Ele lhe dá toda a flexibilidade de um banco de dados relacional. Mas você não está mais limitado a uma máquina. Você pode realmente escalar horizontalmente esse banco de dados. Agora, costumava ser que você tinha que escolher entre como bancos de dados NoSQL, se você quiser, computação distribuída e um grande banco de dados relacional monolítico se você não fez. E ainda há algumas limitações aqui. Lembre-se que fazer grandes junções ainda não será muito eficiente em um ambiente de servidor particionado horizontalmente. Mas você pode fazer isso se quiser escrever. Então é o melhor dos dois mundos. Agora, como eu mencionei, as linhas estão borradas em alguns casos aqui. Então, essas APIs mais modernas que vamos analisar mais tarde no Spark usando dataframes e conjuntos de dados. Eles também são muito semelhantes ao SQL em sua estrutura e como eles são usados. Então, você sabe, faz isso, você considera dataframas e conjuntos de dados parte do Spark SQL ou Spark Core. Novamente, as linhas meio borradas lá, mas as interfaces baseadas em SQL estão se tornando a maneira predominante de usar o Spark. Nós também temos ML Lib, Sparks Machine Learning Library. E se você quiser fazer aprendizado de máquina distribuído no Apache Spark, você pode fazer isso também. É um conjunto um pouco limitado de algoritmos, embora haja a maioria dos que você precisaria na prática. Então vamos olhar para isso em uma seção posterior do curso também. E isso é muito excitante, certo? Porque se você tem aprendizado de máquina que deseja processar em um conjunto de dados massivo, você não está mais limitado ao que pode fazer em uma única máquina? Existem alguns algoritmos que até hoje, você sabe, são difíceis de escalar, mas o Spark descobriu para muitos dos algoritmos de aprendizado de máquina mais populares que você pode querer usar. E finalmente, este gráfico X, não quero falar muito sobre isso. É meio que caiu no caminho. Graphx não é sobre, você sabe, gráficos e gráficos estão imprimindo, você sabe, pequenas linhas e coisas assim. São mais gráficos no sentido da ciência da computação. Então estamos falando sobre como redes de informação. Por exemplo, uma rede social onde você tem usuários conectados a outros usuários é um gráfico nesse sentido. E gráficos podem fazer coisas como, você sabe, analisar esses gráficos de informação, dizer-lhe atributos sobre isso, e permitir que você tipo de iteração através deles de uma maneira distribuída. Esse gráfico x é, novamente meio que caiu no caminho. Ele realmente não tem sido bem mantido ultimamente e existem APIs alternativas mais recentes nos dias de hoje que são mais populares. Falaremos mais sobre isso no final do curso. Neste curso, estamos usando a linguagem de programação Scala. Por que, por que estamos usando Scala? É uma linguagem meio obscura, não é? Bem, há algumas razões. Uma delas é que a própria faísca está escrita em Scala. Então, escrevendo seus scripts em Scala, você é como se aproximar de como o próprio Spark é escrito em otimizado. Então, você sabe disso, isso pode potencialmente levar a um melhor desempenho. A outra coisa é que Scala é o que chamamos de linguagem de programação funcional. E, como tal, é realmente um bom ajuste para processamento distribuído. Scala realmente impõe que você escreva seu código de tal forma que suas funções podem ser distribuídas em um cluster inteiro. Enquanto outras linguagens como Java e Python realmente não tentam forçá-lo a isso. Então, escrevendo seus scripts de driver do Spark no Scala, é mais provável que você esteja escrevendo código que possa ser paralelizado de forma segura e fácil. Ele também lhe dá um desempenho rápido. Então escala ele compila para baixo para código de byte Java. Então, no final do dia, ele está sendo executado na JVM, o interpretador Java, e isso é muito rápido na maioria dos sistemas. Obviamente, Java também lhe dará um desempenho rápido porque isso também irá compilar para baixo para códigos de bytes Java. Mas contrasta isso para escrever seus scripts de faísca em Python, o que você pode fazer. Mas você tem que passar por outra camada, certo? Assim, o código python precisa ser de alguma forma transformado em código de bytes Java no final do dia. Então, escrevendo em Scala apenas porque você deixa você um pouco mais perto desse nível inferior final onde seu código será realmente executado. Agora, para ser justo, python é muito rápido em Spark nos dias de hoje. Então a diferença não é tão grande como costumava ser, mas ainda há uma pequena diferença. A outra vantagem de Scala se você quiser colocá-lo contra Java, é que é mais fácil de usar. Então vai haver muito menos código. Você tem que escrever muito menos material do que você teria que escrever se você está codificando em Java. Java tem um monte de sobrecarga associada a ele em termos de como você pode realmente compilar esse código e distribuído e coisas assim. É muito mais fácil em Scala acaba. E como eu disse, em comparação, Python mais lento, não é tão lento como costumava ser. Você ainda vai ter um pouco de vantagem com Scala, mas essa comparação de velocidade tem sido fechando ao longo do tempo. Mas onde estão as desvantagens para Scala? Bem, uma é que você pode não conhecer Scala ainda. Sabe, não é uma linguagem muito comum. Então você vai ter que aprender o básico da casa que Gallo trabalha, mas não é tão difícil quanto você pensa. Por exemplo, vamos dar uma olhada nesse pequeno trecho de código. Estamos fazendo a mesma coisa aqui em Python e em Scala. Nós só vamos escrever algum código para quadrar os números em um conjunto de dados. Coisas muito simples. Então, na versão Python e na versão Scala, se você olhar para ela, eles não são tão diferentes, certo? Então sintaticamente há pequenas coisas como, você sabe, você tem que declarar em Scala que é uma constante imutável que você está usando dizendo Val. A sintaxe para definir uma lista de coisas é ligeiramente diferente. A sintaxe para funções do Lambda é um pouco diferente, mas é a mesma idéia, certo? Então Scala é uma sintaxe estranha. Às vezes as coisas podem ser um pouco para trás e vamos falar sobre isso. Não se preocupe com isso. Mas no final do dia, ele não parece muito diferente do código Python no contexto de um script de driver de faísca. E com isso, vamos realmente mergulhar em um curso intensivo em Scala se você precisar. Nesta próxima seção, nós estamos realmente indo para ir para o básico de Scala. O que há de diferente nisso? O que há de estranho nisso? Espero que você tenha alguma experiência anterior em escrever código em algum lugar, algum script ou linguagem de programação. Não estou aqui para te ensinar a programar a partir do zero caras. Seria um curso diferente. Mas se você tem algum Python sob seu cinto, ou C ou Java ou algo assim, eu acho que você pode pegar, escalar muito rapidamente. Então, nesta próxima seção, se você precisar, temos um pouco de uma introdução ao Scala que irá desmistificar a sintaxe para você. E à medida que passamos pelo curso, você verá muitos e muitos exemplos de uso do Scala. E eu acho que ele só vai afundar olhando para ele o suficiente e vendo exemplos suficientes. Então vamos mergulhar em nosso curso intensivo Scala se você precisar dele. Se você não se sentir livre para pular a próxima seção e nós vamos apenas mergulhar direito em como Spark funciona. 4. [de idade: Oi, sou Frank Cane e bem-vindo ao meu escritório. Vamos começar fazendo um curso intensivo sobre a própria linguagem de programação Scala. Agora, obviamente, se você já está familiarizado com Scala, você pode pular esta seção e tudo bem. Mas se você é novo no Scala, mas já teve alguma experiência de programação antes, você encontrará uma seção muito útil para entender o código que vamos analisar ao longo deste curso. É o suficiente para ser perigoso, certo? Portanto, não espere uma introdução abrangente ao curso Scala aqui nesta seção, mas é o suficiente para levá-lo através deste curso pelo menos e através dos exemplos que vamos passar nesta seção e os exemplos mais adiante no curso. Eu acho que você vai terminar este curso com uma boa compreensão de como Scala funciona e até mesmo como escrever seu próprio código Scala. No entanto, se você é novo em programação completamente, isso não será suficiente para você. Eu encorajaria você a ir e encontrar um curso introdutório sobre Scala que vai em mais profundidade primeiro e depois voltar para este. Mas para o resto de vocês, vamos avançar e aprender Scala. Tudo bem, vamos aprender Scala apenas para definir expectativas. Você não vai ser um especialista em Scala no final de assistir vídeos comigo. Então o que eu realmente estou tentando fazer aqui é apenas familiarizá-lo com a sintaxe da linguagem de programação Scala e introduzir algumas das construções básicas como como eu chamo uma função em Scala? O que são trabalho de controle de fluxo onde algumas estruturas de dados básicas que eu poderia usar com Scala, mostrar-lhe código Scala suficiente que ele não vai parecer assustador e intimidante para você como passamos pelo resto do curso. Então, com isso, vamos falar sobre escala em um nível alto primeiro. Primeiro de tudo, por que aprender Scala? Bem, você provavelmente nunca ouviu falar disso antes. Talvez tenha, mas certamente não sabe disso. É usado principalmente para programação Spark. Mas ele é exclusivamente adequado para spar porque é realmente estruturado de uma forma que se presta a fazer o processamento distribuído de dados em um cluster. E você vai ver por que um pouco mais tarde. É também com o que o próprio Spark é construído. Assim, aprendendo Scala, você terá acesso a todos os mais recentes e melhores recursos de faísca à medida que eles saem. E, normalmente, pode levar muito tempo para que esses recursos se espalhem para dizer suporte a Python dentro do Spark. E também será a maneira mais eficiente de executar o próprio código do Spark. Então, usando Scala, você terá os trabalhos mais rápidos e confiáveis do Spark que você pode criar. E eu acho que você ficaria muito surpreso com o quanto mais rápido e o quanto mais confiável. O mesmo trabalho faísca escrito em Scala é comparado a dizer, o mesmo trabalho faísca escrito em Python. Então, mesmo que possa ser tentador ir embora e ficar com a linguagem que você já conhece. Aprender Scala vale a pena o esforço e realmente não é tão difícil. Verdade é o mesmo código Spark para Scala e Python olhar muito semelhante um ao outro no final do dia. Agora, o crânio é executado em cima da máquina virtual Java. Então ele apenas compila para baixo para código de byte Java e é executado pela JVM. Então, uma coisa boa sobre isso é que você também tem acesso a todo o Java. Se houver uma biblioteca Java que você deseja extrair em seu código Scala, você pode fazer isso. Então você não está limitado ao que está na linguagem Scala em si. Você pode realmente chegar até a camada Java e puxar para cima. É um trabalho que você quer usar também. E vamos fazer isso mais tarde neste curso, por exemplo, para lidar com expressões regulares em um pouco mais de uma questão intuitiva do que você poderia de outra forma. Outro ponto-chave sobre Scala é que ele está focado em torno do que é chamado de programação funcional. Onde funções são o cerne do que estamos lidando. As funções são passadas para outras funções e acorrentadas de maneiras que você pode não estar acostumado. Mas é assim que Spark funciona em um nível fundamental. Basicamente tomamos uma abstração sobre um pedaço de dados e atribuímos uma função para fazer algum processamento sobre esses dados. E programação funcional em Scala torna isso muito intuitivo de fazer do ponto de vista da linguagem. Certo, então vamos pular direto para o fundo da piscina e afundar ou nadar com Scala, vamos escrever um código e ver o que acontece e sujar as mãos. Agora eu realmente não forneci uma cópia deste código que eu vou estar passando porque há realmente um valor e digitando você mesmo para fazer uma espécie de afundar dentro Então vamos começar criando o que é chamado de uma planilha New Scala. Isso vai nos dar um ambiente interativo onde podemos apenas experimentar com o código Scala e avaliado interativamente. Então vá para o seu menu de arquivo e inteligência e diga folha de cálculo New Scala. E vamos chamar este aprendendo Scala um. E nesta primeira palestra, vamos apenas falar sobre a sintaxe e estrutura da linguagem Scala porque é um pouco estranho em comparação com outras línguas lá fora. Então, primeiro de tudo, se você quiser um comentário, você pode apenas fazer uma barra dupla como você faria em muitas outras línguas. E primeiro vamos falar sobre valores. Então os valores são constantes imutáveis. Então esse é um exemplo de uma linha de comentários. Agora em outras línguas temos o conceito de variáveis. Você sabe, é uma coisa muito universal e programação para atribuir algum valor a uma variável nomeada, certo? E como usar isso em todo o seu código. Agora, em Scala, há dois tipos diferentes quando é chamado valores que são imutáveis e variáveis que são imutáveis. E em Scala você quer ficar com os valores, tanto quanto possível. Então aqui está um exemplo de como definir um. Poderíamos dizer val para o valor, Olá, dois pontos, string é igual a citação Ola. E se você quiser realmente executar isso, nós podemos apenas apertar um pequeno botão play aqui. Ou você pode ver que há também um atalho de teclado de Control Alt W que eu vou usar a partir de agora. E ele está criando um ambiente para executar isso agora e lá nós temos ele. Então você pode ver que ele realmente executou esse comando e atribuiu o valor o law a uma string chamada Hello. Então vamos passar algum tempo falando sobre a sintaxe aqui porque é meio que para trás de muitas outras linguagens, certo? Então começamos dizendo que isso é um valor. Isso significa que estamos definindo uma constante imutável. Uma vez que definimos o que é “olá “, não podemos mudá-lo nunca mais. Então vamos chamar esse valor Olá. E depois do cólon, temos que declarar que tipo é. Então estamos dizendo que olá é um tipo de string. Então isso é ao contrário da maioria das outras línguas, certo? Normalmente você vai ver como corda Olá, mas em Scala é Olá, cadeia de dois pontos. E, em seguida, atribuímos a um valor. Nada muito estranho. Eles são apenas a corda hola entre aspas. Ok, então isso faz sentido, certo? É um pouco para trás, mas você se acostuma muito rápido. Agora vamos falar sobre variáveis. Então as variáveis são imutáveis. Isso significa que você pode realmente alterá-los depois de defini-los. Então, para definir uma variável, é a mesma coisa. Você só usa um var em vez de um Val. Então, podemos dizer var Olá lá, que também é uma string, e vamos definir isso para Olá. Nós vamos atribuir isso ao valor da string constante, a constante Olá imutável. Então eu vou dizer Control Alt, W. E você pode ver lá que Olá lá foi atribuído o valor de cadeia o lei porque isso foi armazenado em nosso valor imutável. Olá faz sentido até agora. Mas olá, há uma variável, podemos mudá-la agora não está preso a ser Olá. Então nós poderíamos dizer algo como Olá lá é igual Olá mais espaço lá e Controle Alt W. E você pode ver que nós realmente modificamos Olá lá também agora contêm a string Olá. Há Ola lá em vez. Então, como você pode ver, variáveis podem ser alterados valores no entanto, não pode. Também podemos usar o comando print line para imprimir esse valor explicitamente. Imprimir linha Olá, o que faz exatamente o que você pensa. Você imprime o valor dessa variável em uma linha Control Alt W ali. Tudo bem, então você viu algumas coisas básicas aqui. Em primeiro lugar, o conceito de valores em variáveis e valores novamente são imutáveis. Depois de defini-los, não é possível alterá-los. Enquanto as variáveis são mutáveis, você não pode alterá-las depois de defini-las. E também observe a sintaxe aqui de declarar valores e variáveis. É valor var, o nome do identificador, dois-pontos, o tipo e, em seguida, é igual ao que você quer que ele o defina. Novamente, isso é ao contrário de muitas outras línguas. E só para mostrar o que acontece e para provar que os valores não podem ser alterados. Vamos mudar que var2 eval e ver o que acontece se tentarmos executar isso novamente, Controle Alt W. Você pode ver que temos alguns erros aqui agora, realocação eval, não podemos dizer olá lá é igual olá mais lá porque você não pode Mudar um Val. Um valor é imutável. Vamos mudar isso de volta para var e executado novamente Controle Alt W. Tudo bem, Até agora tão bom, certo? Agora, por que temos essa distinção entre valores e variáveis em Scala? Bem, é porque isso é o que chamamos de linguagem de programação funcional para escalar é meio centrado em torno da idéia de passar funções e potencialmente executá-las em paralelo. É por isso que é uma boa combinação para o Apache Spark. E a razão pela qual queremos ficar com constantes imutáveis sempre que pudermos é para evitar um monte de problemas de segurança do fio e para meio que enfrentá-los na passagem. Então imagine que você tem uma função que tem uma variável nela que você obtém, que ela pode mudar e você passa essa variável em muitos, muitos threads. O que acontece se um thread está tentando alterar essa variável ao mesmo tempo que outro thread está tentando alterá-la para outra coisa, os resultados se tornam indefinidos, certo? Então evitamos muitas dessas condições de corrida tentando usar constantes imutáveis sempre que possível. Se nossas funções estão agindo e processando dados imutáveis, não precisamos nos preocupar com todos esses tópicos, condições de segurança e corrida. Isto não te limita tanto quanto pensas. Você ainda pode fazer muito apenas usando valores constantes imutáveis. Então, por exemplo, se eu queria fazer a operação acima e construir a string o la lá a partir do valor Olá. Ainda posso fazer isso usando valores. Eu poderia dizer algo como Val imutável olá lá é igual a olá mais lá. Certo? E eu poderia imprimir esse resultado. Controle Alt W. E isso funciona porque eu estou definindo Olá imutável lá na mesma linha aqui eu estou tomando um valor anteriormente imutável, adicionando em outro valor imutável e atribuindo isso a um valor imutável. Então está tudo bem com as variáveis. Fizemos de uma maneira diferente. Como nós começamos definindo Olá lá para Olá, e em seguida, em outra operação, nós adicionamos a string lá para ele. Então, desde que façamos tudo em uma linha, em uma operação atômica, ainda estamos seguindo as regras de uso de valores sempre que possível. Tudo bem, então nós vimos o tipo de dados string aqui em ação, certo? Portanto, há muitos outros tipos de dados disponíveis para você no Scala. Vamos falar sobre tipos de dados. Então, por exemplo, poderíamos dizer Val número um. Opa, se eu digitar direito, número um cólon int. Então um int é exatamente o que você acha que é um inteiro, um número inteiro, um número inteiro. Também podemos dizer “Val”. A verdade é um booleano. E vamos definir isso como verdade. Note que em Scala, constantes verdadeiras e falsas são todas minúsculas. Há idiomas onde você capitalizaria para verdadeiro e falso, mas não em Scala. Então isso é apenas um valor booleano, verdadeiro ou falso. Também podemos ter personagens. Então podemos dizer val, letra a. Como um tipo de carro, um único caractere, um único valor ascii. Temos também números de precisão dupla, é claro. Então podemos dizer que Pi é um duplo. E defina isso para 3.14159265 ou seja lá o que for. E também podemos representar um único valor de ponto flutuante de precisão com precisão única de Pi. E vamos declarar isso como um flutuador, que é uma variável de ponto flutuante de precisão única. E vamos definir isso para 3.14159265 F, que significa precisão única de ponto flutuante. Vamos controlar Alt W para ver que temos até agora que está funcionando. Assim, você pode ver que todas essas variáveis foram definidas como esperado. Vamos continuar. Há também um tipo de dados longo, digamos Val grande número. Vamos definir isso como um longo. E vamos definir isso para algum grande número inteiro. 1, 2, 3, 4, 5, 6, 7, 8, 9, fora no que quiser. E poderíamos dizer também um único número de caractere. Podemos salvar todos os pequenos números. Declare que como um byte é igual a 127. Então, um byte é basicamente um número que é amontoado em um único byte. Assim, ele só pode representar números de 127 negativo para 127 positivo. Ou se fosse sem sinal de 0 a 255, Controle Alt W para executá-los. Está bem, está bem. Seguindo em frente, vamos falar sobre como realmente imprimir e exibir seus dados e formatar sua saída. Isso é sempre uma coisa importante, certo? Então vamos dizer que queremos concatenar um monte de strings juntos ou um monte de valores juntos e imprimi-los. Obviamente, você quer ser capaz de visualizar os resultados de seus programas Spark. Então é assim que você faria isso. Poderíamos dizer linha de impressão. Aqui está uma bagunça. E o segredo aqui é que você pode usar o operador mais para concatenar coisas juntas e impressas como uma grande corda. E não tem que ser apenas cordas também. Pode ser qualquer tipo de dados. Ele irá implicitamente converter isso em uma string. Então eu posso dizer aqui uma bagunça mais número 1 mais verdade, mais letra A, mais pi, mais grande número. E isso deve funcionar. Controle Alt W. Lá está ele. Caranguejo tudo junto porque eu não inseri nenhum espaço entre tudo, mas funciona. Observe também, a propósito, não há ponto e vírgula ou qualquer coisa no final das linhas aqui. Ele apenas assume que cada nova linha é um novo comando basicamente. Portanto, não há necessidade de terminar explicitamente suas linhas de código em Scala. O que você quer fazer como imprimir estilo F, se você está vindo de um fundo como C ou C plus, você pode estar familiarizado com o comando print f, que permite colocar em uma espécie de dicas de formatação para como realmente exibir dados numéricos ou inserir strings e outros dados em uma string existente. Aqui está como isso parece em Scala. Podemos dizer a linha de impressão F, o que significa que queremos imprimir formato. Citação pi é sobre cifrão pi, precisão única, porcentagem 0,3 F. Ok, então vamos quebrar isso um pouco. Então, primeiro de tudo, note que temos aquele cifrão lá que indica que temos um nome de variável ou nome de valor em vez disso, neste caso, seguindo esse sinal de cifrão. Então Pi é precisão única vai inserir o valor de Pi precisão única. E por cento 0,3 f significa que é um valor de ponto flutuante que vamos exibir lá. Isso é o que o “F” significa. E por cento 0,3 significa que após o ponto decimal, queremos apenas três dígitos de precisão exibidos. Então vamos em frente e aperte Controle Alt W. e você pode ver que ele fez exatamente o que dissemos. Pi é cerca de 3.142. Então ele só exibiu esses três dígitos seguindo o ponto decimal lá porque era tudo o que queríamos. Isso pode ser útil se você estiver exibindo uma precisão dupla ou mesmo um único número de precisão que tem um grande número de dígitos definido tem mais precisão do que você precisa. Você também pode fazer coisas como vamos ver como isso funciona com inteiros. Então, por exemplo, poderíamos dizer linha de impressão F, Novamente apenas indicando impressão f formato 0, preenchimento à esquerda. Símbolo de dólar número 1, por cento 05 D. Então, desta vez, estamos dizendo que vamos inserir o valor do número 1 e o percentual 05 D. O D apenas significa que é um número, um inteiro, e porcentagem 05 significa que eu quero ter pelo menos cinco dígitos à esquerda de a vírgula decimal. Então vamos ver o que isso faz. Controle. Alt W. E temos 000 000 001, prometendo os cinco dígitos de precisão à esquerda que queríamos. Isso pode ser útil quando você está tentando alinhar a saída e as colunas, certo? Então, isso também é um truque útil às vezes. Além disso, se você quiser apenas substituir variáveis em uma string sem realmente especificar a formatação. Isso também é fácil de fazer. Por exemplo, imprima a linha S para aspas substitutas. Eu posso usar o prefixo S para usar variáveis como cifrão número um, verdade, e letra a. Tudo bem, Controle Alt W. E funcionou. Então você pode ver que é uma maneira muito fácil de apenas inserir nomes de valores em sua string lá sem ter que usar o operador de concatenação desnecessariamente. Então é só uma maneira diferente de fazer isso. Certo, o que mais podemos fazer? Podemos incluir expressões em nossos comandos de impressão. Então deixe-me mostrar como isso funciona. Imprimir linha S. O prefixo S não se limita a variáveis. Posso incluir qualquer expressão como Ross, um cifrão, colchete aberto, um mais dois. E completou automaticamente essa linha para mim. Então a chave aqui são esses colchetes. Depois que você tem um colchete definido depois de um cifrão, ele vai realmente avaliar a expressão dentro desses colchetes e imprimir o resultado disso como parte da string Control Alt W. E se rolarmos, Devemos ver que ele imprimiu o número três. Então esse é um truque legal para escrever. Então, esses colchetes depois do sinal de dólar poderiam realmente avaliar uma expressão dentro de um comando de linha de impressão se você usar o prefixo S. Há também expressões regulares. Então, se você está familiarizado com eles, essa é uma ferramenta poderosa para realmente mastigar seus dados de string. Vamos ver como isso funciona. Então vamos começar com uma corda que é Val, a resposta final. Vamos definir isso como uma string. Novamente, não estávamos voltando a como definir um valor. E vamos definir isso para a vida, o universo. E tudo é 42. E se você reconhecer essa referência, então U2, nosso fã do Guia do Caroneiro para a Galáxia. Bem-vinda. Tudo bem, então nós temos essa corda e nós queremos fazer é escrever uma expressão regular que irá extrair a resposta para a última questão da vida, do universo, e tudo mais. Então vamos configurar uma expressão regular para extrair esse número a partir do final dessa string. Então podemos dizer que o padrão val é igual a aspas triplas 123. E então vamos escrevê-lo em uma expressão regular para extrair as informações que queremos dessa string. Estrela do ponto, parêntese, colchete, barra invertida d, n colchete quadrado. Além disso, o ponto R significa que esta é uma expressão regular que estamos definindo aqui. E revisar como as expressões regulares funcionam provavelmente está fora do escopo para este curso. Mas há uma ferramenta muito útil para coisas como extrair informações de arquivos de log e coisas assim. Uma rápida análise do que está acontecendo aqui. A estrela de ponto significa corresponder a qualquer coisa nessa string seguida por um espaço. E então dentro dos parênteses está a coisa que estamos tentando extrair desse padrão. E os colchetes e a barra invertida d significa que eu quero extrair um número. Tudo bem, e qualquer número de números, isso é o que o sinal de mais significa, seguido de qualquer outro personagem. Ok, então, procurando por um monte de personagens seguidos por um espaço e então um número seguido por qualquer outra coisa que vai puxar aquele 42 para fora dessa corda. Não precisamos desse controle Alt W só para ter certeza que está funcionando. Tudo bem, legal. Então vamos dar uma olhada aqui. Então nós temos essa cadeia que definimos para a vida do universo e tudo é 42. E agora definimos um objeto de expressão regular correspondente que consiste nessa expressão regular. Ok, então foi isso que aconteceu com esta linha aqui. Agora, para aplicar essa expressão regular à string, é muito simples. Podemos apenas dizer padrão val, parênteses Respostas, string é igual a resposta final. Certo, então a sintaxe é um pouco estranha. Significa que vamos tomar a expressão regular que definimos no padrão. Nós vamos atribuir a saída de que a cadeia de resposta. Então a sintaxe aqui, está basicamente dizendo, eu quero pegar o que está nesses parênteses e transferir esse resultado para o que está nesses parênteses. Ok, isso é uma maneira de pensar sobre isso. E vamos atribuir a resposta final a esse padrão. Então, a sintaxe lá novamente, um pouco para trás de como você pode estar pensando sobre as coisas em outras linguagens. E então podemos imprimir qual é a resposta. Primeiro, vamos convertê-lo em um inteiro. Podemos dizer val, resposta é igual a respostas string para int. Então isso é apenas mostrar-lhe como realmente converter um tipo para outro. Ajudaria se eu digitasse a string de resposta corretamente. E então eu posso imprimir isso. Linha de impressão, resposta. Tudo bem, então nós definimos uma string, definimos uma expressão regular para extrair informações dessa string, definimos uma instrução. Na verdade, aplique essa expressão regular à string e armazene o resultado em algum lugar. Estamos chamando essa sequência de resposta. Nós convertemos isso de uma string para um inteiro, e então nós vamos imprimir esse ferimento fora Control Alt W. E funcionou. Então você pode ver que extraímos a string 42. Nós convertemos isso para um inteiro 42 e imprimi-lo quando terminamos. Tudo bem, seguindo em frente. Vamos falar sobre Booleans. Tão fácil que eles funcionam exatamente como você esperaria. Então vamos falar sobre Booleans. Então, por exemplo, poderíamos dizer val é maior e definir isso igual a um maior que dois. O que você acha que isso vai sair? Um é maior que dois? Não, a resposta é falsa. Então isso funciona da maneira que você esperaria. Diamos que Val é menor igual a um, menos de dois. Isso é verdade. Poderíamos dizer que Val Impossível é maior e menor. E você pode ver que podemos usar um único e comercial lá. Isso é bom. Mas também podemos dizer um comercial duplo. Vamos ver o que eles fazem. Controle Alt W. Então estes realmente não são a mesma coisa aqui. Assim como em C ou C plus, mais um e comercial duplo é na verdade um fim lógico onde é um único e comercial é um bit a bit. E então a única razão pela qual isso funciona é porque suas asas maiores e menores podem ser avaliadas até zeros e uns e ainda acaba funcionando. E nós simplesmente convertemos implicitamente isso para verdadeiro ou falso. Mas se você está tentando fazer uma operação lógica, que é o que realmente estamos tentando fazer aqui. Você deveria estar usando o “e comercial duplo”. Esse é o operador lógico ou booleano. Então eles dão-lhe o mesmo resultado neste caso, mas é realmente melhor forma para usar o comercial duplo e não funciona da mesma maneira com ou se você quiser dizer é maior ou menor, isso funciona. Isso seria verdade, presumivelmente, sim. Então você entendeu a idéia. Os booleanos funcionam praticamente como seria de esperar de outras línguas. Vamos brincar com ele um pouco mais. E poderíamos dizer Val, a carta, que é uma corda, e definir isso igual a Pickard. E podemos dizer “Val melhor capitão”. Outro valor apenas com um nome diferente. Também uma corda é igual a Pickard. E podemos dizer que Val é o melhor. Declare isso como um booleano. E vamos definir isso para Picard. Igual a melhor capitão. Então vamos em frente e executar isso e Control Alt W faz o que você pode pensar. Então ele é igual, igual aqui está realmente indo dentro dessas cordas e comparando os valores das strings. Então isso significa que queremos comparar os valores dessas duas coisas e ver se elas são idênticas. Portanto, não é realmente comparar os próprios objetos ou o endereço dos próprios objetos. Na verdade, está entrando nessa corda e comparando as cordas umas com as outras. Então, se você quiser comparar duas strings, basta usar o operador igual igual igual. Isso pode ser algo estranho em algumas línguas. Então, é importante apontar isso aqui. E se você quiser debater no Q e um tempo, Picard é o melhor capitão. Congratulo-me com essa discussão. Tudo bem. Se quiserem sujar as mãos, brinquem com estas coisas, façam mais coisas, continuem, rapazes. Então, por exemplo, você pode escrever algum código que leva o valor de pi e o dobra e, em seguida, imprime dentro uma string com três casas decimais de precisão à direita. Ok, então na verdade eu vou colar isso aqui como um pequeno desafio para você. E é muito fácil. Nem sequer te vou dar a resposta. Vocês podem falar no “Q “e “A “se quiserem falar sobre a solução real. Mas aí está o meu desafio para ti. Vá e aplique o que aprendeu e faça isso. Sim, basta escrever um pequeno trecho de código que leva o valor de Pi. Nós definimos, multiplicá-lo por dois, e impresso dentro de uma string com três casas decimais de precisão à direita. Tudo o que você precisa fazer para conseguir isso deve estar acima de você aqui. Tão pouco simples maneira de obter alguma exposição prática. Então suje suas mãos, brinque um pouco mais. E então vamos passar para o próximo capítulo de aprendizagem Scala. 5. Controle de fluxo no Scala: Então, seguindo em frente, se você quiser salvar o que você fez até agora, você pode apenas dizer Control-S, fechar isso é mantê-lo por perto para referência futura, se você quiser. E vamos fazer outro caderno Scala ou worksheet Scala em vez disso. E vamos chamar este de o nome criativo de aprender Scala. E desta vez vamos falar sobre controle de fluxo. Então vamos ver como se outras declarações funcionam. Eles funcionam exatamente da mesma forma que em outras línguas. Não é nada muito estranho aqui. Por exemplo, poderíamos dizer se um é maior que três, linha de impressão, impossível. Else imprimir linha. O mundo faz sentido. Então exatamente como qualquer outra língua lá, se alguma expressão é verdadeira, você faz essa expressão, outra expressão. E se você quiser fazer tudo em uma linha, isso é o que parece. Então Controle Alt W, o mundo faz sentido como deveria. Agora, se você quiser dividir isso em várias linhas, a sintaxe novamente é bastante familiar para você. Aqueles de vocês que programaram antes, poderíamos apenas dizer se um é maior do que três colchete encaracolado. E isso nos permite colocar várias expressões nesse caso positivo. Então poderíamos dizer linha de impressão impossível. E se quiséssemos, poderíamos imprimir outra coisa de novo. Senão, faça outra coisa. Podemos dizer linha de impressão, o mundo faz sentido. E ainda assim, não sei, estou inventando isso. Controle Alt W. O mundo faz sentido, ainda frio. Então, nada de muito surpreendente lá. É muito semelhante a outras línguas lá. Bem, então você sabe como nós podemos ter como mudar declarações em alguns idiomas onde você meio que tem como correspondência entre diferentes casos. Bem, o que isso parece em Scala? Vejamos um exemplo disso. Então poderíamos dizer Val número é igual a 3 SAT o número 32, um valor chamado número. E podemos dizer que o número corresponde ao colchete, caso um. Uma pequena seta estranha é igual a sinal maior que a linha de impressão 1, caso 2. Você pode ver onde eu estou indo com isso. Imprimir linha 2, caso 3, impressão linha três. E então podemos dizer caso, sublinhado, linha de impressão, outra coisa. Provavelmente adivinhe o que isso faz Controle Alt W. Temos o valor livre impresso fora. Então o que está acontecendo aqui é que temos esta declaração de caso aqui onde podemos ter uma lista de casos diferentes que vamos verificar em relação ao número de valor. É igual a 1. Vamos executar essa expressão. Se for igual a 2 mais q, essa expressão é igual a 3, executamos essa expressão, que acaba sendo. E esse sublinhado é como um “pega-tudo”. É como a declaração padrão de onde qualquer outra coisa, qualquer outro caso que não combinamos, vamos acertar isso em vez disso. Então, por exemplo, nós poderíamos definir isso para 30 e isso deve atingir a declaração final “pega-tudo “, certo? Controle Alt W. Claro que temos outra coisa e mudar isso para, para chegar. Então é assim que funciona uma declaração de correspondência. Você não vê isso muitas vezes em Scala, mas está lá se você precisar. Em seguida, vamos falar sobre for-loops. Coisa muito comum a se fazer na maioria das linguagens de programação, certo? Então, como é que isso funciona? É um pouco estranho em termos de sintaxe. Então. Uma maneira de fazer isso é por x menos do que traço um a quatro. E então podemos dizer val ao quadrado é igual a x vezes x e imprimir linha ao quadrado. Então, o que isso faz é iterar através dos valores de um a quatro. E a cada vez através dele, se sinais que o valor atual dessa iteração atual para o valor x. E então nós calculamos um novo valor chamado quadrado que multiplica x por si só e imprime o resultado. Então o que devemos ver, nossos quatro resultados aqui, cada um com o quadrado dos números de um a quatro, Controle Alt W. E lá estão eles, 14916 porque isso é um quadrado, dois ao quadrado, três ao quadrado e quatro ao quadrado. Então funciona do jeito que você esperaria, certo? Nós também temos loops while, assim como você faria em outros idiomas. Então nós também poderíamos fazer algo como var x é igual a 10. E note que estou usando uma variável mutável aqui. Esta geralmente não é uma boa prática em Scala. E eu vou dizer enquanto x maior ou igual a 0, colchete encaracolado, linha de impressão x e, em seguida, x menos é igual a um. Então vamos começar definindo x para 10. Enquanto x é maior ou igual a 0, vamos imprimir o valor de x e, em seguida, subtrair um dele. Então você pode ver que tivemos que fazer x uma variável lá, a fim de continuar modificando o valor de x. Então, não uma estrutura. Você vai ver muitas vezes em Scala, mas você não pode fazer isso se você precisar. Vamos nos certificar de que funciona. Controle Alt W. E com certeza ele conta regressiva de 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0. Legal. Interessante como a planilha formatou que, a propósito, está saindo de seu caminho para tentar manter as coisas compactas. Isso é meio legal. Outra estrutura para controle de fluxo é o loop de fazer while. Mais uma vez, semelhante a outras línguas. Então nós também poderíamos definir x igual a 0. Ainda estamos usando a mesma variável que definimos anteriormente. E podemos dizer Do print line x, ponto-e-vírgula x mais é igual a um, enquanto x menor ou igual a 10. Então desta vez vamos começar em 0 e imprimir cada valor contando por um, enquanto x é menor ou igual a 10. Então estamos fazendo essa comparação no final do bloco em vez do início. É assim que funciona. Controle Alt W e ainda funciona 0123, todo o caminho até 10. Ok, isso é sobre isso para controle de fluxo, vamos falar mais sobre expressões. Então, seguindo em frente, expressões. Então uma coisa que é meio estranha sobre Scala é que quando você tem uma expressão, é uma espécie de implicitamente retorna o valor dessa expressão automaticamente dentro desse bloco. Então, por exemplo, digamos que o colchete Val X é igual a 10 ponto-e-vírgula, x mais 20 ponto-e-vírgula. O que vai acontecer aqui? O que isso realmente faz? Controle Alt W. Então o que ele fez foi realmente retornado o valor 30, mesmo que nós realmente não disse, eu quero imprimir isso, eu não disse explicitamente, eu quero devolvê-lo, apenas o ato de ter essa expressão é a última coisa em esse bloco, significa que isso é o que o bloco produz como resultado. Então isso é uma coisa importante para envolver sua cabeça em termos de programação funcional e expressão, qualquer tipo de bloco de código como este pode ser passado em torno de uma função tem sua própria pequena entidade. E a coisa que esta função retorna é qualquer que seja a última coisa e essa expressão é. Agora você pode retornar explicitamente as coisas para como um canhão outras línguas. Mas implicitamente a última coisa que acontece dentro de um bloco de código será o valor de retorno dessa expressão. Então este pequeno pedaço de código aqui é uma função em si mesmo implicitamente. E ele retorna neste caso, o valor 30. Certo, isso é meio importante. Eu poderia imprimir isso. E eu posso dizer linha de impressão. E imprima essa expressão, val x é igual a dez, ponto-e-vírgula x mais 20, assim. E isso vai realmente imprimir para fora espero que o valor 30. Certo, veja como isso funciona. Ponto importante lá, porque esse é provavelmente um dos pontos mais confusos de Scala. Se você aprender programação em uma linguagem diferente, o que para a maioria das pessoas é o caso. Esse último pouco dentro do bloco é o valor de retorno dessa expressão. E você pode tratar essa expressão como sua própria entidade. Ok, isso vai ser importante quando falarmos sobre funções a seguir. Tudo bem, isso é o suficiente para este pequeno quarteirão aqui. Então, novamente, eu vou te dar um desafio aqui para praticar o que você aprendeu. Deixe-me copiar e um pouco de exercício que escrevi para o lado aqui. Então você deve ter ouvido falar da sequência de Fibonacci. E é isso que é. Basicamente é uma sequência onde cada número é a soma dos dois números antes dele. Então seus resultados devem ser 011235 e assim por diante. Veja o que está acontecendo aqui. Então temos, então começamos com um valor 01, e então iteramos adicionando os valores dos dois números antes disso. Então 0 mais 1 é 1, 1 mais 1 é 2, 1 mais 2 é 3. 2 mais 3 é 5. 3 mais 5 é 8, e assim por diante e assim por diante. Então seu desafio é escrever um pequeno trecho de código em Scala que faz isso. Então você vai ter que aplicar o que você aprendeu sobre controle de fluxo aqui e valores e variáveis para fazer isso, este é um pouco mais de um exercício desafiador. Mais uma vez, eu não vou te dar a resposta. Você pode procurá-lo com bastante facilidade se você ficar preso. Mas esta é uma pergunta bastante comum de entrevista para mostrar às pessoas que você sabe como codificar e pode envolver sua cabeça em torno de algoritmos. Então eu encorajo você a ter um tempo para passar por esse exercício porque eu fui útil em uma entrevista de emprego algum dia. E também é uma boa prática para controle de fluxo dentro da linguagem Scala. Então vá se divertir com isso. E quando voltarmos, aprenderemos um pouco mais. 6. Funções no Scala: Seguindo em frente, a próxima palestra é mais curta, mas é muito importante. Vamos falar sobre funções em Scala. E dado que é uma linguagem de programação funcional, obviamente isso é de grande importância. Vamos fechar o esqueleto de aprendizagem e criar mais uma worksheet, New Scala worksheet, e vamos chamar este, adivinhe? Aprendendo Scala três. E desta vez vamos falar sobre funções. Então o formato de uma função em Scala vai ser a morte. Nome da função, parâmetro, nome, tipo de dois-pontos para tantos parâmetros quanto você tiver. E, em seguida, o tipo de retorno de dois pontos é igual, e, em seguida, alguma expressão que define o que essa função faz. Esta é uma sintaxe muito, muito estranha se você está acostumado a outras linguagens de programação não-funcionais. Então, vejamos alguns exemplos. Podemos dizer, por exemplo, def quadrado. X dois-pontos int, dois-pontos int é igual a colchete x vezes x. Então é assim que você define uma função que leva em um valor e quadrados retorna o quadrado desse valor. Vamos quebrar isso. Então, novamente, começamos com def para definir uma função, o nome da função, neste caso, quadrá-lo. Um parâmetro. Neste caso, temos apenas um parâmetro chamado x, e que é do tipo inteiro. Então x dois-pontos int significa que o primeiro parâmetro é um inteiro chamado x. e, em seguida, o valor de retorno desta função vai ser um inteiro em si. Então que dois-pontos int é o valor de retorno, novamente, totalmente para trás de muitas outras línguas. Então temos que dizer igual para atribuir essa função a alguma expressão. Então estamos dizendo que essa definição de função é igual a essa expressão nos colchetes, x vezes x. Não se esqueça que é igual, isso é um erro muito comum. Então, novamente, não estamos explicitamente retornando um valor. Apenas a última coisa que é avaliada dentro da função é o valor de retorno implícito dessa função. Então isso é tudo o que há para ele. Outro exemplo, digamos def cubit x int, dois-pontos int é igual a x vezes x vezes x. Então nós poderíamos fazer tudo isso em uma linha para isso é simplesmente para um one-liner rápido. Vamos ver isso em ação. Então podemos dizer linha de impressão, quadrá-lo, passando no parâmetro dois. E podemos dizer impressão de linha cúbita, passando no parâmetro três. Vamos controlar Alt W e executar tudo isso. E você pode ver que atribuímos a função raiz quadrada e cubo-lo. E nós realmente passamos o valor 2 para o quadrado e obtivemos o valor para trás. Passamos o valor três para Cuba e recuperamos 27. Assim como deveria estar funcionando. Então, novamente, é foco por um momento nessa sintaxe. É preciso algum se acostumar a def nome da função, dois pontos de parâmetro, tipo de valor de retorno de dois pontos igual e, em seguida, a expressão que define a própria função. Agora, aqui é onde fica estranho. Se não achasse que era estranho o suficiente. Funções podem realmente tomar outras funções como parâmetros. É como a criação. Se você não entende a referência da cultura pop, eu peço desculpas, mas digamos, por exemplo, a transformação da morte. E vamos levá-lo em X, que é um parâmetro inteiro. E também um f, que vai definir uma função que leva um inteiro e retorna um inteiro como seu valor de retorno. E esta função de transformação em si irá retornar um inteiro e vamos definir que igual à seguinte expressão, f de x. Tudo bem, isso leva algum pensamento, certo, então o que está acontecendo aqui? Estamos definindo uma nova função chamada transform int. Ele leva em ambos um valor, um valor inteiro chamado X. E ele também leva uma função que leva em um inteiro e retorna outro inteiro. Então isso pode ser qualquer função que leva um inteiro e o transforma em algum outro inteiro. Sabemos que isso, por sua vez, retornará um inteiro e é definido para a expressão f de x. Então vamos pegar a função que passamos chamada f e passar para essa função, o parâmetro x que passamos para transformá-lo. Se você precisa sentar e pensar um pouco sobre como isso funciona, não tenha medo de pressionar pausa porque esse é um conceito muito importante para a programação funcional. Vamos ver o que ele realmente faz quando tentamos usá-lo. Vamos dizer Val resultado é igual a transformar int, e vamos passar em dois e a função cubo-lo. Então, o que acha que vai acontecer aqui? Estamos passando o valor dois em x, a função cúbita em F. Então vamos acabar chamando cúbito no valor dois aqui dentro transformá-lo. Então transformamos int. Vamos chamar a função cúbica que passamos com o valor X então devemos voltar ao cubo, certo? Controle Alt W. Claro que temos o valor oito. Tudo bem, de novo, macarrão sobre isso. E se você quiser realmente imprimir esse resultado para fora, em vez de apenas confiar no que foi avaliado para, poderíamos dizer linha de impressão, resultado, Control Alt W e voltar avaliar explicitamente lá. Ok, então ainda mais importante é o conceito de funções do Lambda, ou às vezes eles são chamados de funções anônimas são uma função literais, você sabe, é uma terminologia muito diferente para isso. Mas, basicamente, você pode declarar uma função inline sem sequer dar-lhe um nome. E você verá isso acontecendo muito no código Spark. Por exemplo, eu poderia dizer transformar int três x igual sinal maior que x vezes x vezes x. Então o que eu fiz é ignorar a necessidade de realmente definir uma função cúbica lá. E eu só gosto de encontrar essa função em linha aqui com se chamar uma função lambda ou uma função anônima ou uma função literal. Novamente, terminologia diferente para a mesma coisa. Então isso faz a mesma coisa que 3 cúbitos. Mas em vez de realmente definir uma função cúbica, estamos apenas definindo as entranhas dessa função cúbica aqui na linha como parte desta linha. Então estamos dizendo transformar int o valor 3, que vai ser passado para x. e agora passando para o parâmetro f transformá-lo. Estamos passando essa expressão, Ross diz que vamos pegar um parâmetro de entrada x e retornar x vezes x vezes x. Então é apenas uma espécie de abreviação de passar em expressões realmente curtas como funções. E vamos nos certificar de que faz o que pensamos que faz. Então, se apertarmos Control Alt W, isso nos devolve o valor 27 porque ele está passando em três, passando três em x e depois cubando isso. Está bem. Vejamos outro exemplo. Mesma idéia, transformar int 10 x x dividido por dois. Então isso é definir uma coisa nova que nunca vimos antes. E nós vamos usar essa transformação e função passar em dez em x e em f. Estamos passando neste tipo de função lambda inline que leva x e divide por dois. Então esperaria que retornasse 1, 5, certo? Claro o suficiente. Outro exemplo, poderíamos dizer transformar int para x. e isso vai para, e podemos colocar, ficamos mais complicados aqui. Poderíamos dizer que val y é igual a x vezes 2 ponto-e-vírgula y vezes y. certo? E feche isso. Achamos que vai acontecer com este. Então o que estamos fazendo aqui é passar em uma expressão multi-linha aqui, em vez de apenas uma única coisa de linha, você pode fazer isso, isso é legal. Então aqui estamos configurando um valor chamado y e definindo como x vezes 2. Então, novamente, dois está sendo passado para esta função como x. Então vamos começar dizendo 2 vezes 2, que é 4. E então vamos dizer y vezes y, então 4 vezes 4. Então devemos ter 16, certo? Controle Alt W. Claro que temos 16. Então você pode ver essas funções lambda podem conter expressões de várias linhas se você apenas colocá-las entre colchetes, tudo bem. Então é apenas uma espécie de novo, uma abreviação de definir uma pequena função curta sem realmente definir a própria função. Então vem a calhar às vezes, mas pode ser um pouco confuso. Tudo bem. Isso é muito para enrolar sua cabeça. Como eu disse, não há muito material aqui, mas é difícil afundar para ajudá-lo a afundar. vez, tenho um desafio para ti. Aqui está o seu exercício para esta lição. Então strings, acontece que têm o método ToupperCase ponto embutido. Então, por exemplo, você poderia dizer foo ponto para maiúsculas e ele vai lhe dar de volta FU em todas as maiúsculas. Então modo de tweet raiva, se você quiser, seu, seu exercício, seu desafio é escrever uma função que converte uma string maiúsculas e, em seguida, usar essa função para algumas cordas de teste. E então eu quero que você faça a mesma coisa usando uma função literal. São estas pequenas funções inline aqui, em vez de usar uma função nomeada separada. Então pratique fazer em maiúsculas usando uma função tradicional e, em seguida, usando uma função literal usando estas pequenas funções lambda inline aqui em vez disso. Não muito difícil, mas é um bom treino. Então vá e cuide disso. E vejo-te na próxima lição. 7. Estruturas de dados no Scala: Tudo bem, seguindo em frente, vamos fazer mais planilhas Scala. E nós vamos chamar este, você nunca vai adivinhar aprendendo Scala 4. E desta vez vamos falar sobre estruturas de dados. Conceito muito importante em qualquer língua. E esta vai ser uma espécie de longa, rapazes, por isso tenham paciência comigo. Portanto, existem muitos tipos diferentes de estruturas de dados em Scala. Temos tuplas. É muito comum quando lidamos com o código do Spark. Temos listas imutáveis. E você pode pensar neles como campos de banco de dados ou colunas de dados. E isso pode ser útil para passar em torno de linhas inteiras de dados juntos, certo, então vamos ver como isso se parece. Podemos dizer coisas do Capitão Val. E se você não está familiarizado com Star Trek II, peço desculpas pelas referências da cultura pop aqui. Picard, empresa D, NCC 17, 0, 1, D, realmente não importa o que isso significa. Há uma lista de cordas que são colocadas juntas no que chamamos de tupla aqui. Agora, apesar do nome de tupla, não necessariamente tem que ter três coisas nele. Só acontece neste caso. Então temos esse trio de objetos diferentes aqui, essas três strings que são agrupadas entre parênteses. E podemos tratar isso como uma única entidade que estamos chamando coisa de capitão”. Vamos imprimir isso. Controle Alt W. E você pode ver que isso imprime como esse próprio objeto, as três cordas, Picard Enterprise D, e NCC 17, 100 one-d. Dentro desses parênteses, é na verdade um único objeto que chamamos de cap e outras coisas, e esse objeto contém essas três strings. Agora podemos rasgar isso e nos referir a esses componentes individuais individualmente. E fazemos isso referindo-se a eles com base em seu índice baseado que é importante. Consulte os campos individuais com um índice baseado em um. Isso pode ser confuso porque em muitas linguagens de programação você começa a contar de 0, certo? Não é o caso neste exemplo em particular. Então, por exemplo, uma linha de impressão, coisas de capitão, ponto sublinhado. Uma é a sintaxe aqui. Digamos que Control Alt W, que imprime um cartão, o primeiro elemento dessa tupla. Da mesma forma, podemos dizer que o capitão da linha de impressão sublinha as coisas dois, e o capitão da linha de impressão sublinham três. E tiramos cada um desses elementos da tupla original. Então é assim que você se refere a elementos individuais de uma tupla usando esse formato de sublinhado começando com um. Certo, o que mais podemos fazer? Podemos criar pares de valor de chave, assim como fazemos em muitos outros idiomas usando o operador de seta. Assim, por exemplo, poderíamos dizer cartões val navio é igual a string Picard traço maior que o símbolo de seta pequena lá, enterprise traço d. E eu poderia então referir-me à parte do valor com uma sintaxe semelhante. Eu poderia dizer linha de impressão, nave de Picard, ponto sublinhado dois, isso vai me dar de volta esse valor. Então Controle Alt W. Então você pode ver que criamos esse mapeamento de Pixar para Enterprise D. E se quisermos extrair esse valor particular, podemos usar sublinhado dois para obtê-lo. E você pode realmente misturar diferentes tipos dentro de uma tupla. A propósito, podemos dizer Val, um monte de coisas é igual entre parênteses Kirk, que é uma corda, 1964, que é um número. O ano em que Star Trek saiu, é claro. E um booleano, vamos executar um booleano, verdade. Isso é uma coisa válida para se fazer? Isso é legal? Sim, é. Assim, você pode ter uma tupla que contém diferentes tipos de dados também. Neste caso, uma string e int e um booleano. Está perfeitamente bem em Scala. Vamos falar sobre listas a seguir. Então as listas são como uma tupla, mas são um objeto de coleção real que tem mais funcionalidade. E as listas não podem conter itens de diferentes tipos. Assim, como uma tupla, mas mais funcionalidade deve ser do mesmo tipo. Muito bem, uma pequena nota para si, por exemplo. Na verdade, é uma lista unificada sob o capô se você estiver em estruturas de dados. Podemos dizer Val, lista de naves é igual a uma lista, L maiúsculo, Enterprise, desafiador, Voyager, Deep Space Nine. Esqueci o índice 01, o melhor de todos de qualquer maneira. Então, o que isso faz? Controle Alt W. E ainda temos um objeto de lista que tem uma lista de strings. Então, novamente, a lista deve conter o mesmo tipo de objeto. Neste caso, é uma lista de objetos de string. E o que podemos fazer com ele? Assim como com uma tupla, podemos extrair elementos individuais dessa lista, mas a sintaxe vai ser completamente diferente. Então, digamos, por exemplo, linha de impressão, navio, lista, parênteses, um, apenas assim. O que acha que isso vai fazer? Vamos devolver o empreendimento ou vai me levar de volta para encontrar, vamos descobrir o Controle Alt W me dá defini-lo. Então, ao contrário da sintaxe de tupla, estamos realmente baseados em zero aqui. Tudo bem, então a nave era 0 nos daria de volta a empresa. Deixe-me provar isso para você. Mas a lista de navios 1 vai dar-nos a defini-lo. Porque estamos começando a contar de 0 neste caso, o que é um pouco mais do que você esperaria. Também temos operadores de cabeça e cauda disponíveis. Então poderíamos dizer linha de impressão, nave, lista, ponto de cabeça. E podemos dizer linha de impressão, navio, lista de pontos cauda, cabeça provavelmente faz o que você espera. Isso vai te dar o primeiro item da lista, mas a cauda provavelmente não é. O que você espera? Ele realmente devolve todos os itens restantes. Além do primeiro, vamos ver, Controle Alt W. E vamos rolar até o fundo. Então cabeça nos deu a primeira coisa na empresa lista que é esperado, mas cauda nos dá tudo o resto. Então isso nos dá a lista de viajante definido e DSpace nove, uma espécie de sublista excluindo o primeiro item. Um pouco estranho de alquimia SQL, estranho às vezes. Digamos que você queira percorrer todos os itens de uma lista. É uma coisa muito comum a se fazer, certo? A sintaxe para isso é bastante simples. Podemos dizer para parênteses, enviar menos que, então jogar o operador seta esquerda sua lista de navios. E então alguma expressão que operará no navio. Vamos imprimir. Ok. Então isso vai percorrer cada item na lista de navios, extrair cada uma dessas cadeias de caracteres e atribuí-la ao envio, e depois imprimi-lo. Vamos assistir. Sim, funcionou. Então isso imprimiu o nome de cada navio individual. E você sabe, se nós não estivéssemos na configuração da planilha, isso seria na verdade em linhas separadas, claro, mas ele está tentando ser inteligente em conservar espaço para nós, o que é bom. Ok, vamos ficar estranhos. Vamos aplicar uma função literal a uma lista. Ok, isso é programação funcional. Podemos fazer coisas assim. Então, podemos usar mapa, a função de mapa para aplicar qualquer função que queremos a cada item em uma coleção. Vamos ver como isso funciona. Podemos dizer, por exemplo, val para trás navios é igual a navio lista ponto mapa. Então isso significa que vamos mapear cada elemento dessa lista para alguma função que vamos fornecer. E aí vem essa função. Nós vamos apenas fazer isso como uma função literal vai dizer que começamos com a nave que é uma string. E isso vai ser transformado em entre colchetes navio ponto inverso porque há um operador reverso embutido no operador string. Certo, então vamos expandir isso um pouco. Vale a pena ver tudo isso em uma exibição lá. Ok, então envolva sua cabeça em torno disso. Agora isso é meio que amarrando muito do que já falamos. Então vamos fazer uma lista. Vamos usar a função de mapa, que é muito importante no mundo da computação distribuída, para mapear alguma função para cada elemento dessa lista. E essa função vai ser uma função literal onde estamos apenas dizendo que alguns navios string vai ser mapeado para o reverso e retornar isso. Então, depois de executar isso, devemos ter uma nova lista chamada naves retroativas que contém todas as naves em sentido inverso. Então, vamos em frente e imprimi-los. Com quatro navios. Naves para trás de novo, estamos apenas a repassar tudo na lista como vimos antes. Imprimir navio linha. Ok, então vamos ver o que ele faz. Aí está você. Então, naves retroativas foram atribuídas a esta lista onde aplicamos a função inversa a cada elemento da lista de navios. E fez cada palavra ao contrário. E então passamos por um iterado através de cada um desses elementos na lista de navios para trás e imprimi-los. Então funcionou. Legal. Bem, vai servir. Então. Vimos o mapa. Talvez já tenha ouvido falar do MapReduce. Então vamos reduzir. Mesmo conceito. Então, como tivemos um mapa, podemos usar reduzir para combinar todos os itens em uma coleção usando alguma função que forneceremos. Ok? Então, por exemplo, digamos que a lista de números val é igual à lista que contém 1, 2, 3, 4, 5. Ok? Simples o suficiente. Agora vamos dizer val sum é igual a número lista ponto reduzir. Assim mapa aplicaria uma função a cada elemento da lista. Mas reduzir vai passar por todos os elementos da lista e executar a mesma função nele, deixar você acumular todos os resultados disso. Fará mais sentido com um exemplo. Assim poderíamos dizer, por exemplo. Parênteses e, em seguida, imprimir o c x dois-pontos int y dois-pontos int. Mapeie isso para X mais Y. Então vamos pensar sobre o que está acontecendo aqui. Então reduzir basicamente mantém um total de algum tipo. Então ele vai pegar a saída anterior da função de redução da iteração anterior, passar isso para x. é então tomado a iteração atual, o número que está olhando agora chamar esse Y e aplicar alguma operação para Isso. E a saída dessa operação será alimentada para o próximo estágio quando formos para o próximo elemento. Então deixe-me ver o que está acontecendo aqui. Vamos começar com um. E vamos dizer 1 mais 2, que é 3, então passará isso para a próxima iteração. E teremos 3 mais 3. O resultado disso será seis. Então temos seis mais quatro. O resultado disso será 10, e então 10 mais 5 deve ser 15. Certo, então é assim que a Reduce funciona. Quando terminarmos, vamos imprimir esse valor, imprimir alguma linha. Vamos executá-lo. Com certeza, tenho 15. Então reduza. É só uma forma de, de alguma forma, colapsar todos os resultados em uma resposta final. E muitas vezes isso é usado para calcular como um total geral ou algo assim. Você poderia pensar em maneiras mais diretas de fazer isso. Mas a coisa boa sobre mapear e reduzir funções é que eles são muito paralelizáveis. Portanto, é muito fácil aplicar funções de mapa em paralelo e, em seguida, combinar os resultados dessas funções de mapa em algum tipo de fase de redução para obter a resposta final que você deseja. Veremos isso mais em ação com exemplos mais tarde no curso. O que mais podemos fazer isso uma operação de filtro também. Se você quiser remover coisas que você não quer. Então o filtro remove coisas. Por exemplo, poderíamos fazer uma nova lista chamada I hate fives e vai passar, atribuir que para número lista de pontos filtro, passando nele outra função in-line aqui. Função literal, se preferir. X-nada é igual a cinco. Tudo bem? Então o que isso vai fazer é aplicar esta função de filtro. Não x nada é igual a cinco e só retorna isso de volta dentro da nossa lista resultante se isso for verdade. Então vamos ver o que isso faz. Isso nos dá de volta uma lista 1234 porque excluiu o valor cinco. Então é assim que funciona um filtro. Ele pode filtrar informações inválidas, outliers, o que você quiser fazer. É uma boa maneira de limpar dados. Novamente, de uma forma que é paralelizável. Fazemos a mesma coisa. Poderíamos dizer em uma sintaxe ligeiramente diferente. Val eu odeio 3s igual número lista ponto filtro. E isso é uma espécie de sublinhado abreviado, não igual a três. Então, em vez de escrever que x em dar um nome a esse valor x, nós realmente não precisamos de um nome. Nós só queremos pegar o valor que existe e verificar isso contra três. Então isso é uma espécie de expressão abreviada de fazer isso usando o caractere sublinhado. Então vamos ver o que isso faz. 12, 45. Então sintaxe equivalente, você notou usando três em vez de cinco e um pouco mais fácil de digitar. Então, se você ver essa sintaxe, é isso que está acontecendo lá. O sublinhado é basicamente um titular de lugar para cada elemento da lista. Ok? Ok. Agora vale a pena notar que o Spark tem suas próprias funções MapReduce e filtro que distribuem essas operações. Eles funcionam exatamente da mesma maneira. Então Scala tem seu próprio built-in MapReduce e filtro. Spark também tem seu próprio MapReduce e filtro. A diferença é que o Spark vai ter certeza de paralelizar isso em todas as máquinas em seu cluster, se possível. Ok, hey, você realmente entende MapReduce agora, a propósito, esse é o conceito fundamental por trás do MapReduce. É muito simples, tão pouco Exército Bonus para você. Mais algumas operações de lista que você pode fazer. Como concatenar listas? Sintaxe para isso? Digamos que Val, vamos criar outra lista. Então temos algo para brincar. Mais números equivale à lista 678. E podemos dizer val, muitos números são iguais a lista de números mais, mais mais números. Então, para concatenar duas listas juntas, use esse operador duplo mais. Vamos ver o que isso faz. Controle Alt W. Então você tem isso. Temos uma nova lista chamada “lotes de números”. Eu posso concatenar a lista de números que contêm 1, 2, 3, 4, 5 e os números mais listados 678 em uma única lista, 1, 2, 3, 4, 5, 6, 7, 8. Note que não recebemos de volta uma tupla de duas listas. É uma única lista que contém todos os valores dessas duas listas. Mais algumas coisas aleatórias que podemos fazer com listas. Então vamos reverter. O que está em uma lista com invertido é igual a número lista ponto inverso, Cinco 4321. E eles costumavam ser uma pergunta de entrevista que eu daria às pessoas na Amazon reverter as palavras em uma string ou reverter os elementos de uma lista costumava ser, isso era uma coisa difícil de fazer e a maioria das linguagens de programação, mas se você entrar em sua usando Scala, você pode fazê-lo em uma linha de código. Tão pouco jeito de trapacear. Eles estão classificando. Você pode dizer val ordenado é igual ao ponto invertido sortido. Opa, espero ter soletrado invertido, certo? Então vamos em frente e resolver isso. E isso está de volta em ordem ordenada. 1, 2, 3, 4, 5. Fácil de peasy. O que mais você vogal? Muitas duplicatas. Igual a lista de números mais, mais inumeráveis. Então vamos concatenar as duas listas e ver o que acontece. Estamos concatenando uma lista para si mesmo e você vê que podemos fazer isso. 1234512345. Portanto, os elementos de uma lista não precisam ser únicos. Você não pode ter duplicatas lá dentro. Isso é o que estou mostrando com esse pequeno exemplo. Mas se você não queria nada além de valores distintos, você pode fazer isso também. Poderíamos dizer que valores-valores distintos equivale a lotes de duplicatas, ponto distinto. E isso retornará apenas esses valores distintos dentro dessa lista. E você pode ver que estamos de volta ao 12345. Não há duplicatas nesse distinto. Eu só quero obter o máximo, o valor máximo em uma lista Isso é fácil. valor máximo da vogal é igual à lista de números ponto x. e isso é cinco. Se você quisesse obter o total, poderíamos dizer que total total total é igual ao ponto da lista de números. maneira um pouco mais direta de fazer isso do que usar uma função reduzida. Isso também funciona. Temos o valor 15. Há muito mais simples. E poderíamos dizer, se você quiser verificar se um elemento existe dentro de uma lista, isso também é fácil de fazer. Val tem três iguais, eu odeio três. Dot contém três, então estamos checando a lista “Eu odeio três “que fizemos antes para ver se contém o valor três, não deveria. Claro o suficiente que voltou como falso. Muito bem, estamos a chegar lá, rapazes. A última coisa que quero falar é sobre mapas. Então você pode saber que estes como dicionários e outros idiomas são um valor chave pesquisas em chaves distintas. Estrutura de dados muito útil em muitas situações diferentes. Então vamos falar sobre como isso funciona. Vamos montar um mapa chamado “mapa da nave”. Um pequeno comentário aqui. Então sabemos que estamos falando de aplicativos que eles são importantes. Então eval mapa de porcaria vai ser igual a um mapa de capital M que contém os seguintes pares de valor chave. Assim, por exemplo, Kirk, seta, empresa, vírgula Picard, seta Enterprise D, Cisco, Deep Space Nine, Janeway, Voyager. Eu poderia continuar, Archer e assim por diante. Mas vou poupá-lo da digitação. Tudo bem, então o que fizemos aqui foi configurar um objeto de mapa. Certifique-se de fechar isso corretamente. E você pode ver que temos de volta um objeto de mapa lá que mapeia strings para strings. Novamente, os tipos de dados precisam ser os mesmos. Então estamos mapeando cordas com nome de capitão para a nave deles, chamadas cordas. E você pode ter cadeias de mapeamento para ints ou algo assim, mas você tem que ter um tipo consistente dentro de cada par de valores de chave, pelo menos. Isso faz sentido. Então, agora, se quiséssemos usar esse mapa, poderíamos dizer algo como linha de impressão, mapa enviado, Janeway entre parênteses, e Controle Alt W, que nos devolve a Voyager. Então você pode ver que temos uma pequena tabela de pesquisa rápida lá que definimos usando um mapa que nos dará volta o valor Voyager dado o nome chave Janeway. Coisa muito útil em muitas situações. E as chaves desaparecidas? Então, na verdade, eu intencionalmente omiti um dos capitães de navios lá. Digamos que a linha de impressão. Nave, o ponto do mapa contém Archer. Archer não está na minha lista no meu mapa. Isso volta como falso. Como faço para lidar com isso? O que acontece se eu tentar olhar para cima Archer, onde ele não existe no mapa. Bem, vamos tentar. Val arqueiros navio é igual a util dot try. Então vamos fazer uma try-block aqui, mapa da nave, Archer, obter ou então Unknown. Tudo bem, então estamos fazendo algumas exceções aqui. E então vamos imprimir linha ou navio turístico. Linha de impressão, arqueiros, nave, controle, Alt W. Então, basicamente, estamos fazendo como um pequeno tratamento de exceção aqui. Então estamos tentando pegar nosso outro bloco aqui. Por isso, embrulhando o mapa do Archer neste bloco de testes, significa que não vai ficar balístico porque a nossa verdadeira não existe. Estamos recebendo de volta uma espécie de valor indefinido nesse caso. Então, a exceção de tentativa lá, ele é acionado. E é esta cláusula getter else em vez disso e retorna uma string desconhecida nesse caso. Então essa é uma maneira de lidar valores ausentes em um mapa ou lidar com a possibilidade de valores ausentes em um mapa. Ok, isso é definitivamente o suficiente. E terminamos com o básico de Scala. Então, você sabe, apenas o suficiente para ser perigoso aqui. Agora, vamos ter muito mais prática à medida que passamos pelo curso, olhando para muitos exemplos diferentes. E é assim que você vai aprender. Mas espero que isso desmistifique alguma sintaxe para você, pelo menos. Um último exercício para você. Deixe-me copiar isso em um último desafio. Então aqui está para você. Seu desafio, se você optar por aceitá-lo, crie uma lista dos números de um a 20. E eu quero que você imprima os números que são uniformemente divisíveis por três. E há algumas dicas aqui no texto aqui que podem guiá-lo. Novamente, esta é uma pergunta de entrevista muito comum que eu costumava dar às pessoas durante telas de telefone e Amazon, você ficaria surpreso quantas pessoas não poderiam fazer isso com sucesso em qualquer idioma que eles queriam tentar e fazê-lo em Scala. Há um operador modulo, como em outras línguas que eu falo aqui que lhe dá o restante após a divisão. Então qualquer coisa que é divisível por três deve ter um módulo 3 que volta como 0. Então essa é a sua primeira dica. Então, basta iterar todos os itens na lista de testes. Esse teste modulo é você ir e você pode então fazê-lo novamente usando uma função de filtro na lista em vez disso. Então, de algumas maneiras você pode fazer isso. Vá em frente e pratique lá. E depois disso, acho que saberá que o esqueleto é perigoso. E vamos seguir em frente e realmente entrar nas entranhas do próprio Apache Spark. 8. A data de Resilient e Resilient: Então vamos mergulhar no próprio Spark e vamos começar com uma visão geral do Spark e também sua API original, o RDD. Falaremos sobre o que isso significa em breve. Essa foi a primeira API que a faísca saiu dentro do Spark One. E mesmo que ele tenha sido amplamente substituído em versões subsequentes por APIs mais recentes, ele ainda está por aí. Você ainda vai precisar usá-lo de vez em quando. E há alguns problemas, como veremos, onde os RDDs ainda são a solução mais eficiente. Você também tem que encontrar algumas bibliotecas de terceiros que você pode querer usá-lo usar RDDs e você pode ter que olhar para algum código legado, bem como um dois, então ainda vale a pena aprender. No entanto, após esta seção, vamos mudar nosso foco para APIs mais modernas, como dataframes e conjuntos de dados. Mas, por enquanto, vamos começar com o básico e aprender o núcleo Spark em si, o RDD. Então vamos começar falando sobre raízes de faíscas e essa é a interface RDD. Rdd significa Resilient Distributed Dataset, para não ser confundido com conjuntos de dados no Spark, isso é uma coisa diferente. Conjuntos de dados são construídos de forma bastante confusa sobre RDDs. É uma API de nível superior. Mas no seu núcleo, Spark é tudo sobre RDDs. E o que é isso? Bem, basicamente um RDD é um monte de linhas de dados de algum tipo. E como ele é dividido em linhas, essas linhas podem ser distribuídas para computadores diferentes e ser processadas em paralelo nesses computadores diferentes. Então é por isso que é distribuído. Então é um conjunto de dados porque é um monte de linhas de informação é distribuído porque podemos potencialmente dividir essas linhas entre vários computadores. E é resiliente porque, bem, faísca garante que o processamento que você está fazendo no RDD seja feito de uma maneira ou de outra, certo? Então, é problema faíscas descobrir o que acontece se um nó cair no meio de sua operação para girar um novo para tomar seu lugar. Portanto, a primeira coisa que você precisa fazer antes de criar um RDD e Spark é criar um contexto Spark. E seu programa de motorista fará isso como uma das primeiras coisas que ele faz. Assim, o objeto de contexto Spark é o responsável por tornar esses RDDs resilientes e distribuídos. Não é necessário escrever o código para se certificar de que não consegue lidar com falhas ou falhas de hardware. Você não precisa escrever o código para descobrir como distribuir esses dados em todo o cluster. O próprio RDD dentro do contexto Spark está descobrindo como fazer isso por você. Tudo o que você precisa se preocupar é como transformar seus dados. Portanto, seu contexto do Spark criará os RDDs que você solicitar. E se você estiver realmente usando o shell Spark interativamente, ele criará um objeto para você automaticamente, que será o seu contexto Spark. Você tem que criá-lo explicitamente, ele já está lá. Isso fará mais sentido quando olharmos para algum código. Então, como faço para criar um RDD? Geralmente é bem simples. Uma maneira é dar uma lista explícita de coisas. Então, o primeiro exemplo lá estava dizendo val nums é igual a lista paralelizar 1, 2, 3, 4. Isso vai criar um RDD chamado nums que contém apenas em cada linha 1, 2, 3 e 4. Obviamente isso não é muito útil no mundo real porque se você é capaz de escrever e codificar o que está em seu RDD. Provavelmente não é big data e provavelmente não é dados reais também. você sabe, para testar as coisas, casos de teste às vezes isso é útil. Mais frequentemente, você estará carregando dados de algum arquivo de texto em algum lugar. E para fazer isso, você pode apenas dizer SC, assumindo que é o seu objeto de contexto Spark dot arquivo txt e passá-lo o, o caminho para o seu arquivo de texto gigante e outras coisas. E isso criará um RDD onde cada linha desse texto arquiva sua própria linha no RDD. E não precisa vir do sistema de arquivos local. Agora meio que derrotar o propósito do big data, certo? Assim, ele também pode lê-lo de sistemas de arquivos distribuídos, incluindo HDFS, que é o Hadoop Distributed File System, ou mesmo Amazon S3, S3 e n seria o prefixo para isso. Portanto, há sempre extensões para carregar dados em um RDD do Spark a partir de várias fontes de dados distribuídas porque desperta tudo sobre big data, certo? Portanto, sua capacidade de carregar dados de armazenamentos de dados distribuídos é fundamental para o que você está fazendo. Mas não precisa ser um arquivo de texto. Você pode até mesmo criar um, um RDD de um, de um contexto de hive. Por exemplo, se você estiver usando o Hive, e você pode então virar e executar comandos SQL nesse alto contexto, se você quiser também. Então, essa é uma maneira de fazer SQL no ambiente Hadoop. Você também pode criar RDDs diretamente do JDBC. Então, se você tem um banco de dados lá fora em algum lugar, você pode facilmente transformar isso em um RDD e Spark. Você não pode falar com bancos de dados SQL como Cassandra ou Hbase. Você também pode integrá-lo ao Elastic Search, se quiser. E não precisa ser um arquivo de texto, você pode usar dados estruturados como JSON ou CSV ou arquivos de sequência ou arquivos de objeto. E também suporta vários formatos compactados. Novamente, com big data, às vezes os dados são compactados. E desde que seja algum formato sem perdas que possa ser paralelizado, então você pode criar um RDD a partir dele também. Uma vez que você tem um RDD, o que você faz com ele? Bem, você provavelmente quer transformá-lo de alguma forma e há várias operações para fazê-lo. Mapa, por exemplo, funciona como MapReduce realmente. Ele permite que você aplique alguma função a cada linha do seu RDD em paralelo. E veremos um exemplo disso em breve. Flatmap é semelhante. A única diferença entre mapa e FlatMap é que mapa tem um relacionamento um-para-um. Então mapa vai tomar uma linha de seu RDD e transformá-lo em uma linha de outro RDD. Flatmap, quem pode dividir as coisas. Assim, FlatMap poderia tomar uma linha de um RDD e criar várias linhas em outro RDD. Então, por exemplo, se você tivesse uma lista de coisas em cada linha, FlatMap poderia dividi-lo em linhas individuais para cada coisa. E veremos isso em um exemplo em breve. Você também pode fazer filtros. Então, se você quiser remover dados, limpar dados, você pode fazer isso também. Você pode definir uma função de filtro com a qual cada linha será testada. E se essa função retornar false, ele irá jogá-lo fora no RDD resultante. Então essa é uma boa maneira de limpar seus dados e se livrar de dados perdidos, coisas assim. Você também pode executar distinta nele. Se você quiser eliminar valores duplicados em seus RDDs, você pode fazer uma amostra. E se você quiser apenas pegar uma pequena amostra de um RDD para fins de experimentação ou o que for. E você também pode fazer operações booleanas extravagantes entre RDDs, como a união de dois RDDs, a interseção de dois RDDs, você pode subtrair um RDD de outro ou fazer um produto cartesiano entre dois RDDs também. Esses são casos de uso mais avançados. Vamos ver isso em ação. Então vamos dizer que eu quero apenas acertar tudo no meu RDD. Digamos que você tenha um RDD que eu estou chamando RDD nome verdadeiro criativo, certo? E nós fizemos isso fazendo esse truque paralelizado novamente, nós apenas temos um RDD de quatro linhas onde cada linha contém respectivamente 1234. Na próxima linha, estamos criando um novo RDD chamado quadrados apenas chamando RDD dot map x x x vezes x. Então o que isso está fazendo é passar a função, tomar X e transformar isso em x vezes x e aplicando isso a cada linha no RDD, RDD, o RDD resultante será chamado de quadrados. Então quando estivermos, depois de terminarmos a operação do mapa, os quadrados conterão as seguintes linhas, 1, 4, 9 e 16, certo? Então, seguimos, sigam-me até lá. E a beleza disso é que, que pode ser distribuído. Então, se D já era realmente enorme, ele poderia realmente dividir esse processamento e lidar com esse quadrado em diferentes partes do RDD em diferentes, diferentes nós dentro do seu cluster, e então sugar todos esses retorna ao script do driver para obter as respostas finais que você deseja. Então isso é uma sintaxe um pouco estranha lá. Você pode não ter visto isso antes. Aquela coisa de x a x vezes x do que está acontecendo lá? Bem, é disso que estamos falando quando dizemos programação funcional. Então, muitos métodos RDD vão aceitar uma função como um parâmetro e não apenas um valor. E é isso que está acontecendo aqui. Então, sintaticamente x e então a seta funky para x vezes x é a mesma coisa que definir uma função para quadrar algo. Vamos chamá-lo de quadrado. E este slide que leva algum inteiro chamado x e retorna x vezes x. Na verdade, a palavra-chave return seria opcional e Scala, você pode apenas dizer x vezes x e ele iria apenas funcionar. E, em seguida, dizendo mapa de pontos RDD passando na função raiz quadrada, aplicaria essa função raiz quadrada a tudo no RDD. Mas sintaticamente é a mesma coisa que dizer RDD dot map x, flecha funky x vezes x. Então você tende a ver essa abreviação. Se você tem uma transformação muito simples que você está fazendo, que você pode entrar em uma linha lá. Mas isso é tudo o que é. Como se estivéssemos passando essa função. Então, neste exemplo, estamos definindo uma função sobre como quadrar números. E estamos passando essa função para o RDD através do operador do mapa lá. E é isso que você entende a programação funcional. Agora, esse é o conceito chave. Estamos apenas a passar funções. E a maior visão aqui é que, você sabe, a linguagem da escala em si está forçando você a escrever essas funções que podem ser distribuídas. Então, as características de escala e tornar mais fácil de fazer isso um pouco, mas isso é, é isso. Isso é tudo o que queremos dizer por programação funcional. Sabe, estamos pensando em paralelo e aplicando funções, dois grandes conjuntos de dados passando essas funções para coisas como RDDs sobre isso, é isso. Não são assim tão duros. Tudo bem, uma vez que você realmente transformou tudo em seu RDD do jeito que você quer. O que você faz com ele? Como você obtém seus resultados de volta? Bem, é disso que se trata uma ação de RDD. Portanto, uma ação é basicamente algo que faz com que seu RDD colapse e devolva um resultado de volta ao seu script de driver. Uma coisa que você poderia fazer é chamar recolher no RDD que só vai dar-lhe tudo em que RDD volta como uma estrutura de dados gigante em Scala. Você sabe, se é um grande conjunto de dados que não vai fazer muito sentido com mais frequência você vai estar tentando obter mais de uma operação reduzida dele. Por exemplo, poderíamos dizer contagem se quisermos apenas contar quanto material está no RDD, podemos dizer contagem por valor. Se você quiser obter uma contagem de quantas linhas existem para cada determinado valor exclusivo em um par chave-valor. Você poderia levar para apenas, você sabe, espécie de amostra de um certo número de linhas do topo RDD para pegar as primeiras linhas ou reduzir para obter algum tipo de total geral de todas as linhas em seu RDD. E há mais ações também. Mas a idéia básica é que uma ação RDD lhe dá alguma resposta de volta ao script de drivers. Então ele tem uma força faísca para sair e dizer, Ok, eu vou você processos executores terminaram o que você está fazendo e me dar uma resposta. E nós vamos dar essa resposta de volta ao meu roteiro de motorista. Então é isso que uma ação faz. E a maneira como isso funciona é interessante. Então você tem que se lembrar disso em Spark. Nada realmente acontece em seu programa de driver até que você cite uma ação. É uma estratégia de avaliação preguiçosa aqui. E há uma boa razão para isso. Então, até que o Spark saiba o que você está tentando alcançar através da ação que você está tentando obter no final, ele não sabe como otimizar todas as operações que você fez. Então lembre-se que a chave ou uma chave para o desempenho do Spark é que ele pode construir este gráfico acíclico direcionado que é muito otimizado para o resultado final que você deseja alcançar. Então isso pode ser um pouco confuso enquanto você está depurando seus scripts de driver do Spark porque, você sabe, você pode chamar alguma operação de mapa ou algum tipo de transformação em seu RDD. E vai parecer que nada aconteceu no seu código. Não é até que você realmente chamar uma ação que qualquer coisa é realmente vai ser executado e enviado para os vários nós em seu cluster e você realmente vai obter um resultado. Então isso pode tornar a depuração um pouco complicada, certo? Às vezes você precisa colocar um pouco de ação temporária lá para voltar e resultado intermediário em. Certifique-se de que é o que você espera ao depurar os scripts de driver do Spark. Então algo para estar ciente, especialmente enquanto você está depurando essas coisas. E com isso, vamos mergulhar em alguns detalhes mais específicos a seguir. 9. Exemplo de histograma: Então, geralmente é melhor entender as coisas através de um exemplo, certo? Então vamos fazer isso. Vamos aprender sobre RDDs olhando para um exemplo realmente simples de usá-los. Então vamos mergulhar em um exemplo simples em nossos materiais do curso que apenas conta o número de uma determinada classificação dentro do nosso conjunto de dados MovieLens. Como você se lembra, o conjunto de dados MovieLens é um conjunto de dados de 100 mil classificações de filmes, onde as pessoas classificaram um monte de filmes de uma a cinco estrelas. E digamos que só queremos descobrir quantas classificações de uma estrela existem, quantas classificações de duas estrelas, quantas classificações de três estrelas, etc. Bem, isso é algo que podemos fazer com o Apache Spark. Então, antes de eu mergulhar no código aqui e o que ele está fazendo, vamos apenas executá-lo e familiarizar-se com o que ele está fazendo e tipo de ficar confortável com o código em si. Então vamos fazer isso. Então, se você abrir a inteligência e ir para o arquivo do contador de classificações aqui, esse é o que vamos jogar aqui e mergulhar em exemplo muito simples de um script de driver apache Spark aqui. E vamos falar sobre cada linha e o que ela faz com mais detalhes. Mas em um nível alto, o que estamos fazendo é carregar o conjunto de dados MovieLens em cada núcleo de CPU de nossa máquina aqui. E vamos contar quantas vezes cada valor de classificação exclusivo ocorre dentro desse conjunto de dados. Então vamos carregar cada linha que representa cada classificação nesse conjunto de dados. E vamos dividir isso em seu próprio RDD. Vamos contar quantas vezes cada classificação aparece, classificar os resultados e imprimi-los. E vamos apenas executá-lo e nos convencer de que funciona e faz algo interessante, certo? Então, vamos clicar com o botão direito no contador de classificações e dizer Executar. E se clicarmos, lá vamos nós. E isso deve explodir no spin up Spark. E aqui estão as nossas respostas. Então o que isso está nos dizendo é que tínhamos 61101 classificações de estrelas, 11.372 classificações de estrelas, 27.145, classificações de três estrelas, e assim por diante e assim por diante. E esses dados em si são meio perspicazes, certo? Como nos diz que a classificação mais comum para um filme é quatro estrelas. E há uma quantidade razoável de três estrelas e cinco estrelas não estão lá também. Mas as pessoas tendem a ser que pareciam ter uma escala razoável para como estão lendo esses filmes. E eles parecem estar reservando uma estrela para o pior dos piores. Então, de 100 mil classificações, apenas 6000 e algumas mudanças, nós somos realmente classificados como uma estrela. Então isso nos dá alguma confiança de que esses dados são significativos apenas neste script muito simples aqui, mesmo. Então, vamos voltar e falar mais sobre o que esse código está fazendo. Então vamos analisar o que este código está fazendo em cada etapa aqui. Então começamos importando o que precisamos. E nós apenas dizemos que estamos declarando isso dentro do pacote que nós nomeamos com Dotson Dogs Software, Dot Spark. Você sabe, isso é uma espécie de convenção no mundo Java de como você dá aos seus pacotes um nome único. Nesse caso, estou usando algum nome de domínio que possuo. E então importamos os pacotes que precisamos. Estamos apenas importando tudo do Spark e tudo do log para J porque vamos usar um log para J para ajustar nosso nível de erro em nosso log. Isso é tudo o que é. Em seguida, configuramos um contexto Spark, como falamos anteriormente. Então, definimos SC para um novo contexto Spark. A estrela de suportes locais significa que vamos estar rodando apenas em nossa máquina local. Então nós não temos um grupo funcionando na nossa sala de estar aqui, certo? Então. Com o propósito de experimentação e aprendizagem, nós vamos apenas estar rodando em nossa própria máquina única. Mas essa estrela significa que eu vou deixar que ela se paralelize, pelo menos através dos múltiplos núcleos de CPU que podem existir na minha máquina. Então, mesmo que esteja em um sistema, ele pode realmente girar mais de um processo e tirar proveito dos vários núcleos de CPU que eu tenho. E contador de classificações é exatamente o que estamos nomeando este aplicativo. Em seguida, carregamos os dados e nós apenas criar um RDD linhas chamando SC dot txt arquivo com um caminho relativo para onde esses dados estão. Em nosso código, esse caminho é mais explícito sobre onde ele realmente reside em nossos materiais do curso, mas você tem a idéia. Portanto, ele tem um caminho para o arquivo de dados u dot, que é o arquivo de dados que contém todas as informações de leituras e o formato disso. Um exemplo disso está no canto superior esquerdo aqui. Então, cada fileira se parece com isso. Começa com um ID de usuário e, em seguida, um ID de filme, uma classificação e, em seguida, um carimbo de data/hora. Então tudo está codificado em algum tipo de ID numérico aqui. Quero dizer, eu não sei o que usuário 196 é ou qual filme ID 242 é. Há um arquivo separado para procurá-los. Mas ID do usuário 106 avaliado filme 2423 estrelas. E eles fizeram isso nessa época, que se traduz em alguns, você sabe, algum encontro e que poderíamos humanamente ganância, mas computadores como Epoch segundos. Então esse é apenas o formato desses dados. Então a primeira coisa que vamos fazer é carregar todas as 100 mil linhas desse arquivo no RDD de uma linha, onde cada linha representa uma linha desse arquivo de dados. Ok? E novamente, estamos começando com RDDs aqui. Vamos na próxima seção falar sobre como fazer todas essas coisas usando conjuntos de dados em vez disso, que é a API mais moderna. Mas, novamente, ambos são uma ferramenta útil. Às vezes, os RDDs serão mais rápidos do que os conjuntos de dados. Às vezes, os RDDs permitem que você faça mais. Então, estamos começando com o básico, a API de nível inferior aqui de RDDs. E você descobrirá que usar conjuntos de dados não é muito diferente. Mas vamos começar com RDDs aqui. Agora temos o RDD de uma linha. Em seguida, precisávamos fazer algo com esses dados. Então, a primeira coisa que queremos fazer é extrair a informação que realmente nos importamos desse RDD. Então vamos chamar mapa nas linhas RDD, passando-o em uma função de como queremos transformar cada linha desse RDD. E neste caso, a função está pegando cada linha e chamando x. E então nessa linha, essa string, vamos convertê-la explicitamente em uma string e chamar split sobre ela, dividindo no caractere tabulação porque isso é dados delimitados por tabulação e extração ajustar o campo número 2. Agora lembre-se, na ciência da computação, muitas vezes começamos a contar a partir de 0. Então, dois é na verdade a terceira coluna de dados. Então o que isso está fazendo é extrair essa terceira coluna, que é a classificação em si, e nada mais. Então ele está extraindo essa classificação de cada linha e inserindo isso em um novo RDD chamado classificações. Siga-me. Então começamos com um RDD linhas, que são aqueles no canto superior esquerdo ali. Chamamos uma função de mapa sobre ele para aplicar esta função a cada linha única das linhas RDD para extrair essa terceira coluna de dados, a própria classificação. E isso vai para um novo RDD chamado classificações, que neste exemplo apenas contém 33 um para um em cada linha das classificações RDD respectivamente. Então é para isso que o mapeamento está sendo usado lá é apenas para extrair os dados que nos importamos. E você sabe, em alguns casos você pode reformatar coisas ou colocá-lo em um formato diferente que algum processo a jusante quer. Mas geralmente é disso que se trata o mapeamento. Então agora precisamos fazer algo com toda essa informação. Então, neste caso, vamos executar uma ação e nossa ação neste caso é contagem por valor. Isso é o que fará com que nossos dados desmoronem e nos devolvam uma resposta. Então o mapeamento que fizemos no slide anterior poderia ter sido distribuído entre muitos nós executores, certo? Mas ao dizer que queremos contar os valores, Isso vai nos dar de volta uma resposta explícita e passar algum resultado de volta para o nosso script como um objeto Scala. Então, neste caso, estamos dizendo que as classificações ponto contam por um valor. Isso vai fazer o que diz. Dê a você uma contagem de quantas vezes cada valor exclusivo aparece. Então, neste exemplo, temos 23 classificações. Então nós recuperamos o valor três vírgula dois, o que significa que para a classificação 3, existem dois deles. Para a classificação um, há dois deles também. E para a classificação dois, há apenas um deles. Então é isso que a contagem por valor retorna. E, neste caso, não está nos devolvendo um novo RDD. É passar isso de volta para nossos scripts de drivers que estão indo para um, um novo valor chamado resultados no nível Scala. Então, chamando essa ação, pegamos esses resultados de volta do cluster e os colocamos de volta em nossa unidade ou script local. E neste ponto nós não estamos mais em terra faísca estavam de volta na linha Scala. Estamos de volta ao guião do condutor. É onde o estado está vivendo neste momento. E nesse ponto nós só queremos classificá-lo e exibi-lo. Então temos um pequeno código Scala aqui para pegar esse conjunto de resultados, convertê-los em uma sequência e classificá-los pelo segundo campo. E então nós apenas imprimi-los aplicando a função de linha de impressão a cada linha do resultado final, a cada linha dessa sequência que definimos, certo? Então, novamente, esta é apenas a sintaxe Scala aqui. Estamos pegando os resultados, convertendo em uma estrutura de dados de sequência, classificando por essa segunda coluna. E, em seguida, para cada linha dessa sequência dentro de Scala, estamos aplicando a função de linha de impressão para imprimir o conteúdo disso. E é assim que vemos o nosso resultado final aqui. Onde tivemos ver que temos que 1 classificação de estrelas, classificação de 12 estrelas, e duas classificações de três estrelas. Então é tão fácil assim. Novamente. Vamos executá-lo e apenas nos convencer de novo que ele funciona agora que temos mais de uma apreciação do que o código está fazendo. Então, agora que falamos sobre esse código em mais profundidade, se olharmos para isso novamente, deve fazer um pouco mais de sentido. Algumas coisas sobre as quais não conversamos. Então, primeiro de tudo, nós envolvemos todo esse código e integração é objeto contador. Então isso é apenas uma espécie de, você sabe, como as coisas precisam ser estruturadas para um script de driver e em Scala. Então, dentro deste objeto de contador de raio, definimos uma função principal. Esta é basicamente a estrutura que cada script de driver precisa estar conformidade para o Apache Spark. E a primeira coisa que fizemos, sobre a qual realmente não falamos com a definição do nível de erro em nossos logs para erro. E infelizmente, como viram aqui, alguns avisos passaram antes que o código fosse executado pelo Spark. Mas uma vez que o script do driver realmente começa a ser executado, isso vai impedir que quaisquer mensagens de log que são algo menos do que um erro sejam exibidas. E isso é apenas para reduzir nosso alcance e nos deixar ver os resultados. Então queremos ver mais do que um monte de avisos que não podemos fazer nada. Depois disso, entraremos no código que falamos nos slides. Então criamos nosso novo contexto Spark. Chamamos de C. Está configurado para usar todos os núcleos em nossa máquina local e chamamos o nome do aplicativo ou contador de classificações. Nós carregamos a partir dos dados ML traço 100 K diretório ru arquivo de dados ponto, que contém cada linha de cada classificação individual nesse conjunto de dados. Esta é a carne de tudo isso aqui. Este é o lugar onde chamamos a função de mapa nas linhas RDD e aplicar esta função que divide e cada linha em seus campos individuais com base no delimitador de tabulação e extrai o terceiro campo. Novamente, começamos a contar de 0. Acontece que esse é o valor real da classificação em si. Isso é jogado em um novo RDD chamado classificações, que contém cada classificação individual. Em seguida, chamamos a contagem de ação por um valor para para Spark ir e nos dar uma resposta e descobrir a maneira ideal de obtê-lo. Uma vez que isso é executado, nós temos uma estrutura de resultados aqui que está apenas vivendo dentro do nosso script de driver agora. Portanto, não estamos mais tendo nossos dados no cluster. Recolhemos isso em alguns resultados dentro do roteiro. E agora podemos tomar essa estrutura de dados de vieira resultante convertido em uma sequência classificada pelo seu segundo campo real lá, que é o valor de classificação real. E, em seguida, aplique a linha de impressão a cada resultado classificado para imprimir a resposta final. E vamos executá-lo mais uma vez só por diversão. Então, novamente, podemos apenas clicar no scanner 3D e clicar com o botão direito e executar. Mas como já fizemos isso uma vez, vai estar em um atalho aqui também, podemos apertar o botão play e fazer de novo. E lá está ele de novo. Tão legal. Certo, falamos sobre o código e como ele funciona, e você tem uma ideia aproximada de como usar RDDs e praticar. Mais uma vez, vamos falar sobre conjuntos de dados mais tarde, muito em breve, não se preocupe, estamos chegando lá. Mas primeiro vamos falar mais sobre o que aconteceu sob o capô quando fizemos tudo isso dentro do nosso grupo. 10. Internals internais: Então, o que realmente aconteceu debaixo do capô quando tudo isso correu? Vamos falar sobre isso em um pouco mais de profundidade. Então, quando nosso script de driver chegou a essa ação, o comando count by value e plano de execução foram criados a partir desses RDDs que definimos. Então é meio que descobrir o que eu preciso fazer para realmente obter a resposta final. Neste caso, parece assim, certo? Então começamos com esse arquivo de texto, os dados brutos do nosso RDD. E nós vamos chamar uma operação de mapeamento que pode ser aplicada em paralelo em vários processos ou vários computadores até mesmo para extrair as classificações que queremos lá. E então, finalmente, vamos fazer uma ação de contagem por valor para adicionar todos eles. Então o plano de execução, ele vai dizer, hey, eu posso fazer todas as coisas primeiro mapeamento totalmente em paralelo. Mas essa ação vai exigir que você essas notas que falam uns com os outros alguma forma e tipo de comunicação e Coli, seus resultados. Então o que acontece é que o trabalho é dividido em estágios com base em quando os dados precisam ser reorganizados. Assim, esse mapeamento paralelo pode ser um estágio que não requer qualquer tipo de reorganização dos dados em si. Mas a contagem por valor embaralha as coisas um pouco, certo? Então, isso precisa ser seu próprio estágio separado no processo. E, em cada estágio, ele é dividido em tarefas que podem ser distribuídas pelo cluster. Então, talvez no primeiro estágio, você sabe, essas setas roxas estão processando partes dos dados e isso vai para um executor. Executor, talvez os verdes vão para outro executor e o azul vai para um terceiro executor, certo? Então ele pensa sobre como eu distribuo esses dados forma eficaz e que contam por operação de valor, bem, isso não é facilmente paralelizável. Então isso se torna uma espécie de estratégia diferente lá. E, finalmente, as tarefas são agendadas em todo o cluster e executadas e você obtém sua resposta. Então, sob o capô, Isso é o que aconteceu para realmente obter nossa resposta final de quantos de cada tipo de classificação existiam em nosso conjunto de dados. Não são assim tão duros, mas sob o capô, é o que está acontecendo. 11. Exemplo de de amigos média por época: Então vimos alguns RED muito simples estes em uso com nosso contra-exemplo de classificações anteriormente. Mas também há um tipo especial de RDD chamado o valor chave RDD. E com esses RDDs, há algumas operações adicionais que você pode executar que podem ser úteis. E vamos olhar para isso com um exemplo com nossos amigos por idade script aqui. O que vamos tentar fazer no final do dia aqui, ou no final desta lição, é descobrir como calcular o número médio de amigos por idade. Então estamos começando com um conjunto de dados que tem um monte de pessoas individuais, seus nomes, sua idade, e quantos amigos eles imaginaram que conseguimos isso de alguma rede social em algum lugar, certo? Então, neste caso, vamos estruturar nossos dados em pares de valores-chave. RDDs podem segurar essas coisas. No nosso caso. Neste caso, a chave será a idade e o valor será o número de amigos. Porque queremos procurar as coisas pela idade, escrever, consolidar as coisas e reduzi-las por essa idade. Então, em vez de apenas uma lista de idades ou lista de número de amigos e um RDD. Podemos armazenar isso de uma forma mais estruturada onde cada rover RDD consiste em uma tupla de uma determinada idade, um número de amigos para um indivíduo, a idade eo número de amigos para outro indivíduo, et cetera, et cetera. Então, agora temos esses pares de valor de chave em cada linha do nosso RDD. Como você cria estes sintaticamente? Não é nada muito especial em Scala. Tudo o que você precisa fazer é mapear pares de seus dados no RDD usando tuplas. Então, por exemplo, se eu quisesse apenas pegar um RDD que tivesse uma coisa lá e criar um par de valor chave dessa coisa como a chave e o número 1 é o valor. Eu poderia chamar uma operação de mapa que diz tomar a linha, todo o seu texto é x e transformá-lo na tupla x vírgula um. E isso se torna um par de valores de chave onde a chave é x e o valor é um. Isso é tudo o que há para ele. Agora você tem um valor de chave, RDD, e você não está limitado a ter uma coisa e a chave é uma coisa e o valor que você pode ter tuplas ou outros tipos de objetos como valores também. Então, em vez de uma, eu poderia ter outra tupla embutida dentro dela. Então eu posso ter cólon x, imprimir o mar, você sabe, algo vírgula algo vírgula algo mais. Feche parênteses se eu quisesse também. Portanto, você não pode ter tipos de dados mais complexos incorporados como parte do seu valor às vezes que são úteis. Assim que você tiver esses pares de valor de chave em seus RDDs, Spark pode fazer algumas coisas especiais com eles. Existem algumas novas funções que se tornam disponíveis para você. Um é reduzido por chave, e isso é útil para combinar todos os valores para a mesma chave juntos de alguma forma. Então basicamente você forneceu uma função que define como eu combinar todos os valores juntos para uma determinada chave? Neste caso, estamos passando nesta pequena função que diz x, y, seta funky x plus y. Então isso significa que para combinar algum tipo de valores nesses valores, eu vou usar o operador de adição para combiná-los juntos. E isso é um pouco confuso o que está acontecendo sob o capô aqui. Então, ele pode estar mantendo um total de execução como ele passa por cada valor para uma chave única sob o capô lá. Então x pode representar nosso total atual. E por que eu represento o novo valor que ele está vendo de uma nova linha e adicionando-o a isso. Então o que é importante aqui é aquele operador do lado direito aqui. Neste caso, estamos dizendo explicitamente, queremos somar tudo em todos os valores para este RDD e devolver-nos uma resposta para cada chave única. Qual é a soma? Todos os valores associados a essa chave fazem sentido. Se não acontecer, teremos um exemplo que fará mais sentido quando você vê-lo em ação. Podemos também dizer grupo por chave. Então, isso vai apenas dar-lhe de volta um grupo de todos os valores para uma determinada chave. Não necessariamente reduzir as coisas, mas apenas permite organizar melhor seus dados e talvez passar isso para alguma outra operação. Mais tarde. Também podemos classificar por chave. Portanto, se você tiver pares de valor de chave, você pode fazer essa classificação dentro do cluster. Lembre-se de volta em nosso exemplo anterior para o contador de classificações, nós realmente obtivemos nossos resultados de volta ao nível Scala dentro do nosso script de driver e os classificamos lá. Essa não é a maneira mais escalável de fazer as coisas, certo? Seria preferível se pudéssemos classificar no cluster. E se tivéssemos um par chave-valor em vez disso, poderíamos ter feito isso. Além disso, temos chaves e valores, para que possamos extrair todas as chaves ou extrair todos os valores de um par chave-valor. Se você precisar voltar na outra direção e criar um RDD de apenas as chaves ou um RDD de apenas os valores que permite dividi-los de volta a partir de um par chave-valor. Além disso, é possível fazer junções de estilo SQL se você tiver dois RDDs de valor chave e teremos um exemplo disso mais tarde. Quero dizer, isso entra na área de onde você pode se perguntar por que você está usando RDDs se você estiver fazendo operação SQL. Então eu vou notar que você pode fazer isso. Mas na prática, obviamente você provavelmente estará usando conjuntos de dados são DataFrames são a API Spark SQL para fazer esses tipos de operações em faísca moderna. Além disso, se você tem que fazer algum tipo de operação de mapeamento em um valor chave RDD e você só vai estar transformando a parte de valor. Um pequeno truque é usar valores MapValues ou FlatMap. Dessa forma, você pode simplesmente aplicar sua transformação apenas para a parte de valor que vai ser mais eficiente do que tentar descobrir como manter a chave fora do lado e afetar apenas a parte de valor. Portanto, é um, tanto mais eficiente em uma maneira mais fácil de aplicar uma operação de mapeamento apenas para os valores de um valor chave RDD. Então lembre-se disso. Então vamos mergulhar um pouco mais no nosso exemplo. Então, novamente, o que estamos tentando fazer é descobrir o número médio de amigos para uma determinada idade, dado algum pequeno conjunto de dados falso aqui. Então, novamente, imagine que temos uma rede social de algum tipo, onde temos um monte de pessoas que estão em nossa rede social. E para cada pessoa, sabemos sua idade em anos, e sabemos quantos amigos eles têm em nossa rede social. Então, por exemplo, cada linha pode se parecer com isso. Algum tipo de ID de usuário seguido de seu nome, seguido de sua idade, seguido de seu número de amigos. Então Will tem 33 anos e tem 385amigos. John Luke tem 33 anos e tem dois amigos. Ele tinha 55 anos e tem 221amigos e assim por diante. Então a primeira coisa que precisamos fazer é mapear os dados de entrada e dividi-los em algum tipo de estrutura. E aqui estamos definindo uma função de linha de análise que leva em cada linha individual desse RDD e divide-a com base na vírgula. Delimitador, extrai o campo H e chama na idade, extrai o campo do amigo num e chama de amigos num. E então devolvemos uma tupla, um par de valores-chave de amigos de idade. Então, a idade neste caso é a chave e o valor é amigos entorpecidos. E vemos aqui na próxima linha que criamos as linhas RDD carregando os falsos amigos ponto-ponto CSVs dados brutos. Em seguida, chamamos mapa com essa função de linha de análise para transformar esses dados brutos em um novo RDD chamado RDD que contém pares chave-valor. Assim, a saída aqui do RDD ficará assim na parte inferior. Um par de chave-valor. Por exemplo, 33 é a chave, o ano, a idade, e 385 é o número de França. Então, novamente, número de idade da França. A chave é a idade, o número de valores da França e outros 33 anos de idade tinha dois amigos. Uma garota de 55 anos tinha 221amigos, assim por diante. E você pode ver que podemos ter valores duplicados aqui para chaves, certo? Portanto, as chaves não precisam ser únicas neste contexto, não até reduzirmos as coisas. Em seguida, queremos começar a reduzir esses dados para baixo no entanto. Então, para calcular a média, precisamos ter duas coisas, certo? Precisamos ter a soma total de quantos amigos existiram para uma determinada idade e quantas pessoas que a representam. Então, para calcular a média, vamos comer o número total de amigos que têm idade e o número de pessoas que existiram para essa idade. E dividindo esses dois obterá a média que queríamos no final do dia. Então, o próximo passo é calcular esses totais. E é isso que está acontecendo aqui. Agora, muitas vezes você verá nos scripts de driver do Spark, pessoas meio que juntando as coisas em uma grande linha longa. Então você pode muito bem se acostumar com isso. Agora, vamos falar sobre o quê, vamos quebrar o que está acontecendo aqui, certo? Então vamos dividir isso em seus dois componentes. Estamos começando com valores de mapa de pontos RDD X a X vírgula um. Então o que isso vai fazer é pegar cada valor e transformar isso em sua própria tupla desse valor e depois um. Agora, o método para esta loucura é que, associando um com cada valor lá, eu posso somar todas essas entradas individuais e obter o grande total de quantos existiram para essa idade. Está bem. Então esse é apenas dizendo que vou contar cada linha individual como uma, e vou resumir isso mais tarde para obter um grande total, um pouco de um truque lá. Então, após este ponto, quando executamos essa operação MapValues, isso é o que nosso RDD será parecido. Então, por exemplo, 33, 35, que nos dizia que um garoto de 33 anos tinha futuro 95. A França vai ser transformada na mesma coisa. A chave ainda é 33, mas o novo valor é uma tupla de 385 vírgula um. E fazemos isso para cada linha no RDD. E a seguir dizemos ponto ReduceByKey. Então não atribuímos explicitamente o resultado disso a um novo RDD chamado. Nós estávamos indo apenas para passar esse novo RDD diretamente para outra operação aqui, neste caso a ação ReduceByKey. Então esta operação aqui irá somar os dois elementos dessa tupla no valor, certo? Então o que está acontecendo aqui é que estamos dizendo que vamos tomar 22 entradas aqui do nosso RDD que estamos reduzindo, chamá-los x e y. vamos adicionar juntos o primeiro elemento de ambas as tuplas e o segundo elemento de ambas as tuplas, e adicioná-los todos para cada chave única. Ok? Então veja onde estamos indo com isso. Então, neste ponto, o que temos aqui é para todas as crianças de 33 anos lá fora, nós reduzimos esses dados para o grande total de todo o número de amigos que as crianças de 33 anos tinham e o número total de 33 anos tinham existido. Então pense nisso por um minuto. É um pouco complicado. Nossa estratégia aqui era voltar aqui, ok, nós mapeamos tudo para essas tuplas de 433 year-old para cada indivíduo, tivemos uma tupla do número de amigos que a pessoa tinha no número de um. E este truque aqui é fazer isso e adicioná-los todos juntos. Se juntarmos todo o primeiro elemento dessa tupla de quantos amigos cada, cada 33 anos tinha, obtemos o total de quantos amigos de 33 anos tinham. E, em seguida, juntando-o, todos esses, nós temos uma contagem de quantas crianças de 33 anos havia. E isso nos dá as duas coisas que precisamos para calcular a média que queríamos. E é isso que fazemos no próximo passo. Dizemos valores de mapa e tudo o que fazemos é passar por cada valor, cada tupla que acabamos com, e dividi-los uns pelos outros para obter o número médio final que queremos no resultado final. Ok? Nesse ponto, podemos simplesmente coletar e exibir os resultados. Então, vamos dizer colete para recuperar que os valores médios reduzidos. E nós vamos classificá-los e chamar a linha de impressão e cada um para exibir o resultado final. Então, com isso, vamos em frente e realmente executá-lo em nossa próxima palestra. 12. Exemplo de [a atividade] de qual de amigos médias por idade: Tudo bem, vamos mergulhar no código e ver como tudo funciona em ação aqui e vamos executá-lo e ver se funciona. Então isso é tudo o que falamos nos slides anteriores. Certo, então vamos passar pelo código aqui uma linha de cada vez. Então começamos declarando que pacote vivemos dentro desse tipo de coisa padrão para qualquer script Scala. E então importamos os pacotes dos quais dependemos. No nosso caso, estamos sendo um pouco preguiçosos e apenas importando tudo do Apache Spark e também do log para J. Nós então definimos os objetos que nosso script vive dentro. Vamos chamá-lo de amigos por idade, que deve coincidir com o nome do arquivo. Eu vou pular a função de linha de pacote por agora e ir para baixo para a função principal porque é onde a execução vai começar dizendo que estamos fazendo novamente é definir o nível de log para erro para que nós não obter um monte de logs spam sobre avisos que não podemos fazer nada. Haverá alguns que escaparam antes que isto seja executado, mas vamos apanhar a maioria deles, pelo menos. Em seguida, criamos nosso contexto Spark, novamente configurado para ser executado em nossa máquina local usando cada núcleo de CPU. E daremos aos nossos amigos nomes de aplicação por idade. A próxima coisa que fazemos é carregar nossos dados brutos e há um traço de amigos falsos, nenhum arquivo CSV heterodoxo. Essa é uma versão dos dados que não tem linha de cabeçalho que pode, que pode atrapalhar você. Então, esteja ciente disso. E vamos carregar isso no RDD de uma linha onde cada linha representa uma linha desses dados. Então, como esses dados se parecem? Vamos dar uma olhada rápida só para nos lembrar. Então parece assim. Lembre-se que a primeira coluna é o ID do usuário, a segunda é o nome e a idade e o número de amigos e tudo o que nos importa para o nosso problema são as duas últimas colunas, certo? Eu realmente não me importo se o ID do usuário é, eu não me importo se o nome deles era. Eu só estou tentando descobrir o número médio de amigos para cada dado um para que eu possa jogar fora as duas primeiras colunas. E isso é o que fazemos na função de linha de análise aqui. Então vamos pegar a função de linha de análise, mapear isso para cada uma dessas linhas de entrada e obter um novo RDD chamado RDD. Vamos ver o que a linha de encomendas faz. Então o que isso está fazendo é dividir cada linha por uma vírgula porque é um arquivo de valor separado por vírgula. E extraímos os campos 2 e 3. Essas são as duas últimas colunas em nossos dados. Ele vai chamá-los idade e amigos NAM e retornar uma tupla de idade e amigos NAM. E novamente, essa tupla se tornará nosso par de valor chave em nosso RDD, RDD. Então agora a idade vai ser a nossa chave e amigos NAM será o nosso valor para cada pessoa individual que temos em nosso conjunto de dados. Então é aí que estamos. E agora temos aquela linha realmente complicada que passamos muito tempo falando. 13. Como filtragem: Então, em seguida, vamos falar sobre filtragem. Seus RDDs. A filtragem é uma operação muito simples que permite que você limpe os dados de seus RDDs e você verá que o mesmo conceito é transferido para as outras APIs em ofertas de faísca também. Ilustraremos isso com alguns exemplos usando dados meteorológicos. Estes são dados do mundo real de duas estações meteorológicas diferentes na Europa. E o que vamos fazer é usar filtragem para limpar esses dados antes de extraí-los para que a temperatura mínima e máxima seja registrada dentro de um determinado ano nessas estações meteorológicas. Usar um filtro é muito simples. Tudo o que você faz é fornecer uma função que retorna um booleano. E se esse booleano retornar verdadeiro, então manteremos essa linha, caso contrário, removemos do RDD. Então, por exemplo, se quiséssemos filtrar entradas que não têm T min como o segundo item na tupla de dados, poderíamos dizer linhas analisadas filtro ponto, assumindo que linhas de análise é que RDD que contém essas tuplas. E passando para a função onde cada linha de dados é chamado x. e verificamos se o segundo elemento de x é igual a equipe em. Se for, então ficaremos com ele. Se isso não acontecer, então nós removê-lo no resultado Min tenta RDD. Assim, termos Min contém os resultados filtrados de linhas analisadas. Aqui está um exemplo desses dados brutos que estão em nossos dados de origem para este exemplo. Então o que vamos tentar fazer aqui é encontrar a temperatura mínima dentro de um ano para uma determinada estação meteorológica. E esse primeiro identificador, primeira coluna de informações em nossos dados de entrada é o identificador da estação. Então isso só representa onde a leitura da temperatura foi feita. Depois disso, é o ano real e a data em que a medida foi feita. Então você pode ver que este é um conjunto de dados muito antigo que remonta ao ano de 1800. E você pode ver que temos muitos tipos diferentes de dados sendo registrados neste conjunto de dados. Tmax indica a temperatura máxima registada naquele dia na estação meteorológica. T min é a temperatura mínima registada e a precisão é a quantidade de precipitação registada. E o formato dos dados de temperatura é um pouco estranho. São graus Celsius multiplicados por 10. Então negativo 75 é realmente negativo 7,5 graus Celsius precisará lidar com isso enquanto analisamos dados e importamos. Aqui está o que esse código parece que faz analisar esses dados. Então, para cada linha que recebemos que lemos para aquele arquivo de texto CSV de 8800 pontos, vamos usar essa função de linha de análise para realmente fazer sentido disso. Você pode ver que no início o divide com base no delimitador de vírgula. Ele extrai o ID da estação, que é o primeiro campo, e o tipo de entrada, que é um segundo campo. E, finalmente, o número de temperatura em si. E vocês podem ver aqui que começamos multiplicando isso por 0,1 para obter dois graus centígrados. E então nós convertemos isso em graus Fahrenheit porque eu vivo nos Estados Unidos, que eu acho que é um dos últimos países que ainda usa a escala Fahrenheit. Mas de qualquer maneira, se você quiser manter essa parte fora e mantê-lo em centígrado, por mim tudo bem, eu não vou dizer a ninguém o que nós devolvemos é uma tupla que contém o ID da estação , o tipo de entrada, que neste caso será equipe em T max ou precipitação e a temperatura associada a essa entrada. Então, a seguir, precisamos filtrar as informações que não queremos. Então só estamos interessados em entradas T min porque a pergunta que estou respondendo é qual era a temperatura mínima ao longo do ano para cada estação meteorológica. Então eu não me importo com as temperaturas máximas que foram registradas. Não me importo com a precipitação. Vou jogar toda essa informação fora. Então, apenas dizendo linhas de análise filtro de pontos, verificando se esse segundo campo é igual a T min. Eu posso jogar fora todos os dados onde isso não é verdade, certo? Então, se x ponto sublinhado dois é igual a equipe e eu vou preservar essa linha e as temporárias Min resultantes RDD. Caso contrário, vou filtrar. Então isso vai se livrar de todas as outras coisas além da equipe em entradas. Então esse é o filtro em ação. Depois disso, podemos criar os pares de valor de chave de temperatura ID da estação porque queremos fazer alguns truques com RDDs de valor chave, base em nossa lição anterior. Então vamos mapear essa temperatura mínima para uma nova tupla que consiste apenas na identificação da estação e na temperatura. Não precisamos mais dessa equipe no campo tipo de entrada porque sabemos que tudo está em uma equipe, então isso é apenas espaço desperdiçado, certo? Então vamos converter isso para apenas um ID de estação e a temperatura da temperatura mínima para cada linha que se qualificou. E chamaremos isso de novos temporários resultantes da estação RDD. E então defina o mínimo. Tudo o que podemos fazer é dizer ReduceByKey. Então, novamente, estamos usando uma espécie de truque chave-valor aqui e fazendo uma operação de redução nele. Então, basicamente, queremos pegar cada total de execução que temos para a temperatura mínima atual, comparar isso com uma nova linha. Então isso vai ser x e y. e nós vamos executar os homens de operação mínima para preservar apenas o valor mínimo visto. Então, basicamente, ele vai continuar passando por linha todas as temperaturas mínimas para uma determinada chave, onde cada chave representa uma estação meteorológica. E vai continuar, tentando manter o controle da temperatura mínima vista. Então ele vai olhar para a primeira fila. Olhe para a segunda linha é um secundário ou menor que a primeira linha. Certo, ótimo, esse é o novo mínimo. O terceiro regrow é grande, menos do que a segunda fila? - Não. Está bem. O segundo continua a ser o mínimo ainda, por isso continua acompanhar a temperatura mínima que é encontrada. E o que vamos acabar com é um RDD muito menor chamado um minuto de tentativas por estação que apenas contém todas as chaves únicas. Neste caso, apenas dois IDs de estação meteorológica diferentes e a cena de temperatura mínima para cada estação. Nesse ponto, tudo o que temos que fazer é coletar os resultados. Então vamos chamar a ação de coleta para ir e forçar são RDDs para ir e realmente fazer algo em nosso cluster. E então vamos iterar através de cada resultado depois de classificá-los e extrair o ID da estação e a temperatura, vamos formatar a temperatura usando um formato de impressão como falamos de volta na introdução às lições de Scala. E imprima novamente usando o formato de substituição que falamos também. Então meio que colocar algumas dessas coisas de formatação de string que aprendemos mais cedo no curso em ação aqui. Então vamos apenas imprimir o ID da estação, as palavras de temperatura mínima dois pontos, e então a temperatura formatada com dois pontos decimais de precisão após o ponto decimal. Então vamos fazer isso e ver se funciona. 14. [de atividade] tendo o exemplo de temperatura mínima e modificá-lo para o máximo: Então, se você abrir o script de temperatura mínima na inteligência aqui, você deve ver este script aqui. Vamos percorrer linha por linha. E dado que você pode ser novo em escala, vou passar um pouco mais de tempo analisando a sintaxe aqui. É um exemplo bem simples, então não deve demorar muito. Então vamos abrir este bloco de importação aqui apenas para ter certeza de que vemos tudo com que estamos usando. Então, como de costume, começamos declarando o pacote em que estamos. Calma Dotson cães software ponto faísca, e importamos tudo o que dependemos. O que estamos importando tudo de Apache Spark, de log para J. E também precisamos Scala dot Math.min, a fim usar essa função Min para manter o controle das temperaturas mínimas que encontramos. Então o declaramos em temperaturas. Objeto para corresponder ao nome do nosso arquivo aqui. E novamente, vou pular a função de linha de análise por agora e ir direto para a função principal porque é aí que a execução começa. A primeira coisa que fazemos é definir o nível de log como erro para tentar e se livrar de todas essas mensagens de aviso que vão desordenar nossos resultados. Em seguida, criamos um contexto Spark. E aqui estamos dizendo que o mestre será estrela local, dizendo que vamos executá-lo ou máquina local usando todos os núcleos de CPU disponíveis e o nome do aplicativo é Temperaturas min. Agora vamos falar um pouco sobre a sintaxe aqui. Então mestre é igual e nome do aplicativo é igual ou apenas pequenas notações que inteligente inserido para nós para fins de exibição. modo geral, você não precisa dizer que Mestre é igual ao nome do seu aplicativo é igual a que você pode apenas passar os parâmetros e ele irá alinhá-lo para os parâmetros esperados para essa função. Então sabemos que um construtor SparkContext começa com o mestre e, em seguida, o nome do aplicativo para os dois primeiros parâmetros. Mas se você quiser ser mais explícito em nomeá-los, você pode fazê-lo assim também. Isso é sintaxe também é um válido e que pode levar a um código mais legível. Então, se eu estivesse olhando para isso fora da Intel J, eu poderia realmente não saber o que temperaturas min significa ou estrela local significa colocando explicitamente nesses nomes de parâmetros, isso torna o código um pouco mais legível e mais fácil de entender . Vimos a mesma coisa aqui em cima no logger, obter nome lager igual a org. Nós não precisávamos dizer nome igual a 0, podemos apenas dizer 4D, mas isso deixa mais claro que o nome desse parâmetro que estamos definindo é nome, e isso nos diz o que é. Depois de obter o logger para o nome da organização, estamos definindo o nível dois erro ponto nível para dizer que queremos apenas mensagens de erro e sem avisos ou mensagens informativas. Seguindo em frente, a primeira coisa que fazemos é carregar nossos dados de entrada. Então dizemos linhas Val. Então estamos fazendo um valor imutável aqui chamado linhas que é definido para o arquivo de texto da barra de dados 1800 dot csv. Então, isso vai levar cada linha desse formato CSV e apenas colocar o texto bruto de cada linha no RDD da linha. Vamos dar uma olhada rápida em como esses dados se parecem. Então esta é uma visualização desse arquivo CSV no Microsoft Excel. Você pode ver que a primeira coluna é o ID da estação, e há apenas alguns deles aqui, seguido pela data, que é no formato de data do ano, mês. Então, 8800, 1 de janeiro. E este arquivo inteiro contém todos os dados do ano de 1800. Então não temos que fazer nada especial para dizer. Só queremos dados do ano de 1800. É tudo o que temos. Esta terceira coluna é o tipo de medição que é registrado nesta linha de dados. Então temperatura máxima, temperatura mínima ou precipitação. E o próximo é o valor associado a essa medida. E mais uma vez, é um formato meio estranho. Então eu acho que a palavra técnica é como deci centi grau ou algo assim. Eu não sei. Basicamente está definido para graus centígrados vezes 10. Então novamente, negativo 75 significa negativo 7,5 graus Celsius. As colunas restantes não são utilizadas para os nossos propósitos, por isso podemos fingir que não existem. Então é isso que estamos lendo em nossas linhas RDD. Em seguida, usamos nossa função de linhas de análise e aplicamos isso para mapear cada linha das linhas RDD para produzir um novo RDD chamado linhas analisadas. Então vamos dar uma olhada no que a linha de análise está fazendo. Então, novamente, vamos abrandar um pouco aqui no formato. Lembre-se, a maneira que declaramos funções em Scala é que começamos com def, o nome da função, e quaisquer parâmetros. E lembre-se que declaramos parâmetros um pouco para trás de outras línguas. Então começamos com o nome dois-pontos e, em seguida, o tipo. Um monte de outros idiomas ou digite o nome em Scala, seu nome, em seguida, digite. Assim, o parâmetro é chamado de linha e é esperado para ser de uma string. E então nós temos dois pontos, e isso é o que ele vai ser produzido pela função. Então, novamente, isso é ao contrário de qualquer outra língua. Muitas vezes você coloca o tipo de retorno antes do nome da função em Scala, é depois dele. Então vá descobrir. Então o que estamos retornando é uma tupla que contém uma string, uma string e um número de ponto flutuante. E definimos essa função igual ao seguinte bloco de código. Primeiro, começamos com o valor de um campo que vai dividir essa linha usando o delimitador de vírgula. E novamente o nome regex desse parâmetro está sendo inserido aqui para nossa conveniência. Em seguida, extraímos o primeiro campo. Começamos a contar a partir de 0 aqui. Então, os Campos 0 estão extraindo o primeiro membro e chamando-o de ID da estação. Extraia o terceiro campo e chama esse tipo de entrada e o quarto campo, e chamamos essa temperatura depois de convertê-lo em Fahrenheit. Então, o que está acontecendo aqui? Estamos pegando esse quarto campo, que é uma string para começar porque nós dividimos isso de uma cadeia de dados. Então temos que converter explicitamente isso para um número de ponto flutuante antes de fazermos operações numéricas nele. Então estamos dizendo para flutuar, para fazer isso em um número de ponto flutuante, vamos multiplicar isso por 0.1 porque, como você se lembra, tudo foi multiplicado por dez e os dados de origem. Então, neste ponto, temos graus centígrados reais. Em seguida, fazemos a conversão para graus Fahrenheit multiplicando por nove quintos e adicionando 32. Se você queria ficar em centígrado, tudo bem. Basta tirar essa parte e você estará em centígrado. O que retornamos é a última coisa que está nessa função, então não temos que devolvê-lo explicitamente. E apenas a última coisa que está lá é implicitamente retornada por esta função. E isso vai ser uma nova tupla que consiste no ID da estação, que novamente é uma string, o tipo de entrada, que novamente é uma string. E isso pode ser equipe e T, Max ou priciple. E a temperatura que calculamos como um valor de ponto flutuante. Então é isso que o, cada linha individual de nossas linhas analisadas resultantes RDD vai conter neste ponto. Em seguida, queremos filtrar tudo menos a equipe nas entradas porque tudo o que estamos tentando calcular é a temperatura mínima para o ano inteiro para cada estação, certo? Então podemos jogar fora todas essas entradas TMax. Podemos jogar fora todas essas entradas de precipitação. E fazemos isso com esta linha aqui. Então estamos dizendo filtro, que é todo o ponto deste exercício, passando nesta pequena função inline aqui. Então nós vamos chamar cada linha de entrada das linhas de pacote já dx. Nós vamos então tomar o segundo campo fora de x. e lembrar que será o tipo de entrada. Então olhando para aqui, o segundo campo é o tipo de entrada. E vamos verificar se esse tipo de entrada é igual a t Min. Se isso retornar verdadeiro, então essa linha é passada para o RDD de temperaturas mínimas caso contrário, terá filtros que entrada e não entrará no MiniTab. Assim, as mintues resultantes RDD contém apenas as linhas que correspondem t min e esse segundo campo. Em seguida, vamos jogar fora essa equipe naquele campo de tipo de entrada porque não precisamos mais dele. Sabemos que todas as linhas e temperatura mínima neste ponto. Então podemos mapear isso novamente para apenas extrair o primeiro campo, que será o ID da estação e o terceiro campo. E só por segurança, diremos explicitamente que é um número de ponto flutuante. Então nossa nova estação, Temps RDD vai conter IDs de estação, que é uma string e uma temperatura, que é um número de ponto flutuante em Fahrenheit. Agora podemos dizer ReduceByKey, apenas mantendo o controle do valor mínimo que encontramos à medida que passamos por todas as tentativas de estação de linha. Então, à medida que passamos por tentações da Estação, vamos continuar comparando o mínimo atual para cada linha recebida e retornar o mínimo entre esses dois que terão o efeito de manter o controle do menor registrado temperatura para cada chave porque estamos reduzindo por chave. Então lembre-se que cada chave é um ID de estação. Então, o que homens tendas por Estação acaba com é um RDD muito menor que contém apenas uma linha para cada chave única que contém o nome da chave e a temperatura mínima associada ao ID da estação meteorológica. Em seguida, coletamos os resultados de volta ao nosso script e colocamos isso no objeto de resultados. Em seguida, classificá-lo com resultados ponto ordenado e iterar através dele com este para loop. Então, para resultado, resultados classificados, que passa por cada linha de resultados classificados cada entrada, e extrai cada um como resultado. Para cada um, extraímos o primeiro campo dessa tupla chamada estação. O segundo campo é a temperatura. Formatamos essa temperatura. O F significa que vamos usar um formato de impressão f. E o percentual 0,2 F significa que queremos dois pontos decimais de precisão à direita do ponto decimal. E colocamos um F no final para indicar que é Fahrenheit. Então só temos que imprimi-lo com linha de impressão. E nós vamos substituir usando estação de sinal de dólar para o valor da estação, temperatura mínima, e então formatar uma temperatura, o sinal de dólar novamente indicando que estamos substituindo nesse valor imutável chamado Temp formatado. Então vamos executá-lo e ver o que acontece. Clique com o botão direito do mouse em Temperaturas mínimas e execute Lá vai ele. E lá temos. Assim, podemos ver que para as duas estações meteorológicas que tinham temperaturas mínimas associadas a elas, a primeira era chamada Easy Easy algo ou outro. E a temperatura mínima registrada foi de 7,7 graus Fahrenheit. E para ITE, seja lá o que for, a temperatura mínima foi de 5,36 graus Fahrenheit. Então parece ter funcionado muito legal. Agora, se você quer sujar as mãos, eu sempre encorajo você a fazer as mãos aqui. Aqui está um desafio muito rápido para você. E se você quisesse manter o controle da temperatura máxima para cada estação meteorológica em vez da temperatura mínima? Bem, as mudanças associadas a isso devem ser bem simples. Se você quer um pouco de desafio, clique em pausa agora e vá e tente você mesmo. Veja se você pode modificar este script para imprimir as temperaturas máximas em vez das temperaturas mínimas. E faz uma pausa se você quiser fazer isso. Se não, vou mostrar-te como o fiz. Então é bem simples, mas você precisa mudar, certo? Então, primeiro de tudo, você deseja alterar o nome do objeto e o arquivo para temperaturas máximas para consistência, análise dos dados será a mesma, certo? Isso não vai mudar. O formato dos dados não mudou em nós. Mas o que extraímos será diferente, certo? Temperaturas mínimas querem mudança. O acontecendo da temperatura máxima é provavelmente o que vamos fazer isso, embora, filtrar tudo com Tmax em vez de t min. Então isso vai nos dar tudo menos as entradas T max. E então aqui quando fazemos nossa redução ou operação ReduceByKey, nós só queremos transformá-los em um máximo. E isso deve ter mudado como estamos exibindo os resultados para dizer que é uma temperatura máxima. Acho que temos que importar matemática esquelética. Max também, certo? Então coisas muito simples, mas é bom para colocar suas mãos em e tipo de obter alguma confiança em fazer alterações no código Scala e no código Spark e ver que você pode fazê-lo, É mais sobre sua confiança em qualquer coisa. Se você quiser ver como eu fiz isso, basta clicar duas vezes no script de temperatura máxima aqui. E faz tudo o que eu disse. Então estamos importando scala dot matemata.max. Mudei o nome dele, mudei o nome do arquivo. Chamamos agora de temperaturas máximas. Estamos filtrando para TMax e reduzindo com base na função máxima e imprimindo a temperatura máxima. Isso é praticamente tudo. Vamos fazer isso e ver o que ele faz. E aí você tem, ele. Acontece que ambos têm o mesmo. Isso é meio curioso, não é? Assim, para ambas as estações, a temperatura máxima foi de 90 pontos 104 graus Fahrenheit. E eu estou supondo que isso corresponde a um bom número redondo e grau de incentivo que acontece de ser o mesmo para ambas as estações. Então, não muito distantes um do outro. Então não é uma grande surpresa. E aí você tem o filtro em ação. E também outro exemplo de escrever um script simples do Apache Spark usando RDDs. Você vai descobrir que isso não é muito diferente. Vamos falar sobre APIs diferentes, mas novamente, eles são muito em breve. 15. [de atividade] contando as Occurrences de palavra usando Flatmap(): Então, temos visto vários exemplos de usar a operação de mapa em Spark até agora, Vamos falar sobre FlatMap, que é um pouco diferente. E temos um exemplo simples para ilustrá-lo, onde contamos o número de cada palavra em um livro para mostrar como ela funciona. Então vamos rever o que o mapa faz. Então, por exemplo, se tivéssemos um arquivo de texto de entrada que continha a leitura rápida em uma linha e Fox pulou em outra linha e sobre o preguiçoso em outra linha e cães castanhos na última linha. Poderíamos ler isso em um RDD chamado linhas onde cada linha de texto corresponde a uma linha desse RDD. E, em seguida, neste caso, estamos chamando mapa nas linhas RDD, passando-lhe uma função para converter cada linha em maiúsculas. Então o que obtemos é uma nova raiva tampas RDD que apenas capitaliza cada linha única ou cada linha única em vez de que RDD entrada. Então, a coisa a observar aqui é que há uma relação um-para-um entre o RDD de entrada e o RDD de saída. E quando você chamar mapa, mapa leva cada linha de entrada e converte-lo de alguma forma para uma e apenas uma linha de saída. Então começamos com quatro linhas e o RDD da linha, e acabamos com quatro linhas e os tampas de raiva de saída RDD, mapa sempre tem esse relacionamento um-para-um. Uma fileira entra, uma fila sai. O mapa plano, no entanto, remove essa restrição. Assim, com FlatMap, você pode retornar qualquer número de linhas para uma linha de entrada, poderia ser 0, poderia ser 20, poderia ser 200, qualquer coisa que você quiser. Então, neste exemplo diferente aqui, começamos com a mesma entrada. Rdd são chamados de linhas, mas agora estamos chamando FlatMap. E nós estamos passando como uma função lá para pegar em cada linha, chamá-lo de x, e então dividi-lo com base no caractere de espaço. Então isso tem o efeito de dividir cada linha em suas palavras individuais. E porque estamos chamando FlatMap, cada palavra individual acaba em sua própria nova linha nas palavras resultantes RDD. Então, usando FlatMap aqui, começamos com quatro linhas, mas acabamos com muitas mais linhas que nas palavras RDD de saída, onde temos uma linha para cada palavra em oposição a uma linha para cada linha. E novamente, FlatMap pode produzir qualquer número de linhas que você deseja, incluindo 0. Para ver isso em ação, vamos fazer um pequeno exemplo de código simples onde contamos quantas vezes cada palavra ocorre dentro de um livro inteiro. E eu não estou tentando vender este livro, mesmo que eu o tenha escrito, ele não tem nada a ver com o Apache Spark, mas é um livro onde eu possuo os direitos sobre ele para que eu possa usá-lo como um exemplo sem pagar royalties. Então, vamos mergulhar e ver com que frequência cada palavra individual aparece no meu livro. Então temos um script muito simples aqui para ilustrar o uso do FlatMap. Chama-se contagem de palavras. Então vá em frente e abra a contagem de palavras e inteligente se você gostaria de seguir ao longo script realmente simples. E isso é frequentemente usado como uma espécie de exemplo HelloWorld para programas Spark. Começamos como sempre declarando nosso pacote, importando o que precisamos para dependências, e declarando o objeto em que vivemos. Nossa função principal começa dizendo que o nível de log é sempre e declarando um novo SparkContext em execução em nosso PC local. Agora entramos na carne dele. Então nós o chamamos de arquivo de texto SparkContext com um caminho para todo o conteúdo do texto do livro inteiro que vive na barra de dados Livro dot txt arquivo. E chamamos isso de RDD resultante nossa entrada, onde cada linha desse RDD de entrada corresponde a uma linha de texto do livro. E agora, assim como vimos nos slides, chamamos FlatMap nessa divisão de cada linha pelo caractere de espaço, o que mais ou menos nos dá as palavras individuais dentro desse livro. Então agora FlatMap gerou um novo RDD palavras, onde cada linha das palavras RDD é uma palavra no livro e pode haver palavras repetidas lá. É cada palavra individual, mesmo que ocorra mais de uma vez, vai ser uma linha nesse RDD e sequência. E agora vamos usar a ação de contagem por valor para contar quantas vezes cada palavra única aparece nas palavras RDD. Então essa é uma maneira de uma linha de fazer o que de outra forma seria uma operação bem complicada, certo? E a beleza do Spark é que ele pode realmente paralelizar isso em um cluster inteiro se você quiser, ou no nosso caso, cada núcleo de nossa CPU. Tudo o que fazemos é percorrer cada resultado naquele objeto de contagem de palavras que recebemos de Spark. E chamamos de linha de impressão em cada um desses resultados para imprimir cada resultado em sua própria linha. Então vamos correr e ver o que acontece. Vamos clicar com o botão direito do mouse na contagem de palavras, dizer executar WordCount, lá vai. E mesmo que este seja um livro inteiro, ele deve fazer um trabalho curto com ele. Lá temos ele. Interessante. Então, se você percorrer isso, você pode ver quantas vezes cada palavra aparece no meu livro. A palavra dinheiro aparece 18 vezes, apenas 77 vezes. Autônomo, apenas 10 vezes. Surpreendente porque é um livro sobre auto-emprego. Mas há algum tipo de palavras únicas aqui também, como a ideia só aparece uma vez. envio de entrega só aparece uma vez. tão legais. Então, no nosso funcionou. É um exemplo de mapa plano em ação. Mas à medida que você olha esses resultados, você pode ver que há alguns problemas aqui que talvez queiramos trabalhar. Então vamos explorar isso em palestras subseqüentes aqui, por exemplo, dependendo da capitalização, eu poderia tratar essas palavras como palavras diferentes. A palavra produtos foi realmente incluída apenas uma vez? Tudo o que isso realmente significa é que os produtos só apareceram uma vez com um P maiúsculo, talvez no início de uma frase ou algo assim, certo? Portanto, há maneiras de melhorar esses resultados para ser mais interessante. E também é como se coisas estranhas como o traço aberto terminassem uma palavra ou duas. E quanto à pontuação? Eu deveria estar tirando esses pontos de interrogação, vírgulas e pontos, certo? Então os proprietários vírgula aparecem duas vezes, mas isso não é realmente falar sobre os proprietários da palavra. Portanto, há algum espaço para melhorias e como analisamos esses dados. Então vamos explorar isso. 16. [de atividade] melhorando o script de contagem de palavras com expressões regulares: Ok, então para revisar em nossa lição anterior, fizemos um exemplo simples de usar o FlatMap para contar quantas vezes cada palavra no meu livro aparece. E nós ingenuamente apenas analisamos esses dados dividindo-os com base em caracteres de espaço para tentar obter palavras individuais, que no início você acha que funcionaria. Mas como você pode ver nos resultados aqui, não. Acabamos recebendo pontuação lá dentro. Então, por exemplo, aspas, y conta como uma palavra única individual. capitalização também é importante aqui. Então Y maiúsculo seria contado como uma palavra diferente do y minúsculo. Temos coisas como vírgulas, marcas de pontuação e maiúsculas afetando nossos resultados. Então vamos consertar isso. Então vamos fechar fora do ponto WordCount Scala e, em vez abrir Word Count melhor. E aqui vamos usar uma expressão regular em vez de obter melhores resultados. Clv, nada realmente diferente aqui é que em vez de ter essa função que se divide com base em um caractere de espaço, quando dividimos os dados de entrada, em vez disso vamos usar uma expressão regular. Então, neste caso, vamos dizer x dot split e definir a expressão regular para este formato de expressão regular, barra invertida, barra invertida maiúscula W plus. E na terra de expressão regular, isso só significa que eu quero quebrar as coisas com base em palavras inteiras. O W maiúsculo significa palavra. Então expressões regulares sabem o que é uma palavra. Ele vai filtrar toda a pontuação e todos aqueles caracteres especiais e apenas nos deixar com palavras que contêm os caracteres reais. Então isso tem que se livrar de todos os problemas que a pontuação atrapalhando nossos resultados. No entanto, ainda temos o problema da capitalização, certo? Então R maiúsculo e lembre-se vai ser uma palavra diferente do que r. minúsculo e lembre-se, mesmo depois de retirar qualquer pontuação que possa ter existido lá. Então, para cuidar desse problema, vamos além disso um mapa de nossos resultados para minúsculas. Então vemos aqui começamos mapeando planos nossos dados de entrada em palavras individuais. Mas neste caso estamos dividindo em palavras de expressão regular em vez de apenas caracteres de espaço, que é mais robusto. E então fazemos um mapa regular para pegar cada palavra individual e mapear isso em uma base um-para-um para sua versão minúscula. Assim, normalizando tudo para caracteres minúsculos, podemos ter certeza de que estamos contando todas as palavras da mesma forma, independentemente da capitalização. E então vamos sair e contar por valor nas palavras minúsculas resultantes RDD e imprimir esses resultados. Então vamos ver se isso nos dá algo um pouco melhor. Vamos clicar com o botão direito do mouse na contagem de palavras melhor e executar isso. E tudo bem, isso parece um pouco melhor, certo? Então, isso é fixe. Então agora não temos nenhuma pontuação estranha acontecendo aqui. Tudo é minúsculo, então estamos obtendo resultados que fazem um pouco mais de sentido, espero. Assim, por exemplo, a palavra publicidade aparece 41 vezes no livro que parece credível. Religioso apenas um cache 19 vezes. Vamos procurar uma palavra muito popular aqui, porém, que apareça 1292 vezes. Então, não é muito surpreendente, essa é uma palavra muito comum. Legal. Então parece ter funcionado como se eu acho que estamos recebendo palavras válidas aqui. Tudo parece normalizado. Não estamos ficando confusos. Eu pontuação, então missão cumprida, mas isso não é muito útil ainda em como usá-lo, certo? Eu tenho que ir pescar por palavras comuns aqui. Eu não deveria ter que fazer isso. Não seria melhor se eu pudesse classificar esses resultados pela frequência com que cada palavra aparece. Então haverá mais útil. Eu posso facilmente encontrar as palavras mais comuns e as palavras menos comuns no livro. E isso pode até me dar uma visão sobre o que é o livro. Ou talvez palavras que estou usando demais ou algo assim, isso é bom. Na verdade, tenho um pedido prático para escritores. Então vamos seguir em frente e tornar este roteiro ainda melhor em nossa próxima palestra e realmente classificar esses resultados para que possamos obter mais significado disso. 17. [de idade: Ok, então em nossa lição anterior, nós refinamos nosso exemplo de contagem de palavras para ser um pouco mais inteligente sobre a identificação de palavras. Então temos uma boa saída aqui das contagens de cada palavra única dentro de todo o nosso livro. Mas não é muito útil porque não é classificado pela frequência com que cada palavra ocorre. Então eu tenho que ir pescar para descobrir quais são as palavras mais comuns e menos comuns no meu livro. Então isso não ajuda muito, certo? Então vamos consertar isso. Queremos classificar os resultados com base na frequência com que cada palavra ocorre. Podemos ver rapidamente as palavras mais usadas no meu livro. Agora, em palestras anteriores deste curso, nós teríamos feito isso apenas classificando os resultados finais que recebemos do Spark que foram devolvidos ao nosso script de driver e apenas classificando-os em Scala. Mas essa não é realmente a forma de big data de fazer as coisas, certo? Seria melhor se pudéssemos classificar isso no cluster se tivéssemos tantas palavras que não pudéssemos realmente processar tudo em uma máquina. Você precisa fazer isso, certo? Quero dizer, isso é uma espécie de exemplo complicado. É improvável que você tenha tantas palavras em um livro, mas você entendeu a idéia. Será preferível fazer essa classificação distribuída no cluster, se pudermos. Então vamos fazer dessa forma e ver como isso pode funcionar. Então vamos abrir o exemplo de contagem de palavras melhor ordenado aqui. Apenas um pequeno refinamento na contagem de palavras anterior melhor script aqui, é praticamente o mesmo, exceto pelo nome do script todo o caminho até este ponto aqui. Então nós carregamos nosso livro em um RDD de entrada. Nós dividimos em palavras usando FlatMap. Então agora temos um RDD palavras contendo cada palavra no livro, e então mapeamos isso para minúsculas para normalizar esses dados. Então agora, anteriormente teríamos usado contagem por valores, certo? Se voltarmos ao nosso exemplo anterior aqui usamos contagem por valor para obter rapidamente o número de vezes que cada palavra ocorre nesse RDD. Mas queremos resolver isso ao mesmo tempo. Então precisamos fazer da maneira mais difícil. Então vamos quebrar o que está acontecendo neste tipo de linha complicada aqui. Então primeiro vamos mapear esse resultado para x r1. Pegue cada linha, cada palavra individual, e mapeie isso para uma tupla da palavra e o número 1. Já vimos este truque antes, certo? Então o que estamos dizendo é que vamos ter cada tupla individual ter essa palavra e representar que ela ocorreu uma vez naquela fila. E isso é um pequeno truque que podemos usar porque isso nos permitirá resumir tudo, certo, e obter o número de vezes que cada palavra única ocorre quando fazemos uma operação de redução. E é isso que estamos fazendo aqui. Estamos dizendo reduzir por chave, somando todos esses totais. Então vamos passar por isso de novo. Estamos transformando cada palavra em uma tupla da palavra e no número um. E porque esta é uma tupla com duas coisas que podem ser consideradas um valor-chave, RDD, onde a chave é a palavra e o valor é o número um. Então agora podemos dizer ReduceByKey porque basicamente temos um valor-chave RDD resumindo todos os valores, ok? Então, para cada palavra única, vamos contar todos os valores, que é apenas o número 1. Então, quando somamos todos os números para cada ocorrência de palavras, acabamos com uma contagem de quantas vezes essa palavra ocorreu. Ok, a próxima coisa que queremos fazer é resolver isso. Então, neste ponto, a operação ReduceByKey nos deixou com uma palavra conta RDD que contém pares chave-valor, novamente, onde a chave é a palavra e o valor é o número de vezes que a palavra ocorre. Agora faísca oferece uma função de classificação por chave aqui que podemos usar, mas ele vai classificar pela chave e o valor que queremos classificar pelo, frequência cada palavra ocorre. Então, precisamos virar isso primeiro. Então isso é tudo o que estamos fazendo nesta operação de mapa. Estamos pegando o RDD contagem de palavras e invertendo para que o valor da chave RDD esteja sendo invertido para a chave de valor, se você quiser. E então nós estamos pegando o RDD de entrada, que contém contagem de palavras, e invertendo isso ao redor para contar palavra, transformando-o em x ponto t2 e x-dot um. O segundo campo no primeiro campo. Uma vez que temos isso, podemos usar classificar por chave para classificar os resultados pelo número de vezes que cada palavra ocorre. Então comigo aqui, vamos passar por isso mais uma vez. Tudo isso é o mesmo de antes. Mas, neste caso, vamos pegar nossas palavras minúsculas RDD, que tem cada palavra única em sua própria linha. Vamos mapear isso para um par chave-valor onde a chave é a palavra e o valor é o número um. Fazemos uma operação ReduceByKey para somar quantas vezes cada chave única, cada palavra única ocorre. E então precisamos inverter esse par de chave-valor resultante em sua cabeça para que possamos realmente usar classificar por chave para classificar pelo número de vezes que cada palavra aparece. Depois passamos e imprimimos os resultados , como fizemos antes. E devemos conseguir algo mais útil. Então vamos em frente e tentar. Clique com o botão direito do mouse na contagem de palavras, melhor classificado e dizer executar E lá temos. E é ordenado em ordem ascendente. Então, as palavras mais populares serão no final. E isso é interessante. Então minhas palavras mais comuns foram também e você não em um poço, eu estou feliz que eu usei as palavras que você em seu mais do que eu e eu. É uma maneira melhor de escrever. Ela quer se conectar com seu leitor e não falar muito sobre si mesmo. Então vou chamar isso de vitória. Mas sim, um no raso aparece com muita frequência. E de todas as palavras comuns que você esperaria ver lá, há ou seja, um negócio aparece muito. Então, quando você detalha a luz, as palavras mais interessantes você pode tipo de dizer sobre o que o livro é apenas sobre quais são as palavras mais comuns, certo? Então a primeira palavra que meio que tem algum significado há negócios, e é um olhar sobre negócios. Tempo de rolagem para cima. Você sabe, nós falamos muito sobre gestão do tempo devido a fazer o produto. Está bem. Sim, falamos muito sobre como escolher o produto a vender. Então, sim, você pode realmente obter algumas percepções sobre o que o livro é tudo apenas de olhar para esses dados agora. E se deslocarmos até as palavras menos comuns, não deveríamos ter algumas coisas bem obscuras aqui. Espuma só eu usei eram telefone. Pergunto-me de onde veio isso. Swot citado. Então, sim, coisas interessantes. Então você pode realmente dizer sobre o que o livro é apenas olhando para esses dados. Então nós meio que gostamos de ver a evolução do roteiro. E ao longo do caminho de tornar este script mais útil, aprendemos não só sobre como usar FlatMap, mas também como usar expressões regulares e como fazer uso criativo de ReduceByKey e classificar por chave para obter os resultados que você Quero. Agora, novamente, vamos descobrir que isso é um pouco mais simples ao usar conjuntos de dados no SQL. Mas estamos chegando lá. Nós só queremos começar com o básico aqui e os fundamentos do Spark, que são construídos em RDDs. E nos casos em que você precisa usar RDDs, é bom conhecer esses truques. 18. [Exercício de ano: Ok, eu acho que você já aprendeu o suficiente sobre RDDs e viu código Scala suficiente neste momento para tentar fazer algo por conta própria. Então é um pequeno desafio, um pouco de atividade prática. Eu vou ter você criar um programa Spark muito simples em Scala que vai apenas contar a quantidade total de dinheiro encomendado por cada ID de cliente individual e um pequeno banco de dados falso de dados de e-commerce. Então eu vou fornecer um arquivo CSV que contém coisas neste formato. E isso representará um ID de cliente e também um ID de item e o valor gasto nesse item. Então cada linha desses dados falsos representa algumas transações, algumas compras em uma pessoa fictícia feita. Você vai escrever algum código e produzir o total geral de quanto foi gasto por cada ID de cliente exclusivo. Então, neste exemplo específico, você pode ver que o ID de usuário 44 comprou algo para 37, 19 e algo mais para 4064. Então o total geral para o nosso usuário 44 é 77, 83. E queremos fazer isso para cada cliente individual em nosso banco de dados. Então eu vou soletrar isso para você um pouco se você está um pouco ansioso sobre isso, não, não, não espreite se você quiser tentar isso por conta própria, mas alguma orientação geral sobre a estratégia para fazer isso. Quero começar dividindo cada linha delimitada por vírgula em seus campos únicos. E como eu disse, isso será ID do usuário, ID do item e quantidade gasta. Em seguida, você mapeará cada linha para um par chave-valor de ID do cliente e valor em dólar. E use a operação ReduceByKey para adicionar o valor total gasto pelo ID do cliente. Quando terminar, colete os resultados e imprima-os. Bastante direto. E você deve ser capaz de descobrir isso estudando os exemplos anteriores neste curso. Eles são bastante parecidos. Alguns trechos de código úteis se você é novo no Scala, que podem ser úteis se você quiser dividir um campo delimitado por vírgula em seus campos individuais, esta linha faria isso por você, campos Val equivale a vírgula de divisão de pontos de linha. E você também precisará em algum momento para se certificar de que você tratar o campo 0 é um inteiro e sentir como um número de ponto flutuante. Então esse pequeno trecho de código também é importante lembrar. Você precisa explicitamente lançá-los em sua representação numérica real e não apenas cordas como elas saem da rocha de arquivo. Então boa sorte. E antes de soltar vocês, vou mostrar brevemente onde encontrar os dados para isso e como criar um novo objeto em nossos projetos para que você possa realmente brincar com ele e começar. Então deixe-me mostrar-lhe isso bem rápido e então eu vou soltá-lo. Então, primeiro deixe-me direcionar sua atenção para onde vivem os dados para este exercício. Então, dentro de sua pasta de materiais do curso, vá para o curso Spark Scala e, em seguida, a pasta de dados. E é o arquivo de pedidos do cliente que vamos estar olhando aqui. Vamos abrir isso, ver como é. Agora lembre-se que isto é valores separados por vírgula. Então, mesmo que o Excel esteja exibindo-o como uma planilha, são realmente colunas individuais separadas por vírgulas que estamos lendo aqui. E esses dados são gerados completamente aleatoriamente. Você pode ver que há um pouco disso, 10 mil linhas de dados aqui, mas é tudo falso. A primeira coluna representa o ID do usuário, seguido de um ID de item e o valor gasto nesse item. Então, cada linha representa uma única compra. E sim, você pode notar que essa segunda coluna não é realmente necessária para o que estamos fazendo, certo? Só precisamos do valor gasto pelo cliente. A ID do item realmente não entra em jogo, então muito tempo, então limpar seus dados vai ser uma grande parte do trabalho e esse é o caso e este pequeno exercício simples também. Agora, para começar com isso, deixe-me mostrar-lhe como realmente ir sobre a criação de um novo objeto em um tele j. Então eu clico no software Calm dot sundown dot Spark e dizer New Scala classe e dar-lhe algum nome único. Coloque seu nome lá só para ter certeza de que é único. Então algo como a quantia total gastada para mim, qualquer que seja o seu nome para você. E clique duas vezes em objeto porque queremos um objeto e não uma classe. Tudo bem, então agora você tem o caldeirão aqui de um novo objeto aqui ele tem o nome correto do pacote porque nós colocamos no lugar certo. E seu objeto está configurado. E agora tudo que você tem que fazer é escrever algum código e testá-lo. Então, quando estiver pronto para experimentar isso, basta clicar com o botão direito do mouse nessa classe e construí-la. E depois disso você pode realmente tentar executá-lo e ver o que acontece. E sim, é isso. Então vá fazer isso. Não é um exemplo muito difícil, não um exercício difícil por qualquer meio, mas eu quero que você suje suas mãos e obter algum conforto em escrever código Scala. Teremos alguns mais desafiadores mais tarde no curso, é claro, então estamos começando fácil. Então vá tentar isso. E quando estiver pronto, volte para a próxima palestra e eu lhe mostrarei minha solução, que está aqui nos materiais do curso. Você já pode ter visto, então resista à tentação de olhar para ele. Tente você mesmo primeiro. 19. [Exercício de exercício de a sua consulta e Sort por o valor total de o tempo de visita: Então, você fez seu dever de casa? Espero que sim. Bem, se você quiser comparar seus resultados com os meus e comparar seu código com o meu, incluí minha solução em seus materiais de curso também. Então, espero que você ainda não tenha escolhido. Basta abrir o total gasto por classe de clientes aqui. E foi assim que eu fiz. Então vamos passar por este código aqui. Comece com a declaração de pacote que você já deve ter e importando o que precisamos. Precisamos de tudo do Spark e do registro para J. Espero que não tenha sido tropeçado, incluindo aqueles. E nós chamamos nosso objeto aqui total gasto pelo cliente. Este é o meu arquivo de solução aqui. E vamos pular para a função principal e começar por aí. Então, começamos definindo nosso nível de log para erro como fizemos antes. E criamos um novo SparkContext. E a única coisa única sobre isso é que dissemos um nome de aplicativo que é diferente dos outros exemplos. Neste caso, o total gasto pelo cliente. Agora entramos na carne de tudo. Nós carregamos nosso arquivo de texto, que é o cliente traço pedidos ponto CSV arquivo que eu direcionei você para anteriormente. E nós estamos indo apenas para carregar isso em um RDD chamado entrada. Agora precisamos analisar esses dados. Então é por isso que nós escrevemos este extrato de pares de preço do cliente função aqui em cima. Claro, podias ter-lhe dado o nome que quisesses. Ele vai levar em uma linha inteira de valores separados por vírgulas e vamos apenas chamar essa linha de string e retornar uma tupla de um inteiro e um flutuador. Então, esses serão nossos pares de valor de chave que teremos mais tarde, onde a chave será o ID do cliente, que é o primeiro campo, e um valor de ponto flutuante. Nós representamos o valor gasto em algum item para esse cliente nessa transação. Começamos dividindo os campos nessa linha com base no caractere vírgula usando a divisão de pontos de linha. E atribuímos isso ao valor dos campos. E então nós apenas retornar a tupla que contém o primeiro campo convertido em um inteiro, e o terceiro campo convertido em um número de ponto flutuante. E lembre-se novamente, começamos a contar a partir de 0 neste formato específico. Então, neste ponto, mapeamos nossa entrada em um novo RDD de entrada mapeado que contém tuplas de IDs de clientes e quantidade gasta. E isso é realmente um par de valores chave porque é uma tupla de duas coisas, certo? Então nossa chave é agora a ID do cliente e nosso valor é agora o valor gasto nessa transação. Agora só temos que reduzir isso usando a operação ReduceByKey. E usamos essa sintaxe aqui para manter um total de execução do total geral gasto por cada ID de cliente. Então, estamos reduzindo por chave por cada cliente e somando esses valores à medida que eles entram. Então, isso leva em um par de dois valores associados com a chave. E vamos dizer que queremos somar essas coisas porque queremos o total. E o que recebemos de volta é o total por RDD do cliente, que conterá as chaves, cada chave exclusiva, cada ID de cliente exclusivo e o total gasto por cada ID de cliente. Podemos então recolher os resultados de volta. Então essa será a nossa ação que recuperará os resultados e os devolverá ao nosso script, ao nosso script de driver rodando localmente aqui. E então podemos simplesmente chamar FoREach com a função de linha de impressão para imprimir cada linha desses resultados. Então vamos executá-lo e ver se funciona. Vou clicar com o botão direito do mouse no total gasto pelo cliente e dizer executar total gasto pelo cliente. Lá vai ele. E lá temos. Muito legal. Tudo bem, parece que funcionou. Assim, por exemplo, o ID de usuário 91 gastou $4.642,26, e assim por diante e assim por diante. O usuário 53 gastou $4.495. Estão todos na mesma vizinhança, porque foram todos dados gerados aleatoriamente com distribuição aleatória uniforme. Mas isso é entrar no meu curso de ciência de dados, suponho. De qualquer forma, funcionou. Então, espero que você tenha uma saída semelhante para ouvir. A ordem pode ser diferente, tudo bem. Mas você sabe, você deve ser capaz de ver que para um determinado ID de usuário, você pode procurar por esse ID de usuário e obter o mesmo número espero. Então, se você quiser procurar o usuário 89 e ter certeza que você tem 4851947, 95. Isso pode ser uma boa ideia. Tudo bem, então eu vou desafiá-lo ainda mais agora, você pode tornar isso ainda melhor tipo de como fazemos em nosso exemplo de contagem de palavras. Será muito mais útil se isto for resolvido, certo? Então, se eu estivesse mais interessado em ver quem são meus grandes gastadores, eu poderia realmente querer ver este Datastore ordenado pelo valor gasto. Assim, eu poderia facilmente ver quem estava gastando a menor quantidade de dinheiro no meu site e quem estava gastando a maior quantidade de dinheiro no meu pequeno site falso de e-commerce aqui. Então esse é o seu desafio. Vá e vá em frente e veja se você pode classificar os resultados pelo valor gasto para uma equipe extra adicional de bônus, Eu quero ver se você pode formatar que realmente tem dois pontos decimais de precisão lá após o cifrão lá. Então faça isso parecer mais como moeda real. Mas eles são, seu único desafio real agora é classificar esses resultados pelo valor gasto. E novamente, referindo-se ao exemplo de contagem de palavras melhor ordenado que tínhamos anteriormente. Exatamente o mesmo truque. Então eu não estou tentando fazer você pensar muito aqui. Eu só quero que você pratique um pouco aqui e aplique o que você aprendeu nesta seção. Como eu disse, ficaremos mais desafiadores em breve. Então vá e tente isso. Agora, veja se você pode classificar os resultados por quantidade gasta e dar uma chance. Voltaremos na próxima palestra e você pode comparar seus resultados em seu código com o meu. 20. Confira seus resultados e implementação em: Ok, então espero que você tenha tido a chance de tentar classificar esses resultados pelo valor gasto para que possamos obter uma saída mais útil lá. Vamos comparar sua solução com a minha de novo. Então, se você quiser olhar para o meu, você pode clicar no total gasto por clientes ordenados. Clique duas vezes sobre isso e veja como eu fiz. Praticamente a mesma coisa o código original que passamos na palestra anterior. Então eu não vou reiterar todas as coisas que não mudaram. Tudo o que mudámos foi esta parte aqui. Então, neste ponto aqui temos o valor total por cliente. Assim, reduzimos nossos dados para termos pares de valor de chave, onde temos IDs individuais de clientes associados ao valor gasto por esse cliente em todo o banco de dados. Assim como fizemos no exemplo classificado contagem de palavras, vamos virar isso em sua cabeça e tentar tirar proveito do tipo por operação chave que a faísca oferece. Dessa forma, podemos realmente distribuir a classificação deste no cluster, se quisermos. Então, para fazer isso, precisamos fazer nossos valores, as chaves e as chaves os valores porque queremos classificar pelos valores, o valor gasto. Então estamos criando esse RDD invertido. Isso é apenas mapeamento total por cliente para pegar o par chave-valor de entrada x e pegar o segundo elemento e torná-lo primeiro. E pegamos o primeiro elemento e o tornamos segundo. Então, é apenas inverter a chave e o valor para fazer a nova chave, o valor gasto e o novo valor, o ID do usuário. Nós então classificamos por chave para realmente classificar isso pelo valor gasto que o primeiro valor lá. Depois podemos recolher os resultados e imprimir cada linha. Então vamos ver se funciona. Clique com o botão direito do mouse no total gasto pelos clientes classificados e executá-lo. E devemos ver quem são os grandes gastadores. Tudo bem, parece que funcionou. Então, temos na primeira coluna agora o valor gasto. Assim, podemos ver que o máximo que alguém gastou com $6.375.45 e que foi pelos números de usuário 68. Então podemos ver que o usuário 68 foi o nosso maior gastador. E se formos rolar para cima, podemos ver o nosso gastador mais barato, se preferir. $3.309 foram para o usuário 45. E novamente, se você quiser se esforçar ainda mais, você poderia tentar formatar esta saída um pouco mais bem. Eu não vou passar por isso com você, mas se você sentir que você quer ainda mais de um desafio, veja se você pode imprimir cada linha apenas para dizer mais detalhadamente, ID de usuário, o que gastou tanto dinheiro e formatar o dinheiro em real formato monetário, cifrão, alguns pontos inteiros dois pontos decimais, certo? E isso não vai ser um problema de faísca. É mais um problema Scala. Mas se você quiser ir mais longe, essa é uma maneira de fazê-lo. Mas sim, é o suficiente por enquanto. Então, aprendemos sobre RDDs. Rdds são a API original do Apache Spark, voltando ao Spark One, e eles ainda têm seu lugar para muitos tipos de problemas. Eles podem oferecer o melhor desempenho e a maior flexibilidade e o que você pode fazer. Mas é hora de seguir em frente. Então vamos falar sobre dataframes e conjuntos de dados a seguir, porque essa é realmente a maneira mais moderna de fazer o código do Spark. E revisitaremos esses exemplos, fazendo-os novamente usando conjuntos de dados na próxima seção. 21. Introdução ao SparkSQL: Então, em nossa próxima seção, estamos introduzindo o Spark SQL. E com ele vêm as APIs mais modernas de Spark DataFrames e conjuntos de dados no mundo da Scala, vamos nos concentrar mais em conjuntos de dados porque isso é ainda mais eficiente. Então esta vai ser a interface mais moderna para o Spark. E vamos nos concentrar nisso daqui para frente no curso. É uma camada em cima do Spark Core. Mas se você pode pensar em seus problemas em termos de um comando SQL, que a maioria dos problemas de análise de dados pode ser Spark SQL e dataframes e conjuntos oferecem uma solução muito eficiente e fácil de usar para obter as respostas que você deseja em um todo o cluster. Então vamos mergulhar e ver como funciona. Então nós conversamos muito sobre a interface RDD no Spark até agora que era a interface original e Spark em tudo é construído em cima dela. Às vezes, ainda é útil voltar a isso e realmente chegar a um nível baixo para a melhor otimização para problemas mais simples. Mas começando com o Spark para, eles realmente começaram a enfatizar a interface Spark SQL e o Apache Spark em vez disso. E o Spark SQL traz para a tabela coisas como dataframes e conjuntos de dados. Vamos falar sobre isso. Então, o DataFrames veio primeiro. Eles expandiram RDDs para um objeto dataframe. E um DataFrame é muito parecido com um banco de dados relacional. Ele contém objetos de linha que contêm algum tipo de informações estruturadas. Tem um esquema. E assim podemos armazenar as coisas de forma mais eficiente. E porque temos um esquema e essas linhas, podemos tratá-lo como um banco de dados SQL e executar consultas SQL reais em nossos DataFrames. E como ele se parece muito com um banco de dados real, você pode ter muita interoperabilidade com bancos de dados e formatos de arquivos relacionados ao banco de dados. Então você pode ler e escrever para JSON ou HIV ou em parquet formatos. E você pode até se comunicar diretamente por meio de uma interface JDBC ou ODBC ou usando o Tableau. Então nós podemos realmente olhar apenas como um banco de dados relacional, mesmo que seja o Apache Spark em execução em um cluster. Muito legal, certo? E porque ele pode pensar em coisas em termos de consultas SQL, isso também traz para a mesa todo o mundo das tecnologias de otimização de consulta, certo? Assim, além das otimizações de gráficos acíclicos direcionados usuais que acontecem com o Spark, também podemos olhar para suas consultas SQL reais que você está tentando emitir em um DataFrame e fazer as mesmas coisas que são banco de dados relacional faria para otimizar essa consulta. Assim, se você estiver fazendo as coisas de uma forma SQL com um DataFrame, às vezes você pode obter ainda mais otimização do que faria com um RDD. Então nós saímos com conjuntos de dados e conjuntos de dados e DataFrames são tipo a mesma coisa. Tecnicamente, um DataFrame é apenas um conjunto de dados de objetos de linha. Então, uma fileira é só uma fila de coisas, certo? Então, o ponto importante aqui é que você também pode ter um conjunto de dados que envolve ajuda e tipo explícito e estrutura explícita ou inexplícita onde sabemos o esquema real na hora da compilação. Por exemplo, eu poderia criar um conjunto de dados de uma classe de caso de pessoa que define exatamente quais são os campos que definem uma pessoa e quais são esses tipos. Ou eu poderia criar um conjunto de dados que diz explicitamente que eu quero uma string e um duplo em cada linha. E ao fazer isso, ele saberá quais são essas colunas desde o início. Então, ao contrário de um DataFrame onde tudo o que eu sei é que eu tenho um conjunto de dados de linhas nessa linha. Row poderia conter qualquer coisa até eu defini-lo, um nariz de conjunto de dados na frente, que tipos estão dentro dele? E por causa disso, o conjunto de dados conhece seu esquema em tempo de compilação. Isso significa que erros relacionados ao tipo serão detectados quando você criar seu script, vez de quando você realmente executar o script. E isso é enorme, certo? Porque executar um script geralmente é uma operação muito cara quando você está fazendo isso em um cluster grande. Então, uma grande vantagem dos conjuntos de dados é que você vai detectar esses erros relacionados ao tipo em tempo de compilação. E isso torna o seu desenvolvimento um pouco mais fácil. Isso também leva a uma melhor otimização. Isso significa que podemos realmente fazer alguma otimização enquanto estamos compilando em vez de em tempo de execução. E isso também é um grande benefício. Agora a captura com conjuntos de dados é que porque ele está fazendo todas essas coisas em tempo de compilação, você só pode realmente usá-los em linguagens que são compiladas. Isso significa Java ou Scala no mundo do Spark. Então esta é mais uma razão para usar Scala em vez de Python. Se não puder, mesmo que Python pareça ser muito mais popular. Com Python, estamos limitados a DataFrames porque ele não pode fazer essa otimização de tempo de compilação. Então, com Scala, no entanto, podemos ser as crianças legais. Podemos usar conjuntos de dados e podemos saber quais são os nossos tipos de antecedência. Python, no entanto, vai ser limitado a DataFrames. Agora, você não tem que ir tudo com conjuntos de dados se você não quiser, você pode realmente converter um RDD para um conjunto de dados com dois ds e você pode ir o contrário também. Portanto, é possível ter o melhor dos dois mundos e fazer algum processamento usando RDDs e fazer algum processamento adicional com conjuntos de dados e fazer o que faz sentido. Como veremos, os RDDs ainda são mais úteis para algumas operações. Mas para SQL como consultas, obviamente você vai querer usar conjuntos de dados. Os conjuntos de dados são realmente o novo hotness. A tendência geral no desenvolvimento do Spark é usar menos RDDs e mais conjuntos de dados. E eu realmente tenho alguns alunos que ficam meio irritados por eu até cobrir RDDs em tudo agora, mas eles realmente têm seu lugar. Conjuntos de dados, quem são muitas vezes mais eficientes, eles podem ser serializados de forma muito eficiente. E por causa desses planos de execução que estavam determinando em tempo de compilação, se você estiver fazendo uma consulta SQL, que muitas vezes pode ser muito mais eficiente, como eu disse, então apenas usar um conjunto de dados RDD também permitir uma melhor interoperabilidade, não apenas com formatos de arquivos e bancos de dados externos, mas também dentro dos vários componentes do próprio Spark. Portanto, a biblioteca do Sparks Machine Learning e o Spark Streaming Engine usam conjuntos de dados como sua API principal em vez de RDDs agora, portanto, se você quiser mover seus dados entre esses diferentes componentes do Spark, você estará usando conjuntos de dados como esse tipo de maneira de fazer isso dentro de Scala. E também, às vezes, usar um conjunto de dados pode realmente simplificar seu desenvolvimento. Se você está apenas fazendo operações SQL e você pode pensar sobre o que você está tentando fazer com sua análise no Spark em termos de um comando SQL, você vai descobrir que é muito, muito fácil fazer isso com um conjunto de dados. Considerando que poderia ter sido muito mais desafiador fazer isso com um RDD. Agora, quando você está usando o Spark SQL, incluindo conjuntos de dados dentro do Scala, há alguma diferença na estrutura aqui para como você aborda seus scripts. E veremos isso com alguns exemplos em breve. O principal é que você vai criar um objeto SparkSession em vez de um contexto Spark quando estiver iniciando seu script. Se você estiver indo para usar o Spark SQL ou conjuntos de dados, você precisa acionar sessão. Pense nisso como uma sessão de banco de dados. E você precisa interromper explicitamente essa sessão quando terminar. Agora, uma vez que você tem essa sessão, você pode realmente obter um SparkContext a partir dele e usá-lo para emitir consultas SQL em seus conjuntos de dados. Ou você pode simplesmente usar a API de conjunto de dados direta, tipo assim. Então, uma vez que você tenha um objeto de conjunto de dados carregado, você pode fazer coisas como mostrar ou selecionar ou filtrar ou GroupBy. E você vai notar que isso se parece muito com comandos SQL, certo? Então, o formato deve parecer muito familiar. Se você conhece SQL, por exemplo, selecione citar algum nome de campo que faça exatamente o que você acha que ele faria. Na verdade, ele seleciona a linha de nome de campo algum do seu conjunto de dados e retorna isso em um novo conjunto de dados. Filtragem. É uma sintaxe interessante, certo? Então, podemos realmente dizer filtro com algum nome de campo no meu conjunto de dados maior que 200. Podemos colocar essa expressão como um parâmetro dentro do nosso comando filter e obter de volta oito. É conjunto de dados onde estamos apenas filtrando coisas que são maiores do que 200. Agrupar por, que funciona assim como não SQL também. Então poderíamos agrupar tudo em algum nome de campo. E isso vai ser a mesma coisa que uma operação de redução, certo? E então podemos dizery.me para calcular automaticamente a média de cada um desses resultados. Então, em uma linha lá, eu acho que nós fizemos todo o exercício, um de nossos exemplos anteriores usando RDDs, certo? Então esse é um bom exemplo de como as coisas podem ser mais simples. E se você precisa fazer algo mais baixo, você ainda pode. Você pode converter isso de volta para um RDD e passar sua própria função de mapa personalizado se você quiser também. Então, como eu disse, você pode misturar e combinar aqui e obter o melhor dos dois mundos com conjuntos de dados e RDDs. Os conjuntos de dados também abrem outras possibilidades. Como eu disse, você não pode falar conosco, JDBC ou ODBC. Então, é possível realmente abrir um shell para acionar SQL e lidar com ele exatamente como se fosse um banco de dados, o que é meio incrível, certo? Quero dizer, isso lhe dá um tipo de banco de dados horizontalmente escalável, se preferir, em todo o cluster do Spark. Quão legal é isso? E alguns dos detalhes aqui estão listados aqui no slide se você quiser mais detalhes, mas eu não quero confundir seu cérebro com isso muito porque nós não vamos fazer isso nos exercícios, mas apenas saiba que é possível. Você também pode ter funções definidas pelo usuário, se desejar. Às vezes, isso será mais fácil de fazer fora dos conjuntos de dados, mas você lá, aqui se você precisar deles. Assim, por exemplo, poderíamos criar uma função simples definida pelo usuário importando apenas org dot apache Spark dot SQL dot, dot UDF. Poderíamos construir um UDF chamado quadrado que apenas contém a expressão tomar x e torná-lo x vezes x. E então poderíamos, por exemplo, dizer coluna de largura e adicionar uma nova coluna chamada quadrado, que apenas chama que funções quadradas definidas pelo usuário. Então você pode fazer isso também, assim como você pode ter UDFs em bancos de dados. Você também pode ter UDFs em conjuntos de dados. Então isso fará muito mais sentido com alguns exemplos. Então vamos apenas mergulhar e passar o resto desta seção olhando para exemplos práticos. Então, vamos voltar para nossos dados falsos de rede social que usamos anteriormente no curso com RDDs. E mostrarei algumas maneiras de usar conjuntos de dados para explorar esses dados. Então primeiro vamos realmente consultá-lo com um comando SQL real, e então vamos voltar e usar funções da API de conjunto de dados para consultá-lo sem usar comandos SQL reais. Mas o código ainda será muito parecido com SQL. E depois disso, vamos voltar aos nossos exemplos de RDD e refazê-los com conjuntos de dados e veremos quais são mais simples agora e quais são mais complexos. E haverá uma boa maneira de entender os pontos fortes e fracos dos RDDs e dos conjuntos de dados. E você pode aprender sobre como escolher realmente qual API usar para um determinado problema. Então vamos mergulhar com a seguinte palestra e voltar para a nossa rede social falsa e brincar com ela. 22. [de atividade: Então vamos brincar com o faísca SQL e Conjuntos de Dados e DataFrames na verdade com este pequeno exemplo simples aqui, abra o exemplo do conjunto de dados Spark SQL em seus materiais aqui. E vamos ver o que está acontecendo neste. Então vamos voltar para o nosso banco de dados de amigos falsos ou conjunto que foi usado para nossos amigos por exemplo de idade na primeira seção. E vamos consultar esses dados usando interfaces SQL SAL em vez de usar Spark SQL. Então, declaramos que um pacote é sempre n. Agora note que estamos apenas incluindo org dot apache, Spark dot SQL. Estamos nos limitando às APIs do Spark SQL. Para este exemplo, temos log para J também. Estamos criando nosso objeto e começamos criando uma classe caso. Sobre o que é isso tudo? Então este é um recurso Scala que não falamos antes. Então, uma classe caso é apenas uma maneira muito compacta de definir uma definição de classe e objeto, se preferir. Então, dizendo pessoa de classe de caso, estamos dizendo que queremos definir um objeto de pessoa. E ele irá conter os seguintes campos com os seguintes tipos. Então, se você está familiarizado com C plus, por exemplo, é como declarar uma estrutura. Mas a sintaxe aqui é um pouco mais compacta. Então, estamos dizendo que uma pessoa consiste em quatro campos diferentes. Ele contém um campo ID e este nome é significativo, que não é mantido direito. E esse ID é um número inteiro. Ele contém um campo de nome do tipo string e o campo H do tipo inteiro, e o campo de um amigo do tipo inteiro também. Ok? E isso será realmente usado para construir as tabelas de banco de dados virtual que consultarão usando o Spark SQL. Então, quando terminarmos, isso corresponderá aos nomes das colunas e os tipos de coluna em nossa tabela terá uma coluna ID que contém inteiros, terá uma coluna de nome que contém strings e assim por diante e assim por diante. Então, com essa linha, definimos o esquema para nossos dados. Certo, isso é muito importante. Com conjuntos de dados. Precisamos ter esse esquema definido em tempo de compilação. Não podemos simplesmente inferi-lo a partir dos dados em si. Então, com isso na mão, vamos para a nossa função principal. Definimos nosso nível de registro. E agora, em vez de criar um SparkContext, estamos criando uma sessão do Spark. Novamente, você pode pensar nisso como semelhante a uma sessão de banco de dados. Então, para criar essa sessão de faísca, dizemos construtor de pontos SparkSession. Para criar o nosso, para realmente construir a nossa sessão. Damos a ele um nome de aplicativo era Spark SQL. Dizemos que nosso mestre é estrela local, mesma sintaxe exata de antes, dizendo que vamos rodar em sua máquina local e eu vou CPU núcleos e obter ou criar. Isso significa que podemos realmente criar uma nova sessão do Spark ou reutilizar uma já existente. Lembra-te que te disse para parares com estas coisas quando acabares. Se avançarmos um pouco aqui, vemos que dizemos ponto de faísca parar no final para fechar essa sessão. É possível que essas sessões continuem sendo executadas além do tempo de vida desse script de driver. Então, se você não o interrompeu explicitamente, ou ele pára inesperadamente, essa sessão ainda poderia estar em execução no seu cluster e obter nossa caixa iria apenas reutilizar essa sessão existente em vez de criar uma nova nesse caso. muito interessantes. Agora vamos carregar nossos dados. Então lembre-se que nossos dados existem em falsos amigos ponto CSV. E nós vamos apenas carregar isso usando Spark dot read. Portanto, o ponto do faísca lido no objeto SparkSession lerá esse arquivo CSV. Vamos dizer-lhe que tem uma linha de cabeçalho. E vamos pedir-lhe para inferir inicialmente o esquema a partir do que está nessa linha de cabeçalho. Assim, as informações da linha de cabeçalho correspondem aos mesmos nomes que demos em nossa classe caso aqui em cima, o cabeçalho é id, nome, idade e amigos. E é importante que isso corresponda neste caso. Então, neste ponto, depois de dizer faísca dot read.csv, temos um DataFrame. Neste ponto, o esquema foi inferido em tempo de execução, certo? Essa é a principal diferença entre um dataframe e um conjunto de dados. Mas ainda queremos usar conjuntos de dados. Queremos todos os benefícios da verificação do tipo de tempo de compilação. Então eu vou pegar esse DataFrame que consiste apenas desses objetos de linha com esquemas inferidos e converter isso em um conjunto de dados com um esquema explícito dizendo ponto como pessoa. Então esse ponto como pessoa pega esse DataFrame que lemos do CSV e converte-o um conjunto de dados com um esquema que sabemos no momento da compilação usando a classe caso pessoa comigo até agora. Está bem, vai fazer mais sentido quando o executarmos. A primeira coisa que vamos fazer é imprimir o esquema para ter certeza de que é o que esperávamos. Então, neste ponto, temos um conjunto de dados de pessoas de esquema. E agora podemos criar uma vista de banco de dados sobre ele, dizendo criar ou substituir vista temporária. Novamente, isso irá criar um novo ou substituir um existente com o mesmo nome. E vamos chamar isso de poucas pessoas. Isso terá o efeito de basicamente criar uma tabela de banco de dados chamada pessoas para todas as intenções e propósitos. E podemos consultar essa tabela agora apenas dizendo Spark dot SQL. Estamos chamando o SparkSession dot SQL com um comando SQL real aqui. Vamos dizer uma estrela selecionada das pessoas. Essa é a visão que criamos a partir do nosso conjunto de dados. Quando a idade é maior ou igual a 13 e a idade é menor ou igual a 19 anos. Então estamos criando uma instrução SQL real aqui e retornando os resultados em uma nova estrutura chamada adolescentes, um novo conjunto de dados. Em seguida, coletaremos o conteúdo desses resultados e iteraremos através deles, imprimindo todos eles, e interromperemos a sessão quando terminarmos. Então vamos fazer isso e ver o que acontece. Legal, funcionou. Então podemos ver esse esquema inferido aqui, na verdade o esquema explícito que demos para o conjunto de dados, certo? Então, podemos confirmar que temos um campo id, nome, idade e amigos dos tipos que esperamos inteiro, inteiro de cadeia e um inteiro. Então esse é o esquema do nosso conjunto de dados de pessoas de esquema que configuramos lá e lemos a partir desse arquivo CSV. E então temos os resultados da nossa consulta aqui. E vemos que temos todos os adolescentes em nosso conjunto de dados aqui. Estes são jovens de 19 anos e 18 anos, e eu acho que só gerou dados de 18 anos e para cima. Então esse é o resultado de nossa consulta lá. Parece que funcionou. Bastante incrível. Então nós realmente executamos um comando SQL real em um conjunto de dados no Apache Spark em um cluster inteiro potencialmente. Então, quão legal é que você tenha todo o poder da linguagem SQL à sua disposição com o Apache Spark usando conjuntos de dados. E quero fazer mais um ponto antes de seguirmos em frente. Então eu não tive que usar um conjunto de dados aqui. Eu poderia ter usado um DataFrame. Deixe-me mostrar como isso funcionaria. Então, se eu apenas comentar esta linha, neste ponto, meu pessoal de esquema vai ser um DataFrame. Vai ter esse esquema inferido no tempo de execução. Não vou dizer explicitamente com essa classe de caso qual é o esquema. Então, ao comentar isso, eu estou perdendo todas as verificações de erros em tempo de compilação e otimizações em tempo de compilação que eu vou obter com conjuntos de dados. Mas ainda vai funcionar. Ele só funcionará em tempo de execução. Então vamos fazer isso e ter certeza de que eu não estou te contando uma mentira. E você pode ver aqui que temos a mesma resposta. Então, a mesma consulta resulta aqui de 18, 19 anos de idade que queríamos, e os esquemas ainda são os mesmos também. Então tudo ainda funciona como um DataFrame. É só que, usando um conjunto de dados e dando a ele esse esquema explícito, obtemos melhor desempenho e melhor verificação de erros em tempo de compilação. Vamos mergulhar em outro exemplo a seguir. 23. [de qual pessoa [Activity]: Então, em nossa palestra anterior, falamos sobre o uso de comandos SQL diretamente em nossos amigos falsos e dados de nossa rede social falsa. Vamos olhar para outra maneira de fazê-lo sem realmente usar comandos SQL, mas em vez disso usando as funções SQL como disponíveis em conjuntos de dados. Então dê uma olhada nessa maneira alternativa de fazer as coisas. Abra o conjunto de dados DataFrames, script de driver. E vamos dar uma olhada nisso. Então, a configuração real e o carregamento de nossos dados serão idênticos da última vez, vamos configurar uma classe de caso pessoa novamente que define o esquema dos dados que pretendemos carregar. E novamente, temos um ID que é um inteiro, um nome que é uma string, e idade que, isso é um inteiro. O número de amigos que também é um inteiro. Dentro da nossa função principal. Assim como antes de definir nosso nível de log, criamos um objeto SparkSession aqui com um determinado nome e mestre e nós obtemos ou criamos. E, novamente, lemos isso a partir do arquivo CSV usando o Spark dot read. E nós realmente forçamos isso a ser um conjunto de dados dizendo ponto como pessoa no final para converter esse esquema implicitamente definido em tempo de execução para um esquema codificado forçando-o para a classe caso pessoa aqui. Então eu meio que contornado sobre isso inicialmente, o ponto de faísca de importação implícita linha de sublinhado ponto é importante sempre que você tem inteligente implicitamente inferindo o esquema, você precisa ter certeza de que você está importando esse pacote logo antes Você faz isso. A sintaxe aqui é um pouco estranha. Normalmente, suas instruções de importação estarão na parte superior do seu arquivo. Mas neste caso nós queremos isso antes de nós vamos realmente usá-lo porque nós só queremos aplicar a este escopo específico aqui. Então sempre que você tem um comando que nós somos os esquemas sendo inferidos. E aqui é bastante explícito que estamos fazendo isso enquanto dizendo faísca dot read para usar o cabeçalho no arquivo CSV. E estamos inferindo que o esquema inicialmente a partir desse cabeçalho CSV, precisamos desencadeado implícitos para realmente ser capaz de puxar isso fora. Agora, quando terminamos, estamos convertendo isso em um conjunto de dados com um esquema explícito. Mas esse passo intermediário requer pontos de faísca implícitos. Existem outras maneiras de carregar conjuntos de dados que veremos mais tarde que não exigem essa etapa intermediária de um esquema inferido, mas vamos chegar lá. De qualquer forma, imprimimos esse esquema como fizemos antes. E agora temos uma maneira diferente de brincar com nossos dados aqui que estamos olhando. Então esta é a coisa nova agora. Então vamos começar selecionando apenas a coluna de nome. Uma coisa que fizemos em nossos exemplos de RDD, modo que era bastante comum, foi descartar colunas de informações que não precisávamos. E essa é uma maneira de fazer isso usando conjuntos de dados. Podemos dizer que as pessoas dot select, name dot show, e que iria apenas selecionar a coluna de nome e nada mais. Nesse caso, não vamos atribuir isso a um novo conjunto de dados. Nós só vamos chamar o ponto show para realmente forçar o Spark a sair e obter esse resultado e realmente exibi-lo para nós do nosso script de driver. Assim como você poderia dizer selecione o nome, estamos dizendo aqui, selecione o nome entre aspas aqui em vez de um comando SQL, sintaxe semelhante, mesma idéia, apenas uma maneira diferente de fazer isso que não requer uma visão de banco de dados real para fazê-lo. Nós também podemos fazer algo semelhante aos nossos amigos por exemplo de idade, onde nós apenas vamos filtrar qualquer pessoa com mais de 21 anos de idade. Então poderíamos dizer que as pessoas filtram pontos, pessoas com menos de 21 pontos mostram. Então isso é a mesma coisa que dizer select name onde idade é menor que 21 e SQL, mas estamos fazendo isso mais explicitamente através de funções no próprio conjunto de dados. Então isso é um pouco estranho, certo? Você sabe, se você está acostumado, outras línguas são línguas não-funcionais. A idéia de ter uma expressão como esta, pessoas com menos de 21 anos e passar isso como um parâmetro para uma função pode parecer estranha. Mas em Scala, você pode fazer isso. Na verdade, funciona. Então é bem legal. Então nós apenas dizemos pessoas e passamos no nome da coluna que queremos filtrar em menos de 21. E essa expressão ao passar pela função de filtro de um conjunto de dados, apenas funciona. Faz a coisa certa. É quase mágico. Novamente, vamos mostrar os resultados, exibi-los, vez de armazenar isso em um novo conjunto de dados em nosso exemplo aqui. Também em SQL, temos o grupo por função. E isso é basicamente a mesma coisa que a operação GroupByKey que tínhamos no RDD. Então ele vai agrupar todos os valores distintos das idades e juntá-los todos. E então nós vamos além disso chamado de contar com isso para apenas obter um grande total de quantas pessoas existem em cada idade, ano e mostrar os resultados em uma linha aqui nós fizemos algo que nós tivemos que fazer um pouco mais complicado usando RDDs, Certo? Se você se lembra, teríamos que transformar as coisas com uma operação de mapa para inserir um número um para cada pessoa individual e, em seguida fazer uma operação ReduceByKey para adicioná-las todas para fazer isso antes. Mas neste caso, podemos usar mais de um tipo SQL de sintaxe aqui e fazer tudo em uma linha de código. Então você pode ver o poder dos conjuntos de dados aqui. Além disso, uma vez que estamos usando conjuntos de dados, ele pode ser mais eficiente também. Então, sim, pense um pouco mais sobre isso. Vamos agrupar por idade. Então, basicamente, combina todas as entradas em pessoas por números únicos AGE. Contamos cada um dentro de cada idade e mostramos os resultados. E aqui está outro exemplo interessante. Neste caso, vamos selecionar todas as pessoas. E nós vamos apenas selecionar a coluna de nome. E então também vamos selecionar pessoas de idade mais 10 anos. Então isso vai mostrar uma exibição de duas colunas. Uma é a coluna de nome do conjunto de dados de pessoas originais. E a segunda coluna que mostrará que estamos selecionando aqui será a coluna de idade com 10 atitudes. Então, novamente, podemos ter essas expressões dentro de funções quando em Scala, e ele realmente funciona. Podemos dizer que as pessoas têm mais 10 anos e passar isso como um parâmetro para a função select. É um pouco estranho se você está acostumado com outras línguas novamente, mas é assim que você faz em Scala e faísca, ele realmente funciona. E lembre-se sempre de parar sua sessão quando terminar. Caso contrário, ele vai continuar correndo e andando por aí e usando recursos que você não quer estar usando. E isso poderia confundi-lo quando você está executando as coisas em corridas subsequentes também. Nunca se esqueça de parar a sessão quando terminar. Então vamos em frente e ver isso em ação e nos convencer de que realmente funciona. Vamos clicar com o botão direito do mouse em DataFrames, Conjuntos de Dados e dizer fugir , ele vai. Certo, e vamos ver o que aconteceu aqui. Vamos até o topo. Vou rolar para cima. A primeira coisa que fizemos foi imprimir o esquema, e lá está. Então, podemos nos convencer de que realmente obteve a estrutura correta do conjunto de dados lá. Parece certo para mim. Então, estamos inferindo um nome de ID, idade e amigos coluna de tipos inteiro, string, inteiro e inteiro, respectivamente. Nosso primeiro passo aqui com a seleção da coluna de nome. E havia este comando aqui, as pessoas dot select col é igual ao nome dot show. E fez exatamente o que você esperava. E parece muito como você esperaria ver de uma saída de banco de dados relacional real, não é? Você sabe, eles estão realmente tentando fechar a lacuna entre o Spark e usar um banco de dados relacional e torná-lo da mesma maneira usá-lo com o Apache Spark e suas versões mais recentes. A diferença, é claro, é que, em vez de um único servidor de banco de dados monolítico, você tem um cluster inteiro fazendo isso potencialmente. Então você pode ver que selecionamos com sucesso a coluna de nome e a mostramos. Então temos esta pequena pré-visualização das primeiras entradas. Nós só mostramos as 20 linhas principais por padrão, ou de outra forma, ele iria continuar para sempre. E nosso próximo experimento aqui foi filtrar alguém com mais de 21 anos passando neste argumento de filtro de pessoas com menos de 21 anos. E com certeza, os dados resultantes que recebemos são apenas mostrando pessoas com idade de 19, 20 ou 18 anos, porque essas são todas as pessoas com menos de 21 anos de idade em nosso conjunto de dados. Então esse trabalho é muito legal. E também tentamos esse comando grupo por idade aqui novamente, um pouco mais chique aqui. Então, novamente para recapitular, agrupamos todos por números únicos de AGE e contamos todos eles e mostramos a eles e parece que funcionou. Então temos 831 anos de idade, 565 anos, 753 anos, etc., dentro do nosso conjunto de dados. Então, novamente, uma linha de código, muito simples, muito fácil de usar. Eles são altamente otimizados. E é muito mais simples do que a maneira como tivemos que fazer isso usando RDDs. Finalmente, nós fizemos isso, fazer todo mundo 10 anos mais velho truque aqui onde nós selecionamos a coluna de nome e também inventamos uma nova coluna que é chamado de pessoas idade mais 10. Então vamos ver se funcionou. E sim, parecia que provavelmente tínhamos 33 anos, mas na coluna de idade mais 10 que criamos aqui, ele agora tem 43 anos. E realmente funciona. Você pode passar em expressões matemáticas como essa e eles realmente serão avaliados e exibidos para você desta maneira. Quando terminamos, paramos a sessão, e foi isso. Então, aí está. Conjuntos de dados usando funções em vez de comandos SQL reais. Você pode fazer de qualquer maneira, mas, você sabe, depende de sua preferência. Então, aí está. Duas maneiras diferentes de usar conjuntos de dados. 24. [Exercício de vocês: Tudo bem, você me ouviu falar sobre conjuntos de dados por tempo suficiente. Acho que é hora de sujar as mãos e tentar usá-las vocês mesmos. Então deixe-me dar-lhe o seu primeiro desafio usando conjuntos de dados. Lembra-se do exemplo de amigos por idade que fizemos com RDDs? Bem, eu queria voltar lá e fazer isso novamente, mas desta vez usando conjuntos de dados em vez de RDDs. Então, apenas para rever o que esse exemplo é tudo sobre, nós fornecemos um arquivo de valor separado por vírgulas de amigos falsos que contém dados neste formato. É basicamente um ID de usuário, seu nome, sua idade e o número de amigos que eles têm. E sua tarefa é me dar o número médio de amigos por idade. Então eu quero saber, em média, quantos amigos como um 33 anos de idade têm, muitos amigos é um 55 anos têm e assim por diante e assim por diante para cada idade representada em meus amigos falsos arquivo CSV ponto. E se chama “amigos falsos “porque são dados falsos. Foi tudo gerado aleatoriamente. Então eles não são como, eu não estou fazendo um julgamento de valor em seus amigos aqui. De qualquer forma, algumas dicas de como passar por isso. Portanto, há um arquivo csv de ponto de amigos falsos em seus materiais do curso que contém uma linha de cabeçalho. E como você viu em nossos exemplos anteriores, usando conjuntos de dados que vai ser importante para permitir vieiras e faíscas para o esquema correto para esses dados. E alguns comandos aqui que podem vir a calhar. Lembre-se, podemos usar o comando select para extrair determinadas colunas de um conjunto de dados e obter um novo que só tem os dados que precisamos. Você deve se lembrar que quando fizemos isso com RDDs, tivemos uma função de mapa que realmente fez isso para nós. Então isso vai ser muito mais simples usando uma instrução select. E você precisará de alguma outra função de conjunto de dados. Então GroupBy nós já olhamos antes que irá basicamente agregar as coisas por idades únicas, como uma operação de redução. Show mostrará os resultados finais e os recuperará. E quando não falamos sobre era AVG para a média. Então, depois de agrupar as coisas por idades, você vai querer obter a média por idade. E então eu sempre vejo os nomes das colunas que coloco aqui para fins ilustrativos, cabe a você colocar os nomes certos lá e colocá-los na ordem certa e o que não. Mas essas são as peças que você deve precisar para fazer isso. E você pode querer se referir de volta ao arquivo Scala do ponto do conjunto de dados DataFrames para obter inspiração. E você não tem que fazer assim também. Você poderia apenas usar um comando SQL straight up se você quiser também. Então, cabe a você em que direção você quer ir. Então vá e tente isso. E quando voltarmos para a próxima palestra, mostrarei minha solução para ela e também algumas maneiras de expandir para fazer algumas coisas mais interessantes com esses dados também. Por isso vai tentar e vê se consegues pôr isso a funcionar e depois volta e eu mostro-te a minha solução. Não espreite a solução. Ele está lá e, claro, materiais, então certifique-se de criar um novo arquivo que tem algum nome único e resistir à tentação de caras de pico e voltar e vamos rever a resposta. 25. Solução de exercício: amigos por idade, com o conjunto de dados: Ok, então espero que você foi capaz de passar por esse exercício e implementar os amigos por atividade H usando conjuntos de dados sem muito problema. Se quiser comparar a sua abordagem com a minha. Aqui está a minha solução. Se você abrir o script de conjunto de dados amigos por idade aqui nos materiais do curso. E, novamente, há muitas maneiras de fazer isso. Então, se o seu código não coincidir exatamente com o meu, tudo bem. Tudo o que realmente importa é que você tem os mesmos resultados finais. Então, verifique alguns dos resultados médios que você tem para diferentes idades e se eles combinam com o meu, Você é bom. Então vamos ver o que eu fiz aqui. Então, muito disso parecerá familiar. Criamos uma classe de caso chamada Fake Friends neste caso em vez de pessoa só para misturar as coisas um pouco. Isso define o esquema explícito de nossos dados vindos do arquivo CSV de ponto de amigos falsos, que consiste em um ID e nome, idade e amigos. Já vimos isso antes, só um nome diferente. A primeira coisa que fazemos é definir nosso nível de log, criar um SparkSession, o mesmo que fizemos antes. E como fizemos antes, carregamos a barra de dados falsos amigos ponto arquivo CSV usando esquema inferido do cabeçalho. E então forçamos esse DataFrame em um conjunto de dados dizendo ponto S e passando, nesse caso classe amigos falsos para definir explicitamente qual é o esquema. Agora podemos em tempo de compilação verificar todos os tipos e o que não e fazer algumas otimizações em tempo de compilação também. Tudo bem, então a primeira coisa que fazemos é ir e selecionar apenas as colunas que precisamos. Então, como você deve se lembrar, as únicas coisas que realmente nos importam neste exemplo são a idade e o número de amigos, os IDs de usuário e os nomes são irrelevantes para esse problema. Então, vamos apenas selecionar a partir desse conjunto de dados, as colunas de idade e amigos, e passar isso para um novo conjunto de dados chamado Amigos por idade. E agora tudo o que temos que fazer é dizer amigos por idade ponto groupby on age. Então isso vai agrupar tudo por valores únicos de idade. E então, uma vez que temos isso, vamos dizer ponto AVG para obter a média das colunas de amigos agrupadas por idade e, em seguida, ponto mostrar para exibir os resultados. E é isso. Nós realmente seria feito neste momento. Há mais alguns truques que quero te mostrar aqui, então há mais para conversar. Mas para o desafio como declarado, isso é tudo que você precisa. Então isso é muito legal, certo? Em duas linhas de código, basicamente fizemos o que fizemos em todo o exemplo usando RDDs antes. Vamos voltar e olhar para isso apenas para fins de comparação. Então aqui estão os amigos por idade dot script Scala onde fizemos isso usando RDDs. E você verá que é muito mais complicado aqui. Então aqui nós tivemos que escrever esta função de linha de análise para ir e analisar tudo e dividir as coisas por vírgulas e extrair os campos que queremos e retornar uma nova tupla. É isso que queremos os campos. Considerando que, com conjuntos de dados, podemos apenas usar o carregador CSV incorporado à nossa sessão do Spark. E use a instrução select para selecionar os campos que queremos. Muito mais simples usando conjuntos de dados. Então, usando RDDs, tivemos que fazer todo tipo de coisas complicadas para calcular essa média, certo? Tivemos que ir e mapear as coisas para x vírgula um aqui. Então podemos contar tudo usando ReduceByKey. E é uma maneira bem distorcida de fazer o que fizemos apenas usando aqui no exemplo de conjunto de dados, agrupar por uma média. E depois disso ReduceByKey, tivemos que calcular a média manualmente também usando MapValues. Então esse código, eu acho que faz muito mais sentido. É muito mais fácil de ler. É muito mais simples. Ao contrário do que tivemos que fazer aqui usando RDDs para fazer a mesma coisa. Então, esse é um bom exemplo de onde conjuntos podem ser muito mais fáceis de usar e pode até ser mais rápido. Mas sob o capô , são RDDs em um nível mais baixo. E então às vezes é bom ir para esse nível mais baixo se você realmente precisa ajustar as coisas nesse nível, vamos seguir em frente e levar isso para o próximo passo. E daí se eu quisesse classificar esses dados? Acontece que também é fácil. Se eu quisesse classificar essas coisas por idade, eu poderia colocar um comando dot sort age antes do show. E isso vai pegar os resultados das minhas médias por idade e apenas classificá-los pela coluna de idade antes de exibi-lo. E além disso, eu poderia formatar isso mais bem. Nossas médias às vezes têm um monte de casas decimais para eles e não faz sentido ter tanta precisão. Eu poderia dizer AGG e, em seguida, média redonda. Isso requer um pouco de colocar sua cabeça em volta. Então temos a média do número de amigos aqui que fizemos antes. E então estamos dizendo que vamos arredondar isso para duas casas decimais de precisão. Então é assim que o comando redondo funciona lá. E nós temos que usar essa função AGG porque estamos agregando todos os dados para essa determinada idade que nós agrupamos, certo? Então, agonias, vamos calcular essa média através do agregado de todos os valores para aquela idade que selecionamos lá. Depois que o arredondamento é feito, nós novamente classificamos os resultados por idade e mostrá-los. E também podemos personalizar nossos nomes de coluna também. E é isso que este exemplo aqui está fazendo. Então aqui estamos adicionando um pseudônimo após esse agregado de arredondar tudo. E nós vamos renomear isso para amigos sublinhado média. E então, novamente, nós classificamos e mostramos. Então vamos passar por isso de novo. Depois de ver a saída, pode fazer um pouco mais de sentido. Vamos clicar com o botão direito do mouse em amigos por conjunto de dados de idade e executá-lo. E aqui vamos nós. Tudo bem, então vamos percorrer cada conjunto de resultados aqui do topo, rolar até o início aqui. Certo, então nosso primeiro exemplo foi o simples em que nós apenas fizemos um grupo por idade e, em seguida, média de amigos e mostramos isso. E isso funciona. Então, o grupo por idade agrupou tudo por idades únicas, e em seguida, a média do computador de um amigo, a média da coluna de amigos para cada idade. É tão fácil e, de fato, isso funciona. No entanto, você notará que as bordas não estão classificadas, por isso é um pouco difícil procurar as coisas e obter uma resposta específica a partir dele. Além disso, a exibição aqui é um pouco estranha, certo? Temos todas essas quantidades loucas de precisão nas médias que provavelmente não são necessárias. Então, no nosso próximo exemplo, resolvemos o problema de classificação. Tudo o que fizemos aqui foi adicionar um tipo de ponto com um parâmetro de idade lá para o, para a mistura lá no final. E isso funcionou. Então vemos que as idades estão agora classificadas. Começamos com 18, 19, 20, 21, etc. E isso parece ter funcionado também. E, além disso, podemos fazê-lo ainda mais bem. Então, se descermos para este terceiro exemplo aqui, neste, estamos arredondando os resultados para duas casas decimais de precisão aplicando uma função redonda para a média e usando Ag para aplicar isso a todos os resultados de idade para esse grupo. Então aqui temos a idade e a expressão de amigos médios vírgula dois, que é arredondar essa média para duas casas decimais de precisão. E você pode ver que realmente funciona como pretendido. Muito legal. E, finalmente, demos a isso um nome de coluna personalizado usando o comando alias dentro desse agregado também. Então, dizendo alias de ponto, nós renomeamos essa coluna de amigos médios redondos vírgula dois para algo mais útil, amigos sublinham média. E se você dissesse isso em um conjunto de dados resultante, isso tornaria mais fácil se referir a essa nova coluna que computamos pelo seu nome sem ter que digitar esses enormes resultados complicados. Então, quando você está encadeando conjuntos de dados juntos, isso geralmente é muito útil para ter uma maneira mais fácil de se referir a esses resultados computados nessa coluna. E lá você tem isso em conjuntos de dados com nossos amigos por exemplo de idade, feito de algumas maneiras diferentes e estendido de algumas maneiras diferentes para fazê-lo, espero que você tenha aprendido algumas coisas lá. Vamos passar para mais alguns exemplos e ficar ainda mais familiarizados com conjuntos de dados. 26. Exemplo de contagem de de de em Word: Então, vamos continuar a aprender sobre conjuntos de dados através de exemplos. E novamente, vamos voltar para nossos exemplos de RDD e adaptar nosso exercício de contagem de palavras para usar conjuntos de dados em vez de RDDs. E vamos direto para a versão mais complicada que realmente usa expressões regulares e classifica os resultados. Agora, neste exemplo, estaremos usando funções SQL para alcançar os resultados que queremos. Então, em vez de usar FlatMap, vamos usar uma função chamada explode que irá explodir colunas em linhas. Então, se cada coluna representa uma palavra explorável, coloque cada palavra em sua própria linha. Usaremos a função de divisão para dividir as coisas por palavra. Usaremos a função inferior para converter tudo em minúsculas. E algumas notas aqui sobre sintaxe para estar ciente. Então, quando você está passando um nome de coluna como um parâmetro para essas funções SQL, a sintaxe é sinal de dólar e, em seguida, o nome da coluna entre aspas. Assim, por exemplo, cifrar sinal de dólar citação valor vírgula, e, em seguida, a expressão regular iria dividir qualquer texto que está na coluna de valor com base nos delimitadores de palavras lá. Da mesma forma, o filtro funcionaria da mesma maneira se quiséssemos filtrar para eliminar quaisquer palavras que tenham uma string vazia, faríamos isso desta maneira. Filtrar sinal de dólar e, em seguida, palavra entre aspas. E observe os operadores de igualdade estranhos aqui quando você está usando declarações de filtros aqui, não vai ser um sinal de banco igual, ele vai ser igual, bang seno igual. Um pouco estranho. Similarmente operador de desigualdade aqui seria igual, igual, igual. Então, apenas algo para lembrar, você receberá um erro no compilador se você não conseguir isso direito. Isso vai lembrá-lo se há um problema, mas uma coisa estranha e peculiar lá. Então, novamente, esse é um exemplo de apenas testando onde ele contra uma string vazia, apenas duas aspas sem nada entre elas. Agora, vale a pena ressaltar que o conjunto de dados realmente funciona melhor com dados estruturados. E quando estamos apenas lidando com linhas de textos, isso não é realmente dados estruturados. Então você está tipo de encaixar uma cavilha quadrada em um buraco redondo aqui usando conjuntos de dados. Até certo ponto. Às vezes, os RDDs são mais simples e este pode ser um desses, mas você não precisa apenas usar conjuntos de dados ou RDDs. Você pode usá-los juntos e falaremos sobre isso em um segundo. Uma outra coisa a observar, porém, é que outra coisa É estranho sobre o uso de conjuntos de dados nesse sentido é que porque não temos dados estruturados chegando, nós também não temos um esquema chegando. Então o esquema que acaba sendo inferido é meio arbitrário. Acabamos com um DataFrame cheio de objetos de linha com um valor de coluna chamado por padrão para cada linha de texto porque não há esquema. Cada, cada linha é apenas uma linha de texto. Então, há um nome padrão para essa coluna chamado valor que você só tem que saber sobre. E é assim que vamos nos referir a esses dados no script. Mas novamente, você pode usar ambos e veremos uma maneira de fazer isso também. Portanto, lembre-se, você pode converter RDDs dois conjuntos de dados. Por isso, às vezes faz sentido divulgar a sua carga, os seus dados utilizando as interfaces RDD e, em seguida, convertê-los para um conjunto de dados para facilitar o processamento mais tarde. Então vamos tentar isso também. Vamos mergulhar e ver como é. Então vamos abrir a contagem de palavras, melhor script de conjunto de dados sortidos aqui e analisar o que está acontecendo aqui. Então vamos fazer isso de duas maneiras diferentes aqui. Vamos começar como sempre importamos tudo o que precisamos, declarando nosso pacote, declarando um objeto. Desta vez vamos ter uma classe de caso muito simples para carregar nosso conjunto de dados inicial. Vamos chamá-lo de livro. E os únicos dados que ele tem é uma string que nós vamos ter que chamar valor. Lembre-se, voltaremos a isso mais tarde para saber por que isso tem que ser chamado de valor. Vamos para a nossa função principal, definir o nível de log, criar uma sessão do Spark como antes. E novamente, vamos importar inicialmente isso como um DataFrame usando readme.txt com texto de ponto do livro de dados. E, a fim de descobrir implicitamente esse esquema, precisamos importar pontos de faísca implícitos para fazer isso no nível DataFrame. Em seguida, chamamos ponto como livro para forçar isso em um conjunto de dados que tem um esquema definido que podemos saber sobre em tempo de compilação. O que é estranho aqui é que quando inferimos que esquema implicitamente com o DataFrame, não havia nenhum esquema fornecido. Então tudo o que sabemos é que temos linhas de texto chegando através do texto ponto-ponto do faísca. E por padrão, cada linha de texto será chamada de valor. Esse é o nome daquela coluna que temos. E nós só temos que saber isso. Então, para que esse conjunto de dados corresponda com o esquema DataFrame inferido, precisamos nomear esse valor de linha. Certo, então não escolhemos esse nome arbitrariamente. Se fosse algo diferente do valor, esta linha não funcionaria. Então, novamente, estamos entrando em como uso de conjuntos de dados pode ser um pouco desajeitado em algumas situações quando você não está lidando com fontes de dados estruturadas reais provenientes de um banco de dados ou algum formato de banco de dados. Mas uma vez que fizermos isso, vamos seguir em frente. Então agora vamos dividir isso usando uma expressão regular como fizemos antes com o operador split, estamos usando RDDs. E, em vez de usar FlatMap para explodir isso em linhas individuais para cada palavra, vamos usar a função explode. Então olhe para isso com mais cuidado. Vamos dizer entrada, que é o nosso conjunto de dados de entrada que contém uma linha de texto em cada linha. E diremos selecionar, explodir, dividir o valor com um padrão de expressão regular para dividir as coisas em palavras individuais. Ok, então vamos começar pelo meio aqui. Então começamos dizendo dividir a coluna de valor. E novamente, esse é apenas o nome que atribuímos automaticamente a essa coluna de texto que temos baseado no delimitador de palavras. Então, neste ponto vamos ter uma série de palavras. Nós vamos chamar explode sobre isso para então dividir isso em uma série de linhas individuais para cada palavra. E então, além disso, vamos dar a isso um apelido chamado palavra porque caso contrário seria esta grande descrição complicada dessa coluna que nós geramos. Então, neste ponto, devemos ter um novo conjunto de dados que tem uma coluna de palavras onde cada palavra está em sua própria linha. Agora, além disso, acontece que acabamos com um monte de strings vazias quando fazemos isso dessa maneira, e queremos filtrá-los para que não obtenhamos essa grande entrada em nossos resultados finais sobre strings vazias sendo realmente comuns. Então, para fazer isso, vamos apenas dizer filtro de pontos. E vamos filtrar para onde a coluna de palavras não é igual a uma string vazia, apenas duas aspas sem nada entre elas. Então, novamente, observe a sintaxe aqui, sinal de dólar e, em seguida, o nome da coluna entre aspas. E neste ponto nós já tínhamos dado um alias para essa nova coluna de palavras chamada palavra, para que possamos referi-lo pela palavra nome na operação de filtro que vem depois dela. Tudo bem, então agora temos um novo conjunto de dados de palavras que tem palavras individuais em cada linha. Filtramos todas as palavras vazias. Em seguida, vamos converter isso em minúsculas. E novamente vamos dizer words.py selecione passando em nossa função inferior. E nós vamos aplicar essa função inferior para a coluna de palavras. E vamos novamente dar um novo pseudônimo e manter a palavra com o nome. Nós vamos basicamente converter isso para minúsculas no lugar. Em seguida, contaremos as ocorrências de cada palavra usando o grupo por operador, e depois contaremos. Então groupby irá reunir todas as palavras únicas juntos e depois contar, isso vai contar todas as ocorrências de cada um? Então agora temos um novo conjunto de dados de contagem de palavras que contém uma contagem de cada palavra individual. Estamos quase terminando. Agora só precisamos classificar os resultados pela coluna de contagem e exibi-los. E observe a sintaxe aqui. Então o que está acontecendo aqui exatamente quando dizemos show word count, sorted dot count, dot t2 int, estamos apenas certificando-se de que o comando show mostra o conjunto completo de resultados aqui. Por padrão, ele mostrará apenas as primeiras 20 linhas. Queremos mostrar todos os resultados. Então a maneira como este show funciona é que você passa a ele o número de linhas que você quer mostrar. E queremos a coisa toda. Então vamos chamar contagens de palavras classificadas contagem de pontos para obter a contagem de quantas linhas estão em contagens de palavras classificadas. E então temos que converter explicitamente isso para um inteiro para ter certeza de que show está recebendo o tipo de dados que ele espera. Então, sempre que você quiser mostrar todo o conteúdo de um conjunto de dados, é assim que você faria. Você diria apenas o conjunto de dados name.com dot t2 int, e passaria isso como um parâmetro para o comando show para ter certeza de que obtemos cada linha exibida. Então vamos em frente e executar isso antes de seguir em frente e ver como isso funciona. Então clique com o botão direito do mouse em executar WordCount, melhor conjunto Lá vai ele. E aqui estão os nossos resultados. Então vamos rolar para cima. E você pode ver que funcionou. Parece que tenho um erro de digitação. Use três. Estas são todas as palavras e só apareceram uma vez em todo o meu livro. E à medida que descermos, veremos mais e mais palavras comuns à medida que avançamos. Então, há o fim disso. Sim. Então a palavra que você é na verdade a palavra mais comum seguida pela palavra, resultados bastante pouco surpreendentes e os mesmos resultados que obtivemos com RDDs também. Agora deixe-me mostrar outra maneira de fazê-lo porque, como eu disse, o processo de carregar esses dados em um conjunto de dados foi um pouco desajeitado. Talvez um RDD seja mais adequado para saquear esses dados brutos. Então, como eu disse nos slides, podemos misturar e combinar. Você pode obter o melhor de ambos os mundos. Então, nesta abordagem alternativa aqui, estamos carregando os dados usando a interface RDD. Então eu vou obter esses SparkContext fora do SparkSession e chamar a antiga função TextFile sobre isso. Então isso só vai carregar todos os dados de texto do ponto do livro em um RDD onde cada linha é uma linha de texto. Então agora podemos chamar FlatMap no livro RDD e dividir isso usando uma expressão regular como fizemos antes. E isso é, sem dúvida, um pouco mais simples do que a maneira como fizemos usando um conjunto de dados. Tivemos que fazer essa coisa estranha complicada com dividir e explodir um alias e filtro para fazer isso funcionar usando um conjunto de dados. Então, aqui está um exemplo em que um RDD é realmente mais simples. Mas quando você quer fazer análise, conjuntos de dados geralmente são a melhor escolha, certo? Porque você tem todo o poder do SQL atrás de você e a melhor otimização que, que oferece. Então, neste ponto, podemos converter o RDD2 um conjunto de dados. E é isso que está acontecendo aqui com dois ds. E a partir desse ponto, o código é basicamente o mesmo. A única diferença é que estamos nos referindo a esse nome de valor em vez de palavra, porque neste ponto, ainda estamos lidando com o nome de coluna padrão do valor aqui que temos quando convertemos o RDD para ds. E isso também funciona. Então, já fizemos isso. Se rolarmos para baixo, podemos ver a segunda execução onde obtivemos os mesmos resultados exatos apenas usando uma maneira diferente, começando usando um RDD para carregar os dados e um conjunto de dados para realmente analisá-lo. Então, às vezes, isso pode ser um truque útil, especialmente se você não estiver lidando com uma fonte de dados estruturada. E você pode ver que temos a mesma resposta lá no final. Então, essas são duas maneiras de fazê-lo usando conjuntos e também usando uma abordagem híbrida de RDD e conjunto de dados. Por isso, ter estas ferramentas no bolso traseiro às vezes pode ser útil. 27. [de atividade, Revisando o exemplo de mínimo de temperatura, com o Datasets: Então, usando conjuntos de dados, é realmente bastante simples como você viu, mas vamos rapidamente passar por mais alguns exemplos aqui apenas para voltar e reimplementar esses exemplos de RDD com conjuntos de dados por exemplo. Então vamos voltar para os exercícios de temperatura mínima e máxima que fizemos e dar uma olhada naqueles que usam conjuntos de dados em vez de RDDs. Não é muito novo neste exemplo. Um, porém, é que nós vamos estar fornecendo um esquema explícito para SparkSession dot read. Então, em vez de inferi-lo a partir de um arquivo CSV, vamos dizer-lhe explicitamente qual é o esquema enquanto ele está lendo no DataFrame. Nós ainda vamos ter que converter isso em um conjunto de dados com uma classe caso. Mas essa é outra maneira de importar dados de um arquivo de texto que veremos. E também veremos o uso da função de coluna de largura em um conjunto de dados para criar uma nova coluna usando nossa própria função personalizada. Então vamos mergulhar e ver como isso funciona. Então vamos dar uma olhada na versão original do RDD deste. Esse é o roteiro de temperaturas mínimas aqui. E só para refrescar sua memória, carregamos um arquivo CSV de 8800 pontos que continha informações meteorológicas do ano 8800. Em seguida, analisamos isso para extrair os campos que queríamos e convertemos para Fahrenheit como fomos. E então aparamos qualquer coisa que não fosse uma entrada T min para o tipo real de entrada meteorológica lá com o comando filter. Nós mapeamos isso para a identificação da estação e tuplas de temperatura e reduzimos por chave para manter o controle da temperatura mínima encontrada para cada estação meteorológica única. Então vamos ver como fazemos isso com um conjunto de dados em vez de um RDD. Clique no conjunto de dados de temperaturas mínimas. E aqui está a nossa nova implementação. Curiosamente, é mais código, não menos. Então, novamente, para coisas simples como esta que não estão realmente lidando com tipos de problemas de banco de dados. Às vezes, um RDD pode ser mais fácil. Mas vamos dar uma olhada. Então vamos começar com a nossa declaração de pacote e estamos importando tipos SQL específicos que vamos usar dentro do nosso script, a função SparkSession e SQL. Então, em vez de importar tudo, geralmente é uma prática melhor importar o que você precisa, que é o que estamos fazendo aqui. Começamos declarando uma classe de caso de temperatura. Este vai ser o formato que lemos no nosso arquivo de dados real. Ele tem o formato de um ID de estação baseada em string, uma data, que podemos interpretar como um inteiro, um tipo de medida, que é uma string, e uma temperatura, que vai ser um valor de ponto flutuante. Definimos nosso nível de log, criamos nossa sessão do Spark como fizemos antes. E agora vamos fazer algo um pouco novo aqui. Vamos declarar um esquema específico para esses dados de entrada. Então, em vez de inferi-lo a partir de um cabeçalho, porque não temos um cabeçalho neste arquivo CSV. Vamos dizer explicitamente o que essas colunas significam que está lendo. Agora antes que enganado dizendo importar o cabeçalho e inferir o esquema do cabeçalho, mas não temos que desta vez. Então aqui está uma maneira alternativa de fazê-lo. Então, estamos configurando um valor de esquema de temperatura que será um StructType. E vamos chamar a função add neste StructType para adicionar campos diferentes a essa estrutura. Então nós apenas dizemos adicionar ID da estação, que é um tipo de string, e pode ser móvel. Data como um tipo de medida de tipo inteiro é um tipo de string, temperatura é um tipo de flutuação C. E isso tudo coincide com os nomes que temos aqui em nossa classe caso também. E os mesmos tipos, os mesmos nomes. Então, agora que temos isso, podemos importar o ponto faísca implícito e ler nossos dados do arquivo CSV. Desta vez, em vez de dizer 3D do cabeçalho, vamos dizer esquema de ponto com esquema de temperatura. Então isso vai nos permitir construir nosso DataFrame corretamente a partir desses dados CSV. E então, como antes, nós convertemos isso explicitamente para um conjunto de dados com uma estrutura de tempo de compilação codificada que está vivendo na classe de caso de temperatura. Então, novamente, você vê a diferença aqui. Na verdade, estamos inferindo o esquema em tempo de execução ainda, porque estamos definindo esse esquema como uma estrutura em tempo de execução. Considerando que ao dizer ponto como temperatura em tempo de compilação, sabemos o que esse objeto de temperatura é e o Spark pode fazer mais otimizações, nos dar erros de tempo de compilação em vez de erros de tempo de execução. Por isso, pode parecer um passo extra que pode não ser necessário, mas estamos a obter um benefício com isso. Então agora vamos voltar e fazer o mesmo que fizemos antes com RDD's, mas usando um conjunto de dados. Então a primeira coisa que vamos fazer é filtrar qualquer coisa que não seja uma equipe na entrada. Então, em vez de usar filtro em um RDD, nós apenas usamos filtro no conjunto de dados. E usamos esta sintaxe aqui, cifrão novamente precedendo o nome da coluna. Então, queremos testar a coluna de tipo de medida e ver se é igual a T min. E novamente, nessas instruções de filtro, a sintaxe é um pouco incomum para igualdade. São três sinais iguais. Então, isso irá criar um novo conjunto de dados tendas MR1 contém apenas equipe inlines. Em seguida, queremos apenas selecionar as colunas que precisamos. Há um monte de coisas que não precisamos como as datas específicas porque estamos apenas procurando o mínimo durante todo o ano. Nós realmente não nos importamos quando isso aconteceu. Então vamos apenas fazer um seleto com uma lista das colunas que queremos. Identificação da estação, temperatura vírgula. É tudo o que precisamos preservar. Agora entramos na carne das coisas. Vamos agrupá-los e encontrar o mínimo. Assim, agrupar por ID de estação irá agrupar todas as entradas juntas para IDs de estação exclusivas. E só deve haver dois deles restantes neste conjunto de dados. E então uma vez que temos esses grupos, nós também chamaremos Min para encontrar a entrada mínima dentro de cada grupo, olhando para a coluna de temperatura e encontrando o valor mínimo de temperatura para cada grupo de IDs de estação. Peguei-o. Então agora temos um conjunto de dados da Estação Espacial Min termo que é apenas ID da estação e temperatura mínima. Estamos quase terminando. A última coisa a fazer é converter essas temperaturas dois graus Fahrenheit. E podemos também classificar os resultados enquanto estamos nisso. Então é isso que está acontecendo aqui. Vamos fazer um novo conjunto de dados chamado Min tentativas pela estação F porque estamos convertendo isso para Fahrenheit. E isso será tomar nosso conjunto de dados Min times by station e aplicar essa função de coluna de largura nele. Então isso vai criar uma nova temperatura de nome de coluna. Isto é realmente diferente do que começamos com aqui. Assim, com coluna pode substituir uma coluna existente ou criar uma nova. Neste caso, estamos realmente criando um novo porque com muitas tentativas por estação, tudo o que obtemos desse comando grupo BY é o ID da estação e uma nova coluna chamada Min à temperatura com temperatura entre parênteses. Então nossa coluna de temperatura que tínhamos originalmente, na verdade foi para o estado e vamos recriá-la agora vamos fazer uma nova coluna de temperatura aqui com o comando width column. Então, com a coluna, vamos chamar a nossa nova temperatura de coluna. E será construído usando esta função. Então vimos com coluna antes quando falamos sobre funções definidas pelo usuário, mesmo conceito aqui. Só não estamos usando uma função real que definimos. Estamos passando uma expressão aqui explicitamente. Então vamos começar pelo meio. Começamos com a coluna de temperatura mínima, e é assim que essa coluna foi automaticamente nomeada quando a criamos com o comando group BY. Assim, agrupar por agrupamento na temperatura Min irá criar uma coluna Temperatura Min. E se você fosse fazer um show nesse conjunto de dados enquanto você está depurando coisas, você teria visto o nome da coluna. Alternativamente, poderíamos ter chamado pseudônimo para dar um nome mais explícito que poderíamos nos referir mais tarde, mas não fizemos. Então, vamos apenas usar este nome padrão aqui. Então vamos pegar isso, multiplicar por 0,1. Isso vai converter o formato de dados brutos em graus reais Celsius. E então vamos converter isso para Fahrenheit multiplicando por nove quintos e adicionando 32. Além disso, isso vai viver dentro da função redonda aqui. Parâmetro de dois, o que significa que queremos arredondar isso para duas casas decimais de precisão. Ok, então isso vai criar uma nova coluna de temperatura novamente, com nossa temperatura convertida em Fahrenheit arredondada para duas casas decimais. Além disso, vamos selecionar os dados que precisamos, então não precisamos mais dessa coluna de temperatura mínima. Nós só queremos a coluna Fahrenheit final convertida em vez disso. Então vamos selecionar o ID da estação e as colunas de temperatura porque isso é tudo o que queremos exibir no final. E finalmente, vamos classificar por temperatura para que possamos obter esses resultados classificados por temperatura, a temperatura mínima que foi observada em cada um. Finalmente, vamos coletar esses resultados exatamente como você teria feito com um RDD. E neste ponto todos os nossos dados estão de volta ao nosso script de drivers e estamos vivendo dentro do mundo de Scala novamente. Então nós apenas passar pelo código Scala aqui, iterar através de todos os resultados em nosso conjunto de resultados. Extraia o primeiro, segundo elementos da tupla, chame-o de estação em temperatura. E vamos, além disso, lançar explicitamente a temperatura como um valor de ponto flutuante. Podemos então formatar que usando o operador de impressão F aqui. E finalmente imprimir linha os resultados reais usando o operador de substituição, como falamos sobre caminho de volta em nosso curso intensivo Scala. Então vamos executá-lo e nos convencer de que funciona. Clique com o botão direito do mouse, execute o conjunto de dados de temperaturas mínimas, e ele vai E funcionou. Ótima. Então temos nossas duas estações meteorológicas lá com suas temperaturas mínimas em Fahrenheit arredondadas para duas casas decimais de precisão. Wu funcionou. Tudo bem, então sim, se você quiser um pouco de desafio extra, você pode ir em frente e tentar modificar isso para fazer temperaturas máximas e definir temperaturas mínimas apenas para obter suas mãos um pouco mais deve ser trivial. Então, eu nem sequer fui para lhe fornecer uma solução para isso. Mas se você quiser brincar com isso um pouco mais, eu certamente encorajo. 28. [Exercício para Implement no problema de "gasto de cliente " com Datasets: Então vamos encerrar esta seção introduzindo conjuntos com outro exercício e outros desafios práticos. O que vamos fazer é voltar ao exercício da seção anterior, onde calculamos o total gasto pelo cliente em nosso falso conjunto de dados de e-commerce. E vamos rever isso usando conjuntos de dados em vez de RDDs, provavelmente viu aquele chegando em casa. Então, recapitulando, o que vamos fazer é somar o valor gasto pelo cliente em nosso conjunto de dados aqui, os dados brutos chegando, é formato CSV. E contém três colunas, um ID de usuário e ID de item e um preço pago por esse item. O que eu quero fazer é somar todo o valor total pago pelo ID de usuário. Então, neste exemplo simples novamente, ID de usuário 44 gastou um total de US$77,83. Userid 35 gastou 7897, e assim por diante e assim por diante. Então, nossa estratégia vai ser um pouco semelhante ao que fizemos com RDDs. É que a técnica será um pouco diferente. Então, vamos estar carregando os dados pedidos do cliente ponto CSV arquivo como um dataframe com oito esquema explícito será a maneira mais fácil de fazê-lo. E você pode optar por converter isso explicitamente em um conjunto de dados, se desejar. Obviamente, isso às vezes leva a um melhor desempenho, mas você não precisa fazer isso. Depois disso, vamos agrupar esse conjunto de dados por ID do cliente. Resume-se pelo valor gasto pelo ID do cliente. E se você quer pontos de bônus, não que alguém esteja realmente mantendo pontuação. Você pode arredondar isso para duas casas decimais enquanto estiver nele, classificadas pelo valor total gasto. Assim, podemos ver nossos principais gastadores e clientes mais baratos, bem como, em seguida, mostrar os resultados. E alguns trechos úteis se você quiser mais algumas dicas aqui, revisando os exemplos anteriores nesta seção, certamente seremos úteis. E há uma função SQL chamada soma que você pode usar para adicionar coisas depois que você agrupá-los juntos. E especificamente a sintaxe para um arredondamento que depois de resumir ele vai parecer AG, arredondar alguns, qualquer que seja o nome da coluna como ele, você está somando vírgula tubária redonda para duas casas decimais. Tão pequeno, pequeno trapaceiro lá. E sim, esta solução está nos materiais do curso. Por favor, resista à tentação de espiar e olhar para frente. Tente isso você mesmo e veja se você pode resolver isso. É um bom treino. E eu voltarei e percorrerei a minha solução na próxima palestra. 29. Solução de exercício: total de pasto por cliente com datasets: Espero que você tenha tido algum sucesso em fazer esse exercício e recriar nosso valor total gasto pela atividade do cliente usando conjuntos de dados. Vamos dar uma olhada na minha solução e você pode comparar minha abordagem com a sua. Abra aqui o total gasto pelo script de conjunto de dados classificado pelos clientes. E mais uma vez, você sabe que seu código não tem que ser exatamente como o meu. O que conta é o resultado final realmente lá, há muitas maneiras de fazê-lo. Então, começamos importando o material que precisamos e criamos um objeto chamado total gasto pelos clientes conjunto de dados classificados e começamos com uma classe de caso definindo o esquema que nosso conjunto de dados será forçado. Então, estamos dizendo explicitamente no momento da compilação que nosso conjunto de dados de pedidos de clientes irá conter um ID de cliente inteiro e um ID de item inteiro e um valor de precisão dupla gasto. Então vá para a minha função principal aqui e nós configuramos nossa sessão Spark como sempre fazemos. E vamos criar um esquema para uso com a leitura no arquivo CSV como um DataFrame inicialmente. Então vamos criar um esquema de pedido de cliente, que é, você sabe, muito parecido com algum código anterior que olhamos. Então, espero que você foi capaz de levantar isso, irá criar um novo StructType e adicionar em um id de cliente tipo número inteiro ID do item inteiro gasto do tipo double type. E então nós realmente lemos isso na frente do arquivo CSV aqui usando o esquema que fornecemos. E forçaremos isso em um conjunto usando a classe de caso de pedidos do cliente como fizemos antes. Agora entramos na carne do exercício. Aqui, criamos um novo total por conjunto de dados do cliente que praticamente faz tudo. Começamos agrupando pelo campo ID do cliente. E lembre-se que definimos esse nome aqui em cima na nossa classe de caso, esse nome tem que coincidir com o nome aqui em cima. Assim, agrupando por ID de cliente, agrupámos todas as várias compras para cada cliente. E então esta próxima linha é o que realmente resume todos eles. Então vamos começar do meio e trabalhar a nossa saída. Começamos somando a coluna valor sublinhado gasto. Assim, para cada ID de cliente exclusivo, vamos resumir todos os valores Spence associados a esse ID de cliente. E isso é ainda mais envolvido por uma função redonda para arredondar isso para duas casas decimais de precisão. Nós vamos usar dot egg para agregar esse resultado em uma única coluna no resultado final. E vamos dar esse novo nome de coluna, dizendo alias de ponto, sublinhado total gasto para tornar mais fácil de se referir. Porque precisamos dar um nome a ele para ser capaz de classificar, certo? Então eu percebi que esta função agg pode ser um pouco confusa. Basicamente, o que está fazendo é dizer que vamos agregar essas funções em uma única coluna, ok? E também vamos dar a essa coluna um nome usando alias de ponto também. Então, neste ponto, a estrutura do nosso conjunto de dados será uma coluna ID do cliente e uma coluna total de sublinhado gasto. Agora podemos classificá-lo apenas dizendo ponto classificar com o total sublinhado gasto nome da coluna que especificamos na linha anterior e mostrar os resultados novamente, razões pouco truque para obter o total geral de quantas linhas são no total por conjunto de dados do cliente, convertendo isso em um inteiro e passando isso como um parâmetro para a função show para garantir que mostramos explicitamente todo o conjunto de dados e não apenas as primeiras 20 linhas. Então vamos em frente e chutar isso fora. E lá temos. Parece que funcionou. Parece que os resultados são classificados por quantidade gasta. Então, nosso maior gastador foi UserID 68, gastando $6.375.45. Muito legal. Tudo bem. Espero que tenha gostado disso e que possa ter ido ainda mais longe. Quero dizer, eu poderia ter levado isso um passo adiante, forçando que para ser um ponto 24 exemplo, eu estou usando um formato de impressão f para realmente iterar através cada linha individual que foi retornado de volta e formatar a saída mais ao meu gosto. Mas sim, se você fez isso, pontos de bônus para você. Mas espero que tenha superado isso. Então, temos a introdução de CAD aos conjuntos de dados e como eles funcionam em um nível bastante alto, há mais para explorar, devo acrescentar. Há muito mais no Apache Spark do que eu posso cobrir neste curso. Então, se você quiser consultar a documentação para o conjunto completo de referência sobre o que você pode fazer. Você pode ir para faísca dot apache.org barra docs barra mais recente para obter a documentação mais recente. Se você quiser aprofundar tudo o que pode fazer com o conjunto de dados, por exemplo, você pode simplesmente navegar para org. Faísca Apache. Conjunto de dados SQL vai ser o caminho para esse nome de classe. E ele vai te contar tudo sobre isso em cada detalhe intrincado. Se você rolar para baixo, verá alguns exemplos que são ainda mais úteis. E você pode ver uma lista de todos os métodos que estão disponíveis no conjunto de dados. A maioria deles parecerá familiar. Nós cobrimos muitos deles. Por exemplo, coletar e contar para cada aplicação de uma função a cada linha. Cabeça é uma maneira de obter as primeiras n linhas do conjunto de dados mostram que usamos muito, certo? Take também pode ser usado para tomar um certo número de linhas do conjunto de dados. Há algumas outras coisas para explorar aqui também. Você pode realmente explicar, para explicar a maneira real que ele vai ser executado, que é meio interessante para fins de depuração. Há maneiras de persistir em um disco. Há uma maneira de convertê-lo em um RDD. Nós olhamos um pouco para isso. Podemos imprimir o esquema. Já fizemos isso antes. Podemos realmente convertê-lo em um DataFrame, bem como se quisermos, bem como uma função certa para armazená-lo em disco. E vamos falar sobre streaming mais tarde, vamos chegar a isso mais tarde. E há outras coisas aqui como várias operações como distintas para obter apenas valores distintos no conjunto de dados. Nós já olhamos para o filtro antes, nós falamos sobre FlatMap. Você pode aplicar isso a um conjunto de dados, bem como um RDD GroupByKey que falamos sobre interseções de junção. Você pode fazer algumas operações booleanas lá para mapear. Você pode fazer isso em um conjunto de dados exatamente como você poderia em um RDD, embora ele vai ser um pouco mais complicado com um conjunto de dados. E sim, basta ir em frente e pescar por isso se você quiser obter um exemplo mais completo do que você pode fazer e do que está disponível. E se você tiver alguma dúvida sobre a sintaxe e os parâmetros que são suportados nessas funções de conjunto de dados. Este é o lugar para você descobrir. Como você pode ver, há uma longa lista do que você pode fazer no conjunto de dados. Nós tocamos em algumas das coisas mais comuns que você pode fazer. Mas como você pode ver, há um belo menu aqui. Então, continuaremos usando conjuntos de dados durante todo o resto deste curso. E observe também que em seus materiais de curso para cada exercício há uma versão RDD e uma versão de conjunto de dados. Então, se você quiser comparar os dois, eles estão todos lá. Não vamos passar por todas as versões de cada script. Como eu disse, vamos nos concentrar em conjuntos de dados de agora em diante. Mas se você tiver curiosidade, você pode olhar para ambas as versões. E há alguns em que não tocamos também. Por exemplo, nosso exemplo de RDD do contador de classificação inicial. É também uma versão de conjunto de dados que lá dentro se você quiser jogar com ele também. Então está tudo lá para sua referência e alegria. E vamos passar para alguns exemplos mais complicados em nossa próxima seção. 30. [de idade: Então, até este ponto do curso, temos apresentado a você o Spark e usando alguns exemplos bem simples. Mas eu quero que você veja que Spark tem muito poder além disso também. Então, se você tiver um problema mais complicado, às vezes se você pensar criativamente, desencadeie problemas não resolvidos que você não pensaria que poderia resolver. E vamos mergulhar em alguns exemplos como esse na seção a seguir usando alguns exemplos muito divertidos usando dados de filmes e dados de super-heróis. Então vamos mergulhar e ver o que você pode fazer com o Spark que você pode não ter pensado que poderia fazer se você apenas pensar um pouco criativamente sobre seus problemas. Ok, Então eu sei que o nome desta seção é exemplos mais avançados do Apache Spark, mas precisamos começar com algo simples e trabalhar nosso caminho até ele. Então, para definir a base do próximo exemplo, vamos fazer algo fácil. Vamos encontrar o filme mais popular no conjunto de dados MovieLens. E para recapitular, realmente fazer, Nós já falamos sobre MovieLens. Fizemos brevemente de volta com o contra-exemplo da audiência. Então vamos ingerir o conjunto de dados MovieLens 100 K aqui. E para recapitular o formato , contém estas quatro colunas. Eles correspondem a um ID de usuário, ID filme, uma classificação e um carimbo de data/hora. E para encontrar o filme mais popular, tudo o que precisamos fazer é encontrar as identificações de filmes que têm mais classificações, certo? Então, se assumirmos que alguém que classificou o filme assistiu, e definimos popular como o filme mais assistido do que apenas encontrando o ID do filme que aparece com mais frequência. Neste conjunto de dados, encontraremos o filme mais popular dessa forma. Então vamos para o código e ver como podemos fazer isso usando conjuntos de dados. Muito simples, mas novamente, vamos construir sobre isso para fazer algo um pouco mais complicado na próxima palestra. Então, vamos explorar o script de conjunto de dados de filmes populares em seus materiais de curso. E vamos passar por isso. Não é muito chique aqui, mas novamente, vamos construir sobre isso para fazer algo um pouco mais profundo e complexo em palestras subsequentes. Então, começamos por si mesmo importante. Precisamos, como de costume, vamos chamar isso de nosso objeto, conjunto de dados de filmes populares. Somos uma classe de caso desnecessária chamada filme. O insight aqui é que tudo o que estamos fazendo é contar quantas vezes cada ID de filme aparece em nosso conjunto de dados. E para fazer isso, só precisamos da coluna de identificação do filme, certo? Não nos importamos com as audiências. Não nos importamos quando foram classificados. Não nos importa quem o avaliou. Tudo o que nos importa é que o ID do filme apareça em cada linha individual. Então, esses são os únicos dados que realmente temos para extrair, o que torna as coisas um pouco mais simples. Mergulhando em nossa função principal aqui, definimos nosso nível de log, maior SparkSession, nada de especial lá. Criamos nosso esquema de filmes para carregar o DataFrame inicial do arquivo CSV. Embora seja, na verdade, um arquivo de dados de valor separado tabulação aqui. Mas está tudo bem. Ainda podemos usar o carregador CSV para frente como veremos. E vamos dizer que a estrutura desses dados é ID de usuário, ID de filme, classificação e carimbo de data/hora com três inteiros e um longo para representar esses dados. Será importado sparked out implícitos para carregar esse CSV usando esse esquema implícito. E vamos carregar, observe que a opção set barra invertida t. Isso é dizer que o carregador CSV que são um separador não é realmente uma vírgula, mas um caractere de tabulação, que é o que esses dados são realmente formatados à medida que passamos no caminho para o arquivo de dados, ou seja, o arquivo de dados que contém as informações de classificação reais. E, em seguida, vamos forçá-lo em um conjunto de dados de filme. E fazendo isso, estamos lançando para aquela primeira coluna que só consiste na identificação do filme e nada mais. Tão pequeno truque interessante lá. Seu conjunto de dados não precisa incluir todas as colunas, portanto, o DataFrame do qual você está construindo. E agora a carne disso acontece nesta única linha. E é muito SQL como e como ele se aproxima do problema. Então começamos agrupando por IDs de filmes. Então nós apenas agrupamos todas as classificações para cada ID de filme. Então contamos todos eles. E então ordenar por é basicamente como você faz uma classificação em SQL para que ele faça a mesma coisa. Estamos basicamente dizendo ordem pela coluna contagem, que vai ser criado por essa função lá. E em ordem decrescente para que tenhamos nossos filmes mais populares no topo da lista e os menos populares na parte inferior da lista. Depois disso, mostraremos os dez melhores resultados e isso nos dará os 10 melhores filmes mais populares. Então vamos começar isso e ver o que conseguimos. Certo, temos os resultados e parece que funcionou. Então, aparentemente, o filme mais popular é o ID 550 do filme, com 583 classificações distintas associadas a esse filme. Mas isso não ajuda muito, não é? Como sabemos que filme ID 50 é? Então, um próximo passo óbvio para estender esse script seria realmente importar o nome do filme associado a cada ID de filme para que possamos realmente obter alguma visão sobre o que esses filmes são. Quero dizer, nós poderíamos fazer isso da maneira mais difícil que esses dados vivem no arquivo do item em nosso conjunto de dados. Então, se abrirmos isso para explorar o que está lá dentro, você pode ver que isso contém todos os tipos de informações extras sobre cada ID de filme. Assim, por exemplo, o ID de filme um é o filme Toy Story e ele informa que o ano foi lançado, vinculado a dados IMDB a partir dele. E esses uns e zeros correspondem aos gêneros em que o filme está. E se você for para o filme ID 50, veremos que nosso vencedor é na verdade Star Wars, o original de 1977. Não é muito surpreendente. Mas sim, não sabemos. Não queremos ter que olhar isso à mão, certo? Então vamos voltar e falar sobre como realmente juntar isso com nossos dados de nomes de filmes. E como fazer isso de uma maneira ideal para que possamos realmente distribuir esses dados para cada nó em nosso cluster. 31. [de atividade] use variáveis de transmissão para exibição de nomes de cinema: Então precisamos tornar esses resultados legíveis por humanos. Essas identificações de filmes não são muito úteis para nós como seres humanos porque não sabemos o que o filme diz representa. Então não há intuição a ser adquirida. Então vamos cuidar desse problema agora. Então queremos exibir os nomes dos filmes e não apenas as identificações. E para fazer isso, precisamos mesclar informações desse arquivo de item u dot do conjunto de dados MovieLens. Agora, há muitas maneiras de fazer isso. O mais simples seria apenas configurar outro conjunto de dados que mapeia IDs para nomes depois de analisar nesse arquivo de item u dot. E então podemos apenas juntar esse conjunto de dados com nosso conjunto de dados de classificações pelos IDs de filmes e juntar-nos nesses nomes de filmes dessa forma. Essa seria a maneira mais direta de fazer isso. E do ponto de vista SQL, é assim que você abordaria esse problema também. Mas essa não é a única maneira de fazer isso. Você não pode fazer isso. Na verdade, encorajo-o a tentar se quiser um pouco de exercício prático para praticar. Mas vamos fazer de uma maneira diferente. Porque fazer uma junção como distribuir um conjunto de dados pelo cluster, isso é uma operação bastante pesada. E não é totalmente necessário para esses dados, certo? Porque não há tantos filmes no mundo. A tabela de IDs de filme para nomes de filmes não é realmente tão grande. Podemos encaixar tudo isso na memória facilmente em um único computador, então não precisamos distribuir isso em um conjunto de dados. Então nós poderíamos apenas manter uma mesa carregada no programa de driver e usar isso para mapear as identificações também. Nomes de filmes enquanto os imprimimos. Isso vai ficar bem. Mas há outra maneira de fazer um dois. Assim, também podemos deixar o Spark automaticamente para isso para cada executor quando necessário. Então imagine, se você quiser, que nós precisávamos ter esses nomes de filmes dentro do próprio script do driver e não apenas para o estágio final de saída. Podemos, na verdade, há uma maneira de usar o que chamamos variáveis de transmissão para encaminhar um objeto que pode incluir um mapa, que pode ser mapeamento de IDs de filmes para mover os nomes, por exemplo, e fording isso automaticamente para cada executor dentro nosso cluster a ser usado conforme necessário. E você sabe, se a tabela é enorme, isso pode ser uma coisa importante para usar essas variáveis de transmissões porque isso irá garantir que nós apenas transferimos ele quer para cada executor e mantê-lo lá. Compare isso com um conjunto de dados onde ele pode estar sendo jogado por todo o lado. É um pouco mais de uma operação complexa. Então, usando uma variável de transmissão, podemos ter certeza de que essa tabela, esse mapa de informações, que mapeia IDs para nomes só é enviado através quer para cada executor, e ele permanece lá até que explicitamente nos livremos dela. Assim, com variáveis de transmissão, podemos transmitir qualquer objeto para todos os executores de tal forma que eles estão sempre lá sempre que necessário. Nós só temos que chamar a transmissão no objeto de contexto do Spark em nosso script de driver para enviar esses dados fora do que você quer enviar para cada nó executor. Só temos de nos certificar de que se encaixará na memória deles, obviamente. E depois que isso foi transmitido, podemos usar o valor de ponto nessa variável de transmissão para recuperá-lo e obter esse objeto de volta e referi-lo dentro do script que está sendo distribuído por todo o cluster. E podemos usar esses objetos transmitidos como você quiser. Você pode usá-los dentro de funções de mapa em RDDs ou, no nosso caso, queremos aplicá-los a conjuntos de dados, que significa que vamos configurar uma função definida pelo usuário para que possamos usá-lo em uma espécie de maneira mais SQL ESC. Então, com isso, vamos mergulhar para o código e ver como as variáveis de transmissão funcionam. Então vamos abrir o script de conjunto de dados mais agradável filmes populares aqui e ver como isso se parece. Então, novamente, a maneira mais direta de lidar com esse problema seria carregar um conjunto IDs de filmes para nomes de filmes e juntando-o em uma espécie de operação SQL. Mas vamos fazer isso de uma maneira um pouco diferente, porque sabemos que este é um conjunto de dados relativamente pequeno e podemos escapar apenas enviando isso para cada executor individual como nosso script iniciado e apenas se referir a ele localmente dentro de cada nó executor. Então é só outra maneira de fazer isso. Às vezes variáveis de transmissão pode ser útil dessa forma você realmente não vê-los usados que muitas vezes na prática para ser honesto, mas é uma ferramenta em seu baú de ferramentas que eu acho que você deve saber sobre. E isso também nos dá a oportunidade de ilustrar o uso de funções definidas pelo usuário em um conjunto de dados, que também é algo bom de saber. Então, mesmo que este seja um pouco de um exemplo inventado, ele ilustra alguns pontos importantes. Então vamos mergulhar no código aqui. Importamos tudo o que precisamos. E vamos configurar uma classe de caso completa tipo de dados de filmes aqui que inclui o ID de usuário, a classificação de ID de filme e o carimbo de data/hora que serão importados do arquivo de dados u dot. Vamos então criar uma função de nomes de filme de carga. E o propósito desta função é apenas criar um mapa Scala que mapeia IDs de filmes para nomes de filmes. Então isso é apenas um código Scala direto. Não é o código do Spark. Tudo o que está fazendo é carregar a pasta de item u dot usando a codificação de caracteres correta, a propósito, que é um pouco obscura. E retornamos um mapa de inteiros para strings que mapeiam IDs de filmes para nomes de filmes. Nós apenas carregamos o arquivo direto do disco, iteramos através de cada linha nesse arquivo, dividimos com base no caractere pipe que o delimita. E fazemos uma pequena verificação de sanidade para ter certeza de que é uma linha válida. E, em caso afirmativo, adicionamos ao nosso mapa de nomes de filme e entrada que mapeia esse primeiro campo, que é o ID do filme para o segundo campo, que é o nome do filme. Feche o arquivo quando terminar e retornar o mapa de nomes de filme resultante. Então, novamente, este não é o código do Spark, este é apenas o código Scala direto, lendo os dados do disco local de onde quer que estejamos, estamos executando nosso script de driver. Então vamos entrar no próprio script. Como de costume, começamos com nosso nível de log e configuramos um objeto SparkSession. E agora vamos chamar essa função de carregar nomes de filmes para carregar esse mapa de IDs de filmes para nomes de filmes. E vamos chamar a transmissão da nossa interface de contexto do Spark. E nós vamos chamar essa variável de transmissão resultante chamou-a abreviação de dicionário de nomes, faz sentido, certo? Então, neste ponto, esse mapa foi carregado e foi enviado para todos os executores que vão estar executando nosso aplicativo Spark aqui. Portanto, ele estará disponível para todos os executores localmente para fazer pesquisas rápidas de IDs de filmes para nomes de filmes. Certo, agora entramos no próprio código do Spark. Nós vamos estar carregando nossos dados de filmes com o seguinte esquema. Então, vamos carregar o arquivo de dados especificando o separador de guias. Novamente, este é o mesmo código exato do exemplo anterior e usando o esquema que estamos fornecendo. E então vamos forçá-lo para a classe de casos de filmes para obter o conteúdo completo dos dados desse filme definido dessa forma. Tudo bem, seguindo em frente, vamos então obter o número de comentários por, por ID de filme, assim como fizemos antes com as declarações simples do grupo BY. Então vamos agrupar pela coluna ID de filme e contar cada ID de filme individual quantas vezes ele ocorre. Então, neste momento, temos o que tínhamos antes. Temos um conjunto de dados de contagem de filmes que contém ID de filme e contagem para cada ID de filme individual. Certo, agora precisamos de uma maneira transformar esses IDs de filmes em nomes de filmes dentro do nosso conjunto de dados. Então, novamente, este é um exemplo inventado. Você poderia ter feito isso facilmente na fase de saída, certo? E nós poderíamos ter apenas iterado através do conjunto de dados resultante que obtivemos de volta e procurar esses nomes de filmes de volta no script do driver localmente quando estamos realmente imprimindo os resultados. Mas estamos apenas tentando ilustrar o uso de UDFs aqui e transmitir variáveis. Então vamos realmente fazer isso distribuído dentro do próprio cluster. Então, para cada executor que está lidando com algum subconjunto dos filmes, algum subconjunto de IDs de filme para este problema, eles estarão individualmente olhando para os títulos de filme para os IDs de filme. Eles são responsáveis por um pouco mais escaláveis, certo? Para fazer isso, precisamos primeiro configurar um funções definidas pelo usuário para que possamos realmente configurar um comando conjunto de dados para criar uma nova coluna usando esta função para gerar dados dessa coluna. Agora a sintaxe para isso é um pouco estranha, então nós realmente não vimos isso antes. Estamos declarando o que é chamado de função anônima aqui. E em Scala, a sintaxe para isso se parece com isso. Então estamos basicamente definindo uma função inline aqui. Vamos chamar-lhe nome de pesquisa. Esse é o nome da nossa função. Estamos dizendo que ele vai pegar um inteiro e retornar uma string. E vamos definir isso igual a esta seguinte função anônima. Então ele leva em um inteiro chamado ID de filme e passa para este bloco de código, que apenas retorna a pesquisa do dicionário de nomes dado que ID de filme, anote o valor de ponto, então nomeou-o novamente como uma variável de transmissão. Não é o mapa real. Para obter de volta o objeto mapa temos que chamar valor ponto queria recuperar o nome objeto de Dick. Então, novamente, chamado dict é a variável de transmissão. Para obter seu conteúdo, precisamos chamar valor sobre ele. Então, neste ponto, temos um mapa Scala real para usar. E então nós podemos apenas passar ID de filme para ele para procurar o que o nome do filme está associado a esse ID de filme. Em seguida, precisamos envolver essa função com um UDF. Então você pode anotar no topo aqui que importamos explicitamente. Aqui está, ou ponto Apache dot Spark dot SQL dot functions.php UDF. E isso nos permite realmente envolver essa função como uma função definida pelo usuário que podemos então usar em uma configuração SQL. Então, agora que temos o nome de pesquisa UDF, podemos usá-lo. E aqui é onde a magia acontece. Então vamos dizer filmes com nomes. Este será o nosso novo conjunto de dados que tem uma coluna adicional chamada título do filme. E para adicionar essa coluna, vamos apenas dizer filme contagens ponto largura coluna. Para adicionar essa nova coluna a esse conjunto de dados, chamaremos esse novo título de filme de coluna. E o conteúdo dessa coluna será gerado usando o nome de pesquisa UDF, essa função definida pelo usuário que acabamos de definir. E os parâmetros para isso virão da coluna ID do filme. Então a sintaxe aqui é usar a função de chamada que vem de funções de ponto SQL para realmente passar no conteúdo de um determinado nome de coluna, neste caso ID de filme. E porque envolvemos isso com um UDF, ele aceitará essa coluna e transformará isso para o inteiro que a função subjacente real espera para você. Então é aqui que tudo acontece. Então, de forma distribuída em todo o cluster, ele usará nossa função definida pelo usuário usando nosso mapa transmitido para procurar IDs de filmes para nomes de filmes e gerar um novo conjunto de dados chamado filmes com nomes. Nesse ponto, podemos então classificá-lo novamente em todo o cluster com base no campo de contagem. E nesse ponto podemos apenas recuperar os resultados e mostrá-los. Neste caso, vamos mostrar a coisa toda, porque talvez queiramos investigar todos os detalhes. E assim vamos apenas passar como um parâmetro, a lista inteira, a contagem D2 e para obter a cada linha única desse conjunto de dados. Além disso, diremos truncar é igual a falso para evitar que ele realmente trunque o comprimento de cada linha individual. Caso contrário, cortaria alguns desses nomes de filmes para caber dentro de uma determinada largura de linha. Então vamos começar isso e ver o que acontece. E lá temos. Então nós não fizemos um tipo descendente neste caso, nós realmente apenas s finais. Então, os filmes mais comuns, os mais populares estarão no final neste caso. E obtivemos o mesmo resultado. Star Wars é, são ensinados filme, seguido de contato, seguido por Fargo, seguido por Retorno dos Jedi. Você pode dizer que este é definitivamente um conjunto de dados datado. Há mais atuais que você pode obter de MovieLens se você quiser experimentar com eles. Então, basta ter em mente que este é um dado antigo, então não se surpreenda que perto de blockbusters favoritos e aparecendo aqui. Mas sim, funciona. Então, novamente, um pouco de um exemplo inventado, mas o objetivo era ensiná-lo sobre variáveis de transmissão e funções definidas pelo usuário. Novamente, muitas vezes você pode realizar o que precisamos fazer com uma variável de transmissão usando um conjunto de dados em vez disso. Mas às vezes uma variável de transmissão será mais eficiente. Então é outra ferramenta no seu baú de ferramentas e agora você a tem. Vamos seguir em frente. 32. [de atividade, encontre o superherói mais popular em um gráfico social: Tudo bem, então em nossas próximas palestras nós vamos estar olhando para um conjunto de dados muito divertido. Na verdade, é baseado no universo dos quadrinhos da Marvel é uma Marvell ou Marvell e todos sabiam como pronunciar isso. Mas de qualquer maneira, estamos falando de super-heróis como Homem-Aranha e Thor e todos naquele mundo. E acontece que você pode realmente pensar no mundo dos super-heróis como um pouco de uma rede social. O conjunto de dados com que vamos trabalhar é interessante. Ele modela super-heróis como uma rede de super-heróis olhando para o que outros super-heróis cada herói apareceu com em um único livro de quadrinhos. Então, se o Homem-Aranha aparecesse na mesma banda desenhada que Thor, então diríamos que há uma conexão entre o Homem-Aranha e minucioso, por exemplo. E acontece que há muitos desses tipos de co-ocorrências de heróis dentro da mesma banda desenhada. E isso leva a essa estrutura de rede realmente interessante entre todos esses heróis no universo Marvel. Então nós temos realmente um conjunto de dados público muito legal lá fora. E contém os dois arquivos nos quais estamos interessados. Um deles é chamado Marvell tracejado texto ponto gráfico. E o que fizemos foi atribuir uma identificação a cada personagem individual que aparece nestes quadrinhos. Então o primeiro número que aparece em cada linha é o personagem que estamos falando, seguido de uma lista de todos os ids de caracteres que, esse personagem apareceu com em outros quadrinhos. Não faço ideia do que é o ID do 395, mas vamos fingir que é o Homem-Aranha. Então isso significaria que o Homem-Aranha apareceu com personagens 22, 37, 17, 6, 7 , 4, 7, 2 e assim por diante. E então podemos procurar quais nomes estão associados a IDs de caracteres individuais. Chamamos-lhes identidades de herói, se quiserem. No arquivo Txt de nomes de traço Marvel, isso é muito simples. É apenas um ID seguido por um nome entre aspas, que corresponde a esse ID de herói. Agora, uma coisa que pode traçar você até aqui é que um herói pode estender várias linhas no arquivo txt do gráfico tracejado da Marvel. Então alguns super-heróis aparecem com tanta frequência que eles têm tantas co-ocorrências com outros heróis que eles não podem encaixar todos em uma linha. Então, nesse caso, podemos ter duas ou mais linhas que começariam com a mesma identificação de herói. Assim, podemos ver como isso pode ser interessante do ponto de vista do processamento de dados. Precisamos combiná-los juntos enquanto estamos processando de alguma forma. E bem, vamos falar sobre como fazer isso. Então nosso desafio é descobrir quem é o super-herói mais popular no mundo dos quadrinhos da Marvel. E vamos definir popular por quem aparece com os outros super-heróis em outros quadrinhos? Quem é, quem fica mais no mundo dos quadrinhos, basicamente. Então aqui está a nossa estratégia para realmente responder este problema. Então vamos carregar nosso conjunto de dados do arquivo de dados lá. E a primeira coisa que vamos fazer é dividir o primeiro número em cada linha porque essa é a identificação de herói que estamos falando. Com essa linha. Vamos então simplesmente contar quantos números separados por espaço estão nessa linha. Nós realmente não nos importamos com quem são as conexões. Só estamos contando, certo? E então tudo o que nos importa é quantas conexões o Hero tem. Então, tirando esse grande total de quantas coisas estão nessa linha. Se apenas subtrairmos um para nos livrarmos desse ID de herói inicial que identifica quem se trata, obteremos o número de conexões com esse ID de herói que são representados por essa linha de dados comigo até agora. Então, vamos contar. Quantos outros IDEs estão nessa linha para corresponder a esse ID de herói para obter uma contagem de quantas conexões são representadas por essa linha de dados. E como dissemos, podemos ter várias linhas para uma determinada identificação de herói, o que significa que precisamos combiná-las de alguma forma. Então, em SQL, podemos fazer um grupo BY comando ou em nosso conjunto de dados que podemos fazer um grupo BY comando para realmente combinar aqueles completamente. E então podemos adicionar todas as conexões juntas para diferentes identificações de heróis que foram divididas. Nesse ponto, podemos apenas classificar pelo total de conexões e arrancar o resultado principal para obter o super-herói mais popular. E, ao mesmo tempo, podemos ter outro conjunto de dados carregado do arquivo de texto de nomes Marvel e apenas fazer um filtro sobre isso pelo ID do ano que estamos interessados para obter o nome do nosso vencedor. Então, com isso, vamos para o código e ver como ele funciona. Então, voltando ao nosso projeto aqui, vamos abrir o script de conjunto de dados de super-heróis mais popular e analisar o que ele está fazendo. Então vamos fazer a mesma estratégia que falamos nos slides aqui. Começaremos importando o que precisamos como sempre e declarando nosso objeto. Temos duas classes de caso aqui, porque temos dois conjuntos de dados para carregar. Um deles será o banco de dados de nomes de super-heróis que mapeiam IDs de super-heróis, que são inteiros, dois nomes que são strings. E também temos um conjunto de dados de super-heróis. E isso só vai ser uma string porque nós realmente não vamos nos preocupar em estruturar esses dados. Nós só vamos nos preocupar com, bem, qual é a linha bruta real de dados de entrada e quantas coisas separadas por espaço estão nela. Então não precisamos ficar chiques aqui. Nós estamos indo apenas para importar na cadeia real da própria linha em sua forma bruta. Então, não realmente fazendo uso completo do que conjuntos de dados podem fazer aqui, mas não precisamos. Não somos como fazer análises chiques aqui. Estamos contando quantos campos há em cada linha. Então, com isso, vamos começar as coisas. Então nosso nível de log definiu nossa sessão do Spark. E vamos começar criando nosso esquema de nomes de super-heróis. Isso nos permitirá carregar que os nomes do traço Marvel dot txt arquivo porque ele não tem um arquivo de cabeçalho que podemos inferir o esquema de. Temos de lhe dizer o que é explicitamente. Então vamos dizer que temos duas colunas nesse arquivo. Um é o ID e o outro é o nome. E eles serão separados por um personagem espacial. Então, mesmo que estejamos usando o carregador CSV, podemos usar qualquer separador que quisermos. E neste caso vai ser o personagem espacial. E você pode dizer que neste momento, mas Frank, e se eu tiver um espaço em meu nome? Bem, a coisa boa sobre o carregador CSV é que ele é inteligente sobre aspas. Então ele vai realmente lidar com isso porque nossos nomes estão entre aspas nesse arquivo, o que é legal. Certo, então precisamos carregar o arquivo de dados do gráfico de traço da Marvel também. E vamos carregar isso diretamente como um tipo de dados de super-herói. Então não há necessidade de inferir um esquema lá porque nós só temos uma linha, nós estamos apenas levando em, digamos, linha bruta de dados. Então não há nenhuma transformação acontecendo lá em tudo. Vamos apenas carregar isso no conjunto de dados de super-heróis, que estamos definindo como apenas uma simples string antiga. Então é aqui que a ação acontece. Pegamos esse conjunto de dados de linhas que contém os dados brutos, e adicionamos uma nova coluna chamada id. E tudo o que vai fazer é conter a primeira entrada na linha. Então estamos usando split aqui. A função de divisão em SQL na coluna de valor. Esse é o nome padrão da coluna que foi importada pelo DataFrame usando o separador de espaço. E nós vamos apenas extrair o primeiro elemento número 0 dessa operação de divisão. Então tudo isso está fazendo é dizer dividir essa linha de dados brutos e arrancar o primeiro resultado e chamar isso de ID. E nós vamos colocar isso em uma nova coluna chamada id. E então nós fazemos algo semelhante para todo o resto. Então, temos outra coluna chamada conexões, que está apenas tomando o tamanho de quantas coisas existem nessa linha divididas por espaços. Então vamos trabalhar daqui de dentro. Estamos começando com a coluna de valor, que é o nome padrão dessa coluna que o DataFrame carregou. São todos os dados brutos. Nós dividimos isso com base no caractere do espaço, e então chamaríamos tamanho para contar quantas dessas coisas existem. Então, depois de dividirmos tudo pelo espaço, quantos campos temos? Em seguida, subtraímos um para subtrair o ID do herói no início dessa linha de dados. E essa é a nossa contagem de quantas conexões estão associadas a esta linha de dados. E colocaremos esse número na nossa nova coluna de conexões. E então vamos agrupar por ID. Isso nos permitirá combinar várias linhas para a mesma ID de herói. E nós usamos são montados Trick agregação aqui, vamos resumir todas as conexões e quaisquer entradas múltiplas para um determinado herói ID que adiciona-los todos juntos. E daremos esse novo resultado para Tidal, o pseudônimo de conexões. Então, estamos introduzindo um novo total de soma para cada grupo juntos, ID de herói. E vamos chamar isso de conexões. Então é basicamente isso. Agora temos um conjunto de dados que contém cada ID de herói exclusivo porque fizemos um grupo BY e o número total de conexões para isso aqui são IID sob uma coluna de conexões. Tudo o que precisamos fazer agora para encontrar os super-heróis mais populares para classificá-los. E é isso que estamos fazendo aqui, classificando em ordem decrescente. E vamos, além disso, arrancar o primeiro resultado, você obtém o super-herói mais popular. Então agora nosso conjunto de dados mais popular contém uma linha, que é o super-herói mais popular, com uma coluna para o ID e para o número de conexões que Hero tem. Em seguida, precisamos procurar o nome do vencedor lá. Então, na verdade significa algo para nós. Então podemos dizer o nome mais popular. Vamos pegar esse conjunto de dados de nomes que carregamos anteriormente, filtrá-lo com base no ID mais popular. Então o mais popular 0 será o primeiro campo que é o ID do herói. E usamos isso para filtrar nosso conjunto de dados de nomes para esse ID que estamos procurando. Então isso vai nos dar de volta aquela linha para a identificação que nos importamos. Em seguida, selecionaremos a coluna de nome desse resultado e novamente arrancaremos o primeiro resultado na situação improvável desta mais de uma linha para o mesmo ID de herói nesse conjunto de dados. E nesse ponto, podemos imprimir os resultados. Então aqui nós arrancamos a primeira e única coluna do nosso conjunto de dados de nome mais popular lá e imprimimos o nome usando o formato de substituição. E dizemos que é o herói mais popular com o mais popular que vai arrancar o segundo campo do resultado mais popular lá que temos, que será o número de conexões que o herói teve. Então vamos começar e ver o que acontece. Botão direito. Corra. Quem você acha que o super-herói mais popular é no universo Marvel? A resposta pode surpreendê-lo. Acontece que é o Capitão América. Eu não previ isso chegando. Mas acontece que de todos os super-heróis do Universo Marvel, Capitão América aparece mais frequentemente em todos os quadrinhos com outros personagens. Então ele anda por aí, vai descobrir, quem sabia. Então lá está, Isso está usando conjuntos de dados para resolver este problema. Eu quero direcionar sua atenção, no entanto, para a versão RDD do script também. Então você vai notar que nós meio que tivemos que fazer algumas coisas complicadas aqui para analisar esses dados, certo? Então nós tivemos que adicionar essas novas colunas que fizeram algumas informações bastante pesadas lá. Tivemos uma carga em torno dessa linha original de dados durante todo o caminho. Então, embora você possa fazer isso apenas usando comandos de conjunto de dados, isso nem sempre significa que é a coisa certa a fazer. Na verdade, quando você olha para um monte de exemplos on-line de análise de dados como este, onde você precisa fazer alguma limpeza real e reorganização dos dados que entram. Muitas vezes você verá que eles começam carregando coisas usando as interfaces RDD e, em seguida, convertem esse RDD em um conjunto de dados para fazer mais análises sobre ele. E se você olhar para a versão RDD disso, esse é o script de super-herói mais popular aqui. Verá que é um pouco mais simples. Então, bem, eu não diria mais simples, mas é mais simples em alguns aspectos, pelo menos a análise dos dados. Então, por exemplo, vejamos como analisamos esse arquivo de gráfico de pontos Marvel aqui no exemplo RDD. Aqui estamos apenas chamando, recarregando isso em um RDD e, em seguida, usando uma função de mapa para contagem co-ocorrências. Vamos ver o que isso faz. Coisas bem diretas, certo? Então aqui nós estamos apenas dividindo a linha com base em espaços e nós apenas retornar de volta o primeiro elemento, o ID do herói e o comprimento do ponto elementos menos 1. De muitas maneiras, isso é mais simples e mais simples do que como fizemos com conjuntos de dados, onde tivemos que fazer esse tipo de complicado com coluna na verdade dois diferentes com comandos de chamada, com todas essas funções SQL aninhadas para obter o mesmo resultado. Então, sem dúvida, isso pode ser mais eficiente. E uma vez que temos isso, podemos apenas fazer um ReduceByKey para obter o grande total de amigos por personagem. Então, novamente, você sabe, às vezes RDDs podem ser mais simples e ainda mais rápidos, às vezes, mas conjuntos de dados estão lá para você também. Se você não queria fazer uma análise de dados mais complicada sobre dados estruturados verdadeiros, é aí que o conjunto de dados realmente brilha e seu poder se torna atraente. Mas lembre-se, embora os conjuntos de dados em DataFrames são uma espécie de maneira moderna de usar o Spark. Nem sempre é a melhor maneira. Às vezes, os RDDs serão mais simples. Então, então você ainda deve se sentir livre para misturar e combinar os dois, porque às vezes RDD é a resposta certa, às vezes conjuntos de dados são a resposta certa. Nem sempre é um conjunto de dados. Mas aí está. O super-herói mais popular, Capitão América, não viu que a seguir, Vamos fazer algumas coisas mais complicadas com este conjunto de dados e extrair algumas informações mais interessantes fora dele. 33. [de exercício ] encontre os Superheroes mais obde: Bem, esta parece ser uma boa hora para você sair e escrever seu próprio código por um tempo aqui e praticar alguma prática prática. Então seu desafio será encontrar os super-heróis mais obscuros em oposição ao super-herói mais popular. E eu gosto de encontrar imagens de fotos cheesy. Às vezes, esse super-herói parece muito obscuro. Talvez seja um trabalhador de escritório. Eu não sei. É um pouco perturbador de qualquer maneira. Então o problema é que eu quero que você liste os nomes de todos os super-heróis em nosso conjunto de dados que têm apenas uma conexão. E isso vai ser um pouco mais difícil do que parece que você pode pensar que você pode simplesmente pegar o script existente que você tem para os super-heróis mais populares e mudar um máximo para um mínimo em algum lugar e ser feito com ele ou classificar por uma ordem diferente. Mas não é tão simples, porque o código que acabei de te dar presume que só há uma resposta, um único super-herói mais popular. No entanto, neste caso, há realmente muitos super-heróis em nosso conjunto de dados que têm apenas uma única conexão. E você vai listá-los todos junto com seus nomes. Isso torna as coisas um pouco mais complicadas. Você vai ter que juntar um conjunto de dados em algum momento com o conjunto de dados nomes , a fim de imprimir todos esses nomes juntos de uma só vez. Quero dizer, você poderia fazer isso depois do fato e, você sabe, meio que fazer com a maneira que fizemos originalmente e procurar nomes individuais enquanto você os imprime. Mas isso não vai ser tão eficiente como apenas juntar os nomes em algum momento para colocá-los todos, de forma distribuída em todo o cluster. E para crédito extra, veja se você pode calcular o menor número real de conexões em vez de apenas assumir que é uma. Se você conseguir descobrir como fazer o comando min para realmente descobrir o menor número de conexões em todo o conjunto de dados, em vez de apenas codificá-lo para um. Isso seria a coisa mais baseada em princípios a fazer, certo? Mas acontece que a resposta é aquela que é o menor número de conexões. Não há nenhum que tenha 0 no conjunto de dados. Eles já foram filtrados aparentemente. E um é o número mágico, mas seria melhor calcular isso de alguma forma, certo? Então, aqui está a estratégia geral que você vai querer usar aqui. Comece com uma cópia do script de conjunto de dados de super-heróis mais popular que acabamos de ver. E se você apenas fazer uma cópia desse script e Intel J e depois colá-lo no pacote. Isso lhe dará a oportunidade de renomear esse script enquanto o copia. Chame de algo como super-heróis obscuros ou algo assim. E esse script pode ser praticamente inalterado até o ponto em que construímos o conjunto de dados de conexões. Isso vai lhe dar esse conjunto de dados que tem cada super-herói e quantas conexões eles têm. E isso ainda vai ser útil para este exercício. Mas de lá em diante, vai ser completamente diferente. Então, nesse ponto você vai querer filtrar isso para baixo para encontrar apenas as linhas que têm uma conexão. E então, quando você filtrar isso para baixo, você deseja juntar esses resultados com nosso conjunto de dados nomes para juntar os nomes de cada super-herói nesse filtro para baixo no conjunto de dados. Agora note que estamos pensando um pouco sobre performance aqui, certo? Eu poderia ter me juntado a esse conjunto de dados nomes antes filtrar todas as conexões que só têm uma conexão. Mas isso forçaria meu grupo a fazer muito mais trabalho do que tem que fazer, certo? Qual é o sentido de juntar os nomes de todos esses super-heróis que têm mais de uma conexão, eu não vou exibi-los. Então, às vezes, mesmo que o Spark seja otimizado e tenha muita otimização automática, você ainda precisa pensar um pouco sobre os resultados que deseja e a ordem certa para fazer as coisas. Certo, assim que tivermos isso, só precisamos selecionar a coluna de nomes e mostrá-la. E é basicamente isso. E se você quiser algumas dicas extras aqui, Aqui estão alguns trechos de código que podem ajudá-lo. Novamente, se você quiser filtrar um conjunto de dados para algum nome de coluna igual a algum valor, seria algo parecido com isso. Apenas o filtro de ponto do nome do conjunto de dados. Lembre-se que a sintaxe é o cifrão e, em seguida, o nome da coluna de aspas. E três sinais iguais para qualquer valor que você deseja filtrar. Também para unir um conjunto de dados com outro. Isso é exatamente como uma operação de junção SQL. Você pode simplesmente dizer o nome do conjunto de dados, o que quer que seja, junção de pontos e, em seguida, especificar o nome de outro conjunto de dados que compartilha um nome de coluna comum que você pode usar para unir esses conjuntos de dados juntos. Então, no nosso caso, essa será a coluna ID. E então você diz que usar coluna é igual a qualquer que seja o nome de colunas comuns. E isso irá juntar-se nos campos do segundo conjunto com o primeiro conjunto de dados onde esse nome de coluna comum corresponde. E finalmente, se você quer o crédito extra, eu não estou mantendo o controle de sua pontuação aqui. Isto está totalmente no sistema de honra. Mas se você quiser realmente calcular o número mínimo de conexões encontradas no conjunto de dados, seria algo parecido com isso. No conjunto de dados, você usaria o comando add e o uso para conter o comando mínimo no nome da coluna que você está interessado em encontrar o mínimo que retornará um conjunto de dados. Mas se você quiser realmente obter esse valor real de volta em seu script de driver como um valor Scala. Para converter isso de volta, você precisa primeiro chamar ponto primeiro para extrair a primeira linha desse resultado. E só haverá uma fila. E isso lhe dará de volta um tipo de dados linha. E isso não vai ser útil por si só. Então nós vamos chamar get long como 0 para extrair o primeiro número dessa linha, que será esse valor mínimo. Então sintaxe há um pouco confuso, mas isso é o que você tem que fazer para realmente obter esse número de volta do conjunto de dados e em um valor real que você pode então usar em sua operação de filtro. Então boa sorte. Se houvesse um homem de brócolis, tenho certeza que ele estaria na lista final dos seus resultados. Essa é uma imagem super perturbadora. Vamos, vamos fazer com que isto desapareça. Vai escrever um código e voltamos na próxima palestra e eu mostro-te a minha solução. 34. Solução de exercício: encontre os Superheroes mais obde: Tudo bem, eu espero que você tenha ido naquele exercício e aqui está a minha solução para o problema. Novamente, há muitas maneiras de fazer isso. Desde que obtenhas os mesmos resultados que eu, é isso que conta. Há muitas maneiras de resolver isso. Você pensa em quão eficiente sua solução foi? E vamos falar um pouco sobre isso. Como sugeri, copiei o roteiro de super-heróis mais popular. E fazendo isso, eu apenas cliquei com o botão direito sobre isso e disse copiar e copiar ou apenas Controle C. E então se você colá-lo em com dot sol dot software dot faísca, isso lhe deu a oportunidade de duplicar esse script com um novo nome. E no meu caso, dupliquei com o nome dos super-heróis obscuros, Dot Scala. Então vamos em frente e dar uma olhada nisso e passar por minhas mudanças. A maior parte do script é inalterada. Tudo o que eu fiz foi mudar o nome, como eu disse, e eu também mudei o nome do aplicativo porque não? E como eu disse, vai ser o mesmo todo o caminho até construir esse conjunto de dados de conexões. Então aqui é onde construímos o conjunto de dados de todos os IDs de super-heróis e o número de conexões que eles têm. E esse número de conexões coluna é chamado conexões. Então, neste ponto, temos um conjunto de dados que tem um ID e conexões. Então isso é inalterado. Usamos essa mesma informação para encontrar o super-herói mais popular. Mas uma vez que temos isso, precisamos filtrar isso até os resultados que tiveram o menor número de conexões. E acontece que eu sei que o número é um, que o menor número de conexões no meu conjunto de dados é um. Mas se eu quisesse definir isso algorítmicamente, eu poderia fazer algo assim. Eu poderia dizer Val, Min conexão contagem. E isso vai ser um valor escalar que contém algum número é igual a conexões ponto agg. Nós só precisamos que para envolver essa função SQL min lá. Nome da coluna homens é igual a conexões. Então, neste ponto, estamos dizendo conexões AG Min, conexões de nome de coluna, então nos dará de volta um conjunto de dados que tem uma única linha nele, novamente contém uma coluna que contém o valor mínimo encontrado na coluna de conexões. Agora, neste momento, temos um DataFrame ainda. E queríamos devolver isso ao nosso guião como um valor, certo? Então primeiro precisamos chamar ponto primeiro para converter esse conjunto de dados em uma única linha. E, em seguida, uma vez que temos esse objeto linha, chamamos getline diferente de zero para extrair o primeiro e único campo nessa linha e convertê-lo de volta para um inteiro longo. Então esta pequena expressão complicada aqui calcula esse valor mínimo e converte-o de volta para um conjunto de dados, trazê-lo de volta para o script do driver com o primeiro comando e, em seguida, as chamadas ficam longas para extrair o número de esse conjunto de dados dessa linha do conjunto de dados mais especificamente. Então, agora a contagem de conexões principal será igual a um. Tudo bem, então agora que sabemos qual é o nosso número mínimo de conexões, podemos filtrar nosso conjunto de dados de conexões dizendo conexões ponto filtro, cifrão conexões igual, igual, igual, igual, igual, lembre-se de três iguais. Uma espécie de peculiaridade estranha da sintaxe aqui, é igual a contagem mínima de conexão, que será um. E se você fez a abordagem mais direta aqui e assumir que era um, você poderia apenas ter dito igual, igual igual igual igual a 1. E isso também funcionaria. Então, estamos pegando esse conjunto de dados filtrado e chamando de conexões Min. Então o conjunto de dados de conexões masculinas agora contém apenas os IDs de herói. Que contêm uma conexão. Então ainda temos a coluna de conexões por aqui. Agora precisamos nos juntar aos nomes desses super-heróis possamos realmente exibi-los e ter resultados legíveis por humanos. E isso é o que está acontecendo nesta linha aqui, estamos dizendo conexões Min com nomes iguais a min conexões ponto juntar com o conjunto de dados nomes usando ID de coluna. Então, você notará que as conexões DataFrame e os nomes dataframe têm um campo chamado ID. E vamos usar isso para unir esses dois conjuntos de dados juntos. Então, para cada linha em nosso conjunto de dados de conexões Min, vamos basicamente procurar o ID nessa linha e juntar o nome do conjunto de dados de nome que tem esse mesmo ID. Assim como um comando de junção SQL se você estiver familiarizado com isso. Então, neste ponto, vamos ter um conjunto de dados que contém não apenas um ID e número de conexões, mas também uma coluna de nome que juntamos a partir de que nomeia DataFrame. Então agora podemos finalmente imprimir nossos resultados. Então, primeiro de tudo, vamos imprimir um pouco de um cabeçalho só porque queremos que os resultados pareçam limpos. Você não precisava fazer isso. Claro, vamos dizer que os seguintes caracteres têm apenas conexões de contagem de conexões Min. Nesse caso, terei 1. E então nós apenas dizemos Min conexões com nomes, dot select name para apenas selecionar essa coluna de nome. Não me importo com mais nada para a saída final. E os pontos mostram isso como a saída do meu script de drivers. Faz sentido. Bastante direto. E mais uma vez, há mais de uma maneira de fazê-lo. Mas você faz uma coisa sobre desempenho. Essa é uma boa maneira de fazer isso. Pode haver uma maneira mais eficiente de realmente obter esse valor mínimo lá sem realmente parar meu script aqui e basicamente parar o mundo aqui para descobrir o que esse valor mínimo é neste momento. Porque ele voltou ao meu script de driver e eu estou usando esse valor em uma seção subseqüente de meus scripts de driver. Então toda esta seção acima aqui tem que correr é um passo. Ele vai parar no cluster, esperar que o resultado volte para o valor mínimo e, em seguida, iniciar as operações subsequentes do conjunto de dados depois disso, que podem não ser totalmente ideais. Mas há uma maneira melhor de fazer isso. Eu não descobri isso. Acho que é inevitável neste caso. Mas uma coisa que eu fiz, como eu disse nos slides, foi ter certeza de que eu só fiz essa operação de junção uma vez que eu filtrado para baixo as conexões para o conjunto final de resultados que eu queria, junta-se são operações caras no Spark. Então você definitivamente quer mantê-los tão pequenos e tão limitados quanto você pode. Então esse foi o método da minha loucura para fazer naquela junção após a operação de filtro em vez de antes dela. E também barulho. Observe que não estou iterando os resultados finais em fazer uma pesquisa de conjunto de dados no conjunto de dados nomes para cada nome e o script do driver. Isso será ainda pior. Então isso é ótimo. Então vamos em frente e executá-lo e ver o que conseguimos. A maioria dos super-heróis obscuros fogem . E aqui vêm heróis obscuros. Os caracteres a seguir têm apenas uma conexão. E é uma lista bem curta. Mas trabalhador para Blair, garoto Marvel. Seguimento desajeitado. Enquanto estes são, você sabe, tem havido muitos filmes de super-heróis da Marvel de alguma forma. Acho que não vamos ver um sobre um acompanhamento desajeitado. É um cartão bem obscuro. Eu não ouvi falar de nenhum desses caras, você tem se você tem, diga isso nos comentários, pode estar interessado em ouvir sobre isso. Então, sim, quando a Marvel começa a fazer filmes sobre esses personagens, você sabe, eles realmente atingiram o fundo do barril. Muito bem, foi um exemplo interessante. Espero que tenha tido sucesso com esse exercício e tenha os mesmos resultados que eu. A ordem obviamente não tem que ser a mesma, mas você deve ter a mesma lista de resultados aqui em tudo o que você fez. Se não, volte a grampear o que você fez e continue iterando nele até obter a resposta certa. E é um bom treino. E com isso, vamos seguir em frente. 35. Graus de separação de heróis: introduz a primeira pesquisa: Portanto, o objetivo deste próximo exercício é mostrar que a faísca pode ser usada para paralelizar problemas que você poderia não ter pensado que Spark poderia fazer. Assim, muitas vezes as pessoas usam o Spark para Data Analytics e especificamente para coisas que podem ser expressas como um comando SQL. Mas pode fazer muito mais se você pensar criativamente sobre isso. Então, como exemplo, vamos descobrir os graus de separação entre os super-heróis em nossa rede social de super-heróis aqui, recapitular com a idéia de graus de separação é se você não está familiarizado com ele, bem, de volta em Hollywood, costumava haver um conceito chamado “Número do Bacon”. E esse era o número de graus de separação e ator de Kevin Bacon. Havia uma lenda em que Kevin Bacon estava tão bem conectado, apareceu em tantos filmes diferentes que quase todos os atores poderiam se rastrear de volta a Kevin Bacon de alguma forma. E é verdade, na verdade. Então, como é que isso funciona? Vamos colocar isso em termos de nossos dados de super-heróis, certo? Então, digamos que, por uma questão de argumento, o Homem-Aranha apareceu na mesma banda desenhada que o Incrível Hulk. E o Incrível Hulk apareceu na mesma banda desenhada que Thor. Nesse caso, diríamos que o Homem-Aranha e o Thor são dois graus de separação, certo? Porque se você olhar para as conexões do Homem-Aranha, o Hulk não está nesse conjunto imediato de conexões. Alguém a quem o Homem-Aranha se conectou está ligado ao Hulk. Então isso fica a dois passos do Homem-Aranha ou a dois graus de separação. Então isso é uma coisa interessante de se olhar. Acontece que as pessoas estão mais conectadas do que você imagina. E acontece que isso também é verdade no mundo dos quadrinhos. Então, como faríamos isso? Bem, há um algoritmo de ciência da computação chamado busca de largura que resolve esse tipo de problema para nós. E isso certamente não é algo onde você simplesmente escreveria um comando SQL e seria feito com ele para encontrar a resposta, certo? Queremos descobrir para qualquer pessoa em um dado nó, neste caso, qualquer super-herói neste gráfico de conexões. quantos passos está um super-herói de qualquer outro super-herói? Então, como faríamos isso usando o Apache Spark? Bem, antes de falarmos sobre os detalhes da implementação, vamos falar sobre o algoritmo. Então, para entender este exemplo, você precisa entender a pesquisa de largura em primeiro lugar ou BFS. Este é um problema de algoritmos de ciência da computação. E se você estiver indo para ser entrevistado para cargos de engenheiro de software, é uma coisa boa de saber, embora não esteja diretamente relacionado com faísca. Então, se você não seguir os detalhes aqui, não fique muito preso nisso. Não é realmente relevante para se acender sozinho. Eu sou apenas relevante para entender este exemplo de como Spark pode ser usado para resolver problemas que você pode não ter pensado Spark pode ser usado para. Então imagine que isso representa nossa rede. Então, cada círculo aqui representa um super-herói, e cada linha entre esses círculos representa uma conexão entre super-heróis. Então isso significa que eles apareceram na mesma banda desenhada juntos. E alguns, você sabe, às vezes você tem muitas conexões saindo de um super-herói e às vezes há muitas rotas entre dois super-heróis para olhar. Então o número dentro de cada círculo representa a distância desse super-herói de qualquer super-herói que estamos medindo os graus de separação. E inicialmente não sabemos a resposta quando estamos iniciando esse algoritmo. Então, tudo está definido para o infinito. Assumimos que eles estão infinitamente longe porque ainda não calculamos. Então, para começar, escolhemos o super-herói com o qual queremos começar e com quem queremos calcular os graus de separação. Então vamos dizer que o Homem-Aranha, e vamos chamar isso de S aqui neste exemplo. Então, o pontapé inicial, o algoritmo, colorimos esse nó inicial de cinza, o que significa que precisamos explorar esse NOAEL, queremos saber mais sobre as conexões desse nó. E colocamos o número 0 porque essa é a distância da pessoa que estamos começando com 2, esse nó. Homem-Aranha é 0 graus de separação do Homem-Aranha porque o Homem-Aranha é o Homem-Aranha. Então, o que fazemos no algoritmo BFS é que vamos à procura de nós cinzentos em nosso gráfico. E para cada nó cinzento que encontramos, exploramos as conexões que saem desse nó cinzento. E quando fazemos se esse nó que estamos explorando seu branco, que significa que ele foi inexplorado anteriormente, vamos colorir cinza, que significa que precisamos explorar esse nó mais iterativamente. E vamos pegar o nó que acabamos de explorar na cor preta, indicando que já exploramos esse nó. Não precisamos voltar a isso de novo. Nós incrementamos a contagem atual de distância. Então foi 0 mais um é um. Então agora sabemos que somos um grau de separação em R e W Faz sentido. Então começamos a explorar aquele nó de cor S inicialmente cinza para preto porque terminamos com ele. E para todas as suas conexões, se elas fossem brancas, nós as tornamos cinza agora e colocamos a contagem atual de distância daquele nó inicial. Então, na próxima passagem, novamente, procuramos as notas cinzentas e exploramos suas conexões. Então vamos começar com w. lá vai quebrar suas conexões. Então, ambos eram brancos originalmente e agora vamos colorir cinza e incrementar a distância novamente. Então agora estamos dois graus de separação de S fará a mesma coisa para a conexão de S para R. Explore É uma conexão para v e cor cinza. E novamente, coloque um dois lá porque nós estamos atualmente na iteração de duas distâncias de S. Agora que nós exploramos estão em W, nós vamos chamá-lo vai preto, que significa que nós não devemos revisitá-los novamente em o futuro. Em seguida, começaremos com T. Novamente. Precisamos passar por todos os nós cinzentos e explorar suas conexões novamente. Agora T está conectado a u, que era branco, então agora vamos colorir esse cinza e incrementar a contagem de distância novamente para três. Agora. Agora note que t também está conectado a x e w, Mas aqueles não são brancos. Vamos tentar preservar a cor mais escura aqui à medida que passarmos. Então não vamos nos incomodar em revisitar o X novamente. Já está marcado como cinza. Definitivamente não vamos visitar W de novo porque está marcado preto. Isso significa que já fizemos isso. Nós não precisamos de um processo que um. Então nós podemos marcar x está sendo explorado agora, nós temos, nós podemos marcar esse preto agora porque nós já determinamos que nós terminamos com ele. E seguir em frente. Também precisamos explorar se ainda não terminamos essa. Então, vamos marcar V como sendo negro agora também. Originalmente era um cinza. Então agora o próximo passo é chamar isso de preto, que significa que terminamos de explorá-lo. Agora só temos mais dois nós cinzentos para explorar aqui. E eles não têm nenhum nó recém-inexplorado associado a eles. Então vamos pintá-los de preto e acabar com isso. Então, o algoritmo geral aqui para recapitular, começamos por colorir tudo de branco com uma distância desconhecida. Nosso nó inicial é cinza, e para cada iteração, procuramos nós cinza, exploramos suas conexões. E para cada nó branco que sai desse nó cinza, vamos marcá-lo como cinza para exploração futura, a menos que já tenha sido colorido cinza ou preto, onde preservando precisamente a cor mais escura à medida que vamos. Além disso, estamos preservando a métrica de distância mais baixa que vemos nesses nós à medida que avançamos. Então nós nunca vamos fazer algo como ir de você de volta para T e dizer que agora é uma distância de quatro porque nós rastreamos, isso faria sentido, certo? Assim, nós sempre preservamos essa métrica de distância mais baixa enquanto estamos atravessando o gráfico. Então, é uma coisa difícil de enrolar sua cabeça. E novamente, se você não seguiu bem isso, não se preocupe muito com isso. Este não é um curso sobre algoritmos, é um curso sobre Spark. Estou apenas tentando transmitir como é possível usar o Spark para resolver problemas que talvez você não pense que Spark é adequado para. Você pode realmente paralelizar este problema muito bem se pensarmos sobre isso de uma forma criativa. Então vamos falar sobre essa implementação no Spark em seguida e fazer isso acontecer em nosso Spark Cluster. 36. Graus de separação de superherói: Então vamos falar sobre como enquadrar isso como um problema de faísca e, na verdade distribuir a pesquisa em primeiro plano em todo o nosso cluster potencialmente. Então a primeira coisa que precisamos fazer é representar nossos dados chegando como esses nós que falamos na palestra anterior. Assim, por exemplo, uma linha de entrada pode estar neste formato, o primeiro número é algum ID de herói, seguido por uma lista dos outros heróis que Hero apareceu com outra banda desenhada. Então queremos estruturar isso de uma forma que represente um desses nós em busca de largura. Então, por exemplo, nós poderíamos estruturar isso como a seguinte tupla de tuplas, se você preferir. Onde o primeiro elemento é o ID de herói que estamos falando. Aquele que é basicamente representado por este nó, seguido por uma lista de todos os outros IDs de herói que estão conectados a este herói. Então imagine uma linha virtual entre 59, 83 e 11, sessenta e cinco, trinta e oito, trinta e seis, et cetera, et cetera. Então essas são todas as conexões que estão conectadas ao nosso herói. E isso em si está dentro de sua própria tupla. Para manter isso tudo auto-suficiente. O próximo elemento em nossa tupla representará a distância associada este nó do personagem do qual estamos medindo a distância. Inicialmente, definimos isso para o infinito. Não há como realmente representar o infinito aqui, então vamos apenas configurá-lo para um número realmente grande. Neste caso, 99. 99 será o nosso substituto para o infinito como o valor inicial da distância. E precisamos associar uma cor. Lembre-se, nossas notas podem ser brancas, cinza ou pretas, onde o branco representa um nó inexplorado. Gray representa um nó que precisa ser explorado, e preto é um não que já foi explorado. Então, inicialmente, cada nó é branco. Então, esse é um exemplo de como podemos representar essas linhas em um formato consistente com nosso conceito de nós em uma busca rápida. Então agora, na verdade, passando por esse algoritmo de busca de largura pode ser pensado como um mapa e reduzir a operação. A função de mapeamento cuidará de converter essas linhas no formato de nó BFS que acabamos de falar. E esse código pode parecer assim. Então nós só precisamos dividi-lo por espaços, converter os IDs de herói para inteiros e as conexões para inteiros construir uma matriz de conexões que são todas as conexões associadas a essa pessoa. Defina a cor inicial como branco. Vamos definir a distância inicial para 99, 99. E se a identificação do herói for uma, estamos começando com o caso inicial do que estamos começando. Cor que um cinza com uma distância de 0, mas tudo o resto deve ser branco com uma distância de infinito como nosso caso inicial. E nós apenas devolvemos nossa estrutura tuplada que falamos com a identificação do herói. E, além disso, a matriz de conexões e a distância e a cor. Agora, talvez seja uma boa idéia falar um pouco sobre a história da computação distribuída aqui. Então note que estamos usando um paradigma MapReduce para pensar sobre esse problema. De onde vem essa ideia? Assim, quando o Google estava lidando pela primeira vez com análise de dados em larga escala e a necessidade processar dados que não cabiam em uma única máquina. Eles inventaram o MapReduce. E MapReduce estava praticamente limitado a funções de mapeamento e reduzir funções. Foi o que fez, certo? E vimos exemplos de mapeadores e redutores em exemplos anteriores neste curso, mas precisa ser, esse é praticamente o único truque que tínhamos nas mangas. O Hadoop foi construído sobre os conceitos que o Google criou. E Hadoop, também tem algo chamado MapReduce. Na verdade, é chamado MapReduce, uma palavra que é um componente essencial do próprio Hadoop. O problema é que MapReduce não era muito inteligente sobre otimização, e foi aí que o Spark entrou. Então Spark inicialmente era apenas uma espécie de uma alternativa mais rápida para MapReduce. Então é daí que veio a interface RDD inicial de faísca. Você notará que os RDDs têm uma função de mapa e uma função de redução disponível para eles. E é por isso, porque eles estavam tentando replicar a funcionalidade da funcionalidade do Hadoop MapReduce. Mais tarde, ao longo do tempo, quando chegamos ao Spark Versão 2, foi quando conjuntos de dados e DataFrames foram introduzidos. Na verdade, os dataframes vieram primeiro. E foi aí que começamos a dizer, Ei, vamos pensar sobre isso em termos de operações SQL. Sql estava se tornando a linguagem comum entre os pacotes de software de análise de dados naquela época. Então, mesmo para coisas que foram distribuídas e tecnicamente não eram adequadas para operações de banco de dados relacional. Sql ainda estava se tornando a sintaxe comum entre todas essas plataformas diferentes. Então nós vimos essa evolução de MapReduce para faísca que foi tipo de construído como uma extensão para fazer MapReduce melhor. Para desencadear se tornando mais uma interface SQL SAL. Mas nem tudo é um problema SQL, certo? Então ainda temos essa funcionalidade de nível mais baixo do MapReduce disponível para nós que podemos usar para resolver problemas de propósito mais geral, como este. Não consigo escrever um comando SQL que diz calcular a distância em um gráfico entre dois nós. Mas eu posso enquadrar isso como um problema MapReduce. Então é isso que vamos fazer aqui. Novamente, trata-se de escolher a ferramenta certa para o trabalho, mesmo que possamos fazer isso com um conjunto de dados. E eu vou mostrar a vocês que, neste caso, usar RDDs e seu mapeamento de nível inferior e funcionalidade de redução será a abordagem mais direta. Ok, fora da minha plataforma, vamos falar mais sobre a implementação. Assim como caminhamos nos slides para busca de largura, vamos passar por coisas iterativamente. E para cada passo, cada distância, vamos procurar por todos os nós cinzentos e expandir esses nós cinzentos. Colore o nariz. Acabamos com o preto dele e continuamos aumentando as distâncias à medida que avançamos. Então você vai ver um grande loop que apenas passa iterativamente por esse gráfico uma e outra vez, procurando por nós cinza e processando esses nós cinzentos acordo com base nas regras que definimos no BFS algoritmo. Tudo bem, então novamente, estamos apenas enquadrando isso como um mapa e um trabalho de redução. Então, toda vez que incrementamos através do nosso algoritmo, o mapeador irá incrementar a distância em um. E vai procurar notas cinzentas. Se ele encontrar um nó cinza, vai olhar para todas as conexões desse nó cinza, colorir cinza para exploração futura. E inicialmente eles não terão conexões porque eles precisam ser explorados para construir essas conexões. Na próxima iteração, o grão de aveia apenas processo será então colorido preto. E ele irá copiar o próprio nó de volta para os resultados para garantir que não o perderemos. O trabalho redutor será lidar com todos os casos em que temos vários caminhos indo para o mesmo nó, muitas conexões. Então precisamos combinar todos os nós que existem para a mesma ID de herói. E se houver um caso em que há várias conexões, queremos preservar a conexão com a menor distância e a cor mais escura. E como está reduzindo coisas que preservarão essa lista de conexões do nó original para garantir que não perderemos aqueles na próxima iteração. Então é assim que tudo funciona do ponto de vista algorítmico. Mas como saberemos quando terminamos? Então aqui é onde vamos introduzir um novo conceito chamado o acumulador em Spark. Então, um acumulador é basicamente um contador compartilhado em todos os executores em seu cluster. Então, se você precisa ter uma espécie de contador comumente mantido, se você quiser, ou uma bandeira de algum tipo. E acumulador pode fazer isso. Ele permite que muitos executores incrementem alguma variável compartilhada em todo o cluster. Então aqui está um exemplo dessa sintaxe. Eu poderia dizer que contador de acertos é um acumulador longo chamado contador de acertos. E, por padrão, seu valor inicial será 0. Então, enquanto estamos passando pelo nosso algoritmo, nossas iterações serão distribuídas por toda a nossa plataforma. E qualquer executor individual pode atingir o personagem em que estamos interessados. Então, quando isso acontece, aquele executor precisa de alguma forma sinalizar de volta para o script do driver como um todo, Ei, terminamos. Na verdade, temos uma pista aqui. Então podemos incrementar o acumulador do contador de acertos nesse caso para indicar que ele realmente encontrou o personagem que estamos tentando encontrar a distância de até o nosso personagem original. Então, quando terminamos com cada iteração, apenas verificamos se o contador de acertos é maior do que um. E se for, sabemos que terminamos e, às vezes, recebemos uma batida de várias direções e esse contador de acertos pode ser mais do que um. Mas é assim que sabemos que terminamos. Aqueles executores podem sinalizar de volta para o script, Ei, eu tenho uma pista. E ele pode manter o controle de quantos hits, tendo este acumulador compartilhado em todos os executores. Então isso é muito para enrolar sua cabeça. Vamos para o código e ver como é. 37. [de atividade] de superheróis de separação: revise o código e run o !: Então vamos mergulhar no código, abrir graus de separação, não o conjunto de dados ainda, apenas graus de separação. E vamos percorrer este código. Agora outra vez. O objetivo deste exercício é mostrar que você pode fazer coisas complexas com o Spark que não se limitou apenas a operações de estilo SQL. Então, se você quiser fazer como a análise de dados tradicional, ótimo, use comandos SQL. Mas para coisas como esta, você pode precisar descer para o nível inferior do Spark e voltar para a interface RDD. E tudo bem, isso está disponível para você também. E você sabe, isso é tipo de pensamento criativo é realmente o que empresas como Amazon, Google e Apple vão estar pagando as pessoas por muito dinheiro, certo? Não é preciso alguém realmente especial para escrever um comando SQL e descobrir quantos acessos de site você teve na última hora. Mas é preciso alguém especial para descobrir como eu posso pegar um problema que nunca foi resolvido antes de usar o Apache Spark e resolvê-lo. E aqui está um exemplo de fazer isso. Então, se você não seguir o código aqui, se você não seguir o algoritmo, não fique muito estressado sobre isso. Esse não é realmente o objetivo desta atividade. O ponto é apenas para mostrar que é possível fazer coisas complicadas em Spark e paralelismo em um cluster que você pode não ter pensado ser possível. Neste caso, estamos pensando mais em um paradigma MapReduce do que em um paradigma SQL. E está tudo bem. Então mergulhando, importamos todas as coisas que rezamos ou objetamos. Agora, a primeira coisa que fazemos é definir que personagem estamos começando e de que personagem estamos procurando. Então o propósito deste roteiro será encontrar os graus de separação entre o Homem-Aranha, que é a identificação do personagem 5306, e o átomo de personagem 3.031, que é francamente o personagem mais obscuro I encontrar no conjunto de dados, pelo menos eu nunca ouvi falar deles. Não faço ideia de quem seja. E sua identificação de personagem é 14. Então o que estamos tentando fazer é encontrar os graus de separação entre o Homem-Aranha e Adam, 3.031 aqui. E falamos sobre usar um acumulador chamado contador de acertos. E vai ser assim que nossos executivos sinalizam de volta para dizer: “Ei, eu realmente encontrei o átomo 3,031 enquanto atravessava o gráfico do Homem-Aranha. Então isso vai ser uma espécie de nosso contador compartilhado que diz, hey, eu tenho uma conexão aqui. Em seguida, configuramos nossos tipos de dados aqui. Então, temos um tipo de dados BFS que é uma matriz de inteiros e um inteiro e uma string que representará uma lista de conexões, a distância ea cor associada com o nó. E o nó em si terá o ID de herói associado a esse nó e os dados associados a ele. Então, um nó BFS vai representar um desses círculos em nossos slides que representa um determinado ID de herói. E as conexões naquele Herói tem a distância do Homem-Aranha. E finalmente, a cor desse nó, que será branco, cinza ou preto. Vamos pular para a função principal e trabalhar para trás a partir daí. Então aqui em algum lugar, temos uma função principal. Comece dizendo o nível de log e criamos um novo contexto Spark. Não estamos usando uma sessão do Spark porque não estamos usando a interface do conjunto de dados neste exemplo, vamos apenas usar RDDs. E para isso, só precisamos de desencadear o contexto. Inicializamos nosso acumulador e damos um nome a ele. E a primeira coisa que fazemos é criar RDD inicial. Então isso está criando as condições iniciais do nosso gráfico. Então vamos ver o que isso faz. Onde está criar RDD inicial? Muito simples, certo? Então, tudo o que estamos fazendo aqui é carregar o texto do ponto do gráfico Marvel em um arquivo de entrada RDD bruto. E, em seguida, chamamos mapa com converge para BFS para converter esses dados para o formato de nó BFS. Vejamos Converter para BFS. Divide a linha em campos individuais, arranca o primeiro faz com que o ID do herói arranque todos os campos subseqüentes aqui e preenche uma matriz de inteiros e que vai representar todos os conexões desse herói para outros heróis. Vamos definir sua cor padrão para branco e sua distância padrão para 99, 99, que é nossa representação do infinito, a menos que você seja Homem-Aranha. Nesse caso, colorimos você de cinza com uma distância de 0. O que significa que queremos começar explorando o nó do Homem-Aranha e os graus de separação do próprio Homem-Aranha 2 é 0. Em seguida, retornamos essa estrutura de notas BFS que falamos, que é um ID de herói e, em seguida, uma tupla contendo a matriz de conexões, a distância atual e a cor atual associada a cada nó. Então, inicialmente, tudo vai ter uma cor branca, uma distância de 99, 99. E todas as conexões associadas a cada ID de herói são lidas nesse arquivo de texto, exceto o Homem-Aranha, que será cinza com uma distância de 0. Tudo bem, então nós fizemos o caso inicial, eles estão armados. O que acontece a seguir? Então agora passamos por essa iteração, como dissemos, e escolhemos dez é um limite superior arbitrário. Acontece que você nunca tem nenhum. Na verdade, são dez graus de separação neste conjunto de dados específico que é mais do que suficiente. Imprimimos quantas iterações já fizemos. Então isso representa a distância que estamos olhando para o Homem-Aranha neste passo. E a primeira coisa que fazemos é fazer uma operação de mapa. Então chamamos FlatMap em BF usando a função de mapa BFS usando essa iteração RDD. Então começamos eu sentado iteração RDD para esse estado inicial. Em seguida, chamamos FlatMap na iteração RDD. E FlatMap, como você pode se lembrar, tem o potencial de criar novos nós, certo? Então vamos ver o que está acontecendo no mapa BFS. Para fazer. Há o mapa da BFS. Certo, então basicamente extraímos o ID do caractere e os dados associados, e explodimos esses dados também para extrair a matriz de conexões, a distância e a cor do nó que estamos vendo que estamos mapeando. Agora, uma vez que este é um FlatMap, podemos retornar uma matriz de nós BFS mais de um se quisermos adicionar ao nosso novo RDD. E enquanto estamos indo, estamos procurando por nós cinzentos toda vez, certo? Então os nós cinzentos são os que precisam ser explorados. Então, se encontrarmos um nó cinzento, processamo-lo. Exploramos todas as suas conexões e criamos um novo nó para essa conexão. Então podemos ter um novo ID de caractere, uma nova distância, que é a distância mais 1 deles. Saiba que começamos, a nova cor será cinza. E se esse é realmente o personagem que estamos procurando, se isso for Adam 3000, 31 ou o que quer que fosse, então vamos incrementar nosso contador de acertos e dizer: “ Ei, encontramos o cara, estamos acabados. Encontramos um nó onde essa pessoa está conectada ao Homem-Aranha. Em seguida, criamos um novo nó com base na nova distância em nova cor que calculamos e adicionamos isso à nossa lista de resultados. Então criamos todos esses novos nós cinzentos que precisamos explorar a partir das conexões do cinza sabemos que acabamos de encontrar. E pegamos o cinza saber que acabamos de explorar e colorir de preto, indicando que terminamos com ele. Ok. Só devolvemos os resultados e acabamos. Então novamente, se você não entende o algoritmo BFS, não fique muito preso nele. Esse não é realmente o objetivo deste curso, mas eu só queria te mostrar o que você pode fazer. Certo, então fizemos a operação do mapa. Em seguida, imprimimos o nosso processo à medida que avançamos e dizemos que processamos quaisquer valores até agora. E se conseguirmos um sucesso, vamos dizer: “Encontramos o personagem que procuramos. Aqui está o total real de quantos hits recebemos dessa iteração. Então, é possível que mais de um executor estava realmente processando esse personagem ao mesmo tempo. E eles podem ter te dado vários hits vindo de direções diferentes e tudo bem. Temos o total impresso aqui. Se assim for. Agora, antes de iterar mais, precisamos combinar dados juntos. Então, podemos ter gerado novos nós para o mesmo ID de caractere que fomos. Então, enquanto exploramos todas essas conexões, podemos ter ramificado em várias direções diferentes e voltar e sabe que já processamos, por exemplo. Então, para lidar com esse caso, precisávamos fazer uma operação ReduceByKey. O ReduceByKey reunirá todas as novas notas que eles podem ter criado para o mesmo ID de caractere. E o trabalho da função reduzida BFS na vida é apenas para preservar a distância mínima e a cor mais escura nesse caso. Então é tudo o que está acontecendo aqui. Eu não vou passar pelo código aqui em muito detalhe porque não é importante. Mas esse é o propósito desta função apenas para lidar com os casos em que temos mais de uma conexão entrando no mesmo nó. E nesse caso, preserve a distância mínima e a cor mais escura associada a esse nó em particular. Então, sim, vamos ver se realmente funciona. Vamos clicar com o botão direito do mouse em graus de separação e executá-lo. Trabalho complicado, certo? Mas Spark pode fazer um trabalho curto com isso. Aqui vamos nós. Já feito tão bem, nós realmente processamos 218.067 conexões lá. Mas descobrimos que mesmo este personagem obscuro é apenas dois graus de separação do Homem-Aranha. Enquanto acontece que mesmo super-heróis fictícios em quadrinhos estão muito bem conectados. E isso realmente é verdade no mundo real. Acontece que se você olhar para, você sabe, redes sociais reais como LinkedIn ou IMDB é banco de dados de conexões de atores que atuam juntos no mesmo filme, você obtém resultados semelhantes. As pessoas são muito mais conectadas do que você imagina. É meio interessante. Então olhe para isso. Funcionou. Muito legal novamente, este é apenas um exemplo de como usando as funcionalidades de nível inferior do Spark, você pode às vezes resolver problemas que você não acha Spark era necessariamente adequado para. Não se trata apenas de resolver problemas SQL. Você pode fazer mais coisas com ele do que isso. Então lembre-se que você tem esse poder à sua disposição. Isso não quer dizer que eu não poderia ter enquadrar isso em termos de conjuntos de dados e operações SQL, você pode, e nós fizemos isso. Então vamos analisar brevemente a versão do conjunto de dados deste script. E faz coisas muito estranhas. Então, quero dizer, tentando gostar de fazer MapReduce sem usar MapReduce, É possível. Não vai ser eficiente. Então, se olharmos para isso, eu não vou entrar em muito detalhe no script aqui, mas você pode ver que estamos fazendo algumas coisas bem complicadas aqui para fazer as mesmas coisas que fizemos nos scripts RDD. Então, mesmo a criação de condições iniciais aqui, apenas uma espécie de construção dessa estrutura de nó acaba sendo essa operação complicada de colunas de largura em funções SQL para tentar replicar o que fizemos com apenas usar, você sabe, em linha reta código Scala em nosso mapa e reduzir funções. E temos todos esses casos especiais para o nosso personagem inicial. Nós basicamente temos que fazer esses filtros e pesquisar através de todo o conjunto de dados procurando por esse caso especial, em vez de apenas lidar com ele na linha. À medida que exploramos cada nó, procurando nós cinzentos, temos que fazer uma operação de filtro e tudo para extrair esses nós cinzentos. Selecione as informações que precisamos. Filtre procurando o ID do caractere de destino que estamos procurando e lide com isso, especialmente. Então faz a mesma coisa. Bem, isso é um código complicado que eu preservo a cor mais escura também, para ser justo, era bem complicado em nosso código também, mas não envolvia fazer uma operação de junção. Bom Senhor. E tudo isso SQL realmente extravagante que provavelmente vai ser muito pesado operações. Então, mesmo que possamos, se pensarmos bastante nisso, enquadrá-lo como um problema SQL, não é a maneira mais eficiente de pensar sobre isso. E só para provar o meu ponto de vista, vamos fazer isto. E nós vamos tipo de contar quantos segundos leva para que esta versão do script seja executada uma vez que Spark gira. Então aqui vamos nós. 1, 2, 3, 4, 5, 6, 7. Levou cerca de sete segundos para conseguir a resposta lá. Temos a mesma resposta. Então isso é bom. Funcionou, mas levou sete segundos para conseguir essa resposta. Em contraste, vamos executar a versão RDD disso. Um a nem três segundos, certo? Então isso foi realmente mais do que duas vezes mais rápido que a versão do conjunto de dados. Então, novamente, trata-se de escolher a ferramenta certa para o trabalho. Conjuntos de dados são incríveis em lidar com tipos de problemas tradicionais de análise de dados. Se você pode enquadrar seu problema em termos de um comando SQL facilmente, um conjunto de dados provavelmente lhe dará o melhor desempenho. Mas se você se encontrar tendo que realmente ficar em sua cabeça para tentar enquadrar o que você está tentando fazer em termos de comandos SQL. Não vai acabar bem, certo? E, às vezes, os RDDs são a melhor ferramenta. Então, neste caso, indo para um nível mais baixo usando a interface RDD de nível inferior do Spark, obtivemos um desempenho muito melhor do que usando a API do conjunto de dados. Mas se estivéssemos realmente fazendo algo que fosse adequado para um comando de estilo SQL implementando isso usando conjuntos de dados. E há funções que se parecem muito com comandos SQL, permite mais otimizações e seria realmente ser mais rápido para problemas como esse. E no mundo real, você sabe, esse é provavelmente o problema mais comum que você receberá com o Apache Spark. Normalmente, você está tentando fazer coisas como responder perguntas sobre dados registrados entrando. Quantos erros eu tive no mês passado ou o que quer que seja? Coisas assim. Conjuntos de dados são incríveis. Mas se você estiver tentando fazer algo em um nível mais baixo, lembre-se que os RDDs também estão lá para você, e você tem essa funcionalidade disponível para você. 38. Filtração colaborativo com a origem em Spark, cache() e persiste (): Então, como outro exemplo interessante de coisas complicadas que você pode fazer com o Spark que você pode não ter pensado que poderia fazer com o Spark. Vamos falar sobre filtragem colaborativa baseada em itens. Este é basicamente um algoritmo de mecanismo de recomendação. É a maneira que a Amazon costumava fazer coisas como pessoas que compraram isso também compraram ou recomendaram coisas para você com base em suas compras anteriores. A ideia de alto nível é que podemos dar uma olhada nas coisas que você comprou no passado, procurar itens semelhantes aos itens que você comprou e, em seguida, recomendar esses itens para nós, coisas que você pode estar interessado em. E vamos fazer isso no contexto de filmes usando o conjunto de dados MovieLens. Então a coisa fundamental que precisamos é de alguma medição de filmes que são semelhantes uns aos outros com base nas classificações dos usuários. Então é isso que vamos fazer aqui. E enquanto estamos nisso, também vamos introduzir o conceito de armazenar em cache seus conjuntos de dados para melhorar o desempenho. Então filmes semelhantes, esta é uma pequena captura de tela e uma mais antiga dos sites GroupLens. Então eles realmente têm uma interface de usuário onde você pode classificar filmes, dizer-lhes explicitamente os movimentos que a luz UV, e ele irá recomendar novos filmes para você com base nessas classificações. Então, uma maneira de fazer isso é dar uma olhada em todos os filmes que você gostou. E para todos esses filmes, olhe para os filmes semelhantes a esses filmes. E essas semelhanças serão baseadas em outros usuários que gostam dos mesmos filmes que você gosta. Ok? Então o algoritmo básico aqui é que vamos começar por encontrar cada par de filmes que foram assistidos pela mesma pessoa. Nosso objetivo aqui é encontrar todos os filmes que são semelhantes a qualquer outro filme. Ok? Para fazer isso, vamos primeiro quebrar todos os filmes que foram lavados pelas mesmas pessoas. Então, se o usuário a e o usuário B assistiram ao filme e gostaram, isso seria um par de filmes. Agora podemos então reunir todos os usuários que gostam desses pares de filmes e medir a semelhança de suas classificações em todos eles que assistiram ambos os filmes. Então, baseado em todos os usuários que assistiram esse par de filmes e gostaram, quão semelhantes são esses filmes em termos de classificações? Então podemos agrupar todos eles pela identificação do filme, classificá-los com base em sua força de similaridade. Isso é algo que calculamos com base nessas classificações. E então temos uma lista ordenada de filmes que são semelhantes a todos os outros filmes apenas por esse algoritmo simples. Então esta é apenas uma maneira de fazer isso. Cuide de você. Existem muitas outras técnicas lá fora também, mas esta é simples e às vezes simples como melhor. Produz bons resultados se você tiver dados suficientes. Deixe-me guiá-lo através do algoritmo e mais de uma maneira gráfica aqui. Então imagine que N aqui assistiu tanto Star Wars quanto The Empire Strikes Back, que é o SQL para Star Wars, significava que você gosta de ambos. E então Bob aqui, o cara com um moicano, também assistiu Star Wars e The Empire Strikes Back e gostou dos dois também. Com base nessa informação, podemos dizer que temos um par de filmes aqui, Star Wars e The Empire Strikes Back. E ambos tinham dois usuários em comum que gostavam deles. Então, para esse par, sabemos que o usuário e o usuário Bob gostam deles e vamos imaginar que ambos deram cinco estrelas a eles. Então, com base nisso, podemos calcular que estes são filmes muito semelhantes com base nesse comportamento de classificação do usuário. Das três pessoas em nosso conjunto de dados. Dois deles adoraram este par de filmes, certo? Então isso produziria uma pontuação muito boa de similaridade. No entanto, podemos escolher medir isso. Agora vamos imaginar Ted aqui no fundo aparece e ele só assistiu “O Império Ataca de Volta”. Talvez ele tenha se mudado para cá e vindo de um país onde Star Wars não é grande coisa. Isso está tudo bem. Mas de alguma forma ele não sabe que o primeiro filme, Star Wars, uma Nova Esperança realmente existiu. Então, como recomendamos a ele o que mais ele poderia estar interessado em assistir com base nas informações que temos aqui. Bem, nós podemos dizer, ok, nós sabemos Ted, você gostou do Empire Strikes Back. E sabemos pela nossa computação anterior que o filme mais parecido, O Império Ataca de Volta é Star Wars uma Nova Esperança, o primeiro filme? E novamente, essa semelhança foi baseada no comportamento de classificação dos outros usuários em nosso conjunto de dados. Então é isso em um nível alto. Basicamente, podemos recomendar filmes semelhantes aos filmes que você adorou com base no comportamento de classificação das outras pessoas em nosso conjunto de dados. E isso é filtragem colaborativa baseada em itens em poucas palavras. Então, no final, isso recomenda um bom filme para o Ted que ele talvez não soubesse antes. Agora vamos nos concentrar aqui nesta atividade apenas na parte da semelhança do filme. Então não vamos realmente fazer recomendações completas para as pessoas, mas vamos computar esse conjunto de dados de semelhanças de filmes. Quais filmes são semelhantes a outros filmes com base no comportamento do usuário. Essa é a parte mais difícil, certo? Porque uma vez que você tem esses dados, você pode fazer recomendações para as pessoas muito rapidamente com base nas coisas que elas já gostaram antes. Então você pode dizer a si mesmo, como diabos podemos fazer isso em Spark? Spark é tipo construído em torno de um paradigma SQL nos dias de hoje, ou talvez um MapReduce na melhor das hipóteses. Como você enquadra isso como um problema que se encaixa nessa estrutura e algo que você pode paralelizar. Bem, você pode, você só tem que pensar sobre isso criativamente. E mais uma vez, você sabe, ser capaz de pensar sobre esses problemas de uma maneira criativa é o que eles pagam muito dinheiro para você. Então, é um exemplo de como você pode usar essa tecnologia para resolver um problema que você talvez não tenha pensado que era adequado. Aqui está o algoritmo geral que vamos usar em nosso exemplo Spark. Então, vamos começar selecionando os IDs de usuário, IDs de filme e classificações. Neste exemplo, nós realmente não nos importamos com os tempos, embora você possa imaginar um mundo onde você também usa essa informação. Em seguida, encontramos todos os pares de filmes que foram classificados pelo mesmo usuário. E isso pode soar como uma coisa complicada de se fazer, mas acontece com uma operação auto-adjunta, que é muito um tipo de banco de dados para fazer. Isso é exatamente o que ele vai te dar. Basicamente, você pega o conjunto de colunas de filme e classificação do usuário e junta-se a isso em si mesmo com base no ID do usuário. E isso lhe dará todos os possíveis pares de filmes que foram classificados pela mesma pessoa. Então, nesse ponto, podemos reformular nosso conjunto de dados auto unidos para ter filme um, filme para classificação um e ler duas colunas que nos dirá os pares de filmes e as classificações associadas a cada um. E novamente, neste ponto, isso será feito para cada usuário único que classificou esses dois filmes juntos. Podemos então passar e filtrar enquanto estamos nele quaisquer pares duplicados, porque uma classificação de filme um para mover os dois é a mesma coisa que filme para filme um. Então vamos ter alguma heurística lá dentro para ter certeza de que só capturamos uma dessas duas variações. Uma vez que temos isso, podemos passar por cada usuário que classificou esse par de filmes e calcular a pontuação de similaridade do cosseno com base nessa informação. Eu não quero entrar na matemática disso porque não é realmente relevante para o desenvolvimento do Apache Spark. Mas se você está curioso sobre como a semelhança do cosseno funciona, eu, há outro curso que eu tenho sobre sistemas de recomendação que entra em mais profundidade sobre ele. Mas em um nível alto, se você der uma olhada em todas as classificações de usuários de um filme, você pode pensar nisso como uma espécie de vetor multidimensional. E uma pontuação de similaridade cosseno seria basicamente o ângulo entre dois vetores para dois filmes diferentes com base nas classificações de usuários que eles têm em comum. Então, uma vez que temos isso, podemos agrupar tudo pelo filme um, filme dois pares e ter certeza de que agregamos tudo juntos para um determinado par de filmes, computação que é similaridade cosseno entre todos os usuários que classificaram esse par de filmes. Então, neste ponto, temos um conjunto de dados que contém todos os emparelhamentos possíveis de filmes e a pontuação de similaridade entre esses pares de filmes. Podemos então apenas filtrar e classificar e exibir os resultados. Assim, podemos agrupá-los por cada ID de filme individual, filtrar coisas que estão abaixo de algum tipo de limite de pontuação de similaridade para garantir que estamos apenas capturando semelhanças fortes e classificá-los por isso pontuação de similaridade e exibir os resultados finais. E isso nos dará a pontuação de semelhança de qualquer filme para qualquer outro filme. Então, antes de mergulharmos no código, deixe-me introduzir a idéia de cache de conjuntos de dados porque isso vai surgir neste exemplo. Muitas vezes, quando você está fazendo coisas complicadas como essa, você acaba consultando ou usando um conjunto de dados mais de uma vez. E se você se encontrar fazendo isso, você deve explicitamente armazená-lo em cache se puder. Caso contrário, há uma chance que provocou pode acabar reavaliando todo esse conjunto de dados novamente uma segunda vez, apenas para fazer aquela segunda operação nele. E se você quiser ter certeza de que isso não aconteça, você pode usar dinheiro ponto em um conjunto de dados depois de terminar computá-lo para garantir que ele fique na memória. Qualquer operação ou análise subsequente que você faça nesse conjunto de dados acontece o mais rápido possível. Também não persistem. Persistir, opcionalmente, permitirá que você pegue isso não apenas uma memória, mas também para o disco. Então, se um nó falhar ou algo assim, você pode se recuperar a partir desse ponto e simplesmente continuar de onde parou. Assim, o dinheiro estará na memória, persiste pode, opcionalmente, ser persistido no disco também. E com isso, vamos pular para o código e ver como ele se parece. 39. [de idade de televisão semelhante usando o cluster de Spark.: Tudo bem, vamos entrar no código aqui para computar semelhanças de filmes usando o Spark. Então abra o script de conjunto de dados de semelhanças de filmes aqui. E este é um caso em que o uso de um conjunto de dados irá superar o desempenho usando um RDD. A parte mais complicada de todo este algoritmo é que auto-join operação, onde tentamos encontrar cada par único de filmes que foram classificados pela mesma pessoa. E isso é um tipo muito SQL de coisa a se fazer, certo? Uma operação de auto-união. Então, isso realmente se encaixa bem nas idéias de usar um conjunto de dados no Spark SQL. É possível fazer isso com RDDs também, mas nesse caso, os conjuntos de dados superam os RDDs, que geralmente é o caso. Então vamos nos concentrar em conjuntos de dados para este. Se você está morbidamente curioso sobre como fazer isso com RDDs, há um script de similaridade de filme também disponível que apenas faz isso usando RDDs em vez disso. Mas vamos nos concentrar em conjuntos de dados. Então, o que temos aqui? Começamos importando tudo o que precisamos, como de costume. E declaramos um objeto de conjunto de dados de semelhanças de filme que contém várias classes de caso. Eles definiram os vários formatos de arquivo que vamos ler e usar para os conjuntos de dados que usamos ao longo do caminho em todo o nosso algoritmo. Então, temos um conjunto de dados de filmes que está apenas espelhando o formato dos dados brutos que estamos lendo. Consiste em um inteiro de ID de usuário, um inteiro de ID de filme ou inteiro de classificação e um carimbo de data/hora longo. Nós também vamos carregar um conjunto de dados de nomes de filmes para que possamos exibir facilmente os nomes legíveis por humanos do ID de filme dado. Isso só vai mapear IDs de filmes para títulos de filmes. Nós também teremos um conjunto de dados pares de filmes ao longo do caminho, e isso incorpora um par único de filmes. Esta é uma espécie de saída daquela operação de auto-junção onde obtemos todos os conjuntos de filmes que foram classificados pela mesma pessoa. E isso consistirá tanto do filme um quanto do filme para IDs de filme e das classificações associadas a cada um desses filmes de um determinado usuário. Assim, uma linha de pares de filmes consistirá em um par de filmes e suas classificações por um único usuário que assistiu a ambos. Consegui. E então também teremos um conjunto de dados de semelhança de Paris em algum momento que contém um par de filmes, filme 1, um filme com uma pontuação de similaridade em formato de precisão dupla, e o número de pares que foram associados na computação que é pontuação de similaridade. Então isso vai refletir quantos usuários realmente assistiram esse par de filmes e os classificaram juntos. Vamos avançar para a função principal e trabalhar a partir daí. Começamos definindo nosso nível de log e criando um objeto SparkSession. Como de costume. Em seguida, criamos um esquema de nomes de filmes, que será usado posteriormente para estruturar nosso conjunto de dados para procurar IDs de filmes para títulos de filmes. Ele só diz que nosso ID de filme será um inteiro, e ele terá um título de filme para cada ID de filme que é uma string. Vamos então declarar um esquema para os dados, os dados de classificações de filmes em si também. Isso terá ID de usuário, ID de filme, classificação e carimbo de data/hora na estrutura que vimos antes carregará esses nomes de filme. Como primeiro passo, importamos sparked on implits porque estamos carregando um DataFrame inicialmente e depois convertendo isso em um conjunto de dados. Então, para inferir implicitamente o esquema de um DataFrame, mesmo que estejamos fornecendo um, você ainda precisa usar o ponto Spark implits para essa etapa. Então dizemos que arquivo de dados particular, você ponto item é separado por um delimitadores de pipe. Ele está no traço ISO 8859 um conjunto de caracteres. E ele usa o esquema de nome de filme que estamos explicitamente fornecendo porque não há nenhuma linha de cabeçalho neste arquivo que podemos usar para inferi-lo de. E quando acabarmos com isso, vamos explicitamente convertê-lo em um conjunto usando a classe de caso de jogos em movimento para um desempenho ainda melhor no Spark. Em seguida, olhamos para os dados de classificações de filmes em si, novamente é um conjunto de dados. mesma ideia aqui. Na verdade, separamos a guia usando o esquema de filme que definimos acima. E vamos converter isso também para um conjunto de dados usando a classe de caso de filmes. Então, neste ponto, temos um conjunto de dados de nomes de filmes e temos um conjunto de dados de filmes que representa todas as classificações de usuários individuais. Em seguida, selecionaremos as informações que nos importamos apenas para nos impedir de transportar informações que não precisamos. Portanto, nosso conjunto de dados de classificações agora será apenas o ID do usuário, o ID do filme e a classificação. Deixando de lado a coluna de carimbo de data/hora, porque não precisamos dessa informação para o que estamos fazendo aqui. Agora é aqui que fica interessante. Esta é a operação de auto-união de que falamos antes. Então vamos ter um conjunto de dados de Paris de filme. A intenção aqui é conter todos os filmes avaliados pela mesma pessoa. Então, a maneira como estamos fazendo isso é antes de tudo, vamos pegar nosso conjunto de dados de classificações. Vamos dar-lhe um pseudónimo de classificações um para que possamos referi-lo facilmente. E vamos juntar isso com outra cópia do conjunto de dados de raio que é referido como classificações para. Então vamos fazer uma junção entre as classificações um e as classificações para as quais são realmente a mesma coisa. Ambos estão apontando para o conjunto de dados de classificação. Então é por isso que chamamos isso de auto-união. Estamos juntando o conjunto de dados de classificações em si mesmo, e vamos juntá-lo com base na coluna ID do usuário. Ok, então estamos dizendo que vamos nos juntar somente se um ID de usuário ou uma classificação que corresponda a ID de usuário e classificações. Então isso terá o efeito de emparelhar todos os filmes que foram classificados pela mesma pessoa. Consegui. Você meio que precisa entender como as operações de associação funcionam no SQL. E esta não é realmente uma classe SQL, mas o resultado é, isso é o que você obtém desta expressão aqui. Cada par de filmes que foram classificados pela mesma pessoa. E além disso, enquanto estamos nisso, vamos impor que o ID do filme para classificações um será menor do que o ID do filme vindo das classificações para. E estamos fazendo isso só para evitar duplicatas. Então, novamente, não queremos ter uma entrada separada para classificações uma emparelhada com leituras para, como faríamos para classificações para com classificações 1. Então, fazendo isso, nós apenas nos certificamos de que estamos capturando apenas um emparelhamento único lá. Uma vez que temos isso, podemos então renomear coisas para torná-lo mais fácil de usar. Então, vamos renomear classificações um ponto ID de filme para filme um, leituras hoje no ID de filme para filme dois, classificações quando estou lendo para ler um e classificações para ponto leitura 2, escrevendo 2, novamente, apenas para facilitar o trabalho. E, além disso, vamos explicitamente fazer este um conjunto usando a classe de caso de pares de filmes que definimos acima. Agora, temos aqui à nossa disposição esse conjunto de dados de pares de filmes que pode prejudicar pares de filmes e suas classificações para cada usuário único que classificou esse par de filmes. Dado isso, agora podemos chamar a semelhança de cosseno computacional para construir nosso conjunto de dados de semelhanças de Paris filme que irá conter para cada par de filmes como eles são semelhantes uns aos outros com base em todos os usuários que classificaram esses filmes juntos. Então, antes de irmos mais longe e falar sobre essa operação de cache, vamos ver o que a semelhança de cosseno computacional faz. Isso é aqui em cima, em algum lugar. Lá está ele. Então, há um pouco de matemática extravagante acontecendo aqui. Eu realmente não quero entrar na métrica de similaridade cosseno em si muito porque isso não é realmente nada a ver com programação Spark. Novamente, se você quiser saber mais sobre isso, você pode conferir meu curso sobre sistemas de recomendação. Mas em um nível alto, estamos criando três novas colunas aqui. Xx e XY. Isso vai calcular x ao quadrado, y ao quadrado, e x, y a partir do algoritmo que usamos para calcular similaridade de cosseno. Novamente, é basicamente um ângulo entre dois vetores virtuais neste espaço de filme do usuário. Podemos então calcular essas pontuações de similaridade. Assim, basicamente usamos esse novo conjunto de dados chamado partituras de Paris. Tem esses termos extras, está anexado a ele. E então chamamos ovo para agregar todas as entradas para cada par de filmes, eles estão usando a seguinte expressão. Então, para todos os pares de filmes, para todos os usuários avaliados esses dois filmes juntos. Vamos cruzá-los com todos com essa função agg. E vamos resumir as colunas X, Y e chamar isso de numerador. Isso vai ser apenas o numerador de nossa expressão para computação de similaridade de cosseno. E, em seguida, para o denominador que o primeiro denominador que acabará sendo a raiz quadrada da soma da coluna XX e raiz quadrada da soma da coluna y, coluna y adicionados juntos. E, finalmente, teremos os não pares, que só vai contar quantos da coluna x y existe. Isso é apenas um atalho para descobrir quantos usuários realmente classificaram este par de filmes juntos. E essa é a informação que precisamos para calcular a pontuação de similaridade real, que é o que vai parar neste conjunto de dados de resultado aqui, nós apenas adicionamos uma nova coluna de pontuação a isso também. E o que fazemos é garantir primeiro que não vamos dividir por 0. Verificamos explicitamente para se certificar de que o denominador não é 0. Caso contrário, nós só temos um resultado nulo lá. Se não, então nós apenas dividimos o numerador pelo denominador. E neste ponto temos nossa pontuação de similaridade real calculada com base na métrica de similaridade do cosseno. Nós então apenas reduzimos isso para as colunas que nos preocupamos, que vai ser filme um e filme para a pontuação de semelhança entre eles e o número de pares que suportam essa pontuação. E vamos forçar isso em um conjunto de dados, bem como usando os pares de filmes classe caso similaridade acima e retornar o conjunto de dados resultado, que novamente neste ponto apenas contém filme um filme para marcar e não pares que, tudo bem, de volta para onde isso foi chamado. Então agora temos esse conjunto de dados de todas as pontuações de similaridade entre cada par único de filmes. E provavelmente vamos usar isso mais de uma vez. Então vamos em frente e armazenar isso para que nós vamos ter isso na memória a calhar para ir. Não importa o que vamos fazer com ele mais tarde. Não só vamos usar isso para exibir nossos resultados, mas você pode imaginar, nós poderíamos realmente fazer um sistema de filtragem colaborativa baseado em item real fora disso, mantendo esse conjunto de dados de semelhanças de pares de filmes na memória. Podemos então tomar o conjunto de tudo o que qualquer novo usuário tem gostado ou manifestado interesse lá, ou avaliado altamente, o que você quer usar como uma indicação de interesse e, em seguida, bater que o estado de semelhança de Paris filme é definido para muito rapidamente voltar todos os filmes semelhantes aos filmes AP pessoa luz. Então, novamente, isso seria muito importante para o dinheiro se você estivesse construindo um sistema de recomendação real aqui. Mas tudo o que vamos fazer aqui é tentar obter os resultados das melhores semelhanças de um determinado filme. Então vamos verificar se passamos em uma discussão aqui. Então a idéia aqui é que vamos passar como um argumento para este roteiro, um ID de filme que estamos interessados em ver todas as semelhanças. E além disso, vamos estabelecer alguns limites aqui. Então nós vamos dizer que a menos que haja uma pontuação de 97% de similaridade entre dois filmes, nós não vamos considerá-lo semelhante o suficiente para ser interessante. E também diremos que você precisa ter pelo menos 50 usuários em comum que classificaram ambas as coisas juntas. Então esse é um tipo de suporte mínimo que precisamos para ter confiança de que este é um resultado confiável. Você não quer fazer uma recomendação baseada no que duas pessoas disseram. Idealmente, você quer que muitas pessoas que concordam entre si para lhe dar um resultado melhor. Então esses limites e um ser importante para obter resultados de qualidade e eles são bastante arbitrários, mas vamos voltar a isso. Então vamos aplicar esses filtros aqui. Vamos filtrar o conjunto de dados de semelhanças de Paris do filme e filtrá-lo não apenas para impor esses limites de pontuação, certificando-se de que a pontuação foi maior do que o nosso limite de pontuação escolar. E nenhum par é maior do que o limiar de início de co-ocorrência. Mas também vamos filtrar para a identificação do filme que estamos interessados. Então, para o filme que passamos como argumento, esse é o filme que queremos ver, filmes semelhantes também. Então, nós aplicamos que filme um é igual a ID de filme ou filme dois é igual a ID de filme. Nós realmente não sabemos se ele vai estar no filme um ou o filme para o lado, pode ser ou dependendo da ordem dos IDs do filme, certo? Então, se qualquer um dos filmes do par de filmes é aquele em que estamos interessados. Vamos elevar isso e também vamos verificar se nossos limites de qualidade também são cumpridos. Uma vez que temos isso, vamos classificar isso descendente com base nessa coluna de pontuação para obter os filmes mais semelhantes àquele filme e tomar o top 10. Então nós chamaríamos isso de um top n recomendador na linguagem do sistema de recomendação porque nós estamos levando os 10 melhores resultados em fazer isso nossas recomendações para este filme. E depois imprimimos e dizemos: “Pegue os 10 melhores filmes similares para qualquer nome do filme, para torná-lo legível por humanos”. Novamente, usando esse conjunto de dados de nomes de filmes que carregamos há muito tempo para esse ID de filme. E para cada resultado único que obtemos de volta, nós iteramos através dele e extraímos esses filmes semelhantes baseados em qualquer ID de filme que não é o que passamos como um parâmetro. Imprima esse resultado juntamente com sua pontuação e a força com base no número de pares que suportaram essa pontuação. Quem? Então, parece que isto deve funcionar. Você sabe, era muito para falar, mas se você olhar para o código de tudo isso, ele faz, realmente não é muito código, certo? Não é assim tão mau. Quero dizer, tem algumas coisas estranhas acontecendo com certeza. Eles NED, envolvem sua cabeça com essas expressões mais complicadas aqui como este agregado aqui ou a operação de auto-junção. Mas uma vez que você supere isso, não é muito código. Então vamos em frente e executá-lo e ver o que acontece antes de executá-lo no entanto, precisamos passar esse parâmetro de qual ID de filme queremos obter de volta, certo? Então, para fazer isso, nós mostramos que pouco mais complicado e inteligência. Clique com o botão direito do mouse em semelhanças de filmes e vamos dizer Criar semelhanças de filmes. Isso criará uma configuração de execução que podemos configurar explicitamente. E isso tem um slot aqui para argumentos do programa. Então você pode colocar qualquer ID de filme que você quiser aqui para qualquer filme que você está interessado, digamos 56, seja lá o que for. E diremos: “Está bem. E agora aqui temos as semelhanças do filme executar configuração que acabamos de definir. E podemos apertar o botão play para executá-lo. Então vamos começar isso e ver o que acontece. Lá vai ele. Carregámos os nomes dos nossos filmes e agora está a calcular essas semelhanças. E aí temos nossos resultados. Então isso é muito bom. Foi um tempo razoavelmente pequeno para uma operação muito complicada. E fazer uma auto-associação em um grande conjunto de dados não é um feito pequeno, se importa? E sim, temos os melhores resultados para Pulp Fiction. Acontece que é isso que o filme ID 56 é, e é meio que um filme ganancioso. E isso voltou com filmes mais corajosos. Então, na verdade, parecia funcionar. Eu já vi fumaça antes. Na verdade, não gosto de fissão, então não sei se quero ver isso eu mesmo, mas Reservoir Dogs, Dani Brass vão. Verdadeiro romance. Estes são todos os resultados razoáveis para um filmes semelhantes ao Pulp Fiction com base em outras classificações de usuários. Então, aí está. Se você fosse construir pessoas que gostaram deste filme também gostaram na Netflix ou algo assim. Agora você sabe como fazer isso e você pode realmente escalar isso usando o Apache Spark para lidar com uma grande quantidade de classificações ou um grande número de filmes. Porque você pode realmente lançar um cluster inteiro nisso agora. Então, aí está. Um exemplo de fazer semelhanças de filmes e filtragem colaborativa baseada em itens, pelo menos a primeira metade usando o Apache Spark. E como você verá mais tarde, há realmente uma função internana há realmente uma função interna biblioteca de aprendizado de máquina para o Apache Spark que faz algo semelhante, mas na verdade não gera resultados tão bons com o conjunto de dados MovieLens. Então, às vezes, apenas usar as ferramentas prontas para prateleira não é bom o suficiente e você precisa voltar e ser meio inventivo e implementar novos algoritmos usando o Spark que talvez não tenha sido visto antes no Spark, novamente, que é o que eles vão pagar os grandes dólares para os rapazes. Mas esse é um bom exemplo e nós vamos acabar com isso. Antes de o fazermos, vou desafiar-te a tornar isto melhor. Então vamos falar sobre isso na nossa próxima palestra. 40. [Exercício de exercício de a qualidade dos filmes semelhantes: Acontece que as semelhanças de filmes são um pouco próximas e queridas para o meu coração por algumas razões. Em primeiro lugar, a maior parte do que eu fiz durante meu tempo trabalhando na Amazon.com estava trabalhando no campo da filtragem colaborativa e seus sistemas de recomendação de usuários. Passei muito tempo tentando melhorar esses sistemas lá. E eram coisas divertidas. É, realmente é um trabalho interessante também eu corri IMDB por um tempo. Então isso é uma espécie de interseção de filtragem colaborativa e filmes que permeia muitos dos meus cursos. Então meu desafio para você é fazer os resultados melhores. E realmente não há resposta certa ou errada para isso, certo. A coisa com recomendações é que muitas vezes são de natureza bastante qualitativa. Quero dizer, você pode medi-los com base em como as pessoas reagem a eles no mundo real. Mas no final do dia, você meio que tem que julgar por si mesmo se eles são bons ou não. Então minha recomendação ver o que eu fiz lá. Recomendação, minha recomendação para você é ir encontrar um filme que você apaixonado por e descobrir que na pesquisa MovieLens Dataset, é ID de filme. E se houver um filme com o qual você esteja realmente familiarizado, você terá uma boa sensação intuitiva de que filmes semelhantes a esse filme podem ser bons. Então comece executando o roteiro que acabamos de ter para aquela identificação de filme que você conhece e ama tão bem. E julgue por si mesmo se essas são boas recomendações e pense em como elas poderiam ser melhores? Então aqui estão algumas idéias de coisas que você pode fazer para modificar esse script para melhorar ainda mais a qualidade dessas recomendações, uma idéia seria simplesmente descartar todas as avaliações ruins. Então, se alguém escreve um filme uma ou duas estrelas, nós realmente queremos que isso influencie nossa medida de como o filme é semelhante? Uma espécie de armadilha deste algoritmo é que filmes que são semelhantes em termos de todos os odiados ainda apareceriam como filmes semelhantes. Então isso não é necessariamente uma coisa boa se você está tentando recomendar bons filmes para ser puxado que eles podem querer assistir. Então essa é uma ideia. Apenas introduziu outro filtro que se livra de qualquer classificação ruim desde o início e ver qual a diferença que tem no resultado. Você também pode tentar métricas de similaridade diferentes. Você teria que procurar isso agora, razão similaridade cosseno, mas há métricas alternativas lá fora, bem como coeficiente de correlação de Pearson, o coeficiente de Jaccard, ou apenas probabilidade condicional direta. Então você pode querer procurá-los e tentar implementar isso em vez da métrica cosseno e ver se isso faz melhor ou pior. Você também pode jogar com esses limites e provavelmente é a coisa mais fácil de fazer. Talvez você devesse ter mais curadores mínimos ou uma pontuação mínima mais alta para chegar ao corte final. Isso terá uma troca ou cobertura no entanto, você sabe, se você tiver filmes mais obscuros, você pode não ter dados suficientes para realmente fazer uma recomendação se você definir esses limites muito altos. Ou você pode inventar sua própria nova métrica de similaridade que leva um número de cooperadores em consideração. Então talvez o número de pessoas que assistiram o par de filmes seja, em si, uma indicação de quão bons esses filmes são. Talvez apenas o fato de que eles são populares. E muita gente viu os dois é algo que você deve levar em conta. Então talvez você possa normalizar isso de alguma forma e introduzir isso em sua métrica de similaridade também. E se você realmente quiser chegar a um ambicioso, você pode até obter informações de gênero do arquivo de dados de itens de ponto UE e do conjunto de dados MovieLens que contém uma matriz de zeros e aqueles que indicam a quais gêneros e filmes pertencem. E talvez você possa filtrar filmes que estão em diferentes gêneros ou aumentar as pontuações de semelhança de filmes que têm muitos gêneros em comum. Então algumas idéias gerais lá e como você pode fazer os resultados melhores. Novamente, não há resposta certa aqui. Não posso mostrar a resposta correta para esta atividade. Eu só quero que você vá brincar com ele e veja se você pode melhorar os resultados. E se você fizer isso, eu ficaria muito curioso para saber o que você fez, seja nos comentários ou no Q e em qualquer mecanismo que a plataforma em que você está assistindo este curso lhe dá para fornecer feedback. Por isso, é realmente uma atividade divertida e uma atividade muito importante para um monte de e-commerce depende de fazer recomendações. Então, se você pode aprender a fazer isso, é uma coisa boa. Vá e brinque com isso. E então voltamos para a próxima seção e falamos sobre escalar as coisas. 41. [de ação] use o de spark-submit para executar scripts de Spark: Até agora neste curso temos vindo a desenvolver no seu PC desktop local porque, bem, isso é barato e fácil, certo? Não quero gastar um monte de dinheiro como você aprende essas coisas necessariamente, mas é hora de aumentar as coisas. Então, nesta próxima seção, falaremos sobre a execução do Spark em um cluster B real que um cluster que seu acompanha possui ou um cluster que você pode estar alugando em um serviço como a Amazon Web Services. Há algumas considerações especiais quando você está escrevendo seus scripts de drivers para uso em um cluster. E algumas maneiras pelas quais você estará implantando seu código e empacotando seu código e executando seu código quando ele estiver em um cluster real. Então vamos entrar nesses detalhes e isso deve armar você com o conhecimento que você precisa para realmente usar o Spark em uma configuração de produção real em grande escala. Até agora, neste curso, temos executado nossos aplicativos Spark em nosso desktop dentro do ambiente de inteligência. E isso é tudo bem e bom para o desenvolvimento. Mas se você quiser realmente executar um aplicativo Spark no mundo real, você provavelmente vai implantá-lo um cluster em algum lugar e não dentro do IntelliJ a, você vai querer ser capaz de disparar isso do algum tipo de trabalho Cron ou algum tipo de sistema de gestão que vai começar o seu aplicativo Scala em algum tipo de programação, certo? Então, como fazemos isso? Bem, vamos começar falando sobre como empacotar e implantar seu aplicativo e executá-lo de fora da inteligência e apenas de uma linha de comando em algum lugar. Então, no mundo real, em um cluster estará executando nossos scripts com algo chamado Spark traço enviar. Então, quando você instala o Apache Spark, ele vem com um aplicativo chamado Spark enviar. E seu trabalho é ler em um arquivo jar que contém seu aplicativo Spark compilado e distribuí-lo para todo o cluster a ser executado. E pode fazer tudo isso fora da inteligência. É tudo completamente autônomo. Agora, antes de fazer isso, há algumas coisas que você precisa ter certeza. Primeiro de tudo, certifique-se de que você não deixou nenhum caminho para o seu sistema de arquivos local dentro do seu script, certo? Então, em nossos exemplos até agora, temos nos referido a arquivos que existem em nosso sistema de arquivos local em um caminho relativo de onde nosso projeto está. Agora, no mundo real, você quer se certificar de que seus arquivos de dados estão acessíveis a qualquer nó em seu cluster pode estar executando seu aplicativo, certo? De modo geral, seus dados serão implantados como algum tipo de sistema de arquivos compartilhado. Talvez seja HDFS, talvez seja S3 da Amazon, algo assim, mas não será o sistema de arquivos local. Porque quando você está distribuindo esse código, esse sistema de arquivos local não estará necessariamente disponível para você. Então, primeiro, certifique-se de que qualquer passado para arquivos está sendo usado para um sistema de arquivos distribuído ou pelo menos para algum arquivo que esteja acessível onde quer que seu script esteja sendo executado. Então vamos empacotar nosso projeto Scala em um arquivo jar de alguma forma. E há algumas maneiras de fazer isso. Por enquanto, vamos começar apenas adicionando um artefato jar em inteligência para realmente exportar nosso próprio código de aplicativo para um arquivo jar. Isso tem limitações no entanto, se você tiver dependências em seu script além das bibliotecas do Spark, isso vai ser um problema que precisamos pensar sobre como distribuir essas dependências. E mais tarde falaremos sobre o uso da SBT para fazer isso. Na verdade, temos feito isso o tempo todo. Você só não sabia disso. E uma vez que temos um arquivo JAR, podemos usar o Spark para pedir enviar para executar esse script de driver fora do IDE. O formato é bem simples. Você acabou de digitar Spark tracejado, enviar, traço, traço classe, qualquer que seja o seu nome de classe que você deseja executar que tem sua função principal. Se você tem dependências para outros arquivos JAR, você pode usar traço, traço jar é especificar onde eles podem ser encontrados. E você também pode usar arquivos traço, traço para colocar arquivos automaticamente ao lado de seu aplicativo. Então, para pequenos arquivos que podem ser pequenos arquivos de pesquisa ou algo assim, você pode se safar com o uso de arquivos traço para isso. E, finalmente, o caminho para o próprio arquivo JAR que contém o código que você deseja executar. Então, com isso, vamos dar-lhe uma tentativa, vai realmente executar nosso exemplo Olá mundo indo caminho de volta para o início do curso usando Spark traço enviar fora da inteligência. Então eu vou te explicar como fazer isso. Então, antes de tentarmos executar nosso aplicativo Spark fora da inteligência, primeiro, precisamos de um ambiente Spark para executá-lo dentro. Então vamos configurar um ambiente independente do Spark em nosso PC desktop aqui, que simulará o mesmo ambiente que podemos ter quando estamos executando isso em um servidor na nuvem em algum lugar. Então vamos abrir nosso navegador e seguir para o faísca dot apache.org. E é aqui que você vai baixar a versão mais recente do próprio Apache Spark. Você também precisará do 7-Zip se estiver no Windows ou algum utilitário que possa descompactar arquivos tar.gz. Então, tudo bem, então se você está no Windows e você ainda não tem um utilitário que permite que você descompacte um arquivo dot tar.gz. Eu recomendo instalar 7-Zip para cuidar disso primeiro. Então, de volta ao Apache Spark. Bem, vá para Download Spark, e estamos usando o Spark 3 neste curso aqui. Então eu escolherei essa faísca liberada por agora. E queremos a versão pré-construída para o Apache Hadoop 2.7 ou o que quer que seja. E vamos bater Download Spark 3 vai usar o site espelho sugerido e esperar que isso venha para baixo. São apenas cerca de 200 megabytes, então só levará alguns segundos aqui. Uma vez feito isso, usaremos 7-Zip no Windows para descompactá-lo. Ou se você estiver no Mac ou Linux, você pode simplesmente ir para sua linha de comando e dizer, você sabe, o zip GAN usual e, em seguida, tar dash X, vf, qualquer comando que você precisa para descompactar isso. Tenho certeza de que você já está familiarizado com arquivos T, G, C se você estiver no Mac ou Linux. Tudo bem, parece que foi baixado. Então vamos para a nossa pasta de downloads e dar uma olhada nela. Desde que eu instalei 7-Zip, eu posso apenas clicar com o botão direito sobre ele e ir para 7 Zip e dizer extrair. E eu acredito, uh, como fazer isso de novo? - Sim. Então isso extraiu o arquivo zip G para um arquivo tar. Esse arquivo tar e virar também precisam ser descompactados. E aqui dentro devemos ter o próprio Spark. Vou pré-compilar para nós. Ele é construído usando Java, por isso é realmente uma plataforma independente. Assim, podemos nos safar com a frente disso no Windows na maior parte do tempo. Como você verá, há algumas falhas. Então vamos em frente e controlar um e copiar tudo isso. Controle C. E eu vou para a minha unidade C e criar uma nova pasta chamada Spark e abri-lo e copiá-lo e colá-lo lá em vez disso. E se você estiver no Mac ou Linux, é claro que você estaria apenas fazendo isso usando make dir e o comando cp para copiar esses arquivos onde quiser. Certifique-se de que se lembra onde as colocou. Tudo bem, então temos acionado 3 instalado. Não foi difícil, certo? Então vamos realmente criar um arquivo JAR e ver se podemos executá-lo usando esta nova versão do Spark que temos instalado. Então, de volta à Intel J. Vamos ver aqui. Então o que vamos fazer é ir ao arquivo e dizer estrutura do projeto. E vamos aos artefatos e clicar no sinal de mais. E vamos dizer jarra. E começaremos com um frasco vazio. Primeiro, vamos dar um nome. Vamos chamá-lo de curso desencadeado. E temos de lhe dizer o que queremos pôr neste frasco. Então vamos abrir este diretório de curso Scala disparado aqui. E você pode ver que há todas as dependências que importamos do próprio Spark em log para J e tudo de que depende. Mas como já temos um ambiente Spark instalado, não precisamos empacotar todas essas dependências. Só precisamos do código para o nosso próprio script. E isso vai viver nestas faíscas de gala curso compilar produção. Então este será o bytecode compilado do nosso código, o material real sob com ponto sol dot software ponto faísca. Então vamos em frente e clicar duas vezes nisso. E adicionamos isso ao nosso arquivo JAR. Vamos também clicar em incluir e projeto construído para garantir que ele realmente é criado. E vamos clicar em OK. E vamos clicar no ícone Construir novamente para forçá-lo a construir isso. Tudo bem, então você pode ver ao longo do caminho que é construído, ver faíscas, curso de gala fora de artefatos, Spark Core, Spark curso dot jar. Então esse é o nosso arquivo JAR que contém o nosso código. Vamos procurar por ele. Se formos ver o curso de gala do Sparks. Há nosso diretório de saída, artefatos, curso de faísca, e há jarra de pontos de cavalo de faísca. Então 399 kilobytes. Isso parece o tamanho certo para todos os compilados por código em todo o nosso projeto aqui. Isso inclui todas as aulas que temos aqui. Então vamos em frente e começar e ver se podemos usá-lo. Agora, como eu disse, você precisa ter certeza de que todos os caminhos de arquivo serão válidos ainda. Então você verá em Olá mundo, nós temos um caminho relativo aqui para dados barra m um através k barra u dados ponto. Então, para isso funcionar, preciso ter certeza de que estou executando isso do local certo onde esse caminho será acessível. Novamente, se este fosse um aplicativo real em um cluster real, eu provavelmente iria querer ter certeza de que os dados estavam em algum tipo de sistema de arquivos compartilhado em vez disso. Mas por uma questão de ilustração, rodando em nosso desktop aqui, vamos mantê-lo assim. Vamos abrir um prompt de comando. E novamente, no Mac ou Linux, basta usar um prompt de terminal. Vamos navegar até a pasta Materiais do curso. Então, para mim que C cólon barra invertida faísca curso Scala barra curso Scala faísca. E daqui temos aquele parente de datapath disponível para nós. Então isso é bom. Então agora vamos realmente executar esses sparked ask enviar comando de nosso ambiente autônomo do Spark que instalamos. Então, como você se lembra para mim, que foi C dois pontos barra invertida faísca barra bin barra faísca tracejado, enviar. O que é a próxima coisa que precisamos passar é o nome da classe que queremos executar. E então vamos dizer traço, classe de traço, com, software Dotson dogs, ponto faísca ponto olá, mundo. E agora precisamos dar-lhe o caminho para o arquivo JAR real que queremos submeter ao Spark enviar. E isso será para mim C dois pontos barra invertida, faísca Scala curso slash faísca Scala curso slash. Foram artefatos, curso de faísca, jarra de partida Spark Core. Certo, então isso deve funcionar. O que ele vai fazer novamente é pegar esse arquivo JAR do meu compilado por código e realmente passar isso para o próprio Spark usando Spark traço enviar. Ele vai procurar esse nome de classe que eu especifiquei e tentar executá-lo. E novamente, se estivéssemos em um grupo real aqui, estimada desencadearia tudo. Ele distribuiria esse código por todo o cluster. Inicie nosso Cluster Manager, faça tudo o que for necessário para distribuir isso e certifique-se de que ele realmente seja executado com sucesso. Então vamos tocar em Enter e ver o que acontece. Novamente, note que estamos fora do inteligente inteiramente aqui estamos usando um ambiente independente inteiramente diferente do Spark. Isso é bastante análogo ao que você estaria fazendo no mundo real. Certo, então temos algumas mensagens de erro assustadoras, mas ignore isso por enquanto. Se você olhar para o topo aqui, nós conseguimos nossa saída. Então diz Hello World, o arquivo de dados tem 100 mil linhas. Na verdade, funcionou. Isso é incrível. Agora, não preste atenção a essas mensagens de erro. Eu sei que isso soa realmente ondulado à mão, mas este é na verdade um bug específico do Windows no próprio Scala que tem existido desde sempre. Há um problema com permissões de arquivo realmente nos diretórios temporários que o Spark usa no Windows. E é disso que se está a queixar. No mundo real. Ninguém realmente executa trabalhos de produção do Spark no Windows, então ninguém nunca se preocupou em corrigir isso. Por isso, vamos ignorá-lo por enquanto. Se você fizer isso no Linux, você não verá que ao ampliar, você estará executando trabalhos do Spark no Linux no mundo real, mas o processo será o mesmo. Você ainda usará estimativa sparked para iniciá-lo, mesmo se você estiver em um cluster gigante, a única diferença é que ele será executado e você não receberá essas mensagens de erro estranhas sobre permissões de arquivo quando terminar. Então lá você tem ele realmente usando Spark traço enviar em uma marca chinesa spanking novo ambiente Spark usando o Spark três, usando nosso código de bytes compilado que geramos a partir da Intel J. Mas nós não estamos realmente executando dentro da inteligência mais. Então, onde nós realmente fomos além dos limites do nosso IDE, o que é importante para implantações do mundo real. 42. [de atividade em atação: Então, não seria ótimo se pudéssemos empacotar tudo o que precisamos, todas as nossas dependências e tudo em um único arquivo JAR e simplesmente distribuir isso para o nó principal do nosso cluster e iniciá-lo. Bem, isso é o que o SBT ou a ferramenta de construção simples permite que você faça. Então, vamos falar sobre o SBT em mais profundidade e como podemos empacotar seu script e todas as suas dependências juntos usando-o. Então, se você está familiarizado com Java, você pode estar familiarizado com Maven. Você pode pensar em SBT é como Maven para Scala. E o que ele faz é gerenciar sua árvore de dependência de bibliotecas para você. Então, se você tem um script que depende de alguma biblioteca Scala ou Java, algum arquivo JAR, ele irá automaticamente sair e descobrir não só onde obter isso, como empacotá-lo em seu arquivo JAR final que você está compilando. Mas também quaisquer dependências nesse pacote tem muitas vezes você tem essas árvores complicadas de dependências e esses arquivos JAR e qualquer pacote que você está dependendo, por sua vez depende de outros pacotes, que por sua vez pode depender de outros pacotes. Então, manter o controle de tudo isso à mão é que ele fica fora de controle muito rapidamente, mas a SBT vai gerenciar essa complexidade para você. Descubra automaticamente quais pacotes você precisa para que tudo realmente seja executado e junte-os para você e empacote-os. Então é isso que a SBT tem. Quatro, torna a vida muito mais fácil se você tem um monte de dependências ou se você tem uma biblioteca que tem um monte de dependências próprias, é muito mais fácil do que rastrear essas dependências manualmente. E é muito mais fácil do que passar uma tonelada de opções para o parâmetro de linha de comando dash, dash jars quando você está executando Spark enviar. Então, em vez de passar um monte de dependências específicas na linha de comando com Spark enviar. Podemos corrigi-lo todos para o próprio arquivo jar para que não tenhamos que realmente lembrar o que são e realmente inserir isso na linha de comando. Para obter SVT É gratuito, é de código aberto. Podemos obtê-lo de Scala traço SBT.org, e vamos mostrar-lhe isso em breve. Usar é bem simples. Você só tem que configurar uma estrutura de diretórios que se pareça com isso. Então, no nível superior em algum lugar, você terá um diretório de projeto onde ele irá compilar coisas e um diretório fonte que, como você pode imaginar, é onde seu código-fonte irá. Sob sua fonte, deve haver um diretório principal, e sob main deve haver um diretório de vieiras. E dentro desse diretório Scala é onde você vai colocar os arquivos Scala reais que você deseja que sejam compilados. Sbt combinará compilando isso para você e empacotando-o em seu arquivo JAR juntamente com quaisquer dependências que você especificar para usá-lo. Como eu disse, você acabou de colocar seus arquivos fonte e a pasta de origem bem simples. Coloque no lugar certo. E, em seguida, em sua pasta de projeto, vamos criar um pequeno arquivo SBT ponto assembly que contém apenas uma linha que se parecia com isso. Agora 0.14.10 pode mudar com o tempo. Isso ainda é bastante atual. Há um 15 0 lá fora agora, mas ainda não foi amplamente lançado. Então, por enquanto, vamos ficar com a versão 14 aqui do plugin assembly SBT. Mas isso é tudo que você tem que fazer. Isso só diz ao SBT que vamos estar usando este plug-in chamado assembly SBT. E seu trabalho na vida é criar aquele arquivo JAR autônomo que queremos. O verdadeiro coração disso, porém, é o arquivo de compilação do SBT. E isso é construir um ponto SBT que deve ser colocado na raiz de sua árvore de diretório SBT lá ao lado dos diretórios de código-fonte e projeto. Então aqui está um exemplo de como alguém pode ser parecido. Nós especificamos o nome do Pai, estamos criando um número de versão, o que você quiser ser. A organização associada a este pacote. A versão Scala que depende, isso é importante para acertar. Lembre-se de que diferentes versões do Spark exigirão diferentes versões do Scala. Então, neste exemplo, estamos especificando uma dependência de biblioteca de org dot apache, Spark, Spark dash core. Ok, então isso está nos dizendo que este script de filme popular que temos em Scala depende do pacote Spark Core. Do Apache Spark. E estamos especificando especificamente a versão 3 com o Spark aqui. Então, porque sabemos que disparou três requer Scala versão 2.12. É por isso que temos o Scala versão 2.12.3 lá em cima ou o que seja, você sabe, a versão mais recente pode ser que você está usando. Agora isso é importante para acertar. Por exemplo, vamos fazer o upload do nosso arquivo JAR para o serviço Elastic MapReduce da Amazon, que a partir dessa gravação ainda não suporta o Spark três, eles suportam a versão 2.4.5 do Spark, que requer Scala versão 2.11. Então, nesse exemplo, vamos especificar Spark Core versão 2.4.5 em vez de 3 e Scala versão 2.11 algo. Então você tem que ter certeza que eles combinam ou então não vai funcionar direito? Note que as dependências da biblioteca aqui é na verdade uma sequência, então podemos ter mais de uma coisa lá se tivermos apenas uma lista separada por vírgulas de linhas lá. Então, além disso, poderíamos ter acionado SQL ou bibliotecas de terceiros, mesmo seja lá o que for que você precisa para seu script para executar, você teria apenas listado aqui e, em seguida, SBT iria sair e obtê-lo e usar Africano empilhando seu código e também para empacotando isso em seu arquivo JAR final. Agora, uma coisa sobre a qual queremos falar em particular aqui é a cláusula fornecida lá. Então fornecido significa que podemos supor que esse pacote será pré-instalado em onde quer que estejamos executando isso. Então, porque eu vou estar implantando isso em um cluster que já tem o Spark instalado. Não há necessidade de eu incluir núcleo sparked dentro do próprio arquivo JAR porque isso vai estar disponível para o sistema como um todo, tudo pronto. Então, dizendo fornecido, isso significa que eu exijo este pacote para compilar meu código, mas eu não preciso empacotá-lo em meu arquivo JAR final porque ele já estará presente onde quer que eu esteja executando isso. Se você quisesse realmente incluir núcleo inteligente no próprio arquivo jar, eu deixaria de fora o fornecido e que iria agrupar tudo em um arquivo char verdadeiramente auto-suficiente. Mas desde que eu já tenho o Spark instalado de onde vou executá-lo. Não precisamos disso, podemos deixar isso de fora com a bandeira fornecida. Então, como outro exemplo, digamos que eu preciso depender de Kafka. Isso não faz parte do Spark. Eu poderia ter outra linha lá nas dependências da biblioteca que diz ou data apache dot Spark, faísca Streaming versão Kafka, qualquer que seja a versão desses pacotes que você precisa. Agora, nesse caso, eu não diria fornecido porque eu sei que não está pré-instalado no meu sistema, então eu vou estar executando a partir de. Então isso realmente iria empacotar esse jar Spark Streaming Kafka no arquivo JAR final que eu vou estar implantando e construindo no meu arquivo JAR final. Então, uma vez que você tem tudo no lugar, tudo que você tem a fazer é executar o assembly SBT a partir da pasta raiz. E vai explodir e fazer a sua magia. E ele vai desligar e compilar seus, seus scripts. Ele irá remendar tudo depois de reunir todas as dependências que ele precisa. E você vai encontrar o arquivo JAR final sob alvos último Scala traço qualquer versão do Scala que você disse para construir contra. E então você tem um arquivo jar que você pode fazer o que quiser. E a beleza novamente é que é completamente auto-suficiente. Desde que você possa obter esse arquivo JAR para o nó principal do cluster do qual você vai executá-lo. Tudo o que você tem a fazer é dizer disparado como caminho Summit para esse arquivo jar e está feito. Você não precisa especificar a classe, sem dependências JAR, nada, é isso. Então vamos tentar. Certo, então primeiro vamos rever o script que vamos realmente empacotar aqui. Então, se voltarmos para IntelliJ e procurar um filme semelhanças conjunto de dados 1M. Isso é o que vamos empacotar aqui e, finalmente, enviar para o Elastic MapReduce da Amazon para realmente executar em um cluster real. Então vamos ver o que é diferente aqui. Não muito, mas há algumas coisas para falar aqui. Em primeiro lugar, para o arquivo DAT de ponto de filmes, observe que estamos passando isso como um caminho específico para filmes dot dat. Isso vai ser esperado para ser ao lado de onde estamos executando Spark enviar, vai assumir que esse arquivo está presente lá no sistema de arquivos local. Agora, como falamos antes, isso não é um grande plano. Como se você tem um sistema de arquivos distribuído onde você pode obter isso, isso vai ser melhor. Mas no nosso caso, filmes dot dat é um arquivo bem pequeno. Então podemos colocar isso em torno de nós mesmos sem um monte de problemas. No entanto, de um modo geral, você gostaria de ter isso em algum tipo de sistema de arquivos distribuído, em vez de confiar que esse arquivo esteja presente em todos os lugares onde você vai executar esse script. Estamos, no entanto, certificando-se de que temos o ponto de classificação arquivo DAT em um sistema de arquivos muito maior aqui. Então isso vai ser na Amazon tem três, Isso é o que o prefixo S3 n lá se refere. Então, hum, então eu tenho um bucket S3 chamado Sun dog does faísca que contém o arquivo de dados de ponto de classificação dat lá. E porque isso é realmente big data per se, bem, realmente Nós poderíamos gerenciar isso em uma única máquina, mas para conjuntos de dados maiores como esse, você geralmente quer ter isso em algum tipo de sistema de arquivos distribuído com certeza. Então, nesse caso, tivemos o trabalho de garantir que ele está disponível no Amazon S3. E não vamos supor que isso esteja no sistema de arquivos local. Agora, este é um formato um pouco diferente do que vimos antes para os conjuntos de dados de 100 K. Então vamos falar um pouco sobre isso também. Vamos ao Grouplens.org. E se formos para conjuntos de dados, podemos aprender mais sobre esse conjunto de dados específico de 1 milhão ou há um conjunto de dados agora para, bem, se você realmente quiser big data, mas há um que estamos usando neste exemplo. Então, se você for para Read Me dot text, ele informa sobre o formato do arquivo com mais detalhes. Vamos rolar para baixo. Portanto, a descrição do arquivo de classificações, por exemplo, está dizendo que o formato é ID de usuário, ID de filme, classificação, carimbo de data/hora, mas neste caso não é separado por tabulação. Na verdade, está separado por esses pares de Coleman. Então é importante perceber. Também as informações do arquivo de filmes é importante saber também que é delimitado por dois pontos pouco incomum. Por isso, tem de se certificar de que compreende o formato com o qual está a lidar antes de escrever o seu código. Se voltarmos à inteligência, podemos ver que especificamos o cólon duplo como separador em ambos os casos. E nós estamos especificando o conjunto de caracteres para os nomes dos filmes também. Isso também é ISO 8859 traço um. Então essa é uma diferença, apenas o formato e o caminho que estamos usando para esses arquivos de dados para o conjunto de dados MovieLens 1 milhão, estamos mudando para o conjunto de dados de 1 milhão aqui apenas para ilustrar realmente operando em big data. Então esta é uma mediana de tarefas em fazê-lo em uma única máquina pode ser um desafio. Então, estamos a lidar com isso agora. Quanto ao que mais é diferente? Bem, não muito. O resto do código é praticamente o mesmo. Então nós só tínhamos que ter certeza de que estamos recebendo nossos dados do lugar certo, que eles estão no formato certo. E além disso, é praticamente o mesmo código que vimos no exemplo de conjunto de dados de semelhanças de filmes no início do curso. Então vamos fechar isso agora que terminamos de falar sobre isso. A primeira coisa que precisamos fazer é baixar o próprio SBT. Então, se você cabeça para Scala traço SBT.org. Você deve ver um botão de download em algum lugar. Tenho certeza que este site vai mudar com o tempo, mas espero que você possa encontrá-lo. Para Windows. Há um instalador do Windows, então vamos em frente e pegar isso. Se você está no Linux ou Mac OS, você pode obter um pacote auto-suficiente aqui a partir de qualquer arquivo zip ou formato TGC, o que você preferir. E você pode apenas descomprimir isso e acabar com isso. Você encontrará o executável SBT lá dentro. Se você está no Ubuntu e você prefere usar um gerenciador de pacotes, você pode ir para a documentação de um Scala SBT e ele irá dizer-lhe sobre isso. Basta ir para este link aqui e que irá orientá-lo através de como se certificar de que você tem o repositório certo no lugar e como instalá-lo usando app.get. Mas eu estou no Windows, então eu vou apenas executar o instalador do Windows e terminar com isso. Sim, sim, eu sei. Corra mesmo assim. Esta caminhada através dela. E o bom é que eles devem colocar a SBT no meu caminho para mim para que eu não tenha que me preocupar com onde Deus instalou dois. Tudo bem, então isso é fora do caminho. Em seguida, vamos realmente obter nossos diretórios SBT para que possamos adicionar algo para empacotar. Então, se você cabeça sobre a mídia http, cães Dotson, traço, soft.com barra faísca, Scala barra barra SPT dot zip. Ok. Vá em frente, pegue isso e descomprima. No entanto, você descompacta coisas em seu sistema operacional. E você deve ter uma pasta SBT que se parece com isso. Então vamos levar isso para um lugar onde não o perderemos. Vou cortar isso e vamos colocar na minha unidade C. Tudo bem, então agora temos uma pasta SBT e se olharmos no conteúdo dela, vemos o que esperamos ver, bem ali está o diretório do projeto. E dentro do diretório do projeto é assembly não SBT. Vamos examinar isso. E ele contém aquela linha que falamos anteriormente, apenas especificando que vamos usar o plug-in de montagem SBT com essa versão. E sob o diretório fonte, temos um diretório principal e um diretório acadêmico que contém as semelhanças do filme. Um arquivo de ponto de conjunto de dados m Scala que acabamos de olhar. E, finalmente, no diretório superior aqui temos nosso arquivo SBT ponto de construção mágico. E se examinarmos isso, podemos ver que temos um nome que corresponde ao nosso ClassName, qualquer número de versão que queremos dar a ele, nome da nossa organização, a versão Scala da qual dependemos, e as versões do Spark Core e Spark SQL de que dependemos para este script. Agora, novamente, neste exemplo no Amazon EMR, eles estão na versão 2.4.5. Então isso é o que eu especifiquei aqui porque é onde eu vou estar implantando isso no final. E eu sei que o Spark 2.4 depende da versão Scala 2.11. Então esse é o método para toda essa loucura. E, novamente, observe que estou dizendo fornecido porque sei que o Spark Core no Spark SQL será pré-instalado no meu cluster do Amazon EMR. Não preciso agrupar o Spark em meu arquivo JAR final. Agora este é um exemplo desinteressante porque eu não tenho nenhuma dependência de terceiros aqui. Então, no final, tudo o que eu realmente vou empacotar é o arquivo JAR para o meu script em si. Mas isso vem em grande uso se você tem uma árvore de dependência mais complicada, certo? Então, por exemplo, não estamos fazendo nada super complicado, mas é assim que você gerenciaria suas dependências se você tivesse um pacote de terceiros que não foi pré-instalado em seu sistema. Você vai executá-lo a partir de. Apenas liste esses aqui. Além disso, certificando-se de que é separado por vírgula e você não diria fornecido naqueles específicos onde você quer que ele seja empacotado. Então vamos ver se funciona. Vamos abrir um prompt de comando, e farei isso com permissões de administrador apenas para garantir. Então, se eu ir para baixo e janelas, que seria sob o prompt de comando do sistema Windows, eu vou clicar com o botão direito do mouse sobre isso, dizer mais executar como administrador. E vamos navegar para aquela pasta SBT. Lá está ele. Agora podemos apenas digitar a montagem SBT. E fora deve ir. E nós vamos realmente precisar sair e recuperar um ambiente Scala e Apache Spark e tudo o que ele precisa para realmente compilar isso. Então é meio mágico como a SBT pode ter todo esse ambiente autônomo que constrói do zero. E lá temos. Então parece que foi bem sucedido. Vamos dar uma olhada e ver o que temos aqui. Então, se formos e aqui temos agora um diretório de destino. Vamos ver o que temos lá dentro. E há um diretório esqueleto 11 e lá dentro está o nosso arquivo JAR. Muito legal. Então é como se ele funcionasse semelhanças de filmes quando eu sou conjunto de dados traço, traço 1 ponto jar, apenas sentado lá esperando por nós para usá-lo. Então, na nossa próxima palestra, vamos usá-la. 43. [Exercício em uma Script com SBT e de o execute de o de o seu de presente: Ok, Então, neste momento eu ensinei você como usar Spark enviar em uma instalação local do Apache Spark para executar seus scripts. E eu também te mostrei como usar o SBT para agrupar seu script em um arquivo JAR autônomo. Então seu desafio é juntar essas duas coisas. Eu quero que você use sbt para agrupar um arquivo JAR e, em seguida, executá-lo localmente usando Spark das enviar em sua área de trabalho local. E a estratégia aqui, escolha qualquer script que você quiser. Eu realmente não me importo, mas eu vou escolher o script do conjunto de dados de temperaturas mínimas. Realmente não importa com qual você quer jogar. E o que você vai ter que fazer é modificar o arquivo SBT de compilação em sua árvore de diretórios SPT e certificar-se de que você está usando a mesma versão do Spark que você instalou localmente para usar o Spark enviar. E também precisamos ter certeza de que estamos usando uma versão compatível do Scala para essa versão do Spark. Então isso vai envolver fazer um pouco de pesquisa online. Você vai ter que descobrir qual versão do Spark você está usando e qual versão do Scala é compatível com essa versão do Spark. E uma vez que você tenha feito isso, além disso, você precisa descobrir qual é a versão atual do Scala para essa grande revisão do Scala. Então eu não quero te dar muita orientação aqui porque ser um desenvolvedor no mundo real é geralmente sobre fazer esse tipo de pesquisa você mesmo e descobrir novos problemas. Você não vai ser capaz de ir até o seu chefe ou seus colegas para descobrir essas coisas para você. Quero dizer, você pode, mas eles vão achar isso muito irritante e você provavelmente não vai durar muito se fizer isso o tempo todo. Quero que pratique um pouco e resolva isso sozinho. Uma vez que você tenha, é deve ser apenas uma questão de certificar-se de que seu script está no lugar certo na árvore de compilação para sbt. E também certificando-se de que você tem o ponto Bill SBT correto montado para a versão certa do Spark e Spark Submit. Nesse ponto, podemos apenas usar o assembly Spark para construí-lo e certificar-se de que executamos Spark enviar a partir do diretório que o script assume. Como você se lembra, a maioria de nossos scripts pressupõe que existe um diretório de dados local que conterá os dados que queremos no sistema de arquivos local. Então precisamos ter certeza de executar esse script a partir do lugar certo onde esse subdiretório de dados existe. E com isso, vá e dê uma chance. E no próximo vídeo, eu vou te explicar como eu fiz isso. 44. Solução de exercício: usando o SBT e o de spark-submit: Então deixe-me explicar como eu fui sobre empacotar o script de conjunto de dados de temperaturas mínimas usando SBT e executá-lo localmente usando Spark enviar fora da inteligência. Então, a primeira coisa que você sempre quer fazer é dar uma olhada no script antes de empacotá-lo e ter certeza de que não há nada lá que você precise alterar antes de executá-lo em um ambiente diferente, certo? Então, em primeiro lugar, note que estamos usando a estrela local. Agora, se eu estava realmente executando em um cluster real, eu provavelmente quero tirar isso porque em um cluster eu quero estar usando cada núcleo e cada máquina no meu cluster, não apenas a máquina local em que eu estou executando o script do driver mas desde que minha intenção é ainda executar isso apenas no meu PC local que pode permanecer inalterado neste caso. Preste também atenção aos caminhos dos arquivos. Isto é assumindo que estamos indo para barra de dados 8800 ponto CSV para o nosso arquivo de dados lá. E isso implica que eu vou ter que ter uma pasta de dados no meu sistema de arquivos local que está ao lado do mesmo local onde eu estou invocando este script usando Spark submit. Então eu poderia mudar isso para um caminho absoluto se eu quisesse. Eu poderia mudar isso para um sistema de arquivos compartilhado, se eu quisesse. Mas novamente, já que eu estou apenas executando no meu sistema de arquivos local, eu apenas vou me certificar de que eu me lembro de executar isso junto com a pasta de dados onde eu já tenho instalado. Então eu não vou realmente mudar nada aqui, mas você sempre quer estar ciente desses tipos de problemas antes de empacotar um script que você está jogando localmente e enviá-lo para você em outro lugar, Seria realmente horrível se eu me esquecesse de tirar aquela linha mestre ali, certo, e realmente enviá-la para um aglomerado. Eu tinha um grupo enorme e eu não estaria aproveitando disso em tudo nesse caso. Então sempre tenha cuidado com esse tipo de coisa. Então vamos começar com a parte fácil. Vamos copiar esse script em si e colocá-lo no SBT. Então vamos minimizar isso no meu curso Spark Scala, vamos encontrar esse arquivo. Está sob fonte, Scala com, software para cães, uma faísca. E o que era? Conjunto de dados de temperatura min, pontos, vieiras, Eu vou em frente e copiar isso. E vá para o meu diretório SBT e vá para o Scala principal fonte. E eu vou colar isso aqui e remover as semelhanças do filme 1 milhão de arquivo de conjunto de dados que usamos na atividade anterior. Então agora eu preciso ter certeza de que eu estou usando a versão certa do Spark e a versão certa do Scala para que isso seja capaz de ser executado localmente no meu ambiente local Spark. Então vamos voltar para o topo do SBT aqui e eu vou editar esse projeto de lei não SBT arquivo, usar o editor que você quiser. Para mim, tenho algo chamado Bloco de Notas Plus, Plus instalado. Qualquer coisa funciona, certo? Qualquer editor de texto fará o trabalho aqui. Então precisamos especificar qual versão do Spark estamos usando e qual versão do Scala. E estes precisam ser compatíveis, não apenas uns com os outros, mas também com o que você instalou para o Spark em seu sistema local. Note que estamos dizendo que a faísca em si é fornecida, por isso não vai empacotar o próprio Spark em nosso arquivo jar resultante. Ele vai usar qualquer versão do Spark presente no meu sistema de arquivos aqui. Então eu preciso ter certeza que isso está construindo contra a versão correta do Spark. Vamos começar com isso. Então vamos voltar para a minha instalação de faíscas e verificar novamente. Então eu instalei o faísca em ver o faísca. E se eu olhar para a versão TextFile lá, ele me diz que estou usando o Spark 3. Ok, então essa é uma peça do quebra-cabeça. Vamos voltar para o meu arquivo SBT em SBT. E vamos mudar o Spark Core para 3. E como eu estou usando conjuntos de dados, eu preciso do pacote Spark SQL também. Então vamos deixar isso lá também. E você também quer pensar sobre quais outras dependências você tem dentro do próprio Spark neste ponto ou fora de uma faísca. E neste caso, não há mais. Mas se eu estivesse empacotando, digamos, um script de aprendizado de máquina, talvez eu queira incluir o Spark ML, arquivos de streaming do Spark fazendo algum script de streaming de tela. Portanto, certifique-se de que você tem quaisquer dependências que você precisa lá. Certo, agora precisamos descobrir qual versão do Scala é compatível com essa versão do Spark. Então, para fazer isso, requer um pouco de pesquisa. Vamos acionar um navegador da web. E eu trarei uma janela de nucleon aqui. Então vamos para faísca dot apache.org. E se olharmos para Spark três pontos, Oh, vá para a área Download Spark aqui, e podemos ver que ele nos diz aqui qual versão do Scala é compatível com, qual versão do Spark. Então ele diz não, que faísca para ponto x é pré-construído com 2.11 exceto para a versão 2.4.2, que é construído com esqueleto 12. Mas faísca de três pontos Oh, isso é nós é pré-construído com Scala para 0.12. Ok, então eu sei que eu preciso do Spark versão 2.12. Isso é específico o suficiente? Bem, vamos olhar. Eu quero uma versão menor também. Está bem. Bem, vamos mudar o 11 para 12, mas o que vem depois do 12? Eu não sei. Vamos fazer mais uma pesquisa. Então, de novo, você meio que tem que ser engenhoso às vezes. Então vamos apenas procurar Scala para 0.12 e ver se podemos descobrir qual é a versão atual do que é. Parece que isso me aponta para escalar um line.org tracejado, que é a casa oficial do Scala. E embora eu não queira, parece que 2.13 está realmente fora, mas novamente, eu preciso usar 2.12 para essa versão do Spark. Vamos ver se as notas de lançamento me dizem alguma coisa. Está bem. Então, aparentemente, a versão mais recente do 2.12 é 2.12.12. Tudo bem, vamos com isso. Então, de volta ao meu arquivo SBT build, vamos especificar 2.12.12 e eu vou salvar isso. Neste ponto, devemos estar prontos para empacotar isso. Vamos em frente e abrir um prompt de comando. Limpe um pouco as coisas aqui. Então vamos ver. Vou ao menu Iniciar. Claro, no Mac ou em um Linux, você simplesmente abriria um terminal. Não é grande coisa. Isso será no prompt de comando do sistema do Windows e queremos executar isso como um administrador apenas para ser seguro. Tudo bem, então vamos navegar até a pasta SBT. E vamos apenas digitar na montagem SBT. E espero que faça a coisa certa. Ok, fez algo parecido com um construído contra o esqueleto 0.12. Então isso parece certo. Vamos ver se temos o arquivo jar resultante. Vamos para alvos esqueleto 12. Esqueci-me de mudar o nome. Tudo bem, tudo bem. Bem, vamos voltar ao SBT e editar o arquivo Bill dot SBT novamente. Esqueci-me de mudar o nome. Então realmente isso deveria ser o que era essa coisa novamente, conjunto de dados de temperatura Min. Tudo bem, vamos fazer de novo. Deve ser mais rápido agora que baixou todas essas dependências. Muito bem, vamos ver o que temos agora. Alvo Scala para 12. Lá está ele, montagem de dados de temperatura min traço 1 O. Então vamos copiar isso e colocá-lo ao lado desse diretório de dados onde eu quero executá-lo a partir. Então Control C, obviamente você poderia usar o comando cp de um prompt de comando se você quisesse também. E vamos para o curso de gala do Sparks. E lá dentro, há o diretório de dados que ele assume que é local relativo ao script. Vamos em frente e colar isso aqui. E agora deve ser capaz de navegar até lá e você executá-lo com Spark enviar. Então vamos mudar nosso diretório para ver faíscas curso de gala barra curso Spark Scala. E vamos começar com Spark enviar e ver o que acontece. Então faíscas envia caminho estava sob a caixa de faísca C, mesa de faísca enviar. Certifica-te de que está lá, está bem? E nós devemos ser capazes de passar em Min temperatura conjunto de dados traço traço 1 ponto char. Só estou usando a tecla Tab para completar automaticamente isso. E deve funcionar. E obtivemos um monte de erros no desligamento. Mas, novamente, isso é normal. Isso é uma coisa do Windows. Nós realmente obtivemos nossa saída embora. Então, olha, funcionou bem. Temos a temperatura mínima para aquelas duas estações meteorológicas. E temos uma embalagem bem sucedida de que é bom com SBT e executá-lo localmente usando Spark mesa enviar tendo cuidado com a versão do faísca que tínhamos instalado e a versão do Scala que, essa versão do A faísca depende disso. Então, espero que você tenha tido algum sucesso com isso também. Se não, eu acho que assistir este vídeo provavelmente mostrou onde as coisas deram errado. Então volte e tente novamente se precisar. E com isso, vamos continuar. 45. Introduzindo o Amazon Elastic: Então, no momento que estávamos esperando, vamos realmente executar nosso script de classificação de 1 milhão de filmes em um cluster real usando a superfície Elastic MapReduce da Amazon e o Hadoop. Muitas palavras de zumbido lá. Vamos falar um pouco mais antes de o fazermos. Vamos falar sobre como o Spark distribuído realmente funciona. Portanto, os mesmos scripts que você tem usado para executar esses trabalhos do Spark localmente em seu próprio PC podem ser usados em um cluster sem muita modificação. Então, cabe ao Spark enviar e ao próprio Spark descobrir qual gerenciador de cluster você está executando. E isso pode ser o gerenciador de cluster interno do faíscas. Pode ser o fio do Hadoop, pode ser o Mesos. E integre-se com isso para realmente distribuir o trabalho de todos os seus mapeadores e redutores, bem como um CAN em todo o cluster que você tem disponível para você. Basicamente, o script do driver do Spark está sendo executado em seu nó principal, seu driver, certo? E isso se comunica com seu gerenciador de cluster para realmente distribuir o trabalho que está no script do driver para diferentes nós executores, ok? E o gerenciador de cluster é responsável por lidar com falhas de nós individuais e clicar nos resultados novamente juntos para retornar ao script de driver quando isso for feito. Agora, alguns outros parâmetros Spark Summit que devemos falar. E primeiro devo notar que em muitos clusters, muitas dessas configurações serão pré-configuradas para você automaticamente. Então, se você não especificar nada em seu script explicitamente para o que o mestre será ou se ele não está sendo especificado na linha de comando. Há também um arquivo de configuração dentro do Spark que pode ser configurado para definir todas essas coisas automaticamente. E, por exemplo, se você configurar um cluster na Amazon, Elastic MapReduce, muitas dessas coisas serão configuradas para você e não da maneira ideal já. Mas, às vezes, deparamos com problemas em que as coisas não se completam. Você fica sem recursos, as coisas começam a diminuir o tempo e você precisa ajustar essas coisas um pouco para que as coisas funcionem de forma mais confiável para que você precise saber que elas existem. A primeira opção que não queremos falar é traço, traço mestre. E isso não é algo que você possa ajustar. É apenas teste para ser definido para a coisa certa para o tipo de cluster que você tem. Então, se você estiver executando em um cluster do Hadoop e quiser aproveitar o gerenciador de cluster do fio do Hadoop que será definido como yarn. Se pretender utilizar o cluster autónomo do Spark, defina-o como o nome do anfitrião e a porta do nó principal no cluster do Spark. Mesos funciona de forma semelhante. E novamente, se você tem uma faísca conf ou qualquer coisa em seu próprio script que substitua isso. Ignorará o que está na linha de comando. Então a hierarquia é o que está em seu script, águas na linha de comando e vencedores nos arquivos de configuração para faíscas. Portanto, nunca se esqueça de verificar novamente seus scripts para se certificar de que você não é difícil codificar um determinado mestre. Por exemplo, se você tiver essa estrela de colchetes locais, isso substituirá a opção mestre aqui. E se você executasse esse script em um cluster, eles não aproveitariam o cluster completo. Quanto ao gerenciamento do uso de recursos em seu cluster, há opções para isso também. Um executor especificará quantos nós executores você deseja usar. Por padrão, são apenas dois. Portanto, se você estiver executando em um cluster maior que tenha mais de dois nós, será necessário aumentar essa configuração. Mais uma vez, geralmente isso será definido para você por outra pessoa, pela administração, mas algo para estar ciente e ter certeza de que isso está de fato definido em algum lugar. A memória do executor gerencia a quantidade de memória disponível para cada executor. E, claro, você quer ter certeza de que isso não excede a memória física disponível para cada nó executor individual. Se você estiver executando em um cluster na Nuvem, essas são muitas vezes máquinas virtuais que têm menos memória do que você imagina. Portanto, certifique-se de que você está ciente da memória disponível para o seu script em cada executor. E você também pode olhar para o total de núcleos de executor. Se você tiver multicores em seus nós virtuais, então você pode querer ajustar isso para realmente colocar um limite superior em quantos núcleos seu script pode consumir. Ok, Amazon Elastic MapReduce, então é isso que vamos usar neste curso. É uma maneira rápida e fácil de girar um cluster Hadoop e você pode realmente dizer-lhe para o Spark pré-instalado nele como para você também, com tudo configurado automaticamente. Então maneira muito fácil de começar e executar seu script em um cluster real onde você apenas alugar tempo e pagar pelo que você precisa. E isso é meio que toda a premissa da Amazon Web Services. Basta escrever tempo e pagar pelos recursos de computação que você realmente precisa para o que estiver fazendo. Então você é cobrado basicamente pela instância de hora, quanto tempo você está gastando em quantos computadores de um determinado tipo. você também será cobrado por qualquer E/S de rede qualquer espaço de armazenamento e qualquer E/S de armazenamento também. Então você paga pelo que usa. E geralmente não é muito. Acho que gastei cerca de 30 dólares e, na verdade, juntei este curso em termos de cobranças da AWS. Mas tenha cuidado. Eu recomendo apenas me ver fazer isso por enquanto, a menos que você tenha uma conta corporativa ou algo que não seja seu dinheiro em jogo. Porque se você errar, é muito fácil esquecer de encerrar seu cluster quando terminar. E se você fizer isso, seu cluster continuará sendo executado para sempre, mesmo que você não o esteja usando. E você vai ser construído para todo esse tempo quando você pode nem perceber até que você veja uma cobrança de cartão de crédito de US $1000. Não quero que isso aconteça com você. Não quero ser responsável por isso. Então, sabe, se quiser brincar com a RM, lembre-se de terminar seus grupos quando terminar. Se não o fizeres, as tuas contas bancárias não vão gostar de ti e não vais gostar de mim, por isso não vás lá. Está bem. Então, com isso, vamos falar sobre realmente correr em um cluster, falando sobre alguns desses pontos já. Mas, novamente, o que o EMR configura para você é um cluster Hadoop e você pode executar o Spark sobre o componente de fio do Hadoop. Então as pessoas meio que misturam Hadoop e Hadoop fios. Às vezes ouço falar de muitas pessoas sobre como o Spark é mais rápido que o Hadoop, mas não é realmente um ou outro. Está bem? O que eles realmente querem dizer é que o Spark é mais rápido do que o MapReduce, que é uma maneira de executar trabalhos distribuídos no Hadoop. Mas o próprio Hadoop é apenas uma tecnologia para gerenciar um cluster. E um componente do Hadoop é yarn, o Cluster Manager, que faísca pode ser executado em cima de muito bem. Ok, então lembre-se as diferentes partes como um driver Spark é um gerenciador de cluster e, em seguida, há o hardware real em si. Hadoop só está preenchendo aquela pequena peça do meio para você. Então Hadoop e Spark não são mutuamente exclusivos, que é um equívoco comum. Está bem? Uma outra coisa que eu quero apontar em termos de práticas recomendadas, porque executar em um cluster real é caro. Estes são recursos caros que você está lidando aqui potencialmente, você sempre quer ter certeza de que está fazendo seu desenvolvimento e testes localmente em seu próprio PC primeiro, ok? Ou algum computador desktop ou algum computador que você tenha acesso a você que não custe muito dinheiro. E uma maneira de fazer isso muitas vezes é usar um subconjunto de seus dados apenas para desenvolver com. Então, se você estiver lidando com um grande conjunto de dados que você só pode gerenciar em um cluster, considere usar apenas uma parte desse conjunto de dados para desenvolver e testar a largura. E dessa forma é mais provável que você tenha uma execução bem-sucedida quando estiver realmente alugando tempo no próprio cluster, você realmente deseja minimizar o tempo que você está trabalhando no cluster, se possível. Ok, então, em termos de configuração, você precisa começar criando uma conta da Amazon Web Services. E eu vou assumir que você pode descobrir como fazer isso. Mais uma vez, só quero que me veja fazer isso agora. A próxima etapa será criar um par de chaves do EC2 para que você tenha a capacidade de realmente fazer login no seu cluster depois de girá-lo de forma segura. E você vai precisar de uma maneira de entrar nessa máquina virtual real em algum momento usando algo como putty no Windows, você precisa de algum tipo de terminal para poder se conectar a essas máquinas e executar seu script e baixar as coisas que você precisa para eles. Então vamos começar e realmente ver como ele funciona. 46. Crie filmes semelhantes de um milhão de classificações no EMR: Então vamos fazer isso. Vamos realmente gerar semelhanças de filmes com base em 1 milhão de classificações de filmes de usuários e fazê-lo de verdade. Então, basta seguir aqui e mostrarei como ele funciona usando o serviço Elastic MapReduce da Amazon. Agora, para configurar as coisas, eu já carregei algumas coisas no serviço S3 da Amazon, que é basicamente um armazenamento de arquivos distribuído no qual você aluga espaço. Certo, tipo HDFS, mas é a versão da Amazon. Uma maneira de pensar sobre isso. Então eu já criei o que é chamado de bucket no S3 chamado Sunday August Spark. E enviei algumas coisas que vou precisar. Um é as semelhanças do filme, um M Jar, arquivo Jar. E esta é a mesma coisa que eu gerei usando SBT no início do curso. Eu só dei um nome de arquivo um pouco diferente. Então ele tem meu script de driver Spark autônomo empacotado em um arquivo jar. Ok, então isso vai ser no S3. Assim, eu posso copiá-lo rapidamente para o meu cluster depois de dividir meu cluster para executá-lo. A outra coisa que eu fiz é que eu movi o MovieLens 1 milhão de dados de classificação para aqui também. Então eu criei uma pasta MNL traço 1M aqui no meu filho morreu inteligente S3 bucket. E isso vai garantir que este sistema de arquivos distribuído do S3 que contém minhas classificações de 1 milhão de filmes também esteja acessível a todo o meu cluster. E dentro disso temos os diferentes arquivos que compõem as classificações do conjunto de dados. Dot dat é a própria classificação de filmes e filmes dot dat é todos os metadados associados com os filmes reais. Então nossa estratégia, se você se lembra, vai ser executar esse arquivo JAR do nó principal do nosso cluster. E vai ter filmes dot dat localizado ao lado dele. Então, ele pode realmente construir essa tabela de pesquisa de IDs de filmes para nomes de filmes quando está produzindo os resultados. Mas tudo o que o cluster precisa são os dados de classificação. Então vamos montar as coisas e fazer um cluster. Então, temos o nosso bom brilhante MovieLens 1 milhão arquivo JAR pronto para implantar em nosso cluster. Mas primeiro precisamos de um cluster para implantar um dois e criar um. Vou usar o serviço AWS Elastic MapReduce para fazer isso. Agora isso custa dinheiro. Então, se você não gosta de gastar dinheiro ou não tem uma conta da AWS, você provavelmente só quer assistir aqui e não realmente acompanhar você mesmo. Ok? Mas eu já tenho uma conta da AWS e um pouco de orçamento para jogar. Então eu vou ir em frente e clicar no EMR aqui ou apenas digitar Elastic MapReduce e encontrar serviços. E vá em frente e crie um novo grupo aqui. Então vamos criar um novo cluster e vamos chamá-lo de faísca Scala divertido. Não sei, ligue para o que quiser. E vamos dizer aqui que estamos usando a versão mais recente do EMR. Isso não é um beta, pelo menos. E isso vai usar o Spark. Queremos selecionar o aplicativo Spark aqui. E você pode ver que agora eles estão oferecendo o Spark 2.4.4. Ainda não tiveram coragem de criar uma faísca três. Mas quando estiveres a ver este vídeo, talvez isso também seja uma opção. Mas é por isso que empacotamos nossos arquivos JAR especificamente para Spark 2.4.4 e Scala para 0.11. Porque sabíamos que isso é o que este cluster vai ter instalado nele. Para configuração de hardware, podemos manter os padrões aqui. Isso realmente vai girar um cluster Spark de três nós. Normalmente, é o Spark em execução em cima do Hadoop, e isso será tudo m5 próximas Instâncias Grandes. As coisas não são baratas, não são Frigyes. Então, mesmo que você seja como uma nova conta onde você está falando sobre nível gratuito. Este não é um hardware de nível gratuito. Então, novamente, isso custou dinheiro real para girar, me custou cerca de 30 dólares para fazer isso quando eu estava fazendo todos esses exercícios juntos. Então, novamente, se isso te deixa enjoada, não faça isso, apenas assista. Você também precisa especificar um par de chaves do EC2. Já criei um que se chama Sun dog EC2. E se você precisar criar um novo, basta seguir esse link para saber como criar seu próprio par de chaves EC2 novo. Então você obtém uma chave pública e uma chave privada que você pode usar para realmente se conectar a este cluster mais tarde, você precisará disso para realmente entrar no nó principal e realmente iniciar o script. As permissões padrão estão bem. Vamos em frente e pressione Create Cluster. E lá vai. Então isso vai explodir e provisionar todo o hardware que precisamos dele. Vamos demorar alguns minutos para realmente obter esse hardware e ter tudo configurado e inicializado nele. Então, voltamos quando isso terminar de ser configurado. Ok, então depois de cerca de cinco ou dez minutos, vemos que agora temos nossas máquinas mestre e núcleo no estado funcionando aqui. E o meu grupo está à espera que eu faça alguma coisa. Tão legal, meu grupo está pronto. Então vamos fazer alguma coisa com isso. Para fazer isso primeiro, preciso me conectar a ele de alguma forma. Então você pode ver aqui sob o DNS público mestre SEC me dá o endereço disponível externamente do nó principal. Então eu vou executar o meu script de. E se eu clicar neste link SSH, ele dirá exatamente como se conectar a ele. Assim, para o Windows você pode usar algo chamado massa para um programa de terminal. É isso que estou usando. E se você precisa instalá-lo, Há um dandy útil baixar o link lá para você. E diz exatamente como se conectar. Usando isso. Se você estiver no Mac ou Linux, eles também têm instruções para você. Mas estou no Windows. Então o que vamos fazer é copiar esse endereço para que eu possa rapidamente colocá-lo lá dentro e abrir a massa. Digite isso para o nome do host. E então eu preciso especificar meu arquivo APK, minha chave privada para realmente fazer login nele. Então lembre-se, eu especifico enquanto eu estava configurando um cluster que eu iria usar a chave Sun dog EC2. E é aí que eu guardo esse arquivo lá. Então agora eu devo ser capaz de apenas apertar Open. E lá estamos logados em nosso nó principal. Agora, dependendo de suas configurações de segurança, você pode realmente obter um tempo limite neste momento. Portanto, se você estiver tentando descobrir por que não consegue se conectar, não importa o que você tente com as configurações do firewall ou sempre que você ainda não conseguir. Azar está bloqueado no lado do servidor. Então, se você encontrar essa dica rápida, você pode clicar no grupo de segurança aqui para o nó principal. E uma vez que você estiver lá, você pode clicar nas regras de entrada aqui e certificar-se de que você tem uma porta SSH aberta. Então, neste caso, eu tinha que realmente adicionar manualmente uma porta SSH TCP para a porta 22 para o endereço IP do qual eu estou conectando. Então, se você está tendo problemas para se conectar, isso é provavelmente o que você precisa fazer. Mas vamos voltar para onde estávamos, para o console EMR. E de qualquer forma, agora estamos logados. Agora podemos começar a fazer coisas divertidas. Primeiro, vamos ver onde estamos. Devemos ter um pequeno diretório home aqui sob o usuário do Hadoop. Primeiro vou fazer é copiar nosso script de driver real no arquivo jar que criamos usando o SBT anteriormente. Então vamos em frente e copiar isso do S3, EMR e AWS EC2 nó tem um conjunto de utilitários incorporados chamado AWS que você pode usar para realmente copiar coisas do S3. E coisas. Então eu posso digitar na AWS, S3 , CP, Vamos ver, s3 cólon barra barra, Sun dog. Não posso dizer a um parque de cães. E como é que eu chamei o ficheiro de novo? A semelhança de filmes é um jarro de ponto m. As semelhanças um m ponto char aqui. Tudo bem, e você pode ver que funcionou. A outra coisa que eu preciso é do arquivo DAT do ponto de filmes. Então eu posso realmente fazer a construção da tabela de pesquisa que IDs de filme para nomes de filmes. E novamente, eu coloquei isso na pasta ML traço um m sub. Então vamos copiar isso também. AWS S3 copiar s3 dois pontos barra barra, faísca barra ML traço 1M barra filmes se adaptaram ao diretório local. Então, lá temos. Muito bem, expandi um pouco a janela aqui para podermos ver melhor os nossos resultados. E tudo o que preciso fazer agora é digitar Spark dash, enviar o nome do arquivo jar, semelhanças de filmes, um jarro de ponto m. E se você se lembrar direito, esta escritura requer um parâmetro de linha de comando do ID do filme que estamos interessados em encontrar semelhanças para. Então acontece que eu sei que Star Wars é 260 no conjunto de 1 milhão de dados. Vamos dar um pontapé. Certo, então vemos algumas mensagens introdutórias aqui. E uma das primeiras coisas que o script faz é desativar qualquer coisa, exceto mensagens de erro. Então não devemos ver nada além mensagens de progresso, pois ele realmente quebra isso e espalha para o cluster. Então, estamos basicamente esperando que ele obtenha o primeiro comando de ação e crie o DAG. Acabei de carregar os nomes dos filmes e agora está espalhando. Agora, enquanto falamos, estamos computando filmes similares para Star Wars usando 1 milhão de classificações em um pequeno grupo de três máquinas. muito legais. Já estamos no estágio 2 e lembro que os estágios são divididos por áreas do DAG que são divididas por operações embaralhadas de dados. E essas etapas, por sua vez, são divididas em tarefas. Então você pode ver agora aqui no estágio dois onde chugging através de 32 tarefas, haverá outro estágio depois disso com um 100 para o, um 100 partições que nós configuramos. E em cerca de cinco minutos, isto será feito. Não leva todo esse tempo, tipo do poder de um cluster chugging através um milhão de classificações e cada possível permutação de cada par possível de filmes e em seguida, filtrar os resultados que queremos estudante muito trabalho, mas ele vai fazê-lo com bastante rapidez. Então vamos voltar em cinco minutos aqui e eu vou te mostrar os resultados. Tudo bem, estamos quase terminando aqui. Lá está ele. Incrível. Então temos os melhores filmes semelhantes para Star Wars Episódio 4 e nova esperança baseada em 1 milhão de classificações de filmes reais. E nos dias de hoje isso é um pouco mais recente de 2003. Então, novamente, não vamos ver nenhum filme atual, mas os resultados parecem bastante razoáveis. Temos um episódio de Star Wars 5 e o poder atinge os apoiadores da Arca Perdida. Retorno dos Jedi, meio que recebendo a razão pela qual a Arca Perdida foi classificada como Retorno dos Jedi mais alto. Mas para ser honesto, acho que gostei mais dos Caçadores da Arca Perdida do que do Retorno dos Jedi. Então, talvez não seja tão louco quanto parece. E o filme original de Indiana Jones, recomendações muito boas para alguém que gosta de Star Wars. E então começamos a entrar em outros grandes filmes que eram bons. A matriz do exterminador, há alguns, alguns muito bons aqui, volta para a futura Princesa Noiva todos apela para uma espécie de demografia nerd. Muito legal. Hey mel Python eo Santo Graal, mesmo estes são realmente muito danado recomendações razoáveis. Legal, e aí está. Então, são recomendações de filmes, filmes semelhantes e Star Wars usando 1 milhão de classificações de filmes são executados em um cluster real usando fio Hadoop e ApachesPark. É disso que se trata. Agora, última etapa, não se esqueça de encerrar o cluster quando terminar. Então eu vou sair dessa, mas isso não é suficiente. E eu preciso voltar para o painel EMR. E no meu cluster bateu terminar. Sim, tenho certeza que terminei com isso. Agora, se você não fizer isso, a conta vai continuar correndo para você. Esse cluster ainda está em execução e mesmo que você não esteja fazendo nada com ele, você ainda será criado para o tempo nesse cluster, para que todos esses três computadores ou até mais se você configurar mais. Então, novamente, se você está fazendo isso em seu próprio centavo e realmente acompanhando, lembre-se, determine seu cluster quando terminar. Eu realmente não quero ouvir sobre isso. Se você receber uma conta de US $1000 no final do mês da Amazon, supostamente 10, que é sobre o que este custo. Tudo bem. Certifique-se de que isso termine com sucesso e, em seguida, é seguro fechar fora dele. Mas com isso, “woo hoo “, parabéns, esse é o ponto culminante do que estamos fazendo aqui. Nós realmente executamos uma grande faísca real, trabalho de big data em um cluster real com sucesso e obtivemos alguns resultados realmente úteis fora, fora dele. tão legais. Vamos falar um pouco mais detalhadamente sobre solução de problemas de trabalhos do Spark e alguns dos pontos mais finos da execução no ajuste de coisas. 47. Partição: Então uma coisa que eu realmente obscurecido foi esta linha aqui nestes filmes semelhança é um arquivo de ponto de dados m Scala aqui que nós não falamos sobre. Isso é diferente do nosso script original de conjunto de dados de semelhanças de filmes. Esta linha aqui, partição numérica partições é igual a 100. Então nós aplicamos isso a nós mesmos juntou-se a um DataFrame antes de converter isso em um conjunto de dados. Então, o que é isso tudo? Sobre o que está reparticionando? Por que eu tenho que fazer isso? Bem, esta é uma operação muito, muito pesada. Eu fazer essa auto-associação através um milhão de audiências vai explodir muito rápido e isso é mais do que você pode realmente fazer em uma única máquina. Então, neste caso, temos que dizer ao Spark, hey, você realmente quer dividir essa operação. E esse parâmetro de repartição diz quantas maneiras você deseja dividir essa operação por. Então vamos falar sobre isso em um pouco mais de profundidade. Então, Spark é geralmente muito mágico. Ele fará automaticamente a coisa certa para distribuir seu trabalho em um cluster inteiro. Mas às vezes você tem que dar algumas dicas e às vezes você precisa pensar um pouco sobre como seus dados serão particionados entre os diferentes executores em seu cluster. Agora, executar esse script de semelhança de filme como estava sem aquela chamada de repartição pode não funcionar sozinho. Isso é auto-junção é uma operação muito, muito cara, e Spark nem sempre é inteligente o suficiente para distribuir isso sozinho do jeito certo. Essa é realmente a parte mais exigente deste roteiro. E precisamos dar algumas dicas a faíscas para ter certeza de que não ficamos sem recursos pedindo a um único executor para fazer mais do que ele pode fazer. Então, chamando explicitamente a repartição nesse DataFrame. E se você estava usando RDDs, há uma função de partição BY que faz a mesma coisa em RDDs. Se você usar isso antes de executar uma operação grande que se beneficia do particionamento, ele irá certificar-se de que as coisas são divididas de uma forma que faça sentido. Agora, algumas operações que se beneficiam do particionamento incluem join, que é o que estamos fazendo neste exemplo. Também grupo COGROUP com essa junção, junção externa esquerda, Bisk, qualquer tipo de junção ou operação GroupBy ou reduzido por operação ou combinado por operação. Também a pesquisa pode se beneficiar disso. Então, se você estiver chamando qualquer um desses métodos em um conjunto de dados muito grande, você pode querer pensar em particioná-lo explicitamente usando a função de repartição. E quando você fizer isso, as operações preservarão esse particionamento e os resultados também. Então você terá seus resultados de volta quebrados por essas partições também. Então, tenha isso em mente. Como você escolhe um tamanho de partição? De onde veio esse número 100? Bem, se você tem poucas partições, isso não vai tirar o máximo proveito do seu cluster, certo? Então, se eu tiver menos partições, então eu tenho executores. Isso vai deixar alguns executores ociosos nesta tarefa. Então eu definitivamente quero pelo menos tantas partições quanto eu tenho executores no meu cluster. Caso contrário, estou apenas desperdiçando recursos, certo? Então, para tornar isso real, se eu estiver tomando a operação de auto-junção que estamos usando neste script. E estou a dizer repartição dois. E eu tenho cinco nós no meu cluster que três desses nós vão ficar sem uso. Isso é inútil porque eu só vou estar distribuindo esse trabalho entre duas partições. Mas se você tiver muitos, isso resulta em muita sobrecarga por embaralhar todos os dados ao redor. Portanto, mover dados em torno do cluster também é uma operação dispendiosa. Você não quer fazer muito isso também. Então você meio que tem que atacar este ponto ideal onde você está aproveitando os clusters e os executores que você tem em seu, em seu cluster. Mas não ter uma quantidade ridícula de partições onde a sobrecarga de gerenciar tudo se torna proibitiva. Portanto, em geral, você quer pelo menos tantas partições quanto você tem núcleos ou executores que se encaixam na memória disponível para o cluster, 100 é geralmente um lugar razoável para iniciar operações grandes. É o que estamos usando aqui. Funciona. Não é um número muito alto que vai ter uma tonelada de sobrecarga. E é provavelmente um número que é mais do que o número de executores que você tem em um cluster típico. Então isso geralmente é um bom ponto de partida. Mas se você tivesse mais de 100 executores, obviamente você gostaria de usar um número ainda maior lá. Então é disso que se trata o particionamento. Novamente, se você estiver usando uma operação de junção muito grande ou grupo por ou reduzido por, isso pode se beneficiar do particionamento explícito. Às vezes, isso pode fazer a diferença entre o sucesso do seu trabalho ou ficar sem memória. Então, se você se deparar com problemas estranhos em que seu script está falhando e ficando sem recursos, mesmo que você tenha um enorme cluster disponível. Talvez seja por isso que você precise voltar e pensar, preciso particionar explicitamente essas operações usando o comando repartition? 48. Best Práticas para a execução em um cluster: Vamos entrar em mais alguns detalhes minuciosos de execução em um cluster. Primeiro de tudo, certifique-se de sempre evitar especificar uma configuração para o Spark no próprio script de driver. Isso incluiria especificar sua configuração mestre. Lembre-se, nós normalmente colocamos em mestres definidos como estrela local para dizer que você deseja executar localmente em sua máquina. Obviamente, você não gostaria de fazer isso em um cluster real. Você deseja usar todo o cluster, não apenas um núcleo de CPU, até mesmo vários núcleos de CPU em um único sistema. O que você deseja fazer no entanto é usar os padrões que o Elastic MapReduce instalou em vez disso, se você estiver executando no Elastic MapReduce e isso se manterá verdadeiro na maioria dos clusters que você pode estar executando onde o Spark está pré-instalado, probabilidades são brilho já ser configurado fora da caixa em seu cluster para ter o direito de cair configuração. E você também quer ter cuidado com quaisquer opções de linha de comando que você passar para o Spark desk enviar de seu nó principal, você pode substituí-los. Dessa forma. A maneira como funciona é que uma coisa em seu script de driver tem prioridade. Depois disso. Qualquer coisa que você passar como um argumento de linha de comando para enviar faísca teria prioridade. E, finalmente, os arquivos de configuração no próprio cluster teriam a última palavra na cadeia de comando lá, se preferir. De modo geral, novamente, seu cluster será configurado com a configuração correta fora da caixa. E isso é verdade para o Elastic MapReduce também. Portanto, você geralmente não deseja especificar configurações no próprio script do driver ou na linha de comando. Você geralmente é melhor deixar a configuração fazer sua mágica por você. Obviamente, se você é um administrador de sistema e é seu trabalho configurar essa configuração, então você tem que pensar sobre isso. Mas como um desenvolvedor de aplicativos geralmente você não vai. No entanto, há situações em que você precisa ajustar as coisas se você achar que seus executores estão falhando e um trabalho grande, talvez você precise ajustar a memória que cada executor tem. Portanto, se você estiver vendo mensagens de erro que sugerem que você está ficando sem memória em seus nós executores. Bem, você tem que fazer algo sobre isso. Uma maneira é apenas aumentar a quantidade de memória que cada executor atribuiu a ele. Então, por exemplo, você poderia dizer estimada, traço, traço de memória executor um G. E isso alocaria explicitamente um gigabyte de RAM para cada executor. Claro, isso pressupõe que você tenha RAM suficiente disponível em cada nó do cluster para fazer isso. Mas, você sabe, isso é uma espécie de aproximação de força bruta, certo? E talvez o que você realmente deveria fazer é pensar mais sobre particionar e dividir seus dados de uma maneira mais eficiente. Além disso, você pode especificar um gerenciador de cluster na linha de comando. Por exemplo, você pode dizer traço, fio mestre traço. Se você quisesse executar explicitamente usando o yarn, um gerenciador de cluster em um cluster Hadoop. Mas, novamente, isso provavelmente será configurado para você por padrão. E no Elastic MapReduce é, ele irá apenas inferir automaticamente que o mestre padrão é o gerenciador de cluster de fios porque o Elastic MapReduce está sendo executado no Hadoop, que tem o gerenciador de cluster de fio. Então você realmente não precisa fazer nada lá, mas você pode especificar um mestre na linha de comando se você quiser ter essa flexibilidade. E mais algumas melhores práticas aqui, uma espécie de lembrete. Novamente, é muito importante certificar-se de que seus scripts em seus dados ou em algum lugar onde o EMR ou qualquer cluster em que você esteja executando possam acessá-los. Se você estiver no EMR, provavelmente estará usando o serviço AWS S3. É um serviço de armazenamento simples. E se você fizer isso, basta usar o S3, um prefixo URL para especificar o caminho para o bucket do S3. E você só precisa se certificar de que suas permissões de arquivo estejam acessíveis ao cluster do EMR. Isso às vezes pode ser algo complicado com a AWS em geral, essas permissões, quero dizer, a coisa mais fácil a fazer é apenas tornar seu bucket acessível publicamente. Mas se eles são dados confidenciais lá, então você precisa pensar em permissões mais explícitas nas quais você vincula as coisas especificamente ao local onde o cluster do EMR está sendo executado. E eu não quero entrar nas especificidades da segurança da AWS neste curso, esse é um tópico totalmente diferente, mas é possível que, uma vez que você tenha tudo onde ele precisa estar, você possa girar seu cluster usando o ou se você quiser usar a API, tudo bem também. E assim que você girar o grupo, é quando o relógio começa. E lembre-se, assim que você girar o cluster, o relógio começa na cobrança, não importa que você não está usando, você vai ser cobrado por hora lá. E para um cluster que contém máquinas grandes e muitas delas que podem ficar extremamente caras, extremamente rapidamente. Então certifique-se de saber o que faz lá dentro. Uma vez que você tem esse grupo girado, você tem que, você tem que se apressar porque tempo é dinheiro, certo? Então você precisa obter o nome DNS externo para esse nó principal. Faça login nele usando a conta do Hadoop e seu arquivo de chave privada que você usou ao configurar o cluster. Uma vez que você está em cópia sobre seu arquivo de programa jar drivers e todos os arquivos que você precisa no driver do próprio script. Você pode usar o comando cp do AWS S3 para copiar coisas que você carregá-lo para o S3 antecipadamente e, em seguida, executar estimativa sparked, e espero que ele funcione. E, novamente, lembre-se de encerrar seu cluster quando terminar. Se você esquecer de encerrar seu cluster depois que seu trabalho for feito, você vai ter uma surpresa muito, muito desagradável em sua conta de cartão de crédito no final do mês. E é possível, a propósito, com o EMR configurar as coisas para executar automaticamente um script assim que ele gira e desliga automaticamente assim que for feito. Então, uma vez que você tenha os bugs trabalhados fora do seu script e você pode executá-lo de forma confiável. Você pode configurar as coisas para que, assim que você girar cluster irá iniciar automaticamente o seu trabalho. E é girar esse grupo para baixo quando você terminar com ele. Em algumas situações isso faz sentido. Em outras situações, sua empresa pode ter dinheiro suficiente para apenas manter esse cluster em execução o tempo todo e mantê-lo acessível para seu desenvolvedor é 24, 7. Mas para a maioria de nós, não temos esse tipo de luxo disponível para nós. Portanto, você precisa pensar em certificar-se de que você está observando quanto tempo executando seu cluster 4. E a melhor maneira de minimizar esse custo é depurar e trabalhar as distorções em seu script localmente. Primeiro antes de tentar executá-lo em um cluster real. Isso é o que temos feito ao longo deste curso. Então, se você tem um conjunto de dados grande que você não pode executar em uma máquina usa um subconjunto desses dados inicialmente para resolver as distorções em seu aplicativo. E, novamente, certifique-se de que todos os arquivos de dados que você precisa estarão acessíveis a cada nota do executor em cada máquina que possa estar em seu cluster. Qualquer coisa que possa realmente ser referenciada ou lida de um executor distribuído precisa estar acessível além do local onde seu script de drivers está sendo executado. Então, desde que você tenha cuidado com essas coisas e tenha cuidado novamente em não especificar a configuração específica para ser executada em um único computador no seu script de driver final, você deve ser capaz de obter as coisas muito próximas ao executado de forma confiável antes de começar a experimentar no próprio cluster. 49. Solução, como resolver os problemas e gerenciar as dependências: Então, vamos aprofundar um pouco mais sobre solução de problemas de seus trabalhos depois que eles estiverem sendo executados em um cluster. Infelizmente, é um pouco de arte escura. Pode ser muito difícil rastrear esses tipos de erros quando eles estão sendo executados dentro da complexidade do próprio Spark e, além disso, na complexidade de serem distribuídos por vários nós. Agora, seu mestre executará um console na porta 4040 que permitirá que você veja algumas informações sobre o que está acontecendo, que às vezes podem levar a alguns insights sobre por que seu trabalho está falhando. Mas se você vir mensagens de erro em seus registros, vai ser meio difícil rastreá-los para uma coisa. Primeiro de tudo, você vai ver essa pilha de chamadas profunda em seus arquivos de log se você tiver um erro, porque lembre-se que você está executando seu código Scala que é compilado para o código Java. E através de todas essas camadas de compilação, é fácil meio que se perder onde as coisas estão correndo. Então, tipicamente, você verá as coisas morrendo profundamente dentro do próprio Spark. E se você olhar duro o suficiente embora eventualmente você deve ver uma mensagem de erro ou algum tipo de exceção que o leva ao problema real em seu script, mas você nem sempre tem essa sorte. No entanto, vamos dar uma olhada no console mestre aqui para ver quais informações ele nos dá agora. E novamente, isto é, isso em si pode ser difícil porque um Elastic MapReduce, é praticamente impossível realmente conectar-se a isso de fora do cluster. Portanto, se você quiser se conectar a esse console do desktop que está sendo executado fora do ambiente EMR. Isso é uma coisa difícil de montar. Um pode ser feito através de coisas como hosts proxy e coisas assim. Mas é difícil. Se você tem seu próprio cluster, rodando em sua própria rede, a vida vai ser muito mais fácil no que diz respeito ao seu ouvido, esses problemas de segurança devem ser algo que você pode resolver um pouco mais facilmente. Então, vamos dar uma olhada no console rodando em nossa própria máquina local como uma maneira de começar. E vamos explorar a informação que ela lhe dá. Certo, então vamos explorar o console do Spark que eu falei. Agora, infelizmente, ele só estará disponível enquanto o Spark estiver em execução. Então, se eu não estou realmente executando uma interface de banco de dados constante para faísca ou algo assim. Eu só vou ser capaz de chegar até ele enquanto meu script faísca está realmente em execução. Então, por uma questão de ilustração, vamos começar um script de faísca realmente carnudo aqui que será executado por alguns minutos, então teremos tempo para explorá-lo nos materiais do curso. Há um conjunto de dados de recomendações de filmes, script local. E isso é configurado para usar o conjunto de dados ML 1 milhão localmente em sua máquina aqui. Então você não precisa executar isso junto comigo necessariamente, mas se você quiser, você verá que eu instalei o conjunto de dados ML dash 1M aqui na pasta de dados dos meus materiais do curso. E este guião é destinado a usar isso. Assim que eu disparar isso, isso vai funcionar por alguns minutos tentando descobrir os filmes mais parecidos com Star Wars. E enquanto está fazendo isso, podemos explorar o console. E eu tenho um navegador aqui pronto para isso. Configurar até 127 ponto 0, que é 0 ponto um dois-pontos 4040, 127, 100, 000 ponto um é o endereço IP do nosso host local. E já que estou executando o Spark localmente na minha área de trabalho aqui, esse será o endereço IP que vou acertar para o console do Spark. E 40, 40 é a porta em que funciona. Então eu vou começar isso fora. E assim que o Spark estiver em execução, vou recarregar esta página e devemos ver um console. Então vamos voltar para a IntelliJ e vamos começar isso. E eu vou dar um pouco de tempo para girar. Queremos ter certeza de que na verdade teve tempo de acender. São executores. Acho que estamos lá. Então vamos voltar ao nosso painel aqui e recarregá-lo. E eu vou em frente e abrir cada um desses em uma nova guia para que possamos explorá-los. E se você for para trabalhos, você pode ver que podemos perfurar qualquer ID de trabalho individual aqui. E você pode fazer coisas como visualizar o gráfico acíclico direcionado. Isso é muito legal. Você pode fazer a mesma coisa a partir dos estágios. Mais uma vez, cavar em qualquer estágio que você quiser. Este, vamos tomá-lo para o bem do exemplo, que um ainda não começou. Então vamos tentar o primeiro. E você pode ver que isso nos dá muito mais informações também. Novamente, há uma Visualização DAG disponível aqui também. Então isto pode continuar a correr e a fazer a sua coisa enquanto exploramos isto neste momento. Então vamos voltar para a guia de empregos aqui. Você pode ver que ele lhe dá uma espécie de representação gráfica da linha do tempo do evento. Então, lançamos o driver neste ponto e foi tentado executar a ação final e descobrir o que ele precisa fazer para cumprir a ação final que temos no script do driver para obter as dez melhores semelhanças de filmes Guerra nas Estrelas. Então isso mostra o progresso que está passando por todas as tarefas para realizar isso. E se você for para a guia de estágios aqui, você pode ver que ela mostra seu progresso ao longo dessas linhas. E lembre-se, os estágios estão representando cada ponto dentro da execução onde ele precisa embaralhar os dados. Portanto, é bom obter alguma visualização em quantos estágios estão realmente envolvidos no cumprimento do trabalho que você deseja. Porque mais estágios é ruim. Toda vez que você tem um estágio, ele tem que embaralhar dados em todo o cluster. E essa é uma operação muito cara. Então, se você vê menos estágios, isso é uma coisa boa. E, novamente, você pode perfurar um estágio individual. Eu acho que ele realmente terminou, então nós podemos realmente olhar para isso. Vamos em frente e chutar o script de novo. Certo, temos alguns resultados para criar uma curiosidade. Ei, isso funcionou muito bem. Então nosso algoritmo de filtragem colaborativa de similaridade funcionou muito bem. Disse que o resultado principal para episódio de Star Wars, Episódio 5, Star Wars, É como tivemos em nossos slides. Então é fixe de se ver. Raios da Arca Perdida, Star Wars Episódio 6, Indiana Jones. Todas as grandes recomendações para Star Wars, mas vamos começar isso de novo para que possamos jogar com o console um pouco mais. Tudo bem, então de volta para a aba de estágios. Acho que era onde brincávamos. Novamente, você pode clicar em um estágio individual. Eu deveria recarregar isso para saber mais sobre o que está acontecendo nele. E diz-te todo o tipo de coisas. Quanto tempo leva para embaralhar esses dados. Lembre-se, os estágios estão associados a dados embaralhados. Podemos visualizar o gráfico acíclico direcionado que ele veio com. Então isso é muito legal de se ver. Então, se você está tentando otimizar o desempenho do seu trabalho, visualizando, isso pode lhe dar algumas informações sobre como ele está realmente quebrando o que você pediu para fazer. E às vezes isso pode levar a uma maneira melhor de estruturar seu script de driver para ser mais eficiente. O que mais podemos olhar? O depósito provavelmente estará vazio. Não estou guardando nada. O ambiente fornece algumas informações sobre o ambiente de tempo de execução. Vamos refrescar isso também. E você pode ver que estamos correndo sob o JDK, correndo sob JDK 14 no meu drive C. Usando essa versão Java, essa versão Scala, apenas algumas informações gerais. Também podemos olhar para as propriedades do sistema. Então, se você quiser obter mais informações sobre o ambiente em que seu script está sendo executado, você pode fazer isso. Eles estão sob executores. Isso mostra quantos executores estão sendo executados, e isso em si é interessante. Portanto, apenas um único executor está realmente em execução agora. Isso me diz, por exemplo, que mesmo que eu tenha vários núcleos de CPU em minha máquina aqui, ele não está realmente usando. Então, essa pode ser a maneira da natureza de me dizer que eu não escrevi as coisas de tal forma que podem ser paralelizadas ou pode haver algo errado com minha configuração que está levando a esse problema. Se eu estivesse executando isso em um cluster real e eu visse apenas um executor em execução durante toda a execução deste. Isso provavelmente me daria uma dica bastante forte de que algo está realmente errado com a configuração no meu cluster que eu deveria descobrir. Então isso é uma espécie de visão geral das coisas que você pode ver usando o console do Spark. Com isso, vamos falar um pouco mais de profundidade sobre a solução de problemas uma vez que você tenha isso. Agora, quando as coisas derem errado, seus logs no modo autônomo também estarão disponíveis na interface do usuário da Web. Mas se você estiver executando em cima do gerenciador de cluster de fios como estamos fazendo com o EMR. Esses logs serão distribuídos por cada nó individual em seu cluster. Agora você pode coletá-los após o fato de usar troncos de fio traço, ID de aplicação traço. Você pode descobrir o ID do aplicativo do seu trabalho que está sendo executado lá. Portanto, se você estiver executando o Spark Cluster Manager autônomo, a vida útil pode ser um pouco mais fácil. Haverá ali mesmo na interface para você. Mas se você estiver executando em cima do Hadoop, as coisas ficam complicadas por realmente encontrar esses registros. Novamente, ele apenas enfatiza novamente a importância de depurar esses problemas localmente em sua própria máquina antes de tentar depurá-los em um cluster onde é mais difícil obter essas informações. Agora, enquanto seu script de driver está sendo executado, ele próprio registrará erros como executores que não conseguem emitir pulsações. Então isso é um bom sinal de que seu executor está falhando e falhando por algum motivo em algum nó remoto. Então, às vezes, a saída de scripts de driver pode lhe dar algumas pistas sobre o que está acontecendo. Se você está vendo erros como esse, provavelmente significa que você está pedindo demais de cada executor. Talvez você precise de mais deles, talvez só precise de mais máquinas em seu cluster para lidar com o trabalho que você está fazendo. Talvez você precise dar mais memória a cada executor. Aprendemos isso na lição anterior. Como fazer isso? Isso pode ser apenas um parâmetro de linha de comando extra no envio do Spark. Ou talvez você precise usar PartitionBy ou repartition para exigir menos trabalho de seus executores individuais usando partições menores. Então jogar mais editores de máquinas ou mais memória é uma espécie de solução de força bruta para problemas como este. Mas, às vezes, se você apenas usar explicitamente o reparticionamento para dividir o trabalho em pedaços menores, você pode sobreviver com menos hardware ou menos memória. Só vai levar mais tempo para terminar o trabalho. Muitas vezes essa é a coisa certa a fazer. Então, não veja apenas nenhum ir jogando mais hardware no problema se você não precisar. Se você estiver fazendo grandes operações conjuntas em seu script ou grandes operações GroupBy ou reduzir operações. Você provavelmente pode resolver esses problemas apenas pelo uso criterioso do comando repartition para dividir as coisas em pedaços menores. E lembre-se de novo, seus executores não estão necessariamente sendo executados na mesma caixa que seu script de drivers. Portanto, você não pode assumir que os dados na memória estarão acessíveis em todo o cluster. Você precisa ter certeza de que esse é o caso. Se você precisar compartilhar dados fora de seus RDDs são conjuntos de dados, você terá que usar variáveis de difusão para fazer isso. Você não pode simplesmente armazená-lo localmente dentro do script do driver e esperar que ele funcione. Se você precisar de algum tipo de um pacote Java ou Scala que não está pré-carregado em seu cluster, certifica-se de que você está empacotando-os em seu jar que você está executando usando a montagem SBT. Ou você pode usar traço, traço jars com Spark enviar para adicionar bibliotecas individuais que estão no nó principal e que irá distribuí-los automaticamente para os executores ER. Mas isso pode ficar realmente complicado muito rápido, porque muitas vezes os frascos que você quer incluir eles mesmos têm dependências JAR e você tem que especificar todas essas dependências junto com ele também. Muito mais fácil de usar apenas sbt para empacotar tudo no próprio frasco. E você sabe, realmente tentar evitar o uso pacotes obscuros que você realmente não precisa em primeiro lugar é provavelmente o melhor conselho. Lembre-se, tempo é dinheiro em seu cluster e se você não está desperdiçando tempo mexendo com os problemas sobre a distribuição desses pacotes jar por todos os seus executores. Bem, tanto melhor. Então, se você pode obter apenas usando os pacotes principais do Spark e um pouco mais, essa provavelmente vai ser a melhor estratégia para simplificar as coisas. Lembre-se, um simples é bom quando se trata de engenharia de software em geral. E com isso, acho que falamos sobre correr em um cluster em profundidade. Então vamos passar para a nossa próxima seção. 50. Introduz o MLLib: Esta próxima seção é muito emocionante para mim, porque eu gosto muito de aprendizado de máquina. Isso é uma grande parte do que eu fiz no passado. E vamos falar sobre como usar o aprendizado de máquina no Spark. E isso é super emocionante porque o poder dos algoritmos de aprendizado de máquina geralmente são limitados a uma única máquina. Muitas vezes as pessoas apenas desenvolvem isso em um único PC executando um notebook em algum lugar, certo? Mas se você tem um enorme conjunto de dados, o que você faz? Bem, Spark realmente tem uma solução para muitos algoritmos populares de aprendizado de máquina. Então, vamos mergulhar e ver como a biblioteca Sparks ML permite que você aplique DataFrames em um cluster inteiro no Spark para resolver problemas complicados de aprendizado de máquina. Coisas muito poderosas. Vamos mergulhar. Vamos falar sobre Sparks Machine Learning Library, que é surpreendentemente o suficiente chamado biblioteca Sparks ML, nome criativo. É muito legal porque permite distribuir o processamento de conjuntos de dados massivos e aplicar algoritmos sofisticados de aprendizado de máquina a eles em grande escala. Portanto, há maneiras mais fáceis de aplicar esses algoritmos e técnicas a dados em uma única máquina usando apenas código Python e Jupiter Notebooks. Mas quando chega a hora de realmente distribuir essas coisas em um cluster inteiro porque você tem um conjunto de dados verdadeiramente massivo. Bem, essas ferramentas que são tão comumente usadas meio que desmoronam e precisamos transformá-lo algo como Spark ML para ser capaz de lidar com esse tipo de tarefas em grande escala. Deve ser um pouco difícil falar sobre o que a ML faz sem ter alguma experiência em aprendizado de máquina. E se você está curioso sobre esses algoritmos, eu definitivamente o encorajo a ir e fazer uma aula dedicada de aprendizado de máquina para aprender sobre o que eles são. Vou dar-lhe uma visão geral muito alto nível deles aqui e como, o melhor que eu posso fazer em um único slide, pelo menos. Assim, as capacidades básicas do pacote Sparks ML ou extração de recurso que inclui algo chamado TF-IDF, que é freqüência de documento inverso frequência termo. E essas são análises que são usadas principalmente para pesquisa. Assim, ele permite que você descubra quais termos são mais relevantes para um documento. maneira muito fácil de fazer isso. Ele também tem algumas estatísticas básicas coisas embutidas. Se você quisesse, como apenas calcular coeficientes de correlação ou testes qui-quadrado e coisas assim. Pode fazer isso em grande escala. E então entramos nos próprios algoritmos de aprendizado de máquina , que são mais interessantes. Então ele pode fazer regressão linear e regressão logística. Regressão linear é apenas basicamente ajustar uma linha a um conjunto de dados. Então, por exemplo, você pode imaginar que você tem um conjunto de dados que mapeia as alturas das pessoas para suas idades. E ajustando uma linha aos dados que você observou, você pode realmente ajustar novos pontos de dados a essa linha para prever seu valor real. Então, se eu tiver uma linha que define a idade como uma função da altura, eu posso realmente perfurar novas alturas em que o modelo nunca viu antes e prever sua idade apenas extrapolando através dessa linha. Isso é regressão linear. Regressão logística é a mesma idéia sob o capô, mas é para fins de classificação. Então, se eu quiser prever se alguém é democrata ou republicano, por exemplo, você pode usar regressão logística para fazer isso. Se eu quiser prever se um carro é um carro esportivo ou um sedan baseado em alguns atributos. Isso pode ser outro exemplo de regressão logística. Estamos novamente, estamos aplicando uma função matemática muito simples para prever classificações em vez de valores reais, que você estará fazendo com regressão linear. Ele também pode fazer máquinas vetoriais de suporte. Essa é outra forma de fazer a classificação que é um pouco mais sofisticada, se preferir. Ele funciona nesses espaços de maior dimensão e pode encontrar divisões mais complexas entre classificações que não são necessariamente lineares. Ele também pode fazer classificação Bayes ingênua. O filho pôster de um aplicativo para um Bayes ingênuo é a classificação de spam. Então, um exemplo muito comum de Bayes ingênuos é alimentá-lo com um corpus de e-mails e ter um conjunto de treinamento marcado como spam e não spam. E você pode treinar esse classificador Naive Bayes para receber novos e-mails que nunca viram antes e prever se seu spam ou não baseado nesse modelo ingênuo do Bayes. Ele também pode fazer árvores de decisão distribuídas em um cluster inteiro, o que é muito legal. Eu gosto de árvores de decisão são apenas divertido de olhar para o seu, como eles soam. É basicamente esta árvore de decisões. Então basicamente você vai começar com alguma decisão como, eu não sei, esta é a temperatura fora acima de 72 graus ou abaixo de 72 graus. Se estiver acima de 72 graus, talvez você vá para outro bloco de decisão. E talvez a próxima decisão. E a árvore decisória é, está chovendo ou não? E talvez isso possa levar você a uma decisão sobre se você deve ir lá fora e jogar hoje, se é um bom dia ou não, certo? É um exemplo muito simples de uma árvore de decisão. Obviamente, você pode ficar muito mais complicado e pode trabalhar em situações arbitrárias onde você tem muitos recursos que são numéricos, que podem ser comparados com alguns valores definidos. E ao tomar decisões em sequência entre esses diferentes recursos de seus dados, você pode chegar a uma decisão com uma árvore de decisão. K-significa agrupamento, apenas uma maneira de agrupar dados com base em seus atributos, com base em como as coisas são semelhantes entre si. De um modo muito simples. Isso é o que chamamos de aprendizagem não supervisionada, onde não estamos treinando um modelo baseado em valores conhecidos. Estamos tentando agrupar as coisas com base em suas propriedades naturais e como as coisas são semelhantes entre si. E também pode fazer análise de componentes principais, conhecido como PCA para decomposição de valor curto e singular, SVD para abreviar. São o que chamamos de técnicas de redução da dimensionalidade. Então, às vezes você terá esse problema em que você tem dados que têm um monte de recursos diferentes para ele. Coisas diferentes que estamos medindo para objetos diferentes. E isso se torna, causa o que chamamos de dimensionalidade cursiva. Este é basicamente um problema de dados esparsos onde você tem muitos recursos. Estas são maneiras de resumir essas até as características mais salientes. Talvez sejam características sintéticas que nem existiam no mundo real. Mas é uma maneira de transmitir dados de feição de dimensões mais altas a dados feição dimensionais mais baixas, o que torna um pouco mais fácil de trabalhar com eles. E, finalmente, ele pode fazer recomendações usando uma técnica chamada Alternando Menos Quadrados. E nós vamos cavar isso em um pouco mais de profundidade muito em breve. Als é legal. Na verdade, houve uma competição há muito tempo que foi patrocinada pela Netflix para desenvolver um sistema de recomendação melhor do que o seu próprio. E uma das entradas vencedoras que fazem parte de sua solução foi usar ALS. Então, isso também está disponível para você dentro do Spark ML. Agora é uma espécie de lista limitada do que você pode fazer. Quero dizer, existem inúmeros algoritmos de aprendizado de máquina lá fora, mas nem todos eles realmente se prestam bem a serem distribuídos em um cluster. Então, ainda hoje, há muitos algoritmos de aprendizado de máquina lá fora onde estamos apenas dimensionando-os verticalmente. Só podemos executá-los em uma única máquina. E estamos meio que de volta aos velhos tempos de grandes bancos de dados monolíticos onde a única maneira de fazer essas coisas é ter uma máquina realmente grande para executá-las com muitas GPUs e muita memória e todas essas coisas boas. Mas meio esparso de abrir o caminho para fazer escala horizontal de aprendizado de máquina. E é realmente excitante. Agora havia uma API anterior que existia no Spark um e no Spark para chamado ML Lib. E essa foi uma API de nível inferior que usou RDDs e alguma estrutura de dados especializada é executar esses algoritmos. Agora, em Spark 3, isso foi obsoleto e partes dele não funcionam mais. E francamente, os mantenedores do Spark não se importam porque está apenas no modo de manutenção neste momento. Então eles realmente querem que você mude para a nova biblioteca ML. A diferença é principalmente que ele usa DataFrames para tudo. Então, em vez de passar RDDs e essas estruturas de dados especializadas, você estará usando dataframes e conjuntos de dados, que é realmente a API para a qual eles querem empurrar todos. A vantagem disso é que, usando DataFrames em todos os diferentes componentes do Spark, você pode passar esses DataFrames de um componente para outro sem problemas. Então isso é meio que eles são visão maior. Eles querem ser capazes de pegar um DataFrame que sai do Spark ML e talvez, você sabe, alimentá-lo para Spark SQL e talvez para GraphX. Quem sabe o certo? Essa interoperabilidade, que se torna empolgante por ter este DataFrame de propósito geral. Essa é uma espécie de lingua franca de todos esses componentes do Spark, incluindo aprendizado de máquina. Se você quiser mais profundidade, Há um livro chamado Advanced Analytics com faísca publicado por O'Reilly, provavelmente um pouco desatualizado agora, Eu não sei se eles têm uma versão atualizada para a nova biblioteca ML, mas é um recurso muito bom. Qualquer coisa do O'Reilly geralmente é uma boa leitura. Os exemplos mais oportunos ou sempre vai estar no próprio SDK faísca. Há um diretório de exemplos no SDK. E se você mergulhar lá, você encontrará um exemplo de cada um desses algoritmos realmente sendo usados. E novamente, para mais profundidade sobre os algoritmos reais e como usá-los e como eles funcionam. Vou encaminhá-lo para um curso diferente, não este sobre aprendizado de máquina em geral. Com isso, vamos colocá-lo em prática. Em nossa próxima palestra, vamos realmente gerar recomendações de filmes usando o módulo ALS que falamos no Spark ML. E é realmente emocionante porque é muito, muito fácil de usar. Assim, os sistemas de recomendação são coisas realmente complicadas e alternando mínimos quadrados está usando este método de fatoração de matriz. É uma matemática muito hardcore sob o capô aqui. Mas para realmente usá-lo no Spark e realmente distribuído em um cluster inteiro, este é todo o código que você precisa fazer. Como isso não é incrível? Então vamos passar por isso um pouco. Tudo o que estamos fazendo aqui é carregar um arquivo de dados que vai ser nosso conjunto de dados de classificações MovieLens de dados u dot. Em seguida, mapeamos isso em um RDD de classificações usando as APIs de nível inferior porque estamos fazendo transformações meio simples aqui. E então nós convertemos isso para um DataFrame para torná-lo compatível com Spark ML. Em seguida, basta criar um novo objeto ALS a partir da biblioteca ML. Nós definimos o que é chamado de um par de hiperparâmetros. Um pequeno segredo sujo do aprendizado de máquina é que muitos desses algoritmos são tão bons quanto os hiperparâmetros que você definiu neles. Assim, o número máximo de iterações, o parâmetro de regularização. Estes são dois exemplos de hiperparâmetros com o algoritmo ALS. E a maioria dos algoritmos de aprendizado de máquina tem vários deles. E o quão bem eles funcionam depende desses parâmetros. E a pequena verdade suja é que ainda é uma questão de tentativa e erro encontrar os valores de parâmetro que funcionam melhor para um determinado problema. Gostamos de pensar que entendemos esses modelos muito profundamente, mas na realidade, muito disso ainda é adivinhação. Mas uma vez que temos esses valores lá para começar, pelo menos podemos criar um novo objeto ALS. Dizemos onde o ID do usuário, o ID do filme e as informações de classificação estão em nosso DataFrame. E então podemos chamar ajuste no modelo ALS. E isso vai disparar e treinar um modelo usando todos os dados do MovieLens. E nesse ponto podemos usar esse modelo para fazer previsões para novos usuários que nunca vimos antes. Então é tão fácil assim. Vamos brincar com ele. Vamos executá-lo. 51. [de atividade] usando o MLlib para produzir recomendações de cinema: Então vamos começar a usar o algoritmo de recomendação Alternating Menos Quadrados que é construído no ML Lib, que é parte do Spark. E vamos olhar para o script de conjunto de dados ALS recomendações de filme para este. Agora, antes de entrarmos nisso, o que fizemos para testar isso foi criar uma espécie de falsa persona de um usuário cujos gostos eu posso, pelo menos , entender um pouco que me dará algum sentido qualitativo sobre se o recomendações são boas ou não. Então, para fazer isso, eu realmente fui para meu conjunto de dados MO 100 K e editei o arquivo de dados u dot. E o que eu fiz foi adicionado em três linhas para um usuário falso 0, usuário 0 não existia anteriormente neste conjunto de dados. E esta é uma pessoa muito simples aqui. Basicamente, eu disse que este ID de usuário gosta itens 50, ID de filme 50 e ID de filme 172 muito. Ele deu a ambos cinco estrelas. E esses correspondem ao filme Star Wars Episódio 4 e Star Wars Episódio 5. Uma Nova Esperança no Império Ataca. Então, estabelecemos que essa pessoa tem um grande fã de ficção científica de Star Wars. E, em contraste, eu também disse que para o filme 133, que é “Levou com o Vento “, isso foi apenas uma estrela. Então eu criei uma personagem muito simples aqui. Alguém que ama Star Wars e ficção científica presumivelmente, mas não é fã de velhos dramas românticos, certo? E então essa é alguém com quem eu posso me relacionar. Então isso me dá uma sensação pessoal ou sentido de saber se esses resultados vão ser bons ou não. Agora, existem maneiras de medir objetivamente o quão bom é um conjunto de recomendações. Mas muitas vezes é uma espécie de coisa qualitativa. Você pode tentar prever se o seu algoritmo pode ou não sentir se alguém realmente teria gostado de um filme que eles irradiam anteriormente. Mas, no final do dia, as recomendações são sobre tentar recomendar coisas que uma pessoa não viu antes. E isso é uma coisa difícil de medir se é ou não um bom resultado ou não. Então, pelo bem da demonstração, vamos manter essa avaliação qualitativa. Vou ver se as recomendações que saio disto fazem sentido para alguém que ama Guerra nas Estrelas e odeia o Vento Levou. Então vamos percorrer o próprio código e ver como ele se parece. Muito fácil de usar, na verdade. Então, estamos importando a recomendação de pontos ML, tudo por baixo disso e as coisas habituais também. Nós montamos nosso objeto e temos duas classes de casos aqui. Um para a pesquisa de nomes de filmes que vamos usar para procurar nomes de filmes para IDs de filmes para obter resultados legíveis por humanos no final. E também temos nosso pequeno conjunto de dados para classificações que inclui um ID de usuário é IDs de filmes e classificações, note que estamos emitindo os carimbos de data/hora porque na verdade não importa para este algoritmo. Vamos descer para a função principal aqui. Comece definindo nosso nível de registro. Então eu acho que com a sessão do Spark como sempre fazemos, e começamos carregando esse conjunto de dados de nomes de filmes. Nós fornecemos um esquema que diz que ele tem IDs de filme inteiro e títulos de filme string. E enquanto estamos nisso, dissemos que o esquema do filme também para os dados de classificações reais que vamos ler também, importamos pontos de faísca implícitos porque vamos estar carregando DataFrames inicialmente e não um conjunto de dados. Lemos na pasta de item de ponto UE que contém esses nomes de filme usando o esquema de nome de filme. E nós transmitimos isso para o conjunto de dados de nomes de filmes usando a classe de caso de nomes de filmes. Espreitando isso porque já fizemos isso um milhão de vezes no início do curso, certo? Nós então realmente coletou que de volta em Scala em um objeto de lista de nomes. Então, neste ponto, nós realmente usamos o Spark apenas para carregar esses dados e analisá-los. Na verdade, copie isso de volta para o nosso próprio script de driver. Agora podemos sair impunes porque não há tantos filmes no mundo, certo? Podemos encaixar isso com segurança na memória dentro de nossos scripts de driver. Então isso não é uma coisa louca para fazer, na verdade, então nós vamos apenas despejar isso de volta em um mapa Scala aqui para procurar aqueles quando estamos exibindo estes no final. No entanto, os dados de classificações de filmes que queremos manter distribuídos e mantê-los em nosso cluster como um conjunto de dados. E isso é o que estamos fazendo aqui é carregar isso usando o esquema que fornecemos, o delimitador de tabulação. E vamos lançar isso como um conjunto de dados de classificação usando a classe de caso de classificação que definimos acima. E, novamente, isso só vai extrair as três primeiras colunas, o ID do usuário, o ID do filme e uma classificação em si. Vamos deixar esse carimbo de data/hora desligado. Depois disso, dê uma olhada em como é fácil usar ML Lib. Então montamos nosso modelo aqui. Então, nós apenas dizemos novo ALS para alternar mínimos quadrados como saindo da biblioteca de algoritmo de recomendação ML Lib lá. E dissemos alguns hiperparâmetros. Então definimos nossas iterações máximas para cinco. Definimos nosso parâmetro de regularização para 0,01. E talvez queiras saber de onde arranjámos estes números. Bem, eu apenas meio que arrancá-los do ar inicialmente baseado em exemplos que eu vi on-line, você vai descobrir que na prática, um pouco de segredo sujo do aprendizado de máquina em geral é que é tudo sobre otimização de hiperparâmetros. E essa é uma maneira muito chique de dizer que vamos adivinhar qual é o número certo até acertarmos. Então, é uma prática muito comum ter esses trabalhos enormes que tentam muitos, muitos, muitos valores diferentes desses hiperparâmetros, como iterações máximas e parâmetros de regularização, e apenas ver quais produzem os melhores resultados experimentalmente. Muitas vezes não há nenhuma orientação real sobre qual o melhor valor deve ser perdoado conjunto e ele irá variar muito do conjunto de dados, o conjunto de dados. Então esse problema de descobrir os parâmetros certos aqui é realmente o núcleo de obter bons resultados de aprendizado de máquina na prática. A outra coisa que o núcleo é apenas limpar seus dados, mas isso não é um curso de aprendizado de máquina, então eu não vou me meter muito nisso. Nós dizemos quais são os nomes das colunas para o ID do usuário, o ID do item e a classificação. É tudo o que o algoritmo precisa. Então nós só precisamos apontar para o que essas colunas de conjunto de dados são realmente nomeadas, para que ele saiba de onde recuperar essas informações. Nesse ponto, tudo o que temos a fazer é dizer ponto encaixar naquele modelo passando no conjunto de dados de classificações. E é isso que realmente executará esse modelo em nossos dados e construirá um modelo que possa prever recomendações para novos usuários de filmes que possam gostar. E é uma espécie de caixa preta nesse ponto, certo? Então o algoritmo ALS está fora fazendo algo. Sabemos que está usando os mínimos quadrados alternados que é sobre isso. Para criar um modelo que possa ter um novo ID de usuário e recomendar filmes que esse usuário possa gostar com base no que ele classificou. Então vamos fazer isso. Vamos em frente e retirar do argumento da linha de comando. O ID do usuário é alguém para o qual queremos obter recomendações. No nosso caso, passaremos o ID do usuário da linha de comando. Nós, em seguida, apenas criar um DataFrame realmente simples que contém nada além dessa ID de usuário. E passamos isso para os modelos recomendados para usuários método de subconjunto passando esse usuário falso DataFrame de um único usuário que não foram resultados. E nós poderíamos realmente passar em vários usuários e obter volta recomendações para muitas pessoas ao mesmo tempo, se você quisesse. E estamos dizendo que só queremos as 10 principais recomendações para cada usuário que estamos passando para esses usuários DataFrame. Nesse ponto, temos nossos resultados, só temos que exibi-los. E estranhamente, essa é a parte mais difícil de tudo isso, descobrir como extrair essa informação. As recomendações DataFrame que recebemos de volta. Então é isso que estamos fazendo aqui e este pequeno loop Aqui, vamos passar por cada recomendação nas recomendações DataFrame que recebemos de volta de recomendar subconjunto freezer, nós extraímos o ID do usuário e as próprias recomendações. Temos que dizer a Scala o que é essa coisa. Então nós temos que lançar explicitamente esse resultado como uma matriz envolta mutável do tipo de linha, que é o que estamos recebendo de volta quando um DataFrame. Podemos então percorrer os resultados de cada recomendação individual, extrair o filme, extrair a classificação. E então podemos traduzir esse ID de filme para um nome de filme usando nossa função get movie name e imprimir os resultados. Finalmente, paramos a sessão quando terminamos e vemos o que acontece. Uma olhada rápida na função get filme nomeado. Ele apenas executa uma informação de filtro na matriz de nomes de filme que passamos e tenta encontrar o ID de filme que corresponde ao que estamos procurando e retorna o título do filme associado a ele. Novamente, isso não está realmente usando um conjunto de dados. Esta é, na verdade, apenas uma matriz que recebemos de volta do conjunto de dados através da operação coletiva. Então vamos executá-lo e ver o que acontece. Clique com o botão direito nisso. Mas precisamos estabelecer um perímetro para isso. Então, vamos dizer Editar recomendações de filme e sentar em um argumento de programa é 0 porque eu quero recomendações de zeros de ID de usuário. Agora eu posso apertar Ok, e ele deve ser capaz de selecionar isso agora e executá-lo. Tudo bem, está fora de treinar esse modelo agora baseado nas 100 mil classificações e aqui estão os 10 melhores resultados. Então, sim, esses resultados são meio estranhos. É dizer isso para alguém que ama Star Wars e não gosta de “O Vento Levou”. O meu melhor resultado com um filme de 1994, nunca ouvi falar, mas chama-se The Endless Summer 2. Acho que isso não é um filme de ficção científica. Tenho certeza que ser ou não ser de 1942 também não é, nem Ball2. Quero dizer, há algumas coisas aqui que fazem sentido Perdidas no Espaço. Transformadores. Eu acho que isso faz sentido para um fã de Star Wars, mas eles podem, eu só tive sorte. Parecem recomendações aleatórias para mim. Então os resultados aqui não fazem sentido para mim. Bem, vamos explorar por que isso pode ser. Então, como mencionamos antes, esses algoritmos tendem a ser muito sensíveis aos hiper parâmetros que você escolher. Muitas vezes, é preciso muito trabalho para encontrar o conjunto ideal de parâmetros para o conjunto de dados que você está usando para obter boas recomendações. Então, uma técnica é usar algo chamado teste de trem, onde reservamos uma parte de nossos dados de classificação e usamos isso para fins de teste. Então, mantemos alguns usuários do nosso conjunto de dados e usamos o modelo treinado nos usuários restantes e vemos se o nosso modelo resultante pode prever com sucesso quais filmes as pessoas no conjunto de testes realmente gostaram, o que eles gostaram, o que eles avaliaram bem. E você pode usar isso para obter uma espécie de medida quantitativa de quão boas são as recomendações. E uma vez que você tem isso, você pode tentar diferentes combinações de hiperparâmetros e ver qual combinação produz os melhores resultados e tentar ajustar as coisas dessa maneira. Mas isso fica desonesto com recomendações. Uma boa recomendação é medida pela sua capacidade de prever coisas que alguém já assistiu? Ou é uma boa recomendação se é algo que eles ainda não viram usando dados históricos, não há como saber isso, certo? Então recomendo, sistemas de recomendação é um tipo de caso estranho onde é difícil medir os resultados realmente além de fazer experiências ao vivo com pessoas reais. Mas passei algum tempo fazendo isso. Então eu tentei valores de parâmetros diferentes. Eu não poderia obter melhores resultados fora desta coisa, não importa o que eu fiz. Então estou pensando que essa coisa não está funcionando como deveria. Então eu nem estou convencido de que esta coisa está funcionando corretamente internamente. Pelo menos para este conjunto de dados, este algoritmo simplesmente não funciona bem. E a lição a ser aprendida aqui é que colocar sua fé em uma caixa preta como esta pode ser uma proposta duvidosa. Você precisa entender o que está acontecendo no algoritmo e entender se ele se encaixa ou não nos dados que você está obtendo. Pode ser que nosso conjunto de dados seja muito pequeno. Pode ser que haja algo nele que não seja particularmente adequado para este algoritmo. Tentei algumas coisas óbvias, como normalizar as classificações para 0 para 1. Isso também não ajudou. Às vezes é isso que você precisa fazer, mas nós realmente obtivemos resultados muito melhores apenas usando nosso exemplo de semelhança de filme no início do curso, certo? Se usássemos apenas a filtragem colaborativa baseada em itens usando métricas de similaridade de cosseno como fizemos antes, teríamos obtido recomendações muito melhores com uma abordagem muito mais simples. E isso funcionou. Então ALS é um algoritmo mais complicado, mas às vezes complicado nem sempre é melhor. Este é um bom exemplo disso. E assim, você sabe, sempre meça os resultados, certifique-se de que você está obtendo os resultados esperados. Joe diz, não confie cegamente nos resultados quando está tentando fazer análise de dados em grandes conjuntos de dados. Porque pequenos problemas nos algoritmos podem se tornar grandes à medida que você joga mais dados nele. E muitas vezes, o problema real é a qualidade de seus dados de entrada. No nosso caso, esse não é o problema. Os dados que estamos colocando já foram limpos. Então, são dados de alta qualidade. Mas muitas vezes o ditado “Lixo entra, lixo para fora” se aplica aqui, certo? Então, se você está transmitindo dados não filtrados que contêm um monte de informações espúrias de robôs e coisas assim, ou pessoas que não são pessoas reais ou pessoas tentando jogar o sistema. Isso vai estragar seus resultados também. Mas isso está ficando mais na prática do aprendizado de máquina do que qualquer outra coisa. A lição aqui, porém, é que, mesmo que o faísca contenha alguns algoritmos empolgantes, eles nem sempre serão o ajuste certo para seus dados. Portanto, não confie cegamente no que a faísca oferece no ML Lib. No entanto, ML Lib ainda é realmente útil em geral. Meio que começou com um mau exemplo lá porque ALS é uma espécie de coisa duvidosa com ele para o MovieLens Dataset de qualquer maneira. Mas o resto dos algoritmos são mais simples e eles farão o que você espera. Então vamos cortar uma mudança para uma nota mais alta usando Sparks ML Lib e mostrar-lhe algo que é mais adequado para. 52. Regression linear com MLLib: Então vamos mudar as engrenagens para um algoritmo mais confiável na biblioteca Spark ML, o algoritmo de regressão linear, é uma coisa bem simples. O que é regressão linear? Bem, se você é novo no mundo do aprendizado de máquina, esse pode ser um novo termo para você. Em poucas palavras, a regressão linear é apenas ajustar uma linha a um conjunto de dados. E uma vez que você tem essa linha, essa é uma espécie de linha melhor para um conjunto de observações. Você pode usar essa linha para prever novos valores para coisas que você nunca viu antes. Por exemplo, nesta pequena ilustração aqui temos medidas dos pesos das pessoas e suas alturas traçadas umas contra as outras. Então você pode imaginar tentando prever a altura de alguém com base em seu peso uma vez que você realmente tem essa linha, aquela linha vermelha que é ajustada a esses dados observacionais. Basicamente, você pega todos os pontos de dados observados da coisa que você está tentando prever. Neste caso, altura com base em algum atributo, que neste caso seria peso. E se você plotar todos eles juntos e encontrar a linha que tipo de encaixe esses dados o melhor. Você pode então usar a equação dessa linha para prever as alturas de novas pessoas apenas com base em seu peso. Então isso acaba com algum tipo de fórmula de inclinação para a linha, certo? Então basicamente estamos dizendo que temos uma inclinação de 0,60 mais uma interceptação y de 1,23. E podemos usar esses atributos para fazer previsões no futuro. Por que lhe chamaram Regressão? É meio confuso para ser honesto. Regressão meio que implica que você está indo para trás no tempo, mas isso não é realmente sobre o que se trata. Há alguma história por trás desse termo, mas tente não ficar muito preso a isso. Basicamente, a regressão linear é apenas ajustar uma linha aos dados históricos. Talvez você possa pensar nisso como a parte de regressão e usar essa linha para prever novos pontos de dados para coisas novas que você nunca viu antes. Como é que funciona? Bem, geralmente usa algo chamado “mínimos quadrados”. É uma técnica matemática para uma minimização do erro quadrado entre cada ponto e a linha. Então, quando ajustamos uma linha para esses pontos de dados observados, para cada ponto, haverá algum erro entre onde esse ponto realmente está e onde a linha diz que deveria estar. E nosso objetivo na criação dessa linha é minimizar o erro quadrado entre cada ponto e essa linha. É quadrado porque assim o erro positivo ou negativo não faz diferença. É tudo a mesma coisa. Então é um pouco interessante matematicamente quando você está pensando em como isso funciona em duas dimensões na verdade. Então, se você se lembrar da equação de interceptação de inclinação de uma linha que é y é igual a mx mais b, onde m é a inclinação e b é o intercepto y. Voltando para o ensino médio lá para muitos de vocês, verifica-se que a inclinação pode ser expressa como a correlação entre as duas variáveis vezes o desvio padrão em y dividido pelo desvio padrão em x. E isso é um monte de bobagem estatística para muitos de vocês. Mas eu só acho que é interessante como alguns desses conceitos estatísticos, como desvio padrão, têm um significado matemático real que pode ser usado para algo tão simples quanto um ajuste de uma linha de dados. Então não é que o desvio padrão seja um corte arbitrário que alguém inventou. Na verdade, tem um verdadeiro significado matemático, o que para mim é interessante, pelo menos. E você também pode calcular a interceptação como apenas a média de y menos a inclinação vezes a média de x. Então essa é outra maneira de calcular isso. Então, dadas essas percepções matemáticas, é bastante simples ajustar uma linha a um conjunto de dados em duas dimensões. Se você está apenas lidando com x e y, as coisas ficam um pouco mais complicadas quando você adiciona mais dimensões na mistura. Então é uma espécie de exemplo fabricado para ser apenas prever algum atributo baseado em algum outro atributo como altura baseada no peso. mundo real, você geralmente está lidando com vários atributos. Então você pode estar tentando prever a altura de alguém baseado em seu peso, onde vive, quantos anos tem, seja lá o que for, certo? Então isso geralmente mais do que uma coisa. E isso entra em toda essa estranheza multidimensional. E uma maneira de lidar com isso é a descida de gradiente estocástica. É outro algoritmo que você vê muito no mundo do aprendizado de máquina e também no aprendizado profundo. E basicamente eu não quero entrar nos detalhes de como ele funciona, mas ele meio que, ele olha para esses contornos em dimensões mais altas, se você quiser. Então ele encontra iterativamente o tipo de linhas de melhor ajuste neste espaço multidimensional para você. Então, o mesmo conceito, só um pouco mais complicado. Mas usando Spark dot HTML, Não é complicado em tudo. Você não tem que se preocupar com como funciona, porque tudo faz isso para você. Tudo que você tem a fazer é dizer Val e definir algum valor para um novo modelo de regressão linear, definir um monte de hiperparâmetros como o parâmetro de regularização ou o parâmetro de rede elástica, o número máximo de iterações, a tolerância de convergência . E como sempre, o aprendizado de máquina é sujo. O pequeno segredo é que nem sempre há uma boa maneira de adivinhar o que esses valores devem ser para um determinado conjunto de dados. Muitas vezes você chega aos valores certos apenas através de tentativa e erro. Mas uma vez que você tem um modelo de regressão linear configurado e configurado, você apenas treina o modelo e faz previsões usando tuplas que consistem em um rótulo e um vetor dos recursos que estão usando para prever esse rótulo. Então, neste caso, o rótulo seria o valor que você está tentando prever. Nós geralmente enquadrar que é o nosso eixo y. Uma feição está no seu eixo x ou nos outros eixos. Essas são as coisas que você está usando para tentar fazer essa previsão. Então basicamente você treina o modelo com um monte de pontos conhecidos. E então você tenta prever novos valores de rótulo y para determinados Xs ou valores de feição usando essa linha para o modelo criado. E você não tem que se preocupar com o que é essa frase. Você pode obtê-lo se quiser, mas você sabe, é como qualquer outro modelo, você apenas cria o modelo e uma vez treinado, você usa isso para fazer previsões. É tudo muito simples. E ele pode, como dissemos, trabalhar com mais de duas dimensões se você tiver vários recursos e é aí que o poder dele realmente entra. Agora existem alguns gotchas usando a regressão linear SGD, que é o que isso está usando. Um deles é que ele não impede o dimensionamento de recursos bem, então ele assume que seus dados são semelhantes a uma distribuição normal e como eles são definidos. Então, se não for, normalmente deve dimensionar esses dados para caber dentro de um intervalo que é mais comparável à sua curva de sino padrão aqui. E você quer ter certeza de que todos os seus recursos também são dimensionados de forma semelhante. Então, se você tem um recurso que é enorme e outro recurso que é um valor pequeno. Você precisa dimensionar tudo para baixo para esta escala semelhante no intervalo semelhante para que o algoritmo funcione bem. Isso significa que você precisará dimensionar seus dados para baixo e, em seguida, fazer backup novamente quando terminar. Então, você treinará seu modelo com base nesses dados de feição dimensionados. E então você tem que se lembrar de escalá-lo novamente usando qualquer que seja o inverso dessa relação quando você está realmente exibindo os valores finais que são previstos por este modelo. Além disso, o algoritmo pressupõe que sua interceptação y é 0, a menos que você chame ajuste interceptação true nele. Se você está lidando com uma situação em que você não acha que sua linha de melhor ajuste vai passar pela origem 0, 0, você precisa chamar o ajuste interceptado verdadeiro para obter bons resultados. Então vamos experimentá-lo. O que vamos fazer é fabricar alguns dados falsos para velocidades médias de página e receita gerada a partir de dados de sessão em uma loja online. Isso é algo que realmente tivemos que fazer na Amazon. Havia uma hipótese há muitos, muitos, muitos, muitos, muitos anos atrás, que o tempo de carregamento da página tinha uma relação muito direta sobre quanto dinheiro o cliente gastou. E agora sabemos que isso é verdade e que é uma espécie de sabedoria comum em toda a indústria agora. Mas naquela época tínhamos que descobrir isso. Então vamos descobrir isso recentemente, dados falsos. Então nós vamos saber que há um relacionamento lá dentro por causa de como nós o fabricamos. Mas dado que vamos tentar construir um modelo de regressão linear usando o Spark ML e ver se podemos prever receita com base na velocidade de página usando este modelo linear. Então vamos mergulhar e tentar. 53. [de ação] tendo um efeito linear com o Spark: Então vamos percorrer nosso exemplo de uso de regressão linear no Spark e ver se ele funciona, abra o script de conjunto de dados de regressão linear. E antes de mergulharmos no código, vamos ver os dados com os quais estamos lidando primeiro, isso é sempre um bom primeiro passo, certo? Então, se entrarmos em nossos materiais do curso e ir para a pasta de dados, arquivo txt ponto de regressão aqui. Vamos apenas familiarizar-se com o que tem nele. Agora, como você se lembra, o que estamos tentando fazer é prever quanto as pessoas gastam com base no PageSpeed. Então, a coisa que estamos tentando prever é anunciado gasto e a quantidade que estamos, nosso recurso que estamos tentando prever que em é PageSpeed. Então, nesta primeira coluna, esses números representam o valor gasto, mas é normalizado e reduzido. Então isso é normalizado para caber em uma distribuição de curva de sino. É por isso que você está vendo coisas como valores negativos aqui. Mesmo que você não veria um valor negativo gasto a menos que alguém tenha um reembolso ou algo assim, certo? Então, como dissemos nos slides, você precisa ter certeza de que está dimensionando seus dados para esse intervalo consistente. E, em seguida, lembrar-se de redimensionar isso novamente quando você terminar. Essa segunda coluna vai corresponder aos nossos dados de recursos. Então, nesse caso, isso vai ser a velocidade da página. Novamente, nós normalizamos isso e reduzi-lo para o que caberia em uma distribuição de curva de sino. Portanto, estes números por si só não são valores brutos. Eles foram reduzidos e isso é uma espécie de engenharia de recursos que chamamos no mundo do aprendizado de máquina é um passo muito importante e obter bons resultados. Muitos modelos de aprendizado de máquina exigem que seus recursos e seus rótulos sejam reduzidos em intervalos semelhantes e, às vezes, ainda mais especificamente, centralizados em torno de 0 ou entre 01. Ele meio que tem que ler a documentação do algoritmo que você está usando para se certificar de que seus dados estão no formato certo. Caso contrário, não vai funcionar. Você vai ter resultados muito estranhos e ele vai estar se perguntando por quê. Por isso não te esqueças disso. Tudo bem, então vamos mergulhar no código. Então o nosso esquema de regressão vai corresponder às nossas duas colunas de informação de precisão dupla. Lá temos o rótulo, que novamente corresponde ao nosso valor gasto e nossos recursos sublinham RA, que corresponde às velocidades da nossa página. E, novamente, estes são reduzidos para uma distribuição normal. Tudo bem, nós acionamos nossas configurações de logger, nós falamos sobre nossa SparkSession, nada de novo lá. E definimos um esquema de regressão que corresponde à classe de caso que acabamos de falar. Então, podemos importar isso do disco usando uma interface DataFrame. Então nós apenas dizemos faísca dot ler com um separador vírgula usando esse esquema. E nós carregamos a partir do arquivo txt ponto de regressão de dados barra que nós apenas olhamos e, em seguida, lançá-lo conjunto de dados usando a classe de caso do esquema de regressão. Agora as coisas ficam interessantes. Então, o formato que é esperado por este algoritmo na biblioteca ML é muito específico e muitas vezes você precisa se referir ao código de exemplo que vem com o Spark para descobrir exatamente o que ele quer. Foi assim que fiz para conseguir este código para ser honesto. Então, o que ele espera é que você crie um objeto VectorAssembler, que também é parte das bibliotecas de aprendizado de máquina. E você deseja definir em suas colunas de entrada como uma matriz de suas colunas de feição. Agora, no nosso caso, temos apenas uma coluna de feição, é nomeada feições sob pontuação bruta. Então nós apenas passar em uma matriz com que um nome de coluna apresenta sublinhado cru. Se você tivesse mais de um recurso, se você tivesse um problema multidimensional, você passaria os recursos adicionais aqui também. E então esse montador vetorial irá produzir em uma nova coluna, algo chamado feições. E isso é realmente o que vamos passar para o nosso modelo. Então, uma vez que temos este assembler, que é este objeto vetorial assembler, vamos chamar transformar nele alimentando esse conjunto de dados de nossos dados brutos. E ele vai transformar isso em que apresenta coluna de saída. Vamos selecionar a partir dela a coluna de rótulo e a coluna de recursos que são produzidos. Então agora temos um DataFrame chamado df que contém apenas rótulos e recursos. E os rótulos corresponderão novamente ao nosso valor gasto e colunas para o PageSpeed. Então, novamente, vou reduzir a escala para uma escala uniforme. Tudo bem, então agora que temos isso, o que vamos fazer para medir o desempenho deste algoritmo é dividir esses dados em dois conjuntos. Vamos reservar metade desses dados para treinar nosso modelo. E vamos colocar de lado a outra metade para testar o modelo. Então a idéia aqui é que vamos treinar este modelo usando apenas metade dos dados que temos. E, em seguida, usando esse modelo treinado, veremos quão bem ele pode prever os valores corretos conhecidos na outra metade dos dados. E vamos medir esse erro para ter uma noção de quão bom nosso modelo realmente é que pode nos informar se precisamos tentar hiperparâmetros diferentes ou não, por exemplo, ou limpar melhor nossos dados, certo? Então, extraímos a primeira divisão disso de divisões aleatórias e chamamos isso de DataFrame de treinamento. E o segundo bloco de teste lá vai ser o teste DataFrame. Então, a divisão aleatória apenas divide um DataFrame usando uma matriz de porcentagens que você dá a ele. Neste caso, 5050. Tomamos esse primeiro DataFrame resultante e chamamos de treinamento Tf e o segundo DataFrame resultante e chamamos de teste df. E isso é apenas baseado em atribuir aleatoriamente cada linha de d f em um ou dois desses DataFrames. Então agora temos tudo. Precisamos criar nosso modelo de regressão linear. E vamos em frente e criá-lo. E a regressão linear, vamos chamar-lhe LIR. E dissemos todos os hiper-parâmetros. Novamente, eu acho que eu apenas tirei estes fora da documentação para lugares onde você pode querer começar a partir das amostras. Novamente, no mundo real, você gostaria de iterar sobre estes e descobrir qual combinação de parâmetros produz os melhores resultados. Uma vez que temos nosso objeto, chamamos ajuste sobre ele passando em nosso DataFrame de treinamento que caminho que nós reservamos para treinar o modelo. E então pegamos esse modelo treinado e fazemos previsões sobre ele. Então pegamos nosso modelo e chamamos transformá-lo, passando em nosso teste DataFrame. E isso criará uma nova previsão completa DataFrame que conterá valor previsto gasto com base no PageSpeed visto no conjunto DataFrame de teste. Agora, o que é interessante aqui é que podemos comparar nosso valor previsto gasto com o valor real gasto que está vivendo em nossos valores de teste DataFrame nos rótulos que temos lá. Note que estou pegando aqui. Não é estritamente necessário para este exemplo simples, mas se você fosse fazer coisas usando esse conjunto de dados de previsões completas repetidamente, você gostaria de armazenar isso em cache para acelerar isso, certo? Então, uma vez que você tenha um modelo treinado e um conjunto de previsões baseadas nele, geralmente falando, você provavelmente vai querer armazenar esses resultados para que você possa usá-los repetidamente, certo? Neste caso, vamos apenas arrancar as previsões e rótulos depois de clicar que de volta a partir das previsões completas DataFrame. E vamos chamar isso de previsão e rótulo. E depois ligamos isso de volta ao guião e imprimimos todos. Então nós podemos apenas dar uma olhada no que os valores reais previstos e reais onde para cada ponto, você provavelmente pode adivinhar o que um bom exercício para o leitor aqui seria em que seria realmente fazer o trabalho de comparando esses valores preditos com os valores reais e realmente medindo esse erro do DataFrame de teste. Mas, por enquanto, vamos apenas olhar para os resultados porque este não é realmente um aprendizado de máquina correspondente. É claro que se trata de usar o Spark. Então, vamos clicar com o botão direito do mouse no conjunto de dados de regressão linear e executá-lo novamente . E funcionou. Novamente, não temos um ou pelo menos não fizemos o trabalho para saber se estas são previsões razoáveis ou não. Mas estas são previsões. Então você pode ver a saída aqui. Novamente, eles são reduzidos para qualquer fator de escala que usamos quando pré-processamos os dados. Então, a fim de fazer bom uso disso, teríamos que redimensioná-lo novamente. Mas parece que funcionou. Estes parecem valores reais e dentro de um intervalo razoável de valores. Então, aí está. Regressão linear em um conjunto de dados usando o Apache Spark. Então, novamente, o poder disso é que você pode pegar um conjunto de dados verdadeiramente massivo e executar regressão linear nele e criar um modelo usando todo o poder de todo o cluster. Então o céu é o limite aqui, praticamente literalmente. Tudo bem, então isso é aprendizado de máquina no Spark. Resumindo, você vai descobrir que a maioria dos modelos funciona de forma semelhante. Você acabou de criar um objeto modelo com um monte de hiperparâmetros. Você ajusta esse modelo a alguns dados de treinamento. E então você pode transformar esse modelo com dados para os quais deseja fazer previsões. E é muito fácil de usar. Então é isso. Vamos seguir em frente. 54. Prede valores com o início com o Decreto no Spark: Então, para o seu próximo desafio, vamos usar o Spark com alguns dados do mundo real aqui vamos tentar prever valores imobiliários usando árvores de decisão, que é outra técnica de aprendizado de máquina semelhante à regressão. Ele também pode ser usado para fins de regressão. E Apache Spark para ser capaz de aumentar a escala se precisarmos. Então, estamos recebendo nosso conjunto de dados em um conjunto de dados que tem o preço por unidade de área. Eles chamam de pings de onde isso vem, baseado em um monte de atributos de casas. E isso vem de Taiwan, de Nova Taipei City. São dados reais e aqui está o crédito necessário para quem inventou esse conjunto de dados. E se você quiser explorar mais sobre o próprio conjunto de dados e ler mais sobre seu formato. Siga o segundo link que vem do repositório de dados da UCI. Esse é um repositório muito útil de conjuntos de dados de aprendizado de máquina para que você possa usar para experimentação e brincadeiras e aprender. Então esse é um bom recurso lá, velas e outros também, se você estiver procurando por mais fontes de conjuntos de dados com dados do mundo real. Então é assim que os dados se parecem. Eu realmente limpei um pouco para você apenas para dar-lhe nomes de colunas mais razoáveis e para convertê-lo formato CSV para tornar sua vida um pouco mais simples para este exercício, ele consiste em várias colunas de dados em formato CSV. A primeira coluna é apenas chamado número é o número associado com essa casa. E então para cada casa temos a data de transação quando foi vendida, a idade da casa, a distância para MRT, que é na verdade a distância para o sistema de transporte público local. O número de lojas de conveniência nas proximidades, que eu acho que é um grande negócio em Taiwan, parece, e a latitude e longitude da própria casa. E finalmente, a coisa que estamos tentando prever, o preço da área unitária. E é claro que é uma moeda local. Então não leia muito sobre o que isso realmente significa. Seu desafio é prever o preço por unidade de área com base na idade da casa, distância até o transporte público e o número de lojas de conveniência próximas. Só para tornar isso um pouco mais fácil, vou jogar fora alguns dos dados que seriam mais difíceis de analisar como a localização real e coisas assim. Obviamente, o número real da transação, que realmente não importa, nem a data para nossos propósitos. Então vamos mantê-lo simples e apenas lidar com dados numéricos aqui. Sua estratégia será usar um regressor de árvore de decisão em vez de um objeto de regressão linear de Spark dot SML, eles trabalharam muito da mesma maneira. Se você quiser, você pode ir ver a documentação na documentação do Spark on-line, mas é praticamente a mesma sintaxe, apenas um nome diferente. Enquanto a regressão linear funciona computando essas inclinações e intercepta para linhas, uma árvore de decisão trabalha com uma estratégia diferente. Basicamente, está construindo esta árvore de decisões que faz onde em cada ponto da árvore diz, este atributo é menor ou maior do que algum valor? E ele trabalha seu caminho para baixo tomando essas decisões com base nessas decisões binárias para tentar chegar a uma previsão final de qual será o seu rótulo final previsto. Então, apenas uma maneira diferente de obter o mesmo tipo de resultado no final do dia, a razão pela qual estamos indo com árvores de decisão é dupla. Um, apenas para expor você a outro algoritmo ML que está disponível no Spark. E também porque as árvores de decisão são menos sensíveis a ter dados que estão em diferentes escalas. Não precisamos realmente nos preocupar em reduzir todos os nossos dados para serem normalizados e, no mesmo intervalo, para obter os melhores resultados com uma árvore de decisão, ele pode lidar com isso muito melhor. Então, para começar, comece com uma cópia da classe Scala conjunto de dados de regressão linear dataframe que olhamos anteriormente. E isso será um ponto de partida muito útil apenas modificando isso um pouco, você deve ser capaz de fazer isso. E também note que temos uma linha de cabeçalho nesse arquivo CSV, então não há necessidade de você para código rígido é esquema para ler que em, podemos apenas ter o leitor de faísca para fazer isso automaticamente se dissermos que o cabeçalho existe, alguns trechos úteis que estamos passando por isso. Primeiro de tudo, em nosso exemplo anterior, nós tínhamos apenas uma coluna de feição única pecado e você não precisa ter apenas uma. Você pode realmente ter várias colunas de entrada em um montador vetorial. Então lembre-se que você também pode dizer definir matriz de chamadas de entrada, e, em seguida, uma lista de colunas, não apenas uma única coluna se você tem vários recursos como nós fazemos aqui. E lembre-se ao ler o arquivo em, em vez de especificar um esquema real, você pode simplesmente dizer cabeçalho true e inferir o esquema true. E vamos ler tudo desde esses nomes de coluna de cabeçalho correspondam ao que você tem na sua classe de caso, tudo vai correr bem. A única coisa sobre o regressor da árvore de decisão você não vai precisar de todos esses hiperparâmetros extras que nós especificamos nas árvores de decisão de regressão linear têm um conjunto diferente de hiperparâmetros, mas não há problema em apenas não especificar eles e ir com os valores padrão. Isso é bom. Então você pode tirar todo esse código extra no exemplo de regressão linear. E também note que há uma função col rótulo conjunto. E isso permitirá que você especifique uma coluna de rótulo que não é nomeado rótulo. No nosso caso, não é nomeado rótulo. É chamado de preço de unidade de área ou algo assim. Então isso deve ser tudo o que você precisa. Então vá e dê uma chance. E na próxima palestra, vou mostrar-te a minha solução e ver o quão perto chegas. 55. Solução de exercício: prevendo uma propriedade com as árvores de decisão com centel: Muito bem, vamos analisar a minha solução para prever o valor de uma casa por área com base em alguns atributos bastante incomuns dessas casas em Taiwan. Como sempre com o aprendizado de máquina, você deve começar estudando a natureza dos dados que você recebe. E para nossos propósitos, já que o status já foi limpo, nós só queremos isso por ter uma referência útil a esses nomes de colunas. Porque combiná-los exatamente vai ser muito importante enquanto escrevemos nosso pequeno script aqui para carregá-lo e convertê-lo para o formato que nosso algoritmo espera. E você sabe, é sempre uma boa idéia, apenas verificar novamente os dados, certificar-se de que não há nada de inesperado neles. Assumimos que são todos números. Então, uma varredura rápida apenas para ter certeza de que esses números parecem estar em mais ou menos o mesmo intervalo e não têm nenhum estranho como valores ausentes ou vales no formato errado, como valores de string aleatórios aqui e ali. Isso vai poupar-te algum problema. Este conjunto de dados, no entanto, já foi limpo para você. Assim, a parte difícil do aprendizado de máquina já está cuidada neste caso, com essa lista, vá para o código. Então eu acabei de começar copiando o conjunto de dados de regressão linear dataframe arquivo Scala e eu chamá-lo de um imobiliário dots gala vez. Mudança principal aqui. Em primeiro lugar, estamos usando um algoritmo diferente para regressão. Estamos importando ou ponto apache ponto faísca ponto ponto HTML regressão ponto ponto regressor da árvore de decisão desta vez, assim como demos uma dica nos slides, se você quisesse usar uma regressão linear ainda poderia, seria Na verdade, ainda funciona. Mas, novamente, só queremos expô-lo a um novo. E as árvores de decisão são menos sensíveis a ter diferentes intervalos de valores nas feições e nos rótulos. Então declaramos um novo esquema de regressão aqui. E como podem ver, é muito mais complicado. Todos os nossos recursos têm nomes diferentes e há mais de um deles agora. Então nós realmente temos cada uma das colunas em que os dados de entrada que estão chegando. E nós mapeamos isso assim. Então temos o nome da coluna NO, que significa número. Estamos assumindo essa data de transação inteira. Vamos chamar essa casa dupla, idade de casal, e et cetera, et cetera. Esses nomes apenas correlacionam-se com esses nomes de coluna no cabeçalho CSV propriamente dito. Tudo bem, seguindo em frente. Nada diferente lá. Quando nós realmente carregar no arquivo e vamos dizer cabeçalho opção true e opção no primeiro esquema verdadeiro, em vez de dar-lhe um esquema codificado que permitirá tirar proveito dessa linha de cabeçalho no arquivo CSV. Então isso torna a vida um pouco mais simples lá. Não precisamos codificar esse esquema duas vezes, o que é irritante quando isso acontece. Em seguida, construímos nosso VectorAssembler como fizemos antes. E a diferença aqui é que em vez de um único recurso, ou eu acho que nós chamamos de recursos brutos ou recursos Ron, eu acho que originalmente nós realmente temos três características diferentes e este exemplo, idade da casa, distância para MRT e número lojas de conveniência. Novamente, estamos combinando isso com os nomes de classe de casos como aqui. Então a afirmação do problema era prever o preço da área unitária com base na idade da casa, distância para MRT um número lojas de conveniência. Então estamos jogando fora as colunas adicionais, você não precisa delas. Estamos apenas definindo as colunas de entrada para aqueles que nos preocupamos que realmente queremos usar como recursos para fazer uma previsão de. E vamos chamar a coluna de saída de feições quando terminarmos, tudo bem. E vamos, além disso, selecionar o preço da coluna de área unitária porque isso vai ser nossos rótulos. Então, neste ponto, o que vamos acabar com é uma coluna chamada preço da área unitária. Isso será o que estamos tentando prever, os rótulos. E uma coluna de recursos que contém apenas uma lista de recursos. Então essa coluna conterá no formato de lista, a idade da casa, a distância para MRT e o número de lojas de conveniência. E esse é o formato que nosso modelo espera. Então temos que nos conformar com isso. Como antes, dividimos isso em um conjunto de treinamento e um conjunto de dados de teste. E agora vamos construir o nosso modelo que é chamado de regressor de árvore de decisão. Eu suponho que eu deveria ter mudado o nome da variável para outra coisa, então LIR, eu acho que deveria ter sido. Mas seja o que for, tudo bem. Nós definimos explicitamente as colunas de feições e nomes de coluna de rótulo aqui. Recursos é o padrão, então tecnicamente eu não tinha que fazer isso, mas o padrão para rótulo é rotulado não preço de área unitária. Então eu tive que dizer explicitamente ao meu modelo que o nome da minha coluna de etiquetas é o preço da área unitária para isso funcionar. Depois disso tudo funciona da mesma maneira. Então nós apenas dizemos ajuste, passando em nosso DataFrame de treinamento. E fazemos um conjunto de previsões transformando isso com nossos dados de teste. E como antes, nós apenas passamos e selecionamos. Nós mudamos o nome da coluna dos rótulos aqui novamente e coletamos de volta e repetimos através dele e imprimimos todos eles. E o que isso vai fazer como um comentário diz, é imprimir o valor previsto eo valor real para cada casa em nosso conjunto de dados de teste. Então vamos ver se funciona. Clique com o botão direito no setor imobiliário e execute. E nós temos saída. Legal. Então, apenas passando por isso de imediato, muitos destes parecem bastante razoáveis. Nós previmos que tinha 50 para o que quer que seja, e é realmente 55. E na maior parte, o modelo funcionou muito bem. Quero dizer, há obviamente maneiras de quantificar o quão bom o modelo está usando métricas como RMSC. Mas este não é um curso de ciência de dados ou aprendizado de máquina. Então eu não vou entrar nisso. Eu fiz alguns deles muito errados no entanto. Então, para este, ele previu um valor de 36, mas o valor real era um 117. Então, claramente, há mais para o que define o valor de um lugar além de quão perto de uma loja de conveniência você está em. Coisas como o quão perto você está da estação de trem mais próxima. Então, não é muito surpreendente que não seja um modelo incrível porque nós não demos um monte de dados incríveis, mas ele funciona surpreendentemente bem na verdade, por ampliar, ele ficou muito perto na maioria desses resultados tão interessantes. Então aí está, espero que tenha superado. vez, esta é apenas uma maneira de o fazer. Se você tomou uma abordagem diferente, tudo bem também. Apenas certifique-se de que você tem saída semelhante e vamos chamá-lo de bom. 56. A API DStream para transmissão de Spark Streaming: E casos de uso cada vez mais comuns, o Spark está lidando com dados de streaming. Então, até este ponto do curso, falamos sobre a análise de conjuntos de dados off-line de uma maneira em lote. Então temos esses dados piloto e queremos analisá-los ou processá-los de alguma forma. Mas no mundo real, os dados nunca param de chegar, certo? Então é aqui que entra o Spark Streaming. Ele permite que você ingerir fluxos de dados em tempo real. Por exemplo, você pode ter uma frota de servidores gerando informações de log, sendo canalizado para o cluster do Spark, sendo analisado à medida que ele entra. Talvez você esteja transformando esses dados e armazenando-os em outro lugar em algum outro banco de dados. Talvez você esteja agregando ao longo do tempo e procurando coisas sobre as quais deseja ser alertado quando elas acontecem. De qualquer forma, o streaming é um caso de uso muito importante no mundo dos negócios nos dias de hoje. Então, vamos mergulhar e ver como o Spark Streaming pode ser usado para analisar dados conforme eles são criados e tomar medidas sobre eles conforme necessário. Então, nesta seção, vamos apresentá-lo ao Spark Streaming. Este é um caso de uso muito comum para o Apache Spark atualmente, onde estamos lidando com fontes de streaming de dados e não apenas transformando um monte de dados de uma só vez em um processo em lote, mas monitorando continuamente os dados recebidos e fazendo algo para ele em tempo real como ele é recebido. Então, um exemplo comum disso seria processar dados registrados vindos de um site ou servidor, ou talvez toda uma frota de servidores que alimentam um site. Esses dados nunca param de chegar, certo? Então não há como realmente simples conjunto de arquivos de log. Então você pode apontar para e dizer, Ei, vá analisar esse pedaço de dados de log. Está sempre a chegar, há sempre novas informações a ser recolhidas o tempo todo. E talvez você queira agregar e analisar isso em algum intervalo ou janela de informação, certo? Talvez você queira configurar algum tipo de alarme onde, se você estiver vendo um monte de erros em seu site, algo é notificado automaticamente, certo? Então, em vez de apenas esperar por uma análise noturna desses dados, estamos analisando esses dados continuamente à medida que eles chegam e fazendo algo com eles. Esses dados não precisam vir de um arquivo bruto que pode vir de alguma porta que está recebendo dados TCP. Ele pode vir do serviço Amazon Kinesis. Ele pode vir de um HDFS ou algum sistema de arquivos distribuído que pode vir de Kafka, vêm de Flume e todos os tipos de outras fontes de dados para assim Spark Streaming pode se integrar com um monte de sistemas diferentes, não apenas arquivos de texto e analisar que os dados à medida que entram. E pode não ser apenas sobre analisar e agregar dados. Pode ser sobre transformá-lo e apenas enviá-lo para outro lugar. Talvez tudo o que o Spark Streaming esteja fazendo no seu caso esteja pegando dados de log recebidos, extraindo as informações que você gosta, estruturando esses dados e, em seguida, armazenando-os em um banco de dados em algum lugar. Esse é um caso de uso perfeitamente válido para streaming do Spark também. E a coisa boa sobre Spark streaming, em vez disso, ele tem um controle de recursos. Portanto, se o seu stream for inativo, se o cluster for inativo por algum motivo, ele terá uma maneira fácil de retomar automaticamente de onde parou automaticamente. Então isso é um bom recurso, com certeza. Então vamos começar a falar sobre a antiga API DStream para Spark Streaming. Basicamente, o Spark Streaming tem um histórico histórico, se preferir, a interface original onde foi chamado DStreams, e foi baseado na interface RDD antiga. E porque era baseado em RDDs, ele estava centrado em torno do que chamamos de microlotes. Então ele só lidou com esses pedaços de dados que foram representados como RDDs. E processou esses pequenos pedaços completamente. Tecnicamente falando, não era verdade em streaming. Ele não estava realmente operando em dados em uma base de campo ou linha por linha. Estava a juntar coisas no que chamamos de micro lotes. Agora, no mundo real, isso geralmente não é um problema se você tiver uma latência de alguns segundos em vez de processamento imediato para a maioria dos aplicativos, isso realmente não importa. Mas essa foi uma das principais coisas que fazem com que eles se afastem dessa interface ao longo do tempo. E bem, coberturas por razões históricas aqui. Mas passaremos para a API de Streaming Estruturado mais moderna depois disso. De qualquer forma, aqui está um exemplo de como o de Streaming pode ser parecido. Assim, você configuraria um contexto de streaming em vez de um SparkContext. E isso é segundos um lá significa que ele vai processar as coisas um segundo de cada vez. Então você terá esses microlotes contendo 1 segundo valor de novos dados que vamos processar como parte do nosso script. Podemos então dizer fluxo de texto soquete ponto stream. E isso vai dizer a ele para ouvir a porta 8888 para dados de texto que estão sendo enviados nessa porta TCP. E então tudo o que ele vai fazer é filtrar essas linhas de entrada para linhas que contêm o erro de palavra. E se ele vir uma linha que contém o erro de palavra, ele irá imprimi-lo. Uma vez que você configurou isso, você só tem que chamar stream dot start para realmente chutá-lo fora e transmitiu para fora uma semana de término para esperar que alguém para pará-lo. Então é um pouco mágico, pouco estranho envolver sua cabeça em torno deste paradigma, certo? Então você tem que lembrar que não estamos processando um único pedaço de dados. Este gráfico acíclico direcionado que estamos construindo aqui para processar esses dados em dados capturados e filtrá-los e imprimi-los se ele, se ele passar esse filtro, isso será aplicado repetidamente a cada 1 segundo de dados recebidos automaticamente. Nós não temos que escrever um loop em algum lugar que diga continuar fazendo isso a cada 1 segundo repetidamente. Spark Streaming faz isso para você. Então essa sintaxe aqui pode parecer um pouco estranha e mágica no início, porque meio que funciona no fluxo. Você não tem que pensar muito nisso, mas funciona. Então, em um nível alto, é assim que funciona. Algumas pegadinhas. Então lembre-se que seus RDDs só vão conter um pequeno pedaço de dados recebidos. Agora o que você pode fazer é operações com janelas. Com uma operação em janelas, você pode combinar automaticamente os resultados de vários lotes sobre uma janela de tempo deslizante. Portanto, existem funções como janela ou reduzida por janela ou ReduceByKey e janela. Assim, essas funções de janela permitem que você faça uma redução ao longo de algum tempo retornando no passado. Então eu poderia dizer voltar para o último minuto, voltar para a última hora, voltar para o último dia, que quer que seja, e reduzir minhas informações com base nessa janela de informações. Assim, essa janela não precisa corresponder ao tamanho do lote que pode ser muito maior e ele irá automaticamente manter o controle desses resultados RDD, esses micro lotes, e aplicar sua operação sobre essa janela de tempo que você definido. Assim, ele automaticamente mantém essa informação ao redor para que você possa analisá-la conforme você avança. Além disso, algo que vale a pena falar é atualizar estado por chave. Isso permite que você mantenha um estado que se estende por muitos lotes à medida que o tempo passa. Portanto, se você precisar manter o controle de algum tipo de estado de execução enquanto processa essas informações no Windows ou em lotes, você pode fazer isso com atualizações estado por chave. Um bom exemplo disso seria executar algum tipo de contador e contagem contínua de algum evento ao longo do tempo desde que você iniciou o script. Então, se você precisa manter o controle de algo como o script é executado como um todo em vez de ao longo de alguma janela de tempo. Atualizar estado por chave, permite que você faça isso. Então vamos mergulhar em um exemplo simples aqui. Vamos rodar um script de streaming do Spark que só monitora os tweets ao vivo do Twitter. E vamos acompanhar as hashtags mais populares à medida que recebemos novos tweets. E para fazer isso, primeiro precisamos configurar uma conta de desenvolvedor do Twitter. Agora, algumas pessoas têm problemas para fazer isso depende de qual país ou de como você preenche o formulário. Que tipo de humor para o Twitter está em muito honestamente, então eu não tenho certeza se você realmente quer passar por isso sozinho. Você pode, se você quiser apenas ir para aplicativos dot twitter.com e aplicar para uma conta de desenvolvedor lá se você quiser seguir junto. Honestamente, acho que deveria me ver fazer essa próxima atividade porque, como eu disse, DStreams estão meio namorados. Agora, se você está apenas fazendo essa aula com o propósito de obter uma certificação, eu posso te prometer que não vai estar no exame de certificação, então você pode apenas querer me ver fazer essa atividade seguinte em vez de seguir adiante. Mas se você fizer isso, você pode simplesmente ir para aplicativos dot twitter.com login para conta de desenvolvedor. E então você pode criar as chaves de API e os tokens de acesso que você precisa para realmente consultar o Twitter e canalizar isso para o streaming do Spark. Então, para armazenar essas informações, suas credenciais, você precisará criar um arquivo txt twitter dot. E eu vou mostrar a vocês onde isso é quando passarmos por ele, ele só vai ter um nome de sua chave de consumidor e acesso a informações de token em cada linha e nosso script de driver, vamos ler isso e usá-lo para autenticar com Twitter. Nossa estratégia geral aqui, uma vez que tenhamos esse fluxo do Twitter estabelecido, nós vamos apenas extrair as mensagens eles mesmos. Há um monte de metadados que o Twitter também fornece. Mas nós vamos criar um Twitter utils dot create stream que vai estar usando uma biblioteca de terceiros que eu incluí com o curso para realmente conectar o Twitter e torná-lo parecido com um DStream. E, em seguida, vamos chamar tweets dot map para extrair o campo de texto em que chamando status dot getText. Então, neste ponto, teremos um novo RDD, um microlote, se você quiser, que contém apenas as mensagens de status de cada tweet recebido. Então, por exemplo, talvez um tweet diga Vote em hashtag bulímico negrito. E alguém poderia dizer um livro para eu gosto de botas grandes e eu não posso mentir e não votar em hashtag. Que iceberg? E alguém poderia dizer, o que você está louco? Hashtag, Bodhi MAC, ousado todo o caminho. E se você está se perguntando do que diabos eu estou falando aqui, isso foi um mal há vários anos. Basicamente, esqueci-me do que era a marinha, mas fizeram um concurso online para deixar a Internet nomear o seu novo navio. E claro que foi uma péssima ideia. O vencedor, é claro, foi pódio mic boldface, que eles não usaram. Mas eu acho que eles colocaram em algum tipo um pequeno resumo ou algo que estava na nave ou algo assim. De qualquer forma, este exemplo estamos tentando manter o controle das hashtags mais populares, certo? Então, neste caso, teríamos hashtag Booleano com ambos rosto aparecendo como número, o resultado número um com duas aparições e hashtag, qual iceberg seria o segundo resultado com uma aparência. Então estabelecemos nosso fluxo de mensagens de status. Em seguida, podemos usar flatmap para dividir isso em suas palavras individuais. Então, chamando FlatMap em que status micro lote, vamos então explodir isso em um RDD maior que tem uma linha para cada palavra que aparece. Então, por exemplo, o voto da mensagem para a macrofase de seu amigo hashtag, seria dividido em três linhas separadas. Vote no fundo hashtag de buffets. E já que só nos importamos com as hashtags, essa é a única coisa que estamos medindo. Podemos então chamar filtro para filtrar quaisquer linhas que não começam com o símbolo hashtag. Então isso reduzirá as coisas apenas para as hashtags que estão aparecendo. E nesse ponto podemos fazer nosso velho truque do caminho de volta na seção um ou seção para o que quer que fosse, onde podemos convertê-los em um RDD de pares de valor chave, onde a chave é a hashtag real e o valor é o número um. Isso nos permitirá mais tarde fazer uma operação de redução para contar todos com o que está acontecendo aqui. E vamos fazer isso sobre uma janela deslizante para tornar as coisas interessantes. Assim, a operação de redução irá somar todos esses juntos e nos dará uma contagem total de quantas vezes essa hashtag aparece. Mas estamos usando um riacho aqui, então não vamos dizer reduzir por chave. Temos que dizer em que período de tempo. E para fazer isso vamos dizer ReduceByKey e janela para executar essa operação de redução ao longo de uma determinada janela e intervalo de slide. Então vamos dizer ReduceByKey e janela, basicamente adicionando tudo. E quando você passa isso, você precisa explicitamente dar-lhe uma função para adicionar e remover elementos conforme ele vai. Isso é o que está acontecendo aqui nesta sintaxe aqui. E vamos dizer que vamos aplicar isso sobre uma janela de 300 segundos. São os últimos cinco minutos com um slide de 1 segundo. Então vamos deslizar nossa janela sobre uma a cada 1 segundo e olhar para os últimos cinco minutos de dados. Então o que isso vai fazer é recomputar essa redução que as hashtags do CONTIF a cada segundo, voltando por cinco minutos. E devemos obter um resultado que se pareça com isso se esses foram os nossos dados de amostra reais. Então, finalmente, só precisamos classificar e produzir os resultados. Vamos chamar uma transformação para classificar esse RDD com base no segundo campo, que é a contagem, e imprimi-los. E deve ser isso. Então vamos ver isso em ação. Note que temos algumas bibliotecas extras que estamos usando, algumas bibliotecas de terceiros. Vou te mostrar como isso é feito. E sim, vamos entrar no código e ver se funciona. Pode ser interessante. 57. Monitoramento em tempo real das Hashtags mais populares no Twitter: Tudo bem, então vamos ver esse exemplo de usar a antiga API do DStream e usar isso para descobrir as hashtags mais populares no Twitter agora. E se você quiser continuar, você pode tentar se você ir para aplicativos dot twitter.com ou desenvolvedor dot twitter.com, você vai pousar no portal do desenvolvedor para o Twitter. E se você ainda não tiver uma conta de desenvolvedor, ela o orientará pelo processo de solicitação de uma. E mais uma vez, não sei se vale a pena passar por isso. Em primeiro lugar, eles estão tornando cada vez mais difícil obter uma conta de desenvolvedor nos dias de hoje porque muitas pessoas estão usando-os para fazer coisas más com bots e outras coisas. Mas se você quiser passar por isso, basta dizer que está fazendo isso para fins educacionais para um curso on-line e listar o nome deste curso. Eles provavelmente vão te dar um bem rápido. Então, se você quiser fazer isso, vá em frente e solicite uma conta. Uma vez que você tem isso, você será capaz de criar ambos um conjunto de chave de acesso. Então vamos ver como isso se parece. Então, se você clicar em chaves e tokens, isso irá levá-lo a um lugar onde você pode obter ambas as suas chaves de acesso de consumidor, o público e secreto, e também um conjunto de tokens para um aplicativo. E uma vez que você tem isso, você vai abrir seu arquivo twitter dot txt em seus materiais de curso e colocá-los lá dentro. Então o meu é assim. Obviamente eu borrei as chaves reais porque eu não quero usar as minhas. Mas basta colar em sua chave de consumidor e segredo do consumidor e seu token de acesso e token de acesso secreto aqui para sua própria conta se você estiver acompanhando. E então o código, vamos pegar isso e usá-lo para autenticar com o Twitter. Tenha cuidado, porém, certifique-se de que você não tem nenhuma linha extra, não tem nenhum espaço extra antes ou depois dessas coisas que vão estragar as coisas. Número um problema que as pessoas têm com este. Uma vez que você tem isso, vamos voltar para a inteligência e abrir hashtags populares. E vamos ver o que está acontecendo aqui. Então, novamente, isso está usando algumas APIs mais antigas aqui, DStreams e RDD. Então nós temos uma função separada aqui para lidar com nosso nível de log aqui, para fazer isso de forma um pouco mais detalhada. Haverá acordo. Chamamos nossa função principal. A primeira coisa que fazemos é ligar para o Twitter. Tudo o que faz é abrir o arquivo txt do twitter e extrair todas essas chaves de autenticação. Então, ele apenas define as propriedades do sistema que o cliente do Twitter precisará para permitir que você se conecte ao Twitter. E sob o capô, isso é usar bibliotecas de terceiros que incluí com os materiais do curso. Este é provavelmente um bom momento para mencionar que tudo isso é construído usando SBT sob o capô em inteligência. Se você realmente vai construir no SBT aqui, você pode ver os pacotes que estamos realmente incluindo para os materiais do curso em si. Então aqui estamos dizendo explicitamente, estamos usando Scala versão 2.12, Spark versão 3. Estamos importando Spark Core Spark SQL, Spark, MLLib, Spark Streaming. É assim que tudo funcionou magicamente até agora ao longo do curso. Foi assim que tivemos o Spark disponível para nós. Mesmo que não tenhamos instalado o Spark explicitamente. SBT saiu e conseguiu isso para nós automaticamente. E também estamos recebendo o Twitter para J core e Twitter para J stream pacotes. Estes são apenas arquivos JAR do Twitter lá fora que permitem que você transmita em dados do Twitter a partir da API do Twitter. Depois de definir essas variáveis de ambiente em um marcador, ele se autenticará para você. Então, ao definir isso em nossas dependências de biblioteca, ele está recuperando automaticamente a versão correta das bibliotecas do Twitter para nos permitir conectar e transmitir esses dados para a versão dada que queremos aqui. Há também uma biblioteca separada que vamos converter esse fluxo do Twitter da API do Twitter em um fluxo de D para streaming do Spark. E nós apenas incluímos isso na lista. E nós apenas incluímos isso nas bibliotecas incluídas no projeto aqui. Se você subir aqui e ir para a pasta lib, isso é o que o arquivo DStream traço Twitter Jar está lá também. Ele foi explicitamente construído com base na versão específica do Spark e Scala e Twitter que estamos especificando nesse arquivo SBT. E a maneira como o SBT funciona é que se há algo na pasta lib, ele simplesmente o coloca automaticamente como uma espécie de dependência local. Então é assim que tudo funciona sob o capô. De volta ao código. Então, em vez de Twitter configurou toda a autenticação que ele precisará para se conectar. E uma vez que temos isso, podemos configurar nosso contexto de streaming com um tamanho de lote de 1 segundo de dados chegando. Vamos configurar o nosso registo para definir o nível de registo. E então chamamos o Twitter utils. Isso é chamar a biblioteca local que incluímos lá. E nós vamos chamar criar stream nele para criar um DStream do Twitter usando essa biblioteca de terceiros, nós apenas passamos em nosso contexto de streaming e um parâmetro opcional que não precisamos. Uma vez que temos isso, podemos apenas chamar status para ponto de status getText e usar isso como nossa função de mapa em que DStream. Então tudo o que está fazendo é extrair o campo de texto de cada tweet. Então não nos importamos com quem o twittou. Não nos importa a que horas eles tuitaram. Tudo o que nos importa é o próprio tweet. E é isso que está entrando em nossos novos status, D-string. E aqui, uma vez que temos isso, usamos flatmap para explodir isso em palavras individuais depois de dividi-las com base no caractere de espaço, filtramos qualquer coisa que não comece com uma hashtag. Então agora ficamos com hashtags que apareceram dentro de nossos tweets que estão entrando através desse fluxo. Em seguida, mapeamos isso para estas tuplas da própria hashtag e do número 1. E então podemos usar ReduceByKey e janela para verificar a cada 1 segundo, voltando cinco minutos para somar todos aqueles para cada hashtag individual e reduzi-lo por essa chave hashtag. Novamente, este é um formato que não vimos antes com ReduceByKey. Às vezes eles querem ter ambos em operação para adicionar algo em uma operação para tirar algo. Então, neste caso, se você adicionar algo, queremos adicioná-lo. Se quiser tirar algo, subtraímos. Normalmente, esse será o caso, mas há casos de uso estranhos onde você quer fazer algo mais complicado. Uma vez que temos isso, nós apenas classificamos e mostramos os resultados, imprimimos os 10 primeiros. Tudo bem, para começar, dissemos um diretório de postos de controle. Não falamos muito sobre isso nos slides. Mas isso é realmente definir uma pasta de ponto de verificação na minha unidade C. Se você estiver em algum outro sistema operacional, provavelmente você vai querer mudar isso para um caminho que faça sentido em seu sistema operacional que não funcionaria no Linux ou Mac, é claro, mas você pode mudar isso para cortar usuários, cortar qualquer que seja o seu nome de usuário é, seu diretório pessoal se você quiser cortar Ponto de Verificação. E isso também funcionaria. É aí que ele irá armazenar uma loja os dados que ele precisa para pegar de onde parou. Se algo ruim acontecer com este script inesperadamente enquanto ele está em execução, então ele pode retomar a partir desse ponto de verificação. Uma vez que temos essa configuração, nós apenas começamos nosso contexto de streaming e deixamos que ele faça sua coisa. Vai fazer continuamente o que lhe dissemos para fazer. Reduzindo a cada 1 segundo nos últimos cinco minutos qual é a hashtag mais popular, e continuaremos fazendo isso até que alguém termine explicitamente o script. Então vamos ver se funciona. Clique em hashtags populares, clique com o botão direito do mouse e execute. E aí vem. E toda vez que faço isso, me lembro que o Twitter é uma plataforma global. Vemos muitas coisas de língua estrangeira e referências culturais que não significam nada para mim. Em todo o mundo. Estamos olhando para cada tweet que está saindo publicamente pelo menos e adicionando as hashtags que aparecem com mais frequência. Então vamos, vamos deixar isso correr por um tempo e ver que resultados interessantes obtemos. Vamos expandir isso um pouco para que possamos ver mais. Lá vamos nós. Então, neste momento, a BTS está em tendência como a hashtag principal. Não faço ideia do que isso significa. Vou ter que ir procurar isso mais tarde. Significa algo culturalmente significativo no momento em que as pessoas estão entusiasmadas. Em vez disso, as pessoas são sobre sorvete. Sorvete é assumido. Sorvete acabou de pegar o número um, muito excitante. Ei, quem não gosta de sorvete até IP3, seja lá o que for. Ainda juntos. Muito dinâmico, certo? Sorvete, porém, segure por conta própria. Como uma guerra entre sorvete e BTS. A Bts está a avançar. De qualquer forma, você pode fazer isso o dia todo, se quiser, e eu garanto que você verá algo diferente se você estiver dirigindo isso sozinho, porque ele muda todos os dias, cada momento que diz o que o mundo está falando agora. Felizmente, acho que não vemos nada ofensivo aqui. Normalmente você faz. Embora, para ser justo, eu não sei o que é BTS ou que língua estrangeira onde é que continua aparecendo também ainda juntos. Não sei a que se refere isso. Cara, tenho que sair mais. Mas de qualquer forma, aí está. Podemos ir em frente e cancelar isso. Aperte o botão vermelho aqui para parar. Isso. Parece que depois desse tempo, o vencedor foi o que quer que isso signifique em qualquer língua que seja, talvez alguém nos comentários possa me dizer. Eu não sei. Talvez eu não queira saber. Deveria ser, pode ser algo desagradável. Mas é um exemplo legal e divertido, certo? Então nós realmente usamos a API DStream aqui para ir e conectar-se a feeds reais do Twitter e manter o controle da hashtag mais popular enquanto passamos o tempo. E se eu fizer isso por cinco minutos, teremos cinco minutos completos de dados. E teríamos então uma janela deslizante dos últimos cinco minutos frente enquanto continuávamos a executar este script. Então pode ser divertido correr por um tempo e ver o que ele faz. Então lá você tem um tipo de exemplo do mundo real usando dados do mundo real. Essa é a parte divertida, mas como dissemos, DStreams são a maneira antiga de fazer isso. Então, vamos mergulhar na nova maneira de fazer as coisas com streaming estruturado a seguir. 58. Streaming estruturado: Então, como eu mencionei, DStreams foram a API de streaming original para o Apache Spark. Nestes dias, as pessoas usam outra coisa. Chama-se Streaming Estruturado às vezes. Então você ainda corre em bibliotecas que esperam DStreams como a biblioteca do Twitter que eu estava usando. Então, ainda é útil saber que ele está lá fora e como ele funciona. Mas você descobrirá que o streaming estruturado é a API mais moderna para streaming e Spark. E também é mais fácil usar suas idéias de que ele usa conjuntos de dados como sua API principal em vez de RDDs são DStreams que se parecem com RDDs. E como eu disse antes, grande parte do Spark está indo o caminho de usar conjuntos de dados e em Scala ou DataFrames em Python como sua API primária. E a beleza disso é que é muito elegante para streaming porque você pode imaginar um conjunto de dados que continua sendo anexado para sempre e você apenas consulta quando quiser, assim como qualquer outro conjunto de dados. Então, a parte de streaming é apenas que continuamos adicionando mais e mais linhas a esse conjunto de dados em tempo real à medida que novas informações são recebidas. E isso torna as coisas muito mais fáceis. Isso significa que você pode usar esses conjuntos de dados deve muito parecido com qualquer outro conjunto de dados. Então, na verdade, não é muito para nós falar nesta palestra. Depois de configurar as coisas, basta usar isso como qualquer outro conjunto de dados. Todas as outras coisas que aprendemos no curso se aplicam exatamente da mesma maneira a um conjunto de dados de streaming como seria para um conjunto de dados lido a partir de um processo em lote. E a outra coisa boa é que, ao fazer isso, streaming é agora verdadeiramente em tempo real. Este foi um verdadeiro ponto de encontro com muitas pessoas. E por um tempo as pessoas estavam dizendo que o Spark streaming era inferior a outras plataformas de streaming por causa disso. Bem, agora eles não podem mais dizer isso porque com o Streaming Estruturado, Streaming agora é realmente em tempo real. À medida que novos dados são recebidos, eles serão imediatamente anexados a esse conjunto de dados e você terá acesso a ele imediatamente. Então, não estamos mais baseados nesses microlotes de pequenos RDDs que contêm 1 segundo valor de dados. Não temos que pensar nisso. Esse nível de pensamento não é mais necessário em nosso código. Configurá-lo, é super fácil. Tudo o que precisamos fazer é dizer fluxo de leitura de ponto faísca em vez de Spark dot read, quando estamos configurando um DataFrame ou um conjunto de dados. E você pode dizer o quê? Por exemplo, se você quisesse apenas lê-lo em arquivos JSON a partir de um bucket de logs no Amazon S3, você poderia apenas dizer logs JSON S3 de ponto de fluxo ponto-ponto sparked e isso iria apenas ficar lá e monitorar esse bucket de logs no S3 durante todo o dia, 24 , 7, procurando novos arquivos JSON para ler e analisar. E ele iria apenas continuar adicionando cada nova linha em cada novo registro JSON que foi encontrado lá no DataFrame de entrada. E então você pode fazer o que quiser. Você pode agrupá-lo por, você sabe, alguma ação. Você pode fazer uma janela como vimos no DStream. Então, se você quiser especificar uma janela de tempo, você pode apenas passar esse parâmetro de janela extra lá para especificar o, o período de tempo ao longo do qual você deseja ir. E você pode contar, certo, o fluxo para fora onde você quiser. Neste caso, vamos formatá-lo para uma conexão JDBC e apenas escrevê-lo em um banco de dados MySQL em algum lugar turnaround e colocá-lo em um banco de dados. Então isso é realmente todo o código específico de streaming que você veria apenas o ativo realmente especificando essa janela, estabelecendo o fluxo e onde você está gravando o fluxo. Além disso, é apenas um dataframe antigo regular ou conjunto de dados, dependendo de como você está usando e tudo o que você faria normalmente com o DataFrame onde conjunto de dados se aplica aqui também. Então vamos fazer um pequeno exemplo aqui de streaming de arquivos de log. Então incluí um arquivo de registro de acesso do Apache nos materiais do seu curso. E o que vamos fazer é apenas configurar um pequeno diretório em nossos materiais do curso e vamos copiar esse arquivo de log e ver se nosso aplicativo de streaming o pega e o processa. Então, para fazer isso, vamos apenas dizer faísca dot read stream dot txt porque estes são apenas arquivos de texto simples, arquivos log com um caminho de diretório para a pasta de logs dentro do meu material de curso. Nesse ponto, eu posso apenas usar operações SQL para analisar os dados dessas linhas de log usando expressões regulares. Você poderia usar isso com uma operação de mapa, se você quisesse também. E, em seguida, basta usar grupo BY para agrupar as coisas em alguma janela se você quiser transmitir a saída, neste caso para o nosso console, mas poderia facilmente ir para um banco de dados ou qualquer coisa que você quiser. Então vamos mergulhar e transmitir alguns troncos. Não é esse tipo de tronco. 59. [de idade estruturado: Tudo bem, então vamos jogar com streaming estruturado de novo, meio que a maneira moderna de fazer streaming hoje em dia e Spark. Vamos abrir o script de streaming estruturado aqui e ver como funciona. Primeiro de tudo, você vê que isso é realmente muito simples. Quero dizer, além das expressões regulares reais de analisar esses dados de log, o código do Spark em si não é muito. É bem conciso. Então vamos passar por isso aqui. Tudo bem, então nós somos coisas importantes. Precisamos de um objeto cratera aqui, definir o nível de log, criar uma sessão Spark. Até agora nada é diferente. A primeira coisa que é diferente, porém, é que em vez de dizer ponto faísca , texto ponto, vamos dizer faísca dot read stream txt. É isso. Isso diz que vamos fazer disso um fluxo contínuo de informações em vez de apenas ler em um bloco de informações de um arquivo de texto estático. E o caminho que passamos aqui é na verdade um caminho de diretório. E, neste caso, vai estar no nosso sistema de arquivos local. Mas você poderia facilmente monitorar um bucket do S3 ou algum sistema de arquivos distribuído se você quisesse também. Então ele só vai ficar aqui assistindo meu diretório de registro de barras de dados para novos arquivos de texto. E como novos arquivos de texto são descobertos lá, ele irá anexar cada linha desse arquivo de texto nas linhas de eixo DataFrame. Está bem, é simples assim. Agora o resto deste código complicado aqui está realmente apenas analisando esses dados. Então os logs de acesso do Apache são um formato bastante estranho e é preciso algumas expressões regulares bastante complicadas para extrair as informações dele e transformar esses dados de arquivo de log não estruturado em informações estruturadas. Então eu não vou entrar nos detalhes de como essas expressões regulares funcionam, mas elas são destinadas a extrair as informações que precisamos de cada campo do log de acesso do Apache. E aplicamos essas expressões regulares aqui dentro desta grande e velha instrução select. Então pegamos essas linhas de eixo DataFrame e chamamos select nele. Agora, por padrão, cada nova linha de textos indo para linhas de eixo estará em uma coluna chamada valor. Então, para cada um desses exemplos, estamos fazendo um extrato reg ex na coluna de valor. Isso significa que ele vai pegar a linha bruta de dados, fazer aplicar uma expressão regular a ele. Nesse caso, a expressão host, que se destina a extrair o nome do host. E nós íamos dar a isso um pseudônimo de hospedeiros. Então, isso basicamente criará uma nova coluna de host que contém o host extraído dessa linha. E fazemos a mesma coisa para o carimbo de data/hora para o método, para o endpoint para o protocolo, para o código de status e o tamanho do conteúdo. Neste ponto, você pode fazer o que quiser, certo? Então, em nosso exemplo simples aqui, tudo o que vamos fazer é agrupar BY o status e contados ao longo do tempo. Então, vamos manter uma contagem em execução ao longo do tempo de quantas vezes cada código de status aparece nesses arquivos de log. Então isso é ele vai ficar lá novamente esperando novos arquivos de log para ser descartado no diretório de log de barra de dados. E ele irá agrupar ao longo do tempo, quantas vezes cada código de status aparece. Temos que dizer onde colocar essa informação. Então construímos o que é chamado de consulta. E nós apenas dizemos status conta DataFrame, Essa é a nossa contagem final DataFrame lá. Nós vamos escrever esse fluxo para fora com o seguinte modo de saída. Vamos dizer que queríamos completar a saída formatada indo para o console. E daremos a essa consulta um nome chamado “contagens”. E vamos chamar o amido para realmente iniciar esse fluxo de saída. Está bem. Então nós definimos nosso fluxo de entrada aqui com Spark dot read stream dot txt. Isso é o que vai monitorar. Definimos uma série de operações que levaram, em última análise, às contagens de status DataFrame que está sendo calculado a partir desse fluxo de entrada. E, em seguida, criamos um fluxo de saída aqui chamado consulta. Então, só esperamos a demissão. Vai correr isso para sempre até pararmos explicitamente. E quando alguém faz isso, chamamos parar na sessão para encerrar as coisas. Então vamos começar e ver se funciona. Primeiro vai executá-lo. Nós nos damos ao luxo de criar um inicialmente não há nada nesse diretório e então precisamos colocar coisas lá para que ele realmente faça algo interessante, certo? Então vamos fazer isso. Vamos ao nosso material de curso aqui e entrar em dados. E você verá que há um arquivo de log de acesso aqui que contém um log de acesso real do Apache de um dos meus sites. Vamos copiar isso e abrir o diretório Logs e colá-lo lá dentro. E o que deve acontecer é que nosso roteiro deve pegar isso. Consigo ouvir o meu ventilador da CPU a funcionar, está a fazer alguma coisa. E funcionou. Então pegou aquele novo arquivo e contou todo o código aéreo. Então nós podemos ver que nós realmente parece ter um erro de código de erro 500 aqui eles estão mostrando um lote terrível. Então isso estaria me alertando para um problema real no meu site se isso fosse um aplicativo real, certo? Talvez eu possa ter algum tipo de limite no número de 500 erros e me alertar se isso exceder algum limite ao longo do tempo. Vamos ver se ele funciona com como mais dados são jogados nele. Então vamos voltar aos dados e fazer uma cópia do nosso arquivo de registro de acesso. Só vou copiar e colar. Então agora temos cópia do traço do registro de acesso. Vamos copiar isso em nossos registros também. E o que devemos ver é todos esses números, lote duplo um, temos outro lote de informações que chegou. E com certeza, todos esses números duplicaram porque eu copiei o mesmo arquivo de log. E mais uma vez, então aí está. Vamos apertar o botão X aqui para parar o fluxo. E sim, isso é Spark streaming e ação, coisas muito legais. Então, como você pode ver, Structured Streaming é realmente fácil de usar. Se você pode usar um conjunto de dados, pode usar streaming estruturado e não está mais limitado ao processamento de dados em lote. Você pode processá-lo como ele vem em tempo real, o que é muito emocionante. Tudo bem, isso é o Spark streaming em poucas palavras. Vamos seguir em frente. 60. [de exercício compartilhado com o Streamer estruturado: Então este próximo exercício realmente interessante. Eu quero que você acompanhe os principais URLs visualizados nos meus registros de eventos lá para meus logs de acesso do Apache. E mantenha o controle disso. Então, em vez de exibir a contagem de códigos de status ao longo do tempo, quero que você exiba a contagem dos principais URLs que foram visualizados a partir dos dados de log em vez disso. E para torná-lo ainda mais interessante, eu não quero que você meça isso desde o início dos tempos. Eu só quero que você olhe para trás nos últimos 30 segundos e apenas me diga quais foram os melhores resultados dentro do último intervalo de 30 segundos. Agora, para fazer isso, você precisa introduzir o conceito de operações em janelas no streaming do Spark. Então deixe-me apresentar isso rapidamente. Uma operação com janela está apenas olhando para trás durante algum período de tempo. Então, por exemplo, se eu quiser considerar apenas eventos que aconteceram nos últimos 10 minutos, eu teria uma janela de 10 minutos. E o intervalo de slides define a frequência com que avaliamos essa janela. Então, temos uma janela de 10 minutos, digamos, das 12 às 12 dez. Se tivéssemos um intervalo de 5 minutos, isso significa que avaliaríamos essa janela em 1205121012151220. Cada vez olhando para a janela de 10 minutos mais recente que estamos dentro. Para tornar isso um pouco mais concreto, deixe-me mostrar-lhe um diagrama que vem diretamente da documentação do Spark aqui. E aqui temos uma janela de 10 minutos com um intervalo de 5 minutos. Então vamos começar esta coisa às 12 horas neste exemplo hipotético. Então temos janelas que funcionam de 12 horas a 12 dez, de 1205 a 1215, de 1210 a 12, 20 e assim por diante. Então, a cada cinco minutos, temos uma nova janela de 10 minutos sendo definida. E ao longo do tempo, agregamos os resultados sem passar por essas janelas. E continuamos adicionando os resultados dessas janelas à nossa tabela de resultados à medida que avançamos. Então, neste exemplo, temos um fluxo de nomes de animais chegando aparentemente. Então um 1202 e 12 03, temos cão gato e cão entrar. Então, um 12 05, temos um pequeno intervalo que é atingido. Então isso vai olhar para a janela 12 horas para 1210 porque essa é apenas a nossa primeira janela que acontece de ter desde que começamos a correr. E o que temos até agora é um gato e três cães que foram recebidos. Em 1207, temos uma coruja e um gato. Então, quando executarmos nosso próximo intervalo de slides em 1210, vamos agora também olhar para as 12 horas para 12 10 e as 1205 para 1215 janelas. Agora acontece que nosso gato realmente foi adicionado em que 12 horas a 12, 10 janelas. Então vamos adicionar isso à nossa tabela de resultados e atualizar isso. E também vamos criar uma nova janela em nossa tabela de resultados para 1205 a 1215 que vamos acompanhar. E continua continuando, certo? Então um 1215, agora vamos ter outra nova janela de 1210 para 1220 que vamos olhar. E voltaremos e atualizaremos todas as janelas anteriores conforme necessário para contabilizar os novos dados. Então temos outro cão e outra hora entre lá. E se você olhar de perto, você pode descobrir. Mas basicamente a idéia é que a janela é o período de tempo em que você está agregando coisas. E o intervalo de slides é a frequência com que você está avaliando isso. O código para fazer isso é bastante simples. Você acabou de dizer grupo BY se você quiser fazer algum tipo de agregação em uma coluna, neste caso, a coluna que estamos agrupando pelo nome dessa coluna. E sintaticamente ele diria “janela”. E, em seguida, especifique uma chamada com o nome da coluna que representa o timestamp está definindo quando essa coisa aconteceu, certo? Portanto, o código em janela na transmissão do Spark não está automaticamente acompanhando quando os eventos foram recebidos. Ele vai estar olhando para uma coluna específica em seus dados que está sendo ingerida. Certo, então tenha isso em mente. Você sabe, você vai ser janela definida em dados que estão no próprio fluxo, não em quando isso foi realmente recebido pelo Spark streaming. Diferença tão sutil, mas importante, especialmente em nosso exemplo aqui, porque estamos usando logs Apache muito antigos que têm carimbos de data/hora de anos e anos atrás. Então isso vai afetar como nós realmente abordamos esse problema. Então você diz que a duração da janela vírgula é igual à duração da janela que você quiser. E isso é apenas especificado em inglês simples como 10 minutos, 30 segundos, o que você quiser lá. Mas acho que há um limite de um mês para isso. E a duração do slide também especificada em inglês simples também. Então sintaticamente, isso é o que você precisa saber sobre como fazer agregações em janelas. Então, seu desafio novamente, modifique esse script de streaming estruturado no qual acabamos de trabalhar para manter o controle das URLs mais visualizadas. E isso é realmente chamado de endpoints neste script específico. Mesma coisa. E eu queria calcular isso com uma janela de 30 segundos e assistir ao segundo slide. Agora você está em precisa de alguns pequenos trechos de código, a fim de fazer isso. Primeiro de tudo, novamente, vou apenas reiterar esse trecho de código sobre como realmente especificar sintaticamente essa janela. Então é assim que esse código seria. Essa não é a linha inteira que você vai precisar no roteiro real, mas é uma boa parte dele. Estou agrupando não é suficiente. Você também precisa contar quantos estão nesse grupo, certo? Então você já viu como fazer isso em exemplos anteriores. Além disso, como eu disse, você vai ter um problema porque os registros de amostras Apache que eu te dei são muito velhos, eles têm anos. E isso não vai funcionar com uma janela de 30 segundos tensa, certo? Então, se você está olhando para trás 30 segundos em um registro que estava capturando dados de três anos atrás, isso não vai funcionar tão bem. Então, o que você pode fazer é fabricar uma nova coluna em seu conjunto de dados que é a hora atual em que ele foi ingerido. E a sintaxe para isso é que o segundo bloco, sua coluna de largura de ponto logs df irá adicionar uma coluna chamada tempo de evento como igual ao carimbo de data/hora atual. Então, isso lhe dará uma nova coluna que você pode usar para a hora atual. Isso será um pouco mais útil para este exercício. E finalmente, você vai querer ter certeza de que você está ordenando as contagens em ordem decrescente. Então, em algum momento você terá que dizer ordem por contador de chamadas, seja lá o que você chamar a coluna de contagem de ponto DESC para especificar que você deseja que em ordem decrescente para que você veja os principais resultados primeiro e não vice-versa. Então vá embora e faça isso, isso é um pouco mais desafiador, pode exigir que você faça um pensamento um pouco mais criativo ou procure coisas on-line. Mas é assim que o mundo real funciona. Então dê uma chance. E quando voltarmos, mostrarei como fiz. 61. Solução de exercício: uma URL de top em uma janela de 30 segundos: Tudo bem, então vamos fazer algo um pouco mais chique com streaming estruturado e dar uma olhada na minha solução para manter o controle dos principais URLs visualizados em nossos logs de acesso Apache usando uma janela deslizante de 30 segundos, em vez de apenas desde o início dos tempos. Então eu só comecei com uma cópia desses scripts Scala de ponto estruturado como eu aconselhei você a fazer. E nada muda até chegarmos a esta linha aqui na linha 42. Agora, como eu mencionei, esta é uma antiga lei de acesso Apache que eu lhe dei dentro dos materiais do curso. E se vamos estar fazendo janelas deslizantes do tempo dos últimos 30 segundos. Bem, precisamos fabricar alguns novos tempos de eventos que são mais atuais, certo? Então isso é tudo que esta linha aqui está fazendo, é pegar nossos logs df dataframe e anexar uma nova coluna usando com coluna chamada tempo de evento que é enviado para o timestamp atual sempre que esses dados são realmente ingeridos. E vamos dar a volta e chamar os logs de DataFrame resultantes df2. Tudo bem, agora as coisas ficam interessantes. Então vamos manter uma contagem desses pontos finais. Então em, em nossa nomenclatura aqui, e ponto final é basicamente a mesma coisa que uma URL. Então temos um método GET seguido pelo ponto final, que vai ser a URL em nosso site que alguém tem atingindo. Então, para fazer isso, vamos usar a mesma sintaxe que falamos nos slides para estabelecer aquela janela de 30 segundos com uma duração de slide de 10 segundos. Nós apenas dizemos logs df2, chamada de janela groupby. O nome da coluna aqui é a hora do evento. Esse é o carimbo de data/hora que vamos abrir. Ok? Nós especificamos uma duração de janela de trinta segundos e nós fazemos check-in, atualizamos essas janelas a cada 10 segundos. E o segundo parâmetro para o comando group BY será chamado endpoint. Então nós vamos estar agrupando pelos endpoints, agrupando todos esses endpoints comuns juntos. E então, uma vez que você tenha esses agrupados dentro dessa janela e na duração do slide, nós vamos contá-los. Então o que esta linha de código está fazendo é contar quantos de cada URL foram encontrados a cada 10 segundos, olhando para a janela atual de 30 segundos em que estamos certos? Agora, isso não é suficiente. Eu também quero classificar estes, que eu veja os URLs mais populares. Só não quero ver listas desordenadas. Então eu vou, além disso, tomar esses pontos finais, contagens DataFrame e classificá-lo dizendo ponto OrderBy chamada cout name é igual a contagem, vai ser o nome da coluna de contagem que é criado por esse Cal comando dot DSC, para dizer que eu procurado em ordem decrescente. Então, os URLs mais populares estão no topo, e é isso. O resto do código é basicamente o mesmo. Saímos para o console lá e iniciamos basicamente. E um pouco à parte aqui, uma última nota, se você quisesse escrever isso em um banco de dados ou um arquivo ou algo assim, você simplesmente definiria o modo de saída é outra coisa e o formato é outra coisa. Então, se você olhar para a documentação lá, você pode ver como podemos escrever para um banco de dados ou para um arquivo de texto ou um arquivo de parquet ou o que você quiser. Não tem de ser para a consola. Vai ser muito mais prático armazenar esses dados em algum lugar, certo? E o que estamos armazenando é essa tabela de resultados. Então vamos obter estes, esta tabela de resultados para cada janela atualizada, para cada duração do slide. Então o resultado que vamos ver é uma tabela que mantém o controle dos resultados que vemos dentro de cada janela, cada janela de 30 segundos que temos. Então vamos ver se estou mentindo para você ou não. Vamos ver o que acontece. Então os URLs principais executados permitirão que isso gire e eu vou fazer essa janela grande para que possamos ver o que está acontecendo. Tudo bem, então ele está sentado lá esperando por dados. Vou voltar aos meus registros aqui no meu material de curso. E vocês podem ver que eu realmente tenho três cópias do meu registro de eixo aqui para brincar. Vamos começar com um. Temos que copiar isso e jogá-lo na minha pasta de registros aqui. Então, já que estamos transmitindo em tempo real, ele deve pegar a existência desses novos dados e ir em frente e atualizar tudo. Está chugging agora. Você pode ouvir meu fã de CPU indo. E lá temos. Assim, podemos ver que esses intervalos de 10 segundos de slide, estamos calculando esse valor de janela cada vez e estamos obtendo um resultado consistente porque ainda não estamos rodando há mais de 30 segundos. Então vamos em frente e jogar mais alguns dados lá apenas para ter certeza de que ele funciona como esperado. Então note aqui estamos vendo que 0, eu deveria ver agora o Lote 1. E há lote um. Curiosamente, é o mesmo número de antes, certo? Porque mais de 30 segundos se passaram desde o primeiro lote. Então esse primeiro lote de informações realmente expirou. Caiu do fim da minha janela. Então, se não estivéssemos abrigando, teríamos visto todos os números dobrados, certo? Mas não o fizeram porque os trinta segundos de dados expiraram. Eu não acho que 30 segundos se passaram bastante ainda, então vamos ver se eu consigo realmente obter um número maior lá. Se eu for rápido o suficiente, colocaremos em uma terceira cópia lá. E aqui vemos um remendo para eu não era rápido o suficiente, caiu do final da janela de 30 segundos. Mas se você tiver a sua própria versão desta corrida, sinta-se à vontade para jogar com ela ou ajustar os tempos do Window para ser um pouco mais amigável com você e como você está trabalhando. E uma boa maneira de ter uma ideia de como o Windows e os intervalos de slides funcionam é experimentar com ele e simplesmente brincar com ele como estamos fazendo agora. Então você já aprendeu sobre o Spark Streaming agora e como lidar com dados em tempo real à medida que eles entram. 62. GraphX, Pregel, e primeiro primeiro pesquisa com Pregel.: Então, nesta seção vamos apresentar Graphx, que é uma API para lidar com gráficos de informação tipo como nossa rede de super-heróis no início do curso. Graphics é uma espécie de um enteado negligenciado de inteligente, para ser honesto, ele não tem visto um monte de desenvolvimento ultimamente e ainda está preso na antiga API RDD. Há uma versão mais recente do mesmo em desenvolvimento chamada frames de gráfico, mas ainda não está pronta para o horário nobre. Então, por enquanto, apenas para completude, eu vou falar sobre o gráfico x e sua forma atual, que usa a interface RDD, mas você verá que ainda é bastante poderosa. E usá-lo se sente um pouco mais como SQL por vez. Então, vamos mergulhar e ver como os gráficos podem ajudá-lo a resolver grandes problemas distribuídos usando gráficos de informações. Vamos mergulhar brevemente no mundo do GraphX, o último componente principal do próprio Spark. E quando falamos de gráficos, não estamos falando de gráficos de linhas ou gráficos ou qualquer coisa assim. Estamos falando de gráficos no sentido da ciência da computação. Então, por exemplo, nossa rede social de super-heróis que vimos no início do curso. Esse é um exemplo do gráfico de que estamos falando, onde temos vértices que, nesse caso, representam super-heróis individuais e bordas entre esses vértices que representam relações entre eles. Gráficos é meio legal, mas é realmente útil apenas para alguma coisa específica. Então, por si só, ele não pode realmente responder as perguntas que estávamos respondendo no código que escrevemos para analisar nossa rede de super-heróis. Mas pode fazer coisas como medir a conectividade, distribuição de graus, comprimento médio do caminho, contagem de triângulos, tipo essas medidas de alto nível do gráfico como um todo. Ele pode fazer coisas como contar todos os triângulos no gráfico e aplicar o algoritmo PageRank ao desigual. Então, eu acho que essa é realmente a força motriz por trás do próprio GraphX. É muito útil para implementar algo como PageRank, que é obviamente um caso de uso importante. E isso também é um problema que envolve grande escala, é claro, onde o poder do Spark é útil. Então é feito para isso mais do que qualquer outra coisa. Você também pode fazer coisas como unir gráficos e transformar esses gráficos muito rapidamente de forma distribuída. Mas para coisas como nossos graus de separação exemplo onde estamos tentando descobrir quantos graus de separação como super-herói é do Homem-Aranha. Você não vai encontrar suporte embutido para operações como essa. No entanto, ele suporta a API Pregel para atravessar um gráfico. E isso permite que você escreva seu próprio código e desenvolva seus próprios algoritmos que tipo de viver dentro de gráficos. E isso lhe dá a flexibilidade para fazer as coisas mais complicadas que você pode sonhar. Eles simplesmente não saem da caixa. Você tem que pensar sobre isso e pensar criativamente como tivemos que fazer quando fazemos isso usando dataframes ou usando RDDs. Assim, os gráficos introduzem um par de novos tipos de dados, o vértice RDD e o Edge RDD, bem como o tipo de dados de borda. E é assim que representamos os vértices e as arestas entre eles que compõem um gráfico. Agora Graphics é um pouco de contenção. Ele ainda está escrito na API RDD, mesmo que o próprio Spark tenha tentado migrar cada vez mais para dataframes e conjuntos de dados. Honestamente, o GraphX meio que caiu no caminho. Ainda não viu muito desenvolvimento ativo. Ainda é uma peça central do próprio Spark, então estou cobrindo isso aqui. Mas você está vendo isso cada vez mais sendo substituído por outras coisas não estão sendo usadas muito no mundo real. Acontece que, realmente não tem muito uso para gráficos. E como resultado, tem sido negligenciado com toda a honestidade. Portanto, o GraphX ainda é criado em RDDs. Mais uma razão para aprender RDDs, há um pacote alternativo chamado frames de gráfico que é construído na nova API DataFrame. Mas ainda não foi lançado. É versão definida como 0.8 última vez que eu verifiquei. Então, em algum momento, podemos ver quadros gráficos substituídos gráficos e faíscas, mas por enquanto temos os gráficos baseados em RDD para trabalhar. E você descobrirá que o código gráfico se parece muito qualquer outro código de faísca RDD na maioria das vezes. E, na verdade, uma vez que você tem um gráfico construído, lidar com ele parece muito parecido com o Spark SQL de qualquer maneira, então não é tão ruim quanto parece. Criar um vértice RDD é bastante simples, realmente. Você só precisa retornar uma tupla que inclua um ID de vértice, algum identificador numérico exclusivo como seu primeiro campo. E quaisquer dados que você queira associar a isso neste pequeno trecho de código aqui que estamos tirando do nosso exemplo. Você está vendo que nós estamos realmente embrulhando isso em uma opção. E é assim que lidamos com valores nulos em Scala. Nós realmente não falamos sobre isso antes, mas você vê que estamos definindo uma opção de um ID de vértice e uma string, e isso significa que nós temos a opção de retornar nada. Então você verá que, no caso em que temos um resultado válido, estamos retornando alguns com uma tupla que consiste em um ID de vértice e os dados associados a esse vértice. Se tivermos uma entrada inválida lá, não retornaremos nenhum. E isso só significa que não há resultados. É basicamente o equivalente Scala de nulo. E isso é útil porque se você estiver chamando FlatMap em um RDD e sua função retornar nenhum, isso apenas é descartado e tudo bem. Então essa é uma maneira de lidar com o caso de não devolver nada de uma operação FlatMap. No caso de nossos dados, tivemos que ter algumas linhas de dados inválidas. Acontece que qualquer ID de herói acima de 6486 não é um personagem real, então precisamos descartá-los. E esse é o caso em que não devolvemos nenhum neste caso. Criar uma borda também é bastante simples. Tudo o que você faz é criar um objeto de borda contendo uma lista dos nós que ele conecta. Então, neste exemplo aqui você pode ver que estamos criando uma borda entre um determinado ID de herói que inicia o início de uma linha em nosso arquivo de dados para o conjunto de dados de super-heróis da Marvel. E construímos uma nova vantagem entre isso em cada super-herói ao qual Herói está conectado, definido por essa linha de texto. Então, uma vantagem, muito direta. É apenas um objeto de borda que consiste em dois IDs de vértice e algumas informações adicionais que você pode querer associar com isso também. Bastante direto de novo. E construir um gráfico, mais uma vez, isso é simples. Você apenas constrói um objeto gráfico e você constrói com a lista de vértices que você deseja ter nele, essas duas arestas entre esses vértices. E é basicamente isso. Você provavelmente vai querer armazenar esse gráfico porque você provavelmente vai querer fazer um monte de operações nele. E ao armazená-lo em cache que garante que ele permanecerá na memória, que pode ajudar a desencadear coisas otimizadas quando você fizer coisas com esse gráfico mais tarde. Então, fazer coisas com um gráfico também é bastante simples uma vez que você construiu, embora às vezes seja útil ver algum código de exemplo para começar. Por exemplo, se você quiser tomar o top 10 heróis mais conectados, poderíamos chamar gráfico médico concorda em obter esses graus de conexão e juntar aqueles com os vértices si. Classifica os resultados fornecidos pelo campo que corresponde ao número de conexões que eles têm em ordem decrescente. Pegue o top 10 e está feito. Então essa é uma maneira fácil de descobrir quem os super-heróis mais conectados estão em apenas uma linha de código depois que você construiu esses objetos de gráfico, um pouco mais fácil. A sintaxe é um pouco mais difícil de seguir aqui, então é um pouco fora do júri, eu acho, sobre se isso é realmente uma maneira mais direta de codificá-lo, mas funciona. Então essa é uma maneira de usar o GraphX. Mas, como dissemos antes, é muito mais flexível quando introduzimos a API do Pregel em cima do GraphX. Então vamos falar sobre isso a seguir e como podemos realmente estender o gráfico x para duplicar os resultados que obtivemos em nosso exemplo de graus de separação no início do curso. 63. Usando a API de pregel com o Spark GraphX: Então, vamos explorar mais detalhadamente como a API do Pregel nos dá mais flexibilidade. Além dos gráficos, podemos realmente recriar o que fizemos com o algoritmo de busca de largura para encontrar os graus de separação entre quaisquer dois super-heróis em nosso gráfico de super-heróis da Marvel que aparecem juntos e livros de banda desenhada. E a maneira como Pregel funciona em um nível alto é basicamente cada vértice tem a capacidade de enviar mensagens para todos os seus vértices vizinhos. E cada gráfico é então processado em uma iteração chamada superstep. E em cada superstep, três coisas acontecem. Mensagens da iteração anterior serão recebidas por cada vértice. Cada vértice irá então executar um programa para se transformar com base nessas mensagens. E, em seguida, cada vértice irá enviar mensagens para outros vértices se ele quer ser pego na próxima etapa. E se você se lembrar de como implementamos o algoritmo de busca de largura, você provavelmente já está pensando, Ei, que mapeia muito bem como o algoritmo funciona. E, na verdade, faz. Então nós podemos inicializar nosso gráfico muito simplesmente aqui, se você se lembra bem, nós apenas começamos definindo todas as distâncias para o infinito exceto para o ponto de partida do qual estamos medindo as distâncias. E para isso vamos definir a distância para 0, é claro, porque a distância entre algo e ele mesmo é 0. Podemos fazer isso com uma linha de código e gráficos. Podemos apenas dizer vértices do mapa de pontos do gráfico e verificar se o ID é igual à idéia do herói que queremos começar a partir do lugar onde estamos medindo. Se assim for, definimos a distância inicial para 0. Caso contrário, definimos que atributos de vértice para infinito positivo. E, em seguida, aproveitamos essa capacidade de mensagens para se espalhar das notas iniciais. Então começamos do nosso ponto de partida inicial lá. E temos retro adicionar um pouco de código para definir o que acontece à medida que enviamos essas mensagens durante essa etapa de mensagens. Então, neste caso, estamos procurando por nós que não são infinito positivo, um que acabamos de processar. E para esses, vamos nos espalhar para seus IDs de destino, seus vizinhos, passando ao longo do atributo desse nó inicial mais 1. Então isso vai aumentar a contagem de distância à medida que vamos e enviar a próxima rodada e mensagens para essa superstep. Então, essencialmente, Pregel vai trabalhar seu caminho através deste gráfico, abanando seu caminho para fora. E ao longo do caminho, procura nós que não são infinitos. E ele vai em frente e os fãs mais longe, aumentando a distância como ele encontra seu caminho para fora. Então Pregel meio que lida com um monte deles mecânica de atravessar o gráfico para nós, que é útil para algo assim. Agora não fique muito preso se você não está seguindo isso, você provavelmente nunca vai ter que fazer exatamente o mesmo algoritmo e o mundo real, certo? O ponto mais importante aqui, porém, é que se você tiver um gráfico de informações que você precisa processar no Spark, e os recursos internos dos gráficos não fazem o que você quer. Às vezes, a API do Pregel permite que você faça isso se você apenas pensar um pouco mais criativamente em profundidade sobre isso, é apenas mais uma ferramenta para ter em seu baú de ferramentas. A outra coisa que temos que fazer no BFS é preservada a distância mínima a cada passo. Então queremos ter certeza de que não estamos recuando em nós mesmos e obtendo essas distâncias erroneamente altas entre nós porque encontramos esses caminhos mais longos para chegar lá. Então podemos escrever um programa de vértice que irá verificar para isso. E preservará a distância mínima entre aquele que recebe e o que tem. Assim como ele recebe essas mensagens de seus nós vizinhos, se ele está recebendo uma distância que é realmente maior do que o que está lá, ele irá preservar a menor dessas duas distâncias. E, além disso, fazemos uma operação de redução também. Então, se nós realmente temos várias mensagens recebidas para o mesmo vértice na mesma passagem, isso também irá pegar esse caso e preservar a distância mínima nesse caso também. Então, juntar tudo é bastante simples. Não é um monte de código na verdade. Então, podemos apenas dizer definir nosso gráfico inicial e gráficos com a distância definida como 0 onde estamos começando com caso contrário é infinito. Em seguida, chamamos gráfico inicial ponto Pregel. E essa chamada de função nos permite definir todos os atributos de partícula que precisamos. Então passamos nesse programa de vértice que mantém que sempre preservamos o valor mínimo recebido para a distância lá. Nós configuramos esse sistema de mensagens onde dizemos que vamos procurar por nós não-infinitos e os fãs estão longe deles incrementando essa distância à medida que avançamos. E finalmente, temos aquela operação de redução que diz que se você tem mais de uma mensagem chegando de uma vez, novamente, vamos preservar a distância mínima que está chegando. Então, esses três componentes de regular passaram como uma única chamada de função para a API Pregel lá. Mais uma vez, temos o programa de vértice. Primeiro, temos a função de mensagens e, em seguida, temos a operação de redução. E isso é tudo que você precisa fazer. Então vamos sair e ver se funciona. 64. [de superherói de separação usando GraphX: Então vamos mergulhar e usar o poder dos gráficos e Pregel para resolver nossos problemas de graus de separação usando gráficos. Então abra o roteiro gráfico aqui e vamos dar uma olhada. Vamos ver o que está acontecendo aqui. É um pouco mais simples do que a implementação baseada em RDD, mas ainda há uma quantidade razoável de código para falar aqui, certo? Então vamos passar por isso. Então vamos pular para a função principal e começar por aí. Nós configuramos nosso contexto de faísca é o tempo. Lembre-se, o GraphX ainda é criado na API RDD, portanto, não estamos usando um SparkSession aqui. Em vez disso, estamos usando um SparkContext. Novamente, há uma nova versão chamada frames de gráfico em desenvolvimento, mas ainda não foi oficialmente lançada. Então, novamente, gráficos um pouco negligenciados, mas quadros gráficos espero que esteja a caminho. No entanto, os gráficos ainda são úteis e, como você pode ver, não é tão difícil de usar. Então começamos lendo o arquivo de nomes de traço da Marvel aqui, e chamamos a função de nomes de análise aqui com um FlatMap. Você pode ver que tudo está acontecendo aqui. Então, retornando uma tupla do ID de vértice, que é a nossa ID de super-herói, e uma string que corresponde ao nome dessa ID. Nada extravagante. Nós apenas dividimos com base no caractere de citação lá para extrair o nome. E se tivermos mais de um campo, nós apenas fazemos uma pequena verificação de sanidade nos dados lá. Nós aparamos esse campo inicial para remover quaisquer espaços estranhos convertidos em um inteiro longo. E verifique se é uma identificação válida. caso afirmativo, retornamos esse número inteiro junto com o nome do herói associado a esse ID. E novamente, estamos usando o formato de opção aqui para dizer que nenhum é um resultado válido. Então, dizendo soma, isso significa que esta função retorna um resultado válido, mas também podemos retornar nenhum. Pode ser que esta linha represente um ID de herói inválido ou dados formatados incorretamente. E nesse caso, retornando o valor none como parte de nossa opção lá, que diz FlatMap que nós só queremos ignorar essa linha e não adicionar nada ao RDD resultante. Em seguida, o que fazemos? Construímos nossas bordas. Então agora vamos analisar o arquivo txt do gráfico do traço Marvel. E como você se lembra, isso é apenas uma lista de linhas que têm uma identificação aqui seguida de uma lista de todas as identificações que o herói foi visto com na mesma banda desenhada. Então fazer arestas cuida disso. Não há muita coisa acontecendo aqui também. Basicamente tomamos que toda a linha de entrada é uma string e retorna uma lista de arestas que consiste em inteiros que correspondem a IDs de vértice reais para cada herói. Então vamos construir um buffer de lista aqui e preencher essa lista com objetos de borda. Então este é basicamente o formato que o gráfico x vai esperar de nós. Nós dividimos essa linha de entrada bruta em campos individuais. E para cada campo que temos, extraímos o primeiro que será nossa origem, aquele de que estamos falando. E então, para cada campo subseqüente, criamos um novo objeto de borda que consiste no ID de vértice do super-herói do qual estamos começando, e o ID de vértice de cada conexão que o Herói possui. Em seguida, retornamos a lista resultante de arestas de volta ao nosso script principal aqui. Então agora podemos construir o gráfico em si, o que é bastante simples. Nós apenas construímos um novo objeto gráfico, dando-lhe a lista de vértices e arestas que especificamos. E estamos apenas passando esses vértices como tuplas basicamente onde o primeiro valor é o ID do vértice. Isso é uma coisa válida para se fazer aqui. Isso só funciona. E nós descontamos o gráfico resultante porque presumivelmente vamos fazer muito trabalho com esse gráfico e queremos manter isso na memória. Como vimos nos slides, podemos calcular rapidamente o top 10 super-heróis mais conectados com esta única linha de código que chamamos médico gráfico concorda e juntando-se com toda a lista de vértices, que significa que queremos obter as conexões para cada vértice que conhecemos e classificar os resultados resultantes pelo campo que corresponde ao número de conexões. Pegue o top 10, imprima-os, é isso. E agora podemos realmente fazer buscas de largura usando Pregel, que na verdade não é tão difícil. Então começamos definindo o ID do nosso vértice raiz aqui. Então acontece que sabemos que o vértice ID 5306 corresponde ao Homem-Aranha. E podemos iterar através da computação das distâncias se todos para o Homem-Aranha. Agora, começamos inicializando o gráfico. Novamente, nós apenas fazer uma operação de vértices mapa aqui, verificando cada vértice e vendo se o ID é igual a Homem-Aranha. Se assim for, definimos a distância inicial como 0, caso contrário, definimos como infinito. E agora neste comando, montamos todo o mundo Pregel, se preferir. Chamamos gráfico inicial ponto Pregel e passamos nesta função que contém, em primeiro lugar, o nosso programa de vértice. Então, novamente, seu propósito na vida é apenas manter a distância mínima como mensagens são recebidas entre a mensagem recebida e o valor atual de um determinado nó. Nós também definimos nosso SendMessage, como falamos antes. Isso vai se propagar para todos os vizinhos com a distância incrementada por um. Então, para qualquer nó que tenha uma distância atual associada a ele, descobrimos que nós mesmos incrementamos essa distância à medida que avançamos. E, finalmente, definimos uma operação de redução que irá preservar o valor mínimo dessas mensagens recebidas por um vértice se várias mensagens são recebidas por um vértice na mesma passagem. Então nós temos dois pedaços diferentes aqui que podem conter que nós sempre manter essas distâncias mais curtas que encontramos enquanto atravessamos o gráfico. E este pequeno trecho aqui define como atravessamos o gráfico e incrementamos essa distância em um a cada passagem. Nesse ponto, podemos sair e imprimir os 100 melhores resultados lá. Podemos dizer vértices de ponto BFS, ponto juntar verts novamente, apenas dizendo que queremos avaliar esse gráfico em todos os nossos super-heróis. Pegue o top 100 e imprima e veremos o que parece. E se quisermos recriar especificamente os resultados de nossos graus de exercício de separação que usamos para usar RDDs sem gráficos, podemos apenas fazer uma pequena operação de filtro lá para extrair o resultado do super-herói ID 14, que é o átomo de caracteres 3,031 e imprimir essa linha especificamente. Então vamos começar isso e ver se funciona. Gráficos executados. E o que é legal é que é bem rápido também. Assim que começar, não devemos ter que esperar muito tempo. Lá vai ele. E temos os 10 melhores mais conectados e temos os nossos graus de separação. Então, se eu me lembro bem, isso é muito mais rápido do que realmente nossa implementação apenas usando RDD straight up. Então, o GraphX está obviamente fazendo algumas otimizações muito legais. Eles estão debaixo do capô também. Vamos verificar nossos resultados, ter certeza de que fazem sentido. Então eu vou rolar para cima. Top 10 mais ligado ao resultado principal ainda é o Capitão América. Foi o que vimos antes no curso. Isso confere graus de separação do Homem-Aranha para todos. Curiosamente, é um ou dois para todos. Eu acho. Sabes que a lenda de toda a gente estar ligada ao Kevin Bacon é provavelmente verdade, certo? Oh, parece que boom é realmente muito longe tinha três. Ele é mais obscuro. Ainda mais obscuro que Adam, 3.031, que novamente volta como dois graus de separação do Homem-Aranha. Também o mesmo resultado que obtivemos antes. Então isso é muito excitante. Na verdade, temos o mesmo resultado. Funciona. E isso é um pouco mais de uma maneira simples e baseada em princípios de computação dessa operação de gráfico para graus de separação usando GraphX e a API do Pregel. E com isso, cobrimos todos os componentes centrais do Spark. Então, parabéns, com o GraphX, estamos encerrando as coisas. Então vamos falar sobre onde ir a partir daqui.