Alura > Cursos de Data Science > Cursos de Machine Learning > Conteúdos de Machine Learning > Primeiras aulas do curso Classificação: validação de modelos e métricas de avaliação

Classificação: validação de modelos e métricas de avaliação

Classificando dados - Apresentação

E aí, beleza? Muitas empresas estão utilizando Machine Learning no dia a dia para tomada de decisões baseadas em dados.

Neste curso, vamos criar um projeto de classificação com Machine Learning para identificar clientes inadimplentes em uma empresa de empréstimo de automóveis.

Audiodescrição: João Miranda é um homem branco de cabelo médio preso em um coque, com as laterais raspadas. Ele tem a barba rente ao rosto, veste uma camiseta preta e está à frente de uma parede com iluminação esverdeada e sentado em uma cadeira gamer com detalhes brancos.

Em nosso projeto, vamos começar desde o início, realizando a leitura da base de dados, criando um modelo de classificação e focando principalmente na etapa de validação de modelos.

O que faremos no projeto?

Como podemos saber se o nosso modelo está realmente aprendendo com os dados?

Vamos utilizar estratégias de divisão dos dados, como treino, validação e teste, e a validação cruzada para realizar essa tarefa!

Além disso, vamos nos concentrar na etapa de avaliação dos modelos. Vamos conhecer as principais métricas para entender se o nosso modelo está indo bem ou quão bem ele está se saindo. Aprenderemos a utilizar a Acurácia, o o Recall, a Precisão e a matriz de confusão.

Por fim, vamos explorar formas de aprimorar o desempenho do nosso modelo e selecionar aquele que teve o melhor desempenho.

Neste curso, não focaremos na etapa de limpeza e tratamento de dados. Nossos dados já estarão totalmente tratados, mas existem cursos aqui na plataforma da Alura onde você pode aprender a realizar esse tipo de tarefa.

Pré-requisitos

Para acompanhar esse conteúdo, é muito importante que você tenha conhecimento na linguagem de programação Python e conhecimentos básicos de classificação usando Machine Learning.

Vamos começar nosso projeto?

Classificando dados - Criando um modelo inicial

Uma empresa de empréstimo de automóveis está passando por uma situação muito complicada. Ela está com uma alta demanda para uma frota reduzida e uma alta taxa de clientes inadimplentes, ou seja, clientes que não pagam o empréstimo no tempo devido.

Isso está gerando um grande prejuízo para a empresa. E nós fomos contratados para ajudar a melhorar essa situação da empresa, para identificar esses clientes inadimplentes antes mesmo da empresa conceder o empréstimo do veículo.

Para resolver essa situação, essa empresa nos forneceu uma base de dados em formato CSV com dados históricos de clientes inadimplentes. Vamos utilizar essa base de dados para construir um modelo de inteligência artificial que vai conseguir classificar os clientes entre adimplentes e inadimplentes.

Para começar o projeto, vamos utilizar o Google Colab, que já possui todas as ferramentas necessárias para a construção do nosso projeto.

Vamos abrir aqui o Google Colab e o primeiro passo é fazer o upload da base de dados.

Vamos clicar no menu lateral esquerdo de arquivos e selecionar a opção "Fazer upload para o armazenamento da sessão".

Será aberto o explorador de arquivos do computador e vamos selecionar o arquivo emp_automovel.csv.

O arquivo emp_automovel.csv será disponibilizado na atividade "Preparando o ambiente". Antes de começar, volte até a atividade e baixe esse arquivo.

Com o upload do arquivo para o Google Colab feito, podemos importar a biblioteca pandas, que será utilizada para fazer a leitura desse arquivo. Mas antes, vamos copiar o caminho do arquivo no menu lateral. Clique com o botão direito no arquivo emp_automovel.csv e selecione a opção "Copiar caminho". Feito isso, podemos fechar o menu de arquivos e importar a biblioteca pandas, que já vem instalada no Google Colab.

Na primeira célula, vamos escrever import pandas as pd e vamos executar esse código com "Ctrl + Enter".

import pandas as pd

Então, com o código já executado e a biblioteca importada, vamos fazer a leitura da base de dados. Na próxima célula, vamos escrever dados = pd.read_csv(), que é a função que será utilizada para fazer a leitura do arquivo em formato CSV. Dentro dos parênteses, vamos passar uma string vazia e apertar o atalho "Ctrl + V", que vai colar o caminho do arquivo que foi copiado no menu de arquivos. Agora, podemos executar esta célula para fazer a leitura da base de dados.

dados = pd.read_csv('/content/emp_automovel.csv')

Na próxima célula, vamos explorar esses dados para identificar quais tipos de informação temos nesse arquivo. Então, escrevemos dados na próxima célula e executamos o código.

Depois de executar o código, obtemos uma tabela com diversas informações a respeito dos clientes. Essas informações são históricas, ou seja, informações passadas a respeito desses clientes.

Temos as colunas de receita do cliente, anuidade do empréstimo, os anos de casa proprietário e assim por diante. A última coluna dessa base de dados é a coluna "inadimplente" que informa se o cliente pagou o empréstimo ou não.

O valor 0 indica que o cliente pagou o empréstimo no tempo devido. E o valor 1 significa que o cliente é inadimplente, ou seja, não pagou o empréstimo do veículo.

Todas as informações que temos a respeito desses clientes estão em formato numérico. Isso é muito importante para os algoritmos de inteligência artificial porque eles só conseguem compreender informações numéricas. Além disso, essa base de dados já veio totalmente tratada, então não precisaremos fazer nenhum tratamento nessa base de dados.

Tudo que precisamos fazer aqui é executar um algoritmo que selecionaremos, que será o de árvore de decisão.

Mas antes de fazermos isso, vamos separar as variáveis, as colunas das variáveis explicativas, ou seja, são as informações que explicam o padrão dos dados, e a variável "inadimplente". Então, vamos colocar essa variável separada das demais, que é a variável alvo. É a classe que estamos querendo identificar, que nós queremos classificar com nosso algoritmo de inteligência artificial.

Na próxima célula, primeiramente faremos essa divisão das variáveis explicativas e da variável alvo. Vamos chamar as variáveis explicativas de "X", escreveremos:

As variáveis explicativas serão todas as colunas da base de dados, com exceção da coluna "inadimplente". Assim, vamos utilizar o método drop() para remover essa coluna "inadimplente".

Então, como parâmetro da função 'drop', vamos passar 'Inadimplente', entre aspas. Além disso, como segundo parâmetro, axis = 1, para identificar que essa remoção está ocorrendo nas colunas da base de dados.

Na mesma célula, vamos separar também a variável alvo, que chamaremos de "Y". Então, escreveremos Y = dados[‘inadimplente’]. Estamos selecionando justamente a coluna 'Inadimplente'. Agora podemos executar essa célula com "Ctrl + Enter". Desta forma, os dados serão divididos, separados entre variável alvo e variáveis explicativas.

x = dados.drop('inadimplente', axis =1)
y = dados ['inadimplente']

Árvore de decisão

Agora, iremos utilizar o algoritmo de Árvores de Decisão, que toma decisões baseadas no padrão dos dados para classificar os clientes entre adimplente e inadimplente.

Para isso, primeiramente, é necessário fazer a importação do método, da função capaz de executar esse algoritmo. Esse algoritmo está disponibilizado na biblioteca scikit-learn, que já vem instalada no Google Colab.

Na próxima célula, escreveremos from sklearn.tree import DecisionTreeClassifier. A palavra "tree" refere-se ao módulo dos algoritmos baseados em árvore, que é a árvore de decisão que usaremos. Aqui as letras "D", "T" e "C" estão em caixa alta, e "Classifier" aqui indica que é um algoritmo do tipo classificação.

Estamos usando um algoritmo deste tipo porque estamos classificando nossos dados entre duas categorias, a categoria 0 e a categoria 1, que representam os adimplentes e os inadimplentes.

from sklearn.tree import DecisionTreeClassifier

Ao executar essa célula, já importamos o algoritmo. Agora, vamos ajustar esse algoritmo em um modelo.

Vamos ajustar o modelo a esses dados de x e y que temos aqui.

Na próxima célula, escreveremos modelo e vamos inicializar esse modelo. Vamos armazenar em uma variável, escrevendo modelo = DecisionTreeClassifier().

Na mesma célula, vamos finalizar o ajuste usando esse algoritmo para moldar nossos dados. Para isso, usaremos o método fit() a partir do modelo. Então, escreveremos modelo.fit(x, y). A partir da aplicação do método fit(), a variável modelo vai armazenar o padrão daqueles dados e vai conseguir classificar dados novos.

Posteriormente, conseguiremos avaliar quão bem esse modelo está apresentando resultados em fazer essa classificação.

Podemos utilizar o método score() para fazer essa avaliação. Portanto, na mesma célula, escreveremos modelo.score(x, y). A partir das variáveis explicativas armazenadas em x, o modelo fará a classificação desses dados da variável x, obterá o resultado da classificação e comparará o resultado com os dados armazenados na variável y.

A partir dessas comparações, obtemos uma taxa de acerto. Vamos agora executar essa célula, para identificar o quão preciso foi o nosso modelo.

modelo = DecisionTreeClassifier()
modelo.fit(x, y)
modelo.score(x, y)

1.0

Obtivemos um resultado de 1.0. Esse "1.0" representa uma métrica conhecida como acurácia, que é a taxa de acerto geral do modelo. Essa métrica é a resultante da comparação da classificação feita com base nas variáveis explicativas, comparando o resultado com os dados reais armazenados na variável y. Fazendo essa comparação, obtivemos um resultado de 1.0, que em porcentagem é 100%. Isso significa que o nosso modelo não cometeu erros de classificação.

Para documentarmos esse resultado, vamos inserir na próxima célula um print com essa informação. Portanto, escreva:

print(f'Acurácia: {modelo.score(x, y)}')

Acurácia: 1.0

Ao executar essa célula, obtemos a informação de acurácia de 1.0. Isso significa que esse modelo não está errando em nenhum momento na classificação dos dados. Seria excelente, pois queremos um modelo que classifique de forma correta os dados de clientes inadimplentes e adimplentes.

Porém, veremos no próximo vídeo que este resultado é enganoso. Estamos utilizando a acurácia somente na avaliação dos dados de treinamento, isto é, os dados que foram usados para ensinar o modelo a identificar os padrões.

Os dados usados para avaliar o desempenho do modelo deveriam ser diferentes dos dados usados para treinamento. Se isso não ocorrer, pode-se cometer um erro em avaliar se o modelo está realmente entendendo o padrão dos dados ou se está apenas memorizando o resultado. No próximo vídeo, explicaremos como fazer essa separação corretamente.

Classificando dados - Validando o modelo

Com o objetivo de identificar clientes inadimplentes para uma empresa de empréstimos de automóveis, criamos um modelo de classificação utilizando os dados fornecidos por essa empresa. Obtivemos um resultado de acerto, conhecido como acurácia, de 100%, indicando que o modelo está acertando todas as classificações que realizou.

No entanto, a validação do nosso modelo foi feita de forma pouco efetiva. Utilizamos os mesmos dados usados para o treinamento do modelo para fazer a avaliação.

Isso equivale a entregar uma prova com gabarito para uma pessoa resolver, nessa prova, com o gabarito a pessoa já terá as respostas de todas as perguntas. Dessa forma, se quisermos que essa pessoa entenda o conteúdo da prova, ela poderia simplesmente memorizar o resultado com o gabarito e aplicar numa nova prova. E é exatamente isso que estamos fazendo. Estamos dando a essa pessoa a mesma prova novamente, com as mesmas questões e, consequentemente, com as mesmas respostas.

Portanto, é natural que essa pessoa acerte tudo, não porque ela entendeu a matéria, de fato, mas porque memorizou o resultado. Isso não significa que o modelo que construímos memorizou o resultado. Ainda não sabemos se isso aconteceu. No entanto, como aplicamos a mesma prova, ou seja, utilizamos os mesmos dados, não sabemos se é isso que está de fato ocorrendo.

Então, precisamos fazer uma validação de forma mais coerente. Precisamos passar novos dados para o modelo fazer a classificação. E nesses dados, já conheceremos a resposta, e poderemos comparar a resposta que o modelo deu para esses dados com as respostas reais e verificar se, de fato, está acertando. Dessa maneira, entenderemos se o modelo está aprendendo, ou seja, se está generalizando para novos dados ou não.

Para realizar essa tarefa de validação, podemos dividir nossos dados em duas partes: uma parte de treinamento e uma parte de validação. Ainda podemos utilizar outra estratégia, em vez de dividir nossos dados em apenas duas partes, vamos dividi-los em três: treinamento, validação e teste.

Qual a diferença de utilizar essas duas estratégias?

Na primeira, onde temos apenas treino e teste, vamos treinar o modelo na base de dados de treinamento e avaliar na base de dados de teste, que são dados que não foram usados no treinamento, sendo assim, verificaremos se o modelo está fazendo a generalização.

Na segunda estratégia, que separa entre treino, validação e teste, deixamos uma parte de teste separada durante todo o projeto e fazemos a validação do modelo no conjunto de dados de validação.

Assim, treinamos o modelo, fazemos a validação daquele modelo num conjunto de validação e deixamos separado um conjunto de teste até o final do projeto.

Por que fazer isso?

Ao longo do projeto, comparamos diversos modelos e aprimoramos o nosso modelo conforme os dados de validação. No entanto, para não carregar um viés para esse modelo, ou seja, estamos sempre melhorando aquele modelo com base em determinados dados. E se formos avaliar o modelo numa base de dados do mundo real, não saberemos como será o comportamento dele, porque sempre utilizamos um determinado padrão de dados para melhorá-lo.

Portanto, quando fazemos a separação de dados de teste, conseguimos, na escolha do melhor modelo durante o projeto, realizar essa última checagem para ver o desempenho do modelo em dados do mundo real, que ele nunca viu no processo de melhoria do modelo.

Desta forma, é isso que faremos.

Vamos dividir nossos dados em três partes: treinamento, validação e teste.

Para isso, utilizaremos uma função da biblioteca scikit-learn chamada train_test_split.

Porém, esta função permite somente a separação dos dados em treino e teste. Então, primeiramente faremos uma divisão que inclui treino e validação juntos, e teste separado. Em seguida, iremos subdividir os dados de treino e validação em duas partes.

Primeiramente, precisamos importar a função train_test_split. Então, escreva:

from sklearn.model_selection import train_test_split

Depois de importada a função, podemos fazer a primeira separação. Vamos fazer a separação de treino e validação em um mesmo conjunto de dados, que será chamado de x. Esse conjunto substituirá o valor x existente. A outra parte será os dados de teste.

Portanto, vamos criar variáveis chamadas de x_test e y_test, que vão armazenar esses dados. Para separá-los, podemos escrever o seguinte:

x, x_teste, y, y_teste = train_test_split(x, y, test_size = 0.15, stratify = y, random_state = 5)

Neste fragmento de código, passamos para a função train_test_split a base de dados com os valores de x, que são as variáveis explicativas, e a variável alvo y. Definimos também que 15% dos nossos dados (ou seja, test_size = 0.15) serão usados para teste.

Além disso, usamos o parâmetro stratify para estratificar os nossos dados. Isso significa que manteremos as proporções de pessoas inadimplentes e adimplentes nesses dois conjuntos de dados.

Assim, mantemos a mesma proporção para que tanto nos dados de teste quanto nos dados de treino estejam representadas as mesmas proporções de dados.

Por fim, definimos o parâmetro random_state como 5. Isso porque a divisão feita por train_test_split é realizada de forma aleatória. Com random_state = 5, mesmo sendo uma escolha aleatória, você obterá o mesmo resultado obtido aqui.

Agora, podemos fazer a subdivisão dos dados de treino e validação. Vamos utilizar a mesma função train_test_split, mas desta vez iremos usar os dados armazenados em x e y. Lembrando que esses não são os mesmos dados iniciais, pois substituímos o dado x e y por essas novas variáveis, ou seja, somente essa parte de treino e validação está sendo separada aqui agora entre treino e validação.

x_treino, x_val, y_treino, y_val = train_test_split(x, y, stratify = y, random_state = 5)

Vamos abrir essa célula e passar o parâmetro stratify igual a y e o random_state igual a 5, isso para manter a proporção dos dados e garantir que o resultado que estamos construindo aqui seja o mesmo que você obterá nas vezes em que executar esse código.

x, x_teste, y, y_teste = train_test_split(x, y, test_size = 0.15, stratify = y, random_state = 5)
x_treino, x_val, y_treino, y_val = train_test_split(x, y, stratify = y, random_state = 5)

Vamos executar essa célula e fazer a divisão dos dados.

Feita a divisão dos dados, vamos criar novamente o modelo. Desta vez, nós não avaliaremos o modelo nos mesmos dados que usamos para o treinamento. Vamos treinar e ajustar nosso modelo com os dados de treino e avaliar o resultado nos dados de validação. Os dados de teste (as variáveis x_test e y_teste) ficarão separados e não serão utilizados agora, guardaremos para um momento posterior do curso.

Vamos iniciar nosso modelo escrevendo: modelo = DecisionTreeClassifier. Em seguida, ajustaremos nosso modelo escrevendo: modelo.fit, passando como parâmetros x_treino e y_treino. Dessa maneira, o modelo será ajustado, compreendendo o padrão dos dados apenas com base na sessão de treinamento.

modelo = DecisionTreeClassifier()
modelo.fit(x_treino, y_treino)

Agora, utilizaremos a acurácia. Faremos duas acurácias diferentes, uma para o treinamento e outra para o teste, para conseguirmos comparar como o modelo performa utilizando os mesmos dados de treinamento e como se sai para dados novos.

modelo = DecisionTreeClassifier()
modelo.fit(x_treino, y_treino)
print(f'Acurácia de treino: {modelo.score(x_treino, y_treino)}')
print(f'Acurácia de validação: {modelo.score(x_val, y_val)}')

Dessa maneira, ele calculará a taxa de acerto para dados não vistos nos dados de validação. Vamos executar a célula:

Acurácia de treino: 1.0

Acurácia de validação: 0.84446128386029091

Executando essa célula, obtivemos um resultado de acurácia de treino de 1.0 e um de validação de 0.84. Nos dados de treinamento, nosso modelo não errou.

Porém, nos dados de validação, que são dados novos, ele obteve uma taxa de acerto de 84%. Isso indica que ele perdeu bastante desempenho ao tentar classificar dados que ele não viu durante o treinamento.

Aconteceu algo muito ruim. A performance desse modelo caiu drasticamente. Ele teve uma performance de 100% nos dados de treinamento, ou seja, não errou, mas nos dados de validação que ele nunca viu, ele teve uma performance de 84%.

O que pode estar acontecendo? Nosso modelo pode estar compreendendo muito bem os dados de treino ou pode estar decorando aquele padrão e tentando replicar o mesmo padrão para os dados de teste.

Parâmetro max_depth

Para resolver essa situação, podemos passar um parâmetro para esse algoritmo de árvore de decisão, que será o parâmetro max_depth. Este parâmetro controla a profundidade máxima da árvore de decisão. Sem a passagem de nenhum parâmetro, o algoritmo tentará capturar todos os traços dos dados que foram utilizados no treinamento para fazer a classificação, levando a um sobreajuste desses dados.

Ele vai entender completamente como os dados funcionam e tentará aplicar isso em dados que nunca viu.

Vamos copiar esse código, colar na célula abaixo e modificar esse parâmetro da árvore de decisão para max_depth igual a 10. Assim, estabeleceremos uma profundidade máxima de 10.

modelo = DecisionTreeClassifier(max_depth = 10)
modelo.fit(x_treino, y_treino)
print(f'Acurácia de treino: {modelo.score(x_treino, y_treino)}')
print(f'Acurácia de validação: {modelo.score(x_val, y_val)}')

Vamos executar esse código e verificar se isso foi o suficiente para melhorar o resultado do nosso modelo.

Acurácia de treino: 0.9206445993031359

Acurácia de validação: 0.9060186394913335

Agora, obtivemos um resultado de acurácia de treino de 0.92. Ou seja, agora, o nosso modelo está errando mesmo para os dados de treinamento. Efetivamente, eu passei os mesmos dados para ele e ele não está tendo um acerto de 100%. Ele está acertando em 92%.

Entretanto, veja que interessante, nos dados de validação, ele obteve uma acurácia de 0.90. Não foi a mesma dos dados de treinamento, mas melhorou em relação ao modelo anterior que era de 0.84. Isso indica que agora o nosso modelo está conseguindo entender melhor o padrão que existe nos dados e não apenas memorizando o resultado.

Conclusão

Mas, até agora, avaliamos o nosso modelo utilizando apenas a acurácia, que reflete uma taxa de acerto geral do nosso modelo, isto é, se ele está acertando ou não de uma forma geral.

Como podemos saber se o nosso modelo está acertando bem apenas para as pessoas inadimplentes ou apenas para as pessoas adimplentes? A acurácia não nos fornece essa informação e é exatamente isso que vamos explorar no próximo vídeo.

Vamos ver uma maneira de avaliar o nosso modelo de forma mais específica para cada uma das classes.

Sobre o curso Classificação: validação de modelos e métricas de avaliação

O curso Classificação: validação de modelos e métricas de avaliação possui 128 minutos de vídeos, em um total de 48 atividades. Gostou? Conheça nossos outros cursos de Machine Learning 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 Machine Learning acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas