Como criar um modelo para predição de churn

Luis Eduardo
Neuronio BR
Published in
7 min readJun 19, 2019

Nota: uma versão em inglês deste artigo pode ser encontrado em “How to create a churn prediction model

Fonte da imagem

Perder seus clientes não é bom, e caso pudesse prever quando um cliente irá parar de utilizar o serviço seria uma grande oportunidade para se tomar decisões que irão manter os clientes. Esse é o nosso objetivo nesse artigo, criar e comparar modelos de Machine Learning para prever quando um cliente irá parar de usar um serviço, ou seja, quando ocorrerá churn.

Em um modelo de Machine Learning, o dado é a coisa mais importante. Um bom modelo não consegue fazer milagre com dados ruins. Por isso é necessário realizar um preparo dos dados para que possam ser utilizados no modelo.

O conjunto de dados que sera utilizado neste artigo é o Telco Churn Customer disponível no Kaggle. E todo o código desse exemplo foi feito em python e está disponível aqui.

Vamos iniciar.

O conjunto de dados

Será utilizada a biblioteca pandas para podermos trabalhar com o conjunto de dados. Primeiramente, vamos ler o arquivo do conjunto de dados.

Podemos visualizar algumas informações sobre o conjunto de dados com a função pandas.DataFrame.info(). Essa função mostra um resumo sobre o DataFrame, ele apresenta quais as colunas/features, o tipo de cada coluna e a quantidade de valores não nulos das colunas.

Informações do conjunto de dados

Nesse caso nós não precisamos lidar com valores faltantes, e temos poucas features numéricas. Também temos a coluna com os rótulos que queremos prever, a coluna Churn, mas, se não estivesse contida no conjunto de dados, precisaríamos gera-las com base na definição do objetivo. Caso o objetivo não esteja definido é necessário defini-lo antes de gerar os valores do rótulo.

O conjunto de dados é referente a uma empresa de Telecomunicação. Nele há informações dos clientes, como se possui parceiro(a), se possui dependentes, etc, e sobre seus contratos, como serviço de telefone, quantidade paga por mês, etc. Algumas features apresentam relação com o tempo de contratação do serviço, como tenure, TotalCharges e MonthlyCharges, que significam, respectivamente, tempo, em meses, que o cliente possui o serviço e total pago pelo cliente.

Agora, vamos ver a distribuição do rótulo utilizando a biblioteca seaborn.

Distribuição de Churn

Podemos notar que está desbalanceado. Temos aproximadamente 27% para Churn e 73% para não Churn nesse conjunto de dados. Isso pode ser um problema para se obter o melhor resultado de um modelo.

Nos podemos utilizar a função head() do pandas para conseguir visualizar as 5 primeiras linhas da tabela pra ter uma noção de como estão os dados.

Pré-processamento de Dados

Em alguns problemas de Machine Learning nos temos que realizar algum pré-processamento de dados. Isso é um passo importante para preparar os dados para o modelo de ML para que possamos obter resultados melhores e também conhecimento sobre o dados.

Vamos aplicar pré-processamento nos dados agora.

Olhando os dados podemos ver que algumas das colunas/features possuem três valores únicos que são redundantes. Por exemplo, na feature MultipleLines temos o valor “No phone service”, porém já temos a feature PhoneService com essa informação, então, iremos substituir esse valor por apenas “No”, ficando assim com apenas dois valores únicos. Podemos fazer isso também para outras features como OnlineBackup, OnlineSecurity, DeviceProtection, TechSupport, StreamingMovies, StreamingTV.

Nós temos algumas features numéricas, e podemos usar funções como countplot() do seaborn e hist() do pandas para ter uma visão geral da distribuição e da relação das features com o rotulo.

Contagem de tenure na esquerda e tenure x Churn na direita
Distribuição de MonthlyCharges na esquerda e MonthlyCharges x Churn na direita
Distribuição de TotalCharges na esquerda e TotalCharges x Churn na direita

É possível identificar diferentes padrões nas distribuições dessas features. Podemos ver que essas features possuem valores numéricos contínuos e possuem distribuições desbalanceadas, para mudar isso podemos aplicar algumas opções, por exemplo, converter em categorias, como dividir em intervalos predefinidos ou quantis, podemos fazer isso para evitar que as distribuições fiquem muito desbalanceadas.

Contagem de Tenure_cat na esquerda e tenure_cat x Churn na direita
Contagem de MonthlyCharges_cat na esquerda e MonthlyCharges_cat x Churn na direita
Contagem de TotalCharges_cat na esquerda e TotalCharges_cat x Churn na direita

Agora nós temos todas as features categóricas e podemos usar dessa forma. Contudo, alguns dos algoritmos que serão utilizados aceitam apenas números e por isso precisamos modificar as categorias para valores numéricos. Para fazer isso temos algumas opções como o One-Hot Encoding e o Integer/Label Encoding.

Integer Encoding é um simples marcador que mapeia as categorias em valores numéricos inteiros com uma relação de ordenação natural. Já o One-Hot Encoding possui uma abordagem diferente, recomendado para features que não seguem uma ordenação natural, nesse método as categorias são mapeadas em colunas e preenchidas com valores binários.

Para aplicar essa mudanças podemos usar o LabelEncoding do sklearn para fazer Integer Encoding e o get_dummies() do pandas para o One-Hot Encoding.

Agora podemos ver a relação entre cada feature nos dados numéricos utilizando a função heatmap() do seaborn.

Heatmap da correlação entre as features

Os modelos

Agora que temos os dados preparados para os modelos, temos que dividir em dados para treinamento e validação do modelo. Para isso vamos utilizar a função train_test_split() do sklearn.

Agora vamos criar e treinar os modelos com os algoritmos Logistic Regression, Random Forest e Gradient Boosting, vamos utilizar o sklearn para isso.

Agora já temos os modelos treinado e podemos valida-los com o método predict() de cada modelo.

Em seguida podemos ver os resultados obtidos.

No nosso caso a Accuracy não é uma métrica muito boa para avaliar nossos modelos, pois ela mede a exatidão geral do modelo, e, como o conjunto de dados está desbalanceado, acarreta em um aumento que não reflete no nosso resultado positivo. Portanto, é bom escolhermos outras métricas que estão disponíveis, como Precision e Recall.

Precision é a porcentagem de predições corretas para o rótulo dentre o total que foi previsto com esse rótulo, ou seja, quão bem o modelo prevê o rótulo. E o Recall é a porcentagem de predições corretas para o rótulo dentre o total de entradas que realmente possuem esse rótulo, ou seja, quão bem o modelo prevê o rótulo dado que este é o rótulo correto.

Podemos notar que os modelos de Logistic Regression e Gradient Boost obtiveram resultados parecidos nesse caso, porém, caso o conjunto de dados seja muito grande o Gradient Boost se mostra melhor em performance.

Conclusão

Para um problema de predição, é necessário gastar um tempo na etapa de Pré-processamento de Dados. Ao analisar o conjunto de dados é possível realizar algumas suposições que possam melhorar o desempenho do modelo. Dependendo do tamanho do conjunto de dados isso pode demorar bastante tempo, porém, é uma etapa muito importante para a qualidade do modelo.

A escolha do modelo pode acabar não tendo tanto impacto nos resultados como o pré-processamento dos dados. Além disso, casos onde o conjunto de dados está desbalanceado é interessante escolher outras métricas além da Accuracy.

--

--