|
2 weeks ago | |
---|---|---|
.. | ||
solution | 3 weeks ago | |
README.md | 2 weeks ago | |
assignment.md | 3 weeks ago | |
notebook.ipynb | 3 weeks ago |
README.md
Regressão logística para prever categorias
Questionário pré-aula
Esta lição está disponível em R!
Introdução
Nesta última lição sobre Regressão, uma das técnicas básicas clássicas de ML, vamos explorar a Regressão Logística. Esta técnica é usada para descobrir padrões e prever categorias binárias. Este doce é chocolate ou não? Esta doença é contagiosa ou não? Este cliente vai escolher este produto ou não?
Nesta lição, você aprenderá:
- Uma nova biblioteca para visualização de dados
- Técnicas de regressão logística
✅ Aprofunde seu entendimento sobre como trabalhar com este tipo de regressão neste módulo de aprendizado
Pré-requisito
Depois de trabalhar com os dados de abóbora, já estamos suficientemente familiarizados para perceber que há uma categoria binária com a qual podemos trabalhar: Color
.
Vamos construir um modelo de regressão logística para prever, com base em algumas variáveis, qual é a cor provável de uma abóbora (laranja 🎃 ou branca 👻).
Por que estamos falando de classificação binária em uma lição sobre regressão? Apenas por conveniência linguística, já que a regressão logística é na verdade um método de classificação, embora baseado em linearidade. Aprenda sobre outras formas de classificar dados no próximo grupo de lições.
Definir a questão
Para nossos propósitos, vamos expressar isso como um binário: 'Branca' ou 'Não Branca'. Há também uma categoria 'listrada' em nosso conjunto de dados, mas há poucos exemplos dela, então não a utilizaremos. Ela desaparece quando removemos os valores nulos do conjunto de dados, de qualquer forma.
🎃 Curiosidade: às vezes chamamos as abóboras brancas de abóboras 'fantasma'. Elas não são muito fáceis de esculpir, então não são tão populares quanto as laranjas, mas têm um visual interessante! Assim, poderíamos reformular nossa questão como: 'Fantasma' ou 'Não Fantasma'. 👻
Sobre regressão logística
A regressão logística difere da regressão linear, que você aprendeu anteriormente, em alguns aspectos importantes.
🎥 Clique na imagem acima para um breve vídeo sobre regressão logística.
Classificação binária
A regressão logística não oferece os mesmos recursos que a regressão linear. A primeira oferece uma previsão sobre uma categoria binária ("branca ou não branca"), enquanto a segunda é capaz de prever valores contínuos, por exemplo, dado a origem de uma abóbora e o tempo de colheita, quanto seu preço vai aumentar.
Infográfico por Dasani Madipalli
Outras classificações
Existem outros tipos de regressão logística, incluindo multinomial e ordinal:
- Multinomial, que envolve mais de uma categoria - "Laranja, Branca e Listrada".
- Ordinal, que envolve categorias ordenadas, útil se quisermos ordenar nossos resultados logicamente, como nossas abóboras que são ordenadas por um número finito de tamanhos (mini,pequeno,médio,grande,xl,xxl).
As variáveis NÃO precisam ser correlacionadas
Lembra como a regressão linear funcionava melhor com variáveis mais correlacionadas? A regressão logística é o oposto - as variáveis não precisam estar alinhadas. Isso funciona para este conjunto de dados, que tem correlações relativamente fracas.
Você precisa de muitos dados limpos
A regressão logística fornecerá resultados mais precisos se você usar mais dados; nosso pequeno conjunto de dados não é ideal para esta tarefa, então tenha isso em mente.
🎥 Clique na imagem acima para um breve vídeo sobre preparação de dados para regressão linear.
✅ Pense nos tipos de dados que se adaptariam bem à regressão logística.
Exercício - organizar os dados
Primeiro, limpe os dados, removendo valores nulos e selecionando apenas algumas colunas:
-
Adicione o seguinte código:
columns_to_select = ['City Name','Package','Variety', 'Origin','Item Size', 'Color'] pumpkins = full_pumpkins.loc[:, columns_to_select] pumpkins.dropna(inplace=True)
Você sempre pode dar uma olhada no seu novo dataframe:
pumpkins.info
Visualização - gráfico categórico
Agora que você carregou o notebook inicial com os dados de abóbora novamente e os limpou para preservar um conjunto de dados contendo algumas variáveis, incluindo Color
, vamos visualizar o dataframe no notebook usando uma biblioteca diferente: Seaborn, que é construída sobre o Matplotlib que usamos anteriormente.
Seaborn oferece algumas maneiras interessantes de visualizar seus dados. Por exemplo, você pode comparar distribuições dos dados para cada Variety
e Color
em um gráfico categórico.
-
Crie tal gráfico usando a função
catplot
, com os dados de abóborapumpkins
, e especificando um mapeamento de cores para cada categoria de abóbora (laranja ou branca):import seaborn as sns palette = { 'ORANGE': 'orange', 'WHITE': 'wheat', } sns.catplot( data=pumpkins, y="Variety", hue="Color", kind="count", palette=palette, )
Observando os dados, você pode ver como os dados de
Color
se relacionam comVariety
.✅ Dado este gráfico categórico, quais são algumas explorações interessantes que você pode imaginar?
Pré-processamento de dados: codificação de características e rótulos
Nosso conjunto de dados de abóboras contém valores de string em todas as suas colunas. Trabalhar com dados categóricos é intuitivo para humanos, mas não para máquinas. Algoritmos de aprendizado de máquina funcionam bem com números. Por isso, a codificação é uma etapa muito importante na fase de pré-processamento de dados, pois permite transformar dados categóricos em dados numéricos, sem perder informações. Uma boa codificação leva à construção de um bom modelo.
Para codificação de características, existem dois tipos principais de codificadores:
-
Codificador ordinal: é adequado para variáveis ordinais, que são variáveis categóricas cujos dados seguem uma ordem lógica, como a coluna
Item Size
em nosso conjunto de dados. Ele cria um mapeamento em que cada categoria é representada por um número, que é a ordem da categoria na coluna.from sklearn.preprocessing import OrdinalEncoder item_size_categories = [['sml', 'med', 'med-lge', 'lge', 'xlge', 'jbo', 'exjbo']] ordinal_features = ['Item Size'] ordinal_encoder = OrdinalEncoder(categories=item_size_categories)
-
Codificador categórico: é adequado para variáveis nominais, que são variáveis categóricas cujos dados não seguem uma ordem lógica, como todas as características diferentes de
Item Size
em nosso conjunto de dados. É uma codificação one-hot, o que significa que cada categoria é representada por uma coluna binária: a variável codificada é igual a 1 se a abóbora pertence àquelaVariety
e 0 caso contrário.from sklearn.preprocessing import OneHotEncoder categorical_features = ['City Name', 'Package', 'Variety', 'Origin'] categorical_encoder = OneHotEncoder(sparse_output=False)
Então, ColumnTransformer
é usado para combinar múltiplos codificadores em uma única etapa e aplicá-los às colunas apropriadas.
from sklearn.compose import ColumnTransformer
ct = ColumnTransformer(transformers=[
('ord', ordinal_encoder, ordinal_features),
('cat', categorical_encoder, categorical_features)
])
ct.set_output(transform='pandas')
encoded_features = ct.fit_transform(pumpkins)
Por outro lado, para codificar o rótulo, usamos a classe LabelEncoder
do scikit-learn, que é uma classe utilitária para ajudar a normalizar rótulos de forma que contenham apenas valores entre 0 e n_classes-1 (aqui, 0 e 1).
from sklearn.preprocessing import LabelEncoder
label_encoder = LabelEncoder()
encoded_label = label_encoder.fit_transform(pumpkins['Color'])
Depois de codificar as características e o rótulo, podemos mesclá-los em um novo dataframe encoded_pumpkins
.
encoded_pumpkins = encoded_features.assign(Color=encoded_label)
✅ Quais são as vantagens de usar um codificador ordinal para a coluna Item Size
?
Analisar relações entre variáveis
Agora que pré-processamos nossos dados, podemos analisar as relações entre as características e o rótulo para ter uma ideia de quão bem o modelo será capaz de prever o rótulo com base nas características.
A melhor maneira de realizar esse tipo de análise é plotando os dados. Usaremos novamente a função catplot
do Seaborn para visualizar as relações entre Item Size
, Variety
e Color
em um gráfico categórico. Para melhor plotar os dados, usaremos a coluna codificada Item Size
e a coluna não codificada Variety
.
palette = {
'ORANGE': 'orange',
'WHITE': 'wheat',
}
pumpkins['Item Size'] = encoded_pumpkins['ord__Item Size']
g = sns.catplot(
data=pumpkins,
x="Item Size", y="Color", row='Variety',
kind="box", orient="h",
sharex=False, margin_titles=True,
height=1.8, aspect=4, palette=palette,
)
g.set(xlabel="Item Size", ylabel="").set(xlim=(0,6))
g.set_titles(row_template="{row_name}")
Usar um gráfico de dispersão
Como Color
é uma categoria binária (Branca ou Não), ela precisa de 'uma abordagem especializada para visualização'. Existem outras maneiras de visualizar a relação dessa categoria com outras variáveis.
Você pode visualizar variáveis lado a lado com gráficos do Seaborn.
-
Experimente um gráfico de dispersão ('swarm') para mostrar a distribuição de valores:
palette = { 0: 'orange', 1: 'wheat' } sns.swarmplot(x="Color", y="ord__Item Size", data=encoded_pumpkins, palette=palette)
Atenção: o código acima pode gerar um aviso, já que o Seaborn pode falhar ao representar uma quantidade tão grande de pontos de dados em um gráfico de dispersão. Uma solução possível é diminuir o tamanho do marcador, usando o parâmetro 'size'. No entanto, esteja ciente de que isso afeta a legibilidade do gráfico.
🧮 Mostre-me a Matemática
A regressão logística baseia-se no conceito de 'máxima verossimilhança' usando funções sigmoides. Uma 'Função Sigmoide' em um gráfico tem a forma de um 'S'. Ela pega um valor e o mapeia para algo entre 0 e 1. Sua curva também é chamada de 'curva logística'. Sua fórmula é assim:
onde o ponto médio da sigmoide encontra-se no ponto 0 de x, L é o valor máximo da curva, e k é a inclinação da curva. Se o resultado da função for maior que 0.5, o rótulo em questão será atribuído à classe '1' da escolha binária. Caso contrário, será classificado como '0'.
Construir seu modelo
Construir um modelo para encontrar essas classificações binárias é surpreendentemente simples no Scikit-learn.
🎥 Clique na imagem acima para um breve vídeo sobre construção de um modelo de regressão linear.
-
Selecione as variáveis que deseja usar em seu modelo de classificação e divida os conjuntos de treinamento e teste chamando
train_test_split()
:from sklearn.model_selection import train_test_split X = encoded_pumpkins[encoded_pumpkins.columns.difference(['Color'])] y = encoded_pumpkins['Color'] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
-
Agora você pode treinar seu modelo, chamando
fit()
com seus dados de treinamento, e imprimir o resultado:from sklearn.metrics import f1_score, classification_report from sklearn.linear_model import LogisticRegression model = LogisticRegression() model.fit(X_train, y_train) predictions = model.predict(X_test) print(classification_report(y_test, predictions)) print('Predicted labels: ', predictions) print('F1-score: ', f1_score(y_test, predictions))
Veja o desempenho do seu modelo. Não está ruim, considerando que você tem apenas cerca de 1000 linhas de dados:
precision recall f1-score support 0 0.94 0.98 0.96 166 1 0.85 0.67 0.75 33 accuracy 0.92 199 macro avg 0.89 0.82 0.85 199 weighted avg 0.92 0.92 0.92 199 Predicted labels: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 1] F1-score: 0.7457627118644068
Melhor compreensão via uma matriz de confusão
Embora você possa obter um relatório de desempenho termos imprimindo os itens acima, talvez consiga entender melhor seu modelo usando uma matriz de confusão para ajudar a avaliar como o modelo está se saindo.
🎓 Uma 'matriz de confusão' (ou 'matriz de erro') é uma tabela que expressa os verdadeiros vs. falsos positivos e negativos do seu modelo, avaliando assim a precisão das previsões.
-
Para usar uma matriz de confusão, chame
confusion_matrix()
:from sklearn.metrics import confusion_matrix confusion_matrix(y_test, predictions)
Veja a matriz de confusão do seu modelo:
array([[162, 4], [ 11, 22]])
No Scikit-learn, as linhas (eixo 0) são os rótulos reais e as colunas (eixo 1) são os rótulos previstos.
0 | 1 | |
---|---|---|
0 | TN | FP |
1 | FN | TP |
O que está acontecendo aqui? Digamos que nosso modelo seja solicitado a classificar abóboras entre duas categorias binárias, categoria 'branca' e categoria 'não branca'.
- Se o modelo prevê uma abóbora como não branca e ela realmente pertence à categoria 'não branca', chamamos isso de verdadeiro negativo, mostrado pelo número no canto superior esquerdo.
- Se o modelo prevê uma abóbora como branca e ela realmente pertence à categoria 'não branca', chamamos isso de falso negativo, mostrado pelo número no canto inferior esquerdo.
- Se o modelo prevê uma abóbora como não branca e ela realmente pertence à categoria 'branca', chamamos isso de falso positivo, mostrado pelo número no canto superior direito.
- Se o modelo prevê uma abóbora como branca e ela realmente pertence à categoria 'branca', chamamos isso de verdadeiro positivo, mostrado pelo número no canto inferior direito.
Como você deve ter imaginado, é preferível ter um número maior de verdadeiros positivos e verdadeiros negativos e um número menor de falsos positivos e falsos negativos, o que implica que o modelo está se saindo melhor. Como é que a matriz de confusão se relaciona com a precisão e o recall? Lembra-te, o relatório de classificação impresso acima mostrou precisão (0,85) e recall (0,67).
Precisão = tp / (tp + fp) = 22 / (22 + 4) = 0,8461538461538461
Recall = tp / (tp + fn) = 22 / (22 + 11) = 0,6666666666666666
✅ P: De acordo com a matriz de confusão, como se saiu o modelo? R: Não foi mau; há um bom número de verdadeiros negativos, mas também alguns falsos negativos.
Vamos rever os termos que vimos anteriormente com a ajuda do mapeamento TP/TN e FP/FN da matriz de confusão:
🎓 Precisão: TP/(TP + FP) A fração de instâncias relevantes entre as instâncias recuperadas (ex.: quais etiquetas foram bem classificadas)
🎓 Recall: TP/(TP + FN) A fração de instâncias relevantes que foram recuperadas, independentemente de terem sido bem classificadas ou não
🎓 f1-score: (2 * precisão * recall)/(precisão + recall) Uma média ponderada da precisão e do recall, sendo o melhor 1 e o pior 0
🎓 Suporte: O número de ocorrências de cada etiqueta recuperada
🎓 Precisão (Accuracy): (TP + TN)/(TP + TN + FP + FN) A percentagem de etiquetas previstas corretamente para uma amostra.
🎓 Macro Avg: O cálculo da média não ponderada das métricas para cada etiqueta, sem considerar o desequilíbrio entre etiquetas.
🎓 Weighted Avg: O cálculo da média das métricas para cada etiqueta, considerando o desequilíbrio entre etiquetas ao ponderá-las pelo seu suporte (o número de instâncias verdadeiras para cada etiqueta).
✅ Consegues pensar em qual métrica deves prestar atenção se quiseres que o teu modelo reduza o número de falsos negativos?
Visualizar a curva ROC deste modelo
🎥 Clica na imagem acima para uma breve explicação sobre curvas ROC
Vamos fazer mais uma visualização para ver a chamada curva 'ROC':
from sklearn.metrics import roc_curve, roc_auc_score
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
y_scores = model.predict_proba(X_test)
fpr, tpr, thresholds = roc_curve(y_test, y_scores[:,1])
fig = plt.figure(figsize=(6, 6))
plt.plot([0, 1], [0, 1], 'k--')
plt.plot(fpr, tpr)
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve')
plt.show()
Usando Matplotlib, desenha a Curva Característica de Operação do Recetor ou ROC do modelo. As curvas ROC são frequentemente usadas para obter uma visão do desempenho de um classificador em termos de verdadeiros positivos vs. falsos positivos. "As curvas ROC geralmente apresentam a taxa de verdadeiros positivos no eixo Y e a taxa de falsos positivos no eixo X." Assim, a inclinação da curva e o espaço entre a linha do meio e a curva são importantes: queres uma curva que rapidamente suba e ultrapasse a linha. No nosso caso, há falsos positivos no início, e depois a linha sobe e ultrapassa corretamente:
Por fim, usa a API roc_auc_score
do Scikit-learn para calcular a 'Área Sob a Curva' (AUC):
auc = roc_auc_score(y_test,y_scores[:,1])
print(auc)
O resultado é 0.9749908725812341
. Dado que o AUC varia de 0 a 1, queres um valor elevado, já que um modelo que acerta 100% nas suas previsões terá um AUC de 1; neste caso, o modelo é bastante bom.
Em futuras lições sobre classificações, vais aprender como iterar para melhorar os resultados do teu modelo. Mas, por agora, parabéns! Completaste estas lições sobre regressão!
🚀Desafio
Há muito mais para explorar sobre regressão logística! Mas a melhor forma de aprender é experimentar. Encontra um conjunto de dados que se preste a este tipo de análise e constrói um modelo com ele. O que aprendes? dica: experimenta Kaggle para conjuntos de dados interessantes.
Questionário pós-aula
Revisão & Estudo Individual
Lê as primeiras páginas deste artigo de Stanford sobre alguns usos práticos da regressão logística. Pensa em tarefas que sejam mais adequadas para um ou outro tipo de regressão entre as que estudámos até agora. O que funcionaria melhor?
Tarefa
Aviso Legal:
Este documento foi traduzido utilizando o serviço de tradução por IA Co-op Translator. Embora nos esforcemos para garantir a precisão, esteja ciente de que traduções automáticas podem conter erros ou imprecisões. O documento original no seu idioma nativo deve ser considerado a fonte oficial. Para informações críticas, recomenda-se uma tradução profissional realizada por humanos. Não nos responsabilizamos por quaisquer mal-entendidos ou interpretações incorretas resultantes do uso desta tradução.