Alura > Cursos de Data Science > Cursos de Engenharia de Dados > Conteúdos de Engenharia de Dados > Primeiras aulas do curso Spark: criando modelos de classificação

Spark: criando modelos de classificação

Preparando os dados - Apresentação

Olá! Eu sou o Igor do Nascimento Alves e vou ser seu instrutor nesse curso de Classificação com PySpark.

Igor é um homem branco, com barba e cabelos pretos e curtos, e olhos também pretos. Ele está vestindo uma camisa preta e usando fones de ouvido internos sem fio. Ao fundo, sob uma iluminação verde, há uma parede com algumas prateleiras e nichos com itens de decoração e livros.

Para acompanhar essas aulas, é importante que você conheça a criação de modelos de Machine Learning para problemas de classificação, além da otimização de hiperparâmetros desses modelos. Assim, você conseguirá entender como aplicar esses conceitos no contexto do Spark.

Projeto

Recebemos a demanda de ajudar o time de marketing a prever se um cliente vai cancelar o serviço ou não, pois eles estão notando um problema com o churn.

Nossa proposta para esse problema é criar um modelo de machine learning capaz de fazer a classificação entre clientes que vão cancelar o serviço e os que não vão.

Para isso, vamos utilizar uma base de dados fornecida pelo time de marketing contendo informações sobre esse cliente, como o tipo de serviço que ele contratou, há quanto tempo seu contrato está vigente, etc. Com essas informações, criaremos o modelo.

Utilizaremos o PySpark para fazer isso, principalmente o modo Spark DataFrame SQL e o MLlib. Com essa ferramenta faremos todo o pipeline do machine learning, passando pela etapa de tratamento dos dados, ajuste dos modelos por meio de algoritmos, otimização desses modelos encontrando os melhores hiperparâmetros e, por fim, a validação dos modelos.

Ao final do pipeline, entregaremos um modelo capaz de realizar a classificação de novos clientes entre provável cancelamento do serviço ou não, oferecendo essa previsão. Ou seja, teremos um modelo com tuning, otimizado para o nosso problema.

Com certeza ajudaremos o time de marketing com essa solução. Então, vamos lá?!

Preparando os dados - O problema e a ferramenta

Vamos recapitular o nosso problema.

Nós, do time de ciência de dados do Alura Voz, recebemos uma demanda do Marketing. Existe um problema, atualmente, com o alto número de churn: basicamente, muitos clientes cancelando o serviço.

Para resolver esse problema, a ideia do time de marketing é oferecer promoções para os clientes que provavelmente cancelarão o serviço, procurando evitar esse cancelamento.

Demanda

Na reunião entre nosso time e o time de marketing, surgiu a ideia de criarmos um modelo de Machine Learning capaz de classificar nossos clientes entre possíveis cancelamentos ou não.

Basearemos esse modelo nos dados históricos da empresa, relacionando as características dos clientes em relação ao contrato estabelecido e as ocorrências de cancelamento.

Nossa liderança técnica estabelece que o recomendado para esse problema é a utilização do PySpark, uma vez que o time de marketing conta com um grande volume de dados acerca de clientes. O PySpark é a única ferramenta capaz de processar todos esses dados e tornar a nossa pesquisa possível.

A ferramenta

Vamos utilizar o ambiente do Google Colab nesse projeto, muito bem configurado, preparado, e conta com diversas bibliotecas pré-instaladas - exceto o PySpark.

Portanto, vamos instalar o PySpark no nosso notebook do Colab, disponível neste link. Esse notebook que vamos fornecer para você possui algumas informações muito interessantes.

Na primeira célula, há uma breve explicação sobre o PySpark e suas ferramentas, como o Spark SQL DataFrame e o MLlib, nos quais focaremos nesse projeto, além do Streaming. Tudo isso é construído em cima do Spark Core. Além disso, oferecemos também alguns links para leitura.

Instalação do PySpark

No canto superior direito da página do nosso notebook do Colab, vamos clicar no botão "Conectar". Com isso, o Google Colab disponibiliza uma máquina para trabalharmos. Sabemos que a conexão foi bem sucedida quando, nesse mesmo lugar na tela, temos um ícone de "check" verde.

Em seguida, na primeira célula de código, digitaremos:

[1]

!pip install pyspark

Então apertamos o atalho "Shift + Enter" para executar essa célula. Esse processo pode demorar um pouco, visto que são realizados o download da biblioteca, a instalação de pré-requisitos e uma série de configurações prévias.

Terminada a instalação, faremos um teste para verificar se tudo funciona como esperado.

SparkSession (ou sessão Spark)

Para esse teste, usaremos a parte de criação de sessão Spark, ou SparkSession, da biblioteca. Basicamente, a sessão Spark é o modo como fazemos a interação com o Spark.

O Spark é responsável por processar grandes bases de dados, e para nos comunicarmos com ele pelo Python, realizamos a conexão através de uma API. Ou seja, precisamos criar essa sessão Spark, que ficará responsável pelos dados, para interagir com ele.

Então precisamos, primeiramente, importar essa etapa da ferramenta, inserindo o seguinte código na célula de SparkSession:

[2]

from pyspark.sql import SparkSession

Apertando "Shift + Enter" novamente, fazemos a importação da ferramenta SparkSession.

Agora vamos criar a sessão. A salvaremos em uma variável chamada spark, em uma terceira célula de código, chamando um construtor SparkSession.builder que criará a estrutura necessária. Em seguida, temos que passar alguns parâmetros importantes para esse construtor.

Precisamos do comando .master() para indicar para esse construtor onde o Spark está rodando. No caso, vamos utilizar o ambiente local, então passaremos 'local[*]' como parâmetro desse comando. Outro comando importante é o appName(), com o qual nomearemos a nossa sessão para identificá-la mais facilmente. Passaremos o nome como parâmetro desse comando, que indicará o problema a resolver: "Classificação com Spark". Por último, podemos criar a sessão, de fato. Para isso, usamos o método .getOrCreate().

Por fim, teremos a seguinte linha de código para a criação da SparkSession:

[3]

spark = SparkSession.builder.master('local[*]').appName("Classificação com Spark").getOrCreate()

Em seguida, executamos novamente esse código com "Shift + Enter". Assim, a conexão e a criação do ambiente com que vamos interagir serão realizadas.

Por fim, em uma quarta célula de código, vamos digitar apenas spark, nossa variável, para analisar os resultados. O retorno é o seguinte:

[4]

SparkSession - in-memory
SparkContext
Spark UI
Version
    v3.2.1
Master
    local[*]
AppName
    Classificação com Spark

Temos a versão utilizada do Spark, o ambiente e o nome que definimos. Ou seja, tudo funciona conforme o esperado e estamos preparados para trabalhar!

Agora, então, vamos analisar a nossa base de dados.

Observação: vamos trabalhar com uma base de dados pequena, porque estamos no ambiente do Colab e não vamos realizar tantas configurações no Spark. Além disso, como nosso objetivo é entender a ferramenta e criar esse modelo de classificação, uma base pequena é o suficiente para esse propósito.

Preparando os dados - Carregar e explorar dados

Os dados com que iremos trabalhar foram fornecidos para nós em um arquivo CSV. Tendo feito seu download, o carregaremos no Colab.

Carregando os dados

Para isso clicamos no ícone de pasta, chamado "Arquivos", no menu lateral esquerdo do Colab. Assim, uma aba será aberta contendo diferentes opções para o carregamento de arquivos. Clicaremos na primeira opção, "Fazer upload para o armazenamento da sessão", representada pelo ícone de um arquivo com uma seta dentro, apontando para cima.

Feito isso, a janela dos nossos arquivos locais será aberta. Selecionamos o arquivo dados_clientes.csv e clicamos em "Abrir" no canto inferior direito da janela. Nesse momento, o seguinte aviso será exibido:

"Observação: os arquivos enviados serão excluídos quando o ambiente de execução for reciclado."

Isso significa que nosso arquivo funciona apenas na sessão, portanto, temos de recarregá-lo a cada vez que reiniciarmos o Colab. Clicamos em "Ok" no canto inferior direito do pop-up.

Assim, nossos dados serão carregados. Verificamos isso pela aba lateral esquerda, que agora exibe dados_clientes.csv. Clicamos no ícone de pasta novamente para essa aba se fechar e ganharmos espaço de tela.

Agora, na sessão "Carregamento dos Dados" do nosso notebook, carregaremos esses dados na variável dados, na primeira célula de código. Essa variável receberá o contexto Spark, ou seja, a nossa variável spark. Em seguida, usaremos o comando .read.csv() para que o nosso arquivo de dados seja lido pelo Spark.

[5]

dados = spark.read.csv()

Agora, precisamos passar alguns parâmetros essenciais para esse comando de leitura. O primeiro deles é a indicação de onde está o nosso arquivo. Como ele está na raiz do nosso projeto, basta digitarmos o seu nome entre aspas simples: 'dados_clientes.csv'.

Outro parâmetro importante é o separador, sep=, que indica qual caractere o nosso arquivo usa para separar os dados. No nosso caso é a vírgula, então a colocamos entre aspas simples ','.

Precisamos, também, indicar se o nosso CSV conta com um cabeçalho (header=) que informa o que cada coluna representa. No nosso caso, sim. Então esse parâmetro terá o valor True.

Por fim, o último parâmetro interessante é o inferSchema, que interpretará o esquema dos nossos dados a partir do arquivo CSV, assumindo o tipo de cada variável. O valor desse parâmetro também será True.

Com tudo isso, teremos a seguinte linha de código:

dados = spark.read.csv('dados_clientes.csv', sep=',', reahder=True, inferSchema=True)

Então, apertamos "Shift + Enter" e nossa base de dados será carregada, criando a representação de DataFrame do SQL do Spark.

Lendo os dados

Na próxima célula de código, podemos executar apenas a variável dados para verificar essa leitura. No entanto, quando digitamos dados, apenas a estrutura do nosso DataFrame é exibida:

DataFrame[id: int, Churn: string, Mais65anos: int, Conjuge: string, Dependentes: string, MesesDeContrato:int, ... //retorno omitido

Ou seja, o DataFrame é composto de um primeiro campo chamado "id" do tipo inteiro, um segundo campo chamado "Churn" do tipo string, e assim por diante.

Para exibir o DataFrame propriamente, vamos executar o comando .show, ou seja, "mostrar":

[7]

dados.show()

Agora, sim, visualizamos os dados na forma de DataFrame (que você pode conferir com detalhes na seção 1.3 do nosso notebook, disponível neste link). Na primeira linha temos os nomes das colunas, separadas por vários caracteres, como "id", "Churn", "Mais65anos", "Conjuge", "Dependentes", "MesesDeContrato", etc.

Abaixo dos nomes das colunas, temos os dados em si. Por exemplo, o primeiro cliente está registrado como id "0", valor de Churn como "Não" (ou seja, ele não cancelou o serviço), valor "0" para Mais65Anos (significando "falso", ao contrário de "1" que significaria "verdadeiro"), etc.

Vemos que nas colunas "Churn", "Cônjuge", "Dependentes" e "TelefoneFixo" foram usadas variáveis de sim e não, diferente de "Mais65Anos", que usa a variável binária de 0 e 1. Inclusive, as variáveis "MaisDeUmaLinhaTelefonica" e "Internet", têm 3 valores possíveis, e não apenas 2. Ou seja, os dados estão registrados sem um padrão, provavelmente porque são informações que vieram de um questionário e não foram tratadas. Devemos nos atentar a isso porque pode ser um problema no futuro.

Agora, vamos explorar outras informações dos nossos dados.

Explorando os dados

Por exemplo, vamos extrair o número de registros que temos nessa base de dados. Para isso, executamos o comando .count() na variável dados, na próxima célula de código. Teremos o seguinte código e retorno, respectivamente:

[8]

dados.count()

10348

Ou seja, temos dez mil, trezentos e quarenta e oito registros. É com esse volume de dados com que trabalharemos nesse projeto.

Outra informação interessante que podemos colher é acerca do balanceamento dessa base. Ou seja, temos a mesma quantidade de assinaturas ativas e de cancelamentos?

Para descobrir isso, precisamos agrupar as informações de churn por meio do comando .groupBy() na variável dados. Passaremos o nome da coluna que queremos agrupar como parâmetro desse comando: 'Churn'.

Mas, se queremos contar quantos registros temos em cada valor dessa variável ("Sim" ou "Não"), usaremos o comando count() novamente.

Por último, queremos visualizar esse DataFrame que será criado exibindo essas informações. Para isso, usamos show() novamente. Enfim, teremos:

[9]

dados.groupBy('Churn').count().show()

Executando essa linha de código, teremos o seguinte DataFrame como retorno:

[9] (retorno

Churncount
Sim5174
Nao5174

Ou seja, temos um DataFrame bem pequeno com o mesmo layout do DataFrame anterior: nome das colunas na linha superior e, abaixo, o valor dessas categorias.

Com esses dados assim dispostos, vemos que nossa base de dados está balanceada: temos o mesmo número de cancelamentos e assinaturas ativas. Essa é uma informação importante para decidirmos que tipo de modelo de Machine Learning nós utilizaremos, a quais métricas podemos recorrer e como podemos fazer a leitura dessas métricas.

Mas a nossa preocupação atual é em relação ao tipo dos nossos dados, pois observamos anteriormente que temos algumas strings no meio deles.

Tipo de dados

Para analisar isso mais detalhadamente, podemos usar o comando printSchema(), que terá o seguinte retorno:

[10]

dados.printSchema()
root
 |-- id: integer (nullable = true)
 |-- Churn: string (nullable = true)
 |-- Mais65anos: integer (nullable = true)
 |-- Conjuge: string (nullable = true)
 |-- Dependentes: string (nullable = true)
 |-- MesesDeContrato: integer (nullable = true)
 |-- TelefoneFixo: string (nullable = true)
 |-- MaisDeUmaLinhaTelefonica: string (nullable = true)
 |-- Internet: string (nullable = true)
 |-- SegurancaOnline: string (nullable = true)
 |-- BackupOnline: string (nullable = true)
 |-- SeguroDispositivo: string (nullable = true)
 |-- SuporteTecnico: string (nullable = true)
 |-- TVaCabo: string (nullable = true)
 |-- StreamingFilmes: string (nullable = true)
 |-- TipoContrato: string (nullable = true)
 |-- ContaCorreio: string (nullable = true)
 |-- MetodoPagamento: string (nullable = true)
 |-- MesesCobrados: double (nullable = true)

Estamos diante do esquema dos nossos dados, que é bastante simples: temos apenas um primeiro nível de colunas, todas alinhadas. Nesse esquema, vemos o nome da coluna e o tipo de informação que o Spark reconhece nela.

O "id" é um inteiro, pois conforme vimos antes, os valores apresentados nessa coluna são numéricos. Já o "Churn" é uma string, pois seus valores são representados por "Sim" e "Nao", e assim por diante.

A maioria das nossas colunas tem os valores representados por string, o que é um problema para os modelos de Machine Learning, que não sabem lidar com dados em texto.

Dessa forma, precisamos encontrar uma maneira de transformar todos esses dados em números. É o que faremos a seguir.

Sobre o curso Spark: criando modelos de classificação

O curso Spark: criando modelos de classificação possui 154 minutos de vídeos, em um total de 49 atividades. Gostou? Conheça nossos outros cursos de Engenharia de Dados em Data Science, ou leia nossos artigos de Data Science.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Engenharia de Dados acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas