Introdução ao Machine Learning com Python Usando Scikit-Learn
O mundo do machine learning está em constante evolução, e com a linguagem Python na linha de frente, entrar nessa área é uma jornada empolgante e cheia de possibilidades. Para desenvolvedores iniciantes, a biblioteca Scikit-Learn é a porta de entrada perfeita para essa jornada. Neste artigo, vamos explorar o básico do machine learning e como você pode começar a aplicar seus conceitos usando Scikit-Learn, uma das ferramentas mais populares e poderosas disponíveis.
Introdução ao Scikit-Learn
Scikit-Learn é uma biblioteca de código aberto para Python que se destaca na implementação de algoritmos de machine learning. Desde seu lançamento, tornou-se a escolha preferida para muitos desenvolvedores, graças à sua simplicidade e eficiência.
Vantagens de usar Scikit-Learn para iniciantes em machine learning:
- Fácil de aprender: Com uma documentação bem escrita e clara, Scikit-Learn é ideal para quem está começando.
- Consistente e intuitivo: A biblioteca segue um design consistente em todas as suas ferramentas, facilitando o aprendizado e a aplicação dos conceitos.
- Ampla comunidade: Por ser uma das bibliotecas mais populares, existe uma comunidade grande e ativa que pode oferecer suporte.
O que é Scikit-Learn
Scikit-Learn é uma biblioteca que fornece uma variedade de ferramentas simples e eficientes para mineração de dados e análise de dados. É particularmente conhecida por sua implementação de algoritmos de classificação, regressão e clustering.
Visão geral das funcionalidades e tipos de problemas que podem ser resolvidos com Scikit-Learn:
- Classificação: Identificar a qual categoria um objeto pertence.
- Regressão: Prever uma resposta contínua.
- Clustering: Agrupar pontos de dados semelhantes.
- Redução de dimensionalidade: Reduzir o número de variáveis aleatórias a serem consideradas.
- Model selection: Comparar, validar e escolher parâmetros e modelos.
- Pré-processamento: Transformar ou encodar dados.
Aprenda Machine Learning em 5 Dias. Curso 100% Prático.
Melhor Preço por Tempo Limitado. Clique Aqui e Teste Sem Risco.
30 Dias de Satisfação Garantida!
Estrutura Organizacional do Scikit-Learn: Classes, Métodos e Atributos
A biblioteca Scikit-Learn é construída com uma estrutura organizacional bem definida, que não só ajuda na consistência do código, mas também torna o processo de aprendizado mais intuitivo para os iniciantes. Vamos mergulhar mais fundo e explorar como as classes, métodos e atributos desempenham papéis fundamentais na interação com esta ferramenta poderosa.
Classes: O Coração dos Modelos de Machine Learning
As classes são essencialmente moldes para criar objetos que representam tanto os modelos de machine learning quanto as ferramentas de pré-processamento de dados. No Scikit-Learn, cada algoritmo de machine learning é implementado como uma classe. Essas classes são agrupadas logicamente em módulos, com base no tipo de problema de machine learning que elas resolvem.
Por exemplo:
- O módulo
linear_model
contém classes para algoritmos de regressão linear, comoLinearRegression
eLogisticRegression
. - O módulo
cluster
oferece classes para algoritmos de agrupamento, comoKMeans
. - O módulo
decomposition
tem classes para redução de dimensionalidade, comoPCA
.
Métodos: As Ações dos Objetos
Após instanciar uma classe para criar um objeto, como um estimador de um modelo de regressão, esse objeto tem vários métodos que você pode utilizar para executar ações específicas. Os métodos são funções incorporadas dentro das classes que realizam operações usando os dados ou o estado do objeto criado a partir da classe.
Os métodos mais comuns encontrados nos estimadores são:
.fit()
: Utilizado para treinar o modelo com os dados fornecidos..predict()
: Após o treinamento, é utilizado para fazer previsões com novos dados..transform()
: Usado em transformadores para alterar ou selecionar características dos dados..fit_transform()
: Uma combinação que realiza o treinamento e a transformação em um único passo, otimizando o processo.
Atributos: As Características dos Objetos
Os atributos são variáveis que armazenam informações sobre o estado do objeto. Após treinar um modelo, por exemplo, ele vai conter diversos atributos que fornecem informações úteis. Esses atributos podem incluir detalhes sobre os dados treinados, como parâmetros ajustados, importâncias de características ou coeficientes do modelo.
Por exemplo, um objeto LinearRegression
terá atributos como:
.coef_
: Que armazena os coeficientes da regressão linear para cada característica..intercept_
: Que contém o termo independente da linha de regressão.
Vale ressaltar que os atributos terminam com um underscore (_
) para diferenciá-los de outros nomes de métodos e para indicar que foram criados a partir dos dados fornecidos.
Exemplo de Uso de Classe, Método e Atributo
Vamos a um exemplo de código onde implementamos um modelo de regressão linear simples com o Scikit-Learn:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
from sklearn.linear_model import LinearRegression import numpy as np # Dados de exemplo X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]]) # y = 1 * x_0 + 2 * x_1 + 3 y = np.dot(X, np.array([1, 2])) + 3 # Instanciando a classe LinearRegression modelo = LinearRegression() # Treinando o modelo com os dados, usando o método .fit() modelo.fit(X, y) # Verificando os atributos coef_ e intercept_ após o treino print("Coeficientes: ", modelo.coef_) print("Intercept: ", modelo.intercept_) |
O código apresentado é um exemplo prático de como implementar um modelo de regressão linear simples usando a biblioteca scikit-learn
em Python. Vamos detalhar cada parte do código para entender seu funcionamento:
1. Importação de bibliotecas:
– from sklearn.linear_model import LinearRegression
: Importa a classe LinearRegression
da biblioteca scikit-learn
, que é uma implementação do modelo de regressão linear.
– import numpy as np
: Importa a biblioteca numpy
com o alias np
. numpy
é uma biblioteca fundamental para computação científica em Python, oferecendo suporte para arrays multidimensionais e diversas operações matemáticas.
2. Preparação dos dados:
– X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]])
: Cria um array numpy
para as variáveis independentes (features), X
. Cada sub-array representa um ponto de dado, com duas dimensões (ou features).
– y = np.dot(X, np.array([1, 2])) + 3
: Gera o array de variáveis dependentes (target), y
, usando uma operação de produto escalar (np.dot
) entre X
e um array de coeficientes [1, 2]
, seguido pela adição de um intercepto 3
. A equação representada é y = 1*x_0 + 2*x_1 + 3
, onde x_0
e x_1
são as variáveis independentes.
3. Instanciando o modelo de Regressão Linear:
– modelo = LinearRegression()
: Cria uma instância da classe LinearRegression
. Este objeto modelo
será usado para treinar o modelo com os dados.
4. Treinamento do modelo:
– modelo.fit(X, y)
: Treina o modelo de regressão linear usando os dados X
(variáveis independentes) e y
(variável dependente). O método .fit()
ajusta o modelo linear aos dados, encontrando os coeficientes (pesos) das variáveis independentes e o intercepto que minimizam a soma dos quadrados dos resíduos, uma medida de erro entre os valores observados e os valores previstos pelo modelo.
5. Verificação dos resultados do treinamento:
– print("Coeficientes: ", modelo.coef_)
: Imprime os coeficientes das variáveis independentes (x_0
e x_1
neste caso) encontrados pelo modelo após o treinamento. Estes valores devem estar próximos de [1, 2]
, que são os coeficientes usados para gerar y
.
– print("Intercept: ", modelo.intercept_)
: Imprime o valor do intercepto adicionado ao modelo, que deve estar próximo de 3
, conforme usado na geração de y
.
Este código é um exemplo clássico de como realizar regressão linear com múltiplas variáveis independentes. O objetivo é prever o valor da variável dependente y
a partir das variáveis independentes X
, baseando-se nos coeficientes (coef_
) e no intercepto (intercept_
) aprendidos pelo modelo durante o treinamento. A saída esperada deve confirmar que o modelo aprendeu corretamente os coeficientes próximos a [1, 2]
e o intercepto próximo a 3
, refletindo a relação linear definida inicialmente entre X
e y
.
Com base nos dados usados no código anterior, vamos imaginar um exemplo prático usando os mesmos dados para facilitar a compreensão. Suponha que você esteja trabalhando em uma lanchonete e queira prever o tempo total de preparo de um pedido com base em duas características: o número de itens no pedido e a complexidade média dos itens.
Dados:
1 2 3 4 5 |
X = [1 1] [1 2] [2 2] [2 3] |
Nesse exemplo:
- A primeira coluna representa o número de itens no pedido.
- A segunda coluna representa a complexidade média dos itens, onde 1 indica baixa complexidade, 2 indica média complexidade e 3 indica alta complexidade.
Cada linha representa um pedido específico. Por exemplo:
- O primeiro pedido tem 1 item com baixa complexidade.
- O segundo pedido tem 1 item com média complexidade.
- O terceiro pedido tem 2 itens com média complexidade.
- O quarto pedido tem 2 itens com alta complexidade.
Agora, vamos considerar a equação:
1 2 |
y = np.dot(X, np.array([1, 2])) + 3 |
Nessa equação:
np.array([1, 2])
representa os coeficientes das características. O coeficiente 1 está associado ao número de itens e o coeficiente 2 está associado à complexidade média dos itens.- O valor 3 representa o intercepto, que é o tempo base de preparo, independentemente do número de itens ou da complexidade.
Agora, vamos calcular o tempo total de preparo para cada pedido:
- Pedido 1: (1 1) + (1 2) + 3 = 6 minutos
- 1 item com baixa complexidade: 1 * 1 = 1
- Complexidade média dos itens: 1 * 2 = 2
- Tempo base de preparo: 3 minutos
- Pedido 2: (1 1) + (2 2) + 3 = 8 minutos
- 1 item com média complexidade: 1 * 1 = 1
- Complexidade média dos itens: 2 * 2 = 4
- Tempo base de preparo: 3 minutos
- Pedido 3: (2 1) + (2 2) + 3 = 9 minutos
- 2 itens com média complexidade: 2 * 1 = 2
- Complexidade média dos itens: 2 * 2 = 4
- Tempo base de preparo: 3 minutos
- Pedido 4: (2 1) + (3 2) + 3 = 11 minutos
- 2 itens com alta complexidade: 2 * 1 = 2
- Complexidade média dos itens: 3 * 2 = 6
- Tempo base de preparo: 3 minutos
Nesse exemplo, o modelo de regressão linear está prevendo o tempo total de preparo com base no número de itens e na complexidade média dos itens. Os coeficientes [1, 2] indicam que cada item adicional aumenta o tempo de preparo em 1 minuto, e cada nível de complexidade adicional aumenta o tempo de preparo em 2 minutos. O intercepto de 3 minutos representa o tempo base de preparo, independentemente do número de itens ou da complexidade.
Para ficar ainda mais claro, vamos tentar visualizar cada passo da multiplicação das matrizes. Vamos fazer isso passo a passo.
Primeiro, vamos relembrar a matriz X e os coeficientes de características:
1 2 3 4 5 6 7 |
X = [1 1] [1 2] [2 2] [2 3] Coeficientes de características: [1, 2] |
Agora, vamos realizar a multiplicação das matrizes:
1 2 3 4 5 |
[1 1] [1] [1 * 1 + 1 * 2] [3] [1 2] * [2] = [1 * 1 + 2 * 2] = [5] [2 2] [2 * 1 + 2 * 2] [6] [2 3] [2 * 1 + 3 * 2] [8] |
O resultado da multiplicação das matrizes é um vetor coluna:
1 2 3 4 5 |
[3] [5] [6] [8] |
Agora, vamos adicionar o intercepto de 3 a cada elemento do vetor resultante:
1 2 3 4 5 |
[3] [3] [6] [5] + [3] = [8] [6] [3] [9] [8] [3] [11] |
Portanto, o resultado final da multiplicação das matrizes com os coeficientes de características e a adição do intercepto de 3 é:
1 2 3 4 5 |
[6] [8] [9] [11] |
Esse vetor coluna representa os valores previstos de y para cada amostra de dados na matriz X, considerando os coeficientes de características [1, 2] e o intercepto de 3.
Em termos da equação de regressão linear, podemos representar esse cálculo da seguinte forma:
1 2 |
y = X * [1, 2] + [3, 3, 3, 3] |
Onde:
X
é a matriz de características[1, 2]
são os coeficientes de características[3, 3, 3, 3]
é um vetor coluna com o intercepto de 3 repetido para cada amostra de dados
Essa representação mostra como a multiplicação das matrizes com os coeficientes de características e a adição do intercepto resultam nos valores previstos de y para cada amostra de dados.
Esse exemplo ilustra como os dados e a equação de regressão linear podem ser aplicados em um contexto prático para prever o tempo total de preparo de pedidos em uma lanchonete. O modelo aprenderia os coeficientes e o intercepto ideais com base nos dados de treinamento e poderia ser usado para fazer previsões em novos pedidos.
Com esta exploração da estrutura organizacional do Scikit-Learn, os desenvolvedores que estão iniciando podem começar a compreender como interagir com as classes, métodos e atributos, que formam o núcleo da criação, manipulação e análise dos modelos de machine learning utilizando esta biblioteca. Este conhecimento é uma base sólida para adentrar ainda mais fundo no universo do machine learning com Python.
Estimators, Transformers e Predictors: Pilares do Scikit-Learn
A biblioteca Scikit-Learn é projetada seguindo uma filosofia orientada a objetos e é construída em torno de três tipos principais de objetos: Estimators, Transformers e Predictors. Essa estrutura é não apenas fundamental para entender como a biblioteca funciona, mas também crucial para aplicá-la efetivamente na prática.
Estimators: O Fundamento do Modelo
Os Estimators são a base para quase todos os algoritmos de machine learning implementados no Scikit-Learn. Eles são responsáveis por estimar parâmetros com base nos dados fornecidos. Para fazer isso, todos os Estimators possuem o método .fit()
, que é o coração do processo de modelagem, usado para treinar o modelo com os dados de entrada.
Exemplo de uso de um Estimator:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from sklearn.cluster import KMeans # Dados de exemplo para o agrupamento X = [[6, 7], [2, 1], [3, 2], [8, 9]] # Instanciação de um Estimator KMeans kmeans = KMeans(n_clusters=2, n_init=10) # Treinando o modelo com .fit() kmeans.fit(X) # Os centróides do cluster podem ser acessados através de um atributo após o treino print(kmeans.cluster_centers_) |
Neste exemplo, KMeans
é um Estimator que é usado para encontrar os centróides de um conjunto de dados dado que estamos tentando clusterizar em dois grupos.
Os centróides são os pontos centrais de cada cluster (grupo) encontrado pelo algoritmo de clustering KMeans.
No algoritmo KMeans, o objetivo é dividir um conjunto de dados em K clusters, onde K é um número predefinido. Cada cluster é representado por um centróide, que é o ponto central do cluster.
O processo do algoritmo KMeans pode ser resumido da seguinte forma:
- Inicialização: O algoritmo começa escolhendo aleatoriamente K pontos do conjunto de dados como centróides iniciais.
- Atribuição: Cada ponto de dados é atribuído ao centróide mais próximo com base em uma medida de distância (geralmente, a distância euclidiana).
- Atualização: Após a atribuição de todos os pontos de dados aos centróides, os centróides são recalculados como a média (ou centro de massa) dos pontos de dados atribuídos a cada cluster.
- Repetição: Os passos 2 e 3 são repetidos iterativamente até que os centróides não mudem mais significativamente ou até que um número máximo de iterações seja atingido.
Ao final do processo, cada centróide representa o centro do cluster correspondente. Os centróides são os pontos que minimizam a soma das distâncias quadradas entre os pontos de dados e seus respectivos centróides.
Baseado no código fonte fornecido anteriormente, o algoritmo KMeans é aplicado aos dados de exemplo X
, que consistem em quatro pontos bidimensionais. O parâmetro n_clusters=2
especifica que queremos encontrar dois clusters. O parâmetro n_init
especifica o número de vezes que o algoritmo KMeans será executado com diferentes inicializações aleatórias dos centróides.
- O algoritmo KMeans é sensível à inicialização dos centróides, o que significa que diferentes inicializações podem levar a resultados diferentes.
- Para mitigar essa sensibilidade e encontrar a melhor solução, o algoritmo é executado várias vezes com diferentes inicializações aleatórias dos centróides.
- O valor de
n_init=10
indica que o algoritmo será executado 10 vezes com diferentes inicializações aleatórias. - Após as 10 execuções, o algoritmo retornará a melhor solução encontrada, ou seja, a solução com a menor soma das distâncias quadradas entre os pontos de dados e seus respectivos centróides.
- Um valor maior de
n_init
aumenta a chance de encontrar a melhor solução, mas também aumenta o tempo de computação.
Portanto, ao criar a instância do KMeans com kmeans = KMeans(n_clusters=2, n_init=10)
, estamos configurando o algoritmo para:
- Encontrar 2 clusters nos dados (
n_clusters=2
). - Executar o algoritmo 10 vezes com diferentes inicializações aleatórias dos centróides (
n_init=10
). - Retornar a melhor solução encontrada entre as 10 execuções.
Após o treinamento do modelo com kmeans.fit(X)
, os centróides encontrados podem ser acessados através do atributo kmeans.cluster_centers_
. Esses centróides representam os pontos centrais dos dois clusters encontrados pelo algoritmo KMeans.
Os centróides são úteis para entender a estrutura dos clusters e podem ser usados para atribuir novos pontos de dados ao cluster mais próximo. Além disso, os centróides podem fornecer insights sobre as características comuns dos pontos de dados em cada cluster.
Em resumo, os centróides são os pontos centrais dos clusters encontrados pelo algoritmo KMeans e representam a média ou o centro de massa dos pontos de dados atribuídos a cada cluster.
Vamos considerar um exemplo prático da vida real baseado nos dados fornecidos.
Suponha que você seja um analista de dados trabalhando para uma rede de restaurantes. A rede possui vários restaurantes em diferentes locais e deseja entender melhor o comportamento dos clientes em relação à localização geográfica. Cada restaurante registra a latitude e a longitude de seus clientes frequentes.
Dados:
- Restaurante A: [6, 7]
- Restaurante B: [2, 1]
- Restaurante C: [3, 2]
- Restaurante D: [8, 9]
Cada par de coordenadas representa a latitude e a longitude média dos clientes frequentes de cada restaurante.
Objetivo: O objetivo é agrupar os restaurantes com base na localização geográfica de seus clientes frequentes, a fim de identificar padrões e segmentos de clientes.
Aplicação do algoritmo KMeans: Usando o algoritmo KMeans com n_clusters=2
, você pode agrupar os restaurantes em dois clusters com base na similaridade da localização geográfica dos clientes.
Resultados: Após aplicar o algoritmo KMeans aos dados, você obtém os seguintes centróides:
1 2 |
[[7. 8. ] [2.5 1.5]] |
Interpretação dos resultados:
- O primeiro centróide [7, 8] representa o centro do cluster que inclui os restaurantes A e D. Isso sugere que os clientes frequentes dos restaurantes A e D tendem a estar localizados em uma região geográfica semelhante, com latitude média de 7 e longitude média de 8.
- O segundo centróide [2.5, 1.5] representa o centro do cluster que inclui os restaurantes B e C. Isso indica que os clientes frequentes dos restaurantes B e C tendem a estar localizados em uma região geográfica diferente, com latitude média de 2.5 e longitude média de 1.5.
Insights e ações: Com base nos resultados do agrupamento, você pode obter os seguintes insights e tomar ações correspondentes:
- Segmentação de clientes: Os dois clusters identificados representam diferentes segmentos de clientes com base na localização geográfica. Você pode adaptar estratégias de marketing, promoções e ofertas específicas para cada segmento de clientes.
- Expansão estratégica: Se a rede de restaurantes estiver planejando abrir novos restaurantes, você pode usar os centróides como referência para identificar locais estratégicos que atendam aos segmentos de clientes identificados.
- Análise de preferências: Você pode realizar análises adicionais para entender as preferências e comportamentos dos clientes em cada cluster. Isso pode ajudar a personalizar o menu, o ambiente e o serviço de acordo com as preferências de cada segmento de clientes.
Esse é apenas um exemplo ilustrativo de como o algoritmo KMeans pode ser aplicado a dados de localização geográfica de clientes em uma rede de restaurantes. O mesmo princípio pode ser estendido para outros setores e casos de uso, como análise de mercado, segmentação de clientes, otimização de recursos, entre outros.
Transformers: Preparando os Dados
Os Transformers são ferramentas poderosas fornecidas pela biblioteca scikit-learn para realizar transformações nos dados antes de aplicá-los a um modelo de aprendizado de máquina. Eles desempenham um papel crucial na preparação dos dados, garantindo que estejam em um formato adequado e otimizado para o treinamento do modelo.
Os Transformers podem ser usados para diversas tarefas, como:
- Pré-processamento: Isso inclui tarefas como padronização, normalização, codificação de variáveis categóricas, preenchimento de valores ausentes, entre outras. O objetivo é garantir que os dados estejam limpos, consistentes e em um formato adequado para o modelo.
- Redução de dimensionalidade: Quando lidamos com conjuntos de dados de alta dimensionalidade, ou seja, com muitas features (variáveis), pode ser benéfico reduzir a dimensionalidade para melhorar o desempenho do modelo e evitar a maldição da dimensionalidade. Os Transformers podem aplicar técnicas como PCA (Principal Component Analysis) ou t-SNE (t-Distributed Stochastic Neighbor Embedding) para reduzir a dimensionalidade dos dados.
- Seleção de características: Em alguns casos, pode haver features irrelevantes ou redundantes no conjunto de dados. Os Transformers podem ser usados para selecionar as features mais importantes e descartar as menos relevantes, melhorando assim a eficiência e a interpretabilidade do modelo.
Os Transformers possuem dois métodos principais:
.fit()
: Esse método é usado para aprender os parâmetros da transformação com base nos dados fornecidos. Ele analisa os dados e calcula as estatísticas necessárias para realizar a transformação. Por exemplo, no caso do StandardScaler, o método.fit()
calcula a média e o desvio padrão de cada feature..transform()
: Após o Transformer ser ajustado aos dados com o método.fit()
, o método.transform()
é usado para aplicar a transformação aos dados. Ele utiliza os parâmetros aprendidos durante o.fit()
para transformar os dados de acordo com a lógica específica do Transformer.
Exemplo de uso de um Transformer:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
from sklearn.preprocessing import StandardScaler # Dados de exemplo para o pré-processamento X_train = [[0, 15], [1, -10], [2, 0]] # Instanciação do Transformer StandardScaler scaler = StandardScaler() # Aprendendo os parâmetros com .fit() e aplicando a transformação com .transform() X_scaled = scaler.fit_transform(X_train) print(X_scaled) |
No código acima, o StandardScaler
é um Transformer que padroniza os recursos, removendo a média e escalando-os para ter uma variância unitária.
Neste exemplo, estamos usando o Transformer StandardScaler
para padronizar os dados. O StandardScaler
é um Transformer que remove a média e escala os dados para ter uma variância unitária. Isso é útil quando temos features com escalas diferentes e queremos que todas tenham a mesma influência no modelo.
Aqui está o que cada parte do código faz:
- Importamos o
StandardScaler
da biblioteca scikit-learn. - Definimos um conjunto de dados de exemplo chamado
X_train
, que consiste em três amostras, cada uma com duas features. - Criamos uma instância do
StandardScaler
chamadascaler
. - Utilizamos o método
fit_transform()
para ajustar oscaler
aos dados de treinamento (X_train
) e aplicar a transformação de padronização em uma única etapa. Isso é equivalente a chamarscaler.fit(X_train)
seguido descaler.transform(X_train)
. - O resultado da transformação é atribuído à variável
X_scaled
, que contém os dados padronizados. - Por fim, imprimimos os dados padronizados.
A saída do código será semelhante a:
1 2 3 4 |
[[-1.22474487 1.33630621] [ 0. -0.26726124] [ 1.22474487 -1.06904497]] |
Cada linha representa uma amostra padronizada, onde cada feature foi transformada para ter média zero e variância unitária.
Mas repare que embora tenha sido mencionado que os métodos .fit()
e .transform()
são os métodos principais, eles não foram mencionados de forma explícita. Isso acontece porque no código fornecido, os métodos fit()
e transform()
estão sendo aplicados de forma combinada usando o método fit_transform()
.
Vamos analisar a linha específica onde isso acontece:
1 |
X_scaled = scaler.fit_transform(X_train) |
Nesta linha, o método fit_transform()
é chamado no objeto scaler
(que é uma instância do StandardScaler
) passando os dados de treinamento X_train
como argumento.
O método fit_transform()
é uma combinação conveniente dos métodos fit()
e transform()
. Ele realiza as seguintes etapas:
- Chama o método
fit()
internamente para ajustar oscaler
aos dados de treinamento (X_train
). Durante essa etapa, oscaler
calcula a média e o desvio padrão de cada feature nos dados de treinamento. - Após o ajuste, o método
transform()
é chamado internamente para aplicar a transformação de padronização nos mesmos dados de treinamento (X_train
). Ele subtrai a média e divide pelo desvio padrão de cada feature, utilizando os parâmetros aprendidos durante ofit()
. - O resultado da transformação é retornado e atribuído à variável
X_scaled
.
Portanto, a linha X_scaled = scaler.fit_transform(X_train)
é equivalente a chamar scaler.fit(X_train)
seguido de scaler.transform(X_train)
, mas de forma mais concisa e eficiente.
É importante ressaltar que o método fit_transform()
é usado apenas nos dados de treinamento. Para transformar novos dados (como dados de teste ou dados futuros), você deve usar apenas o método transform()
, pois o scaler
já foi ajustado aos dados de treinamento anteriormente. Por exemplo:
1 2 |
X_test = [[3, 5], [4, 2]] X_test_scaled = scaler.transform(X_test) |
Neste caso, o scaler
já foi ajustado aos dados de treinamento usando fit_transform()
, então podemos aplicar a transformação nos dados de teste usando apenas o método transform()
.
Os Transformers são uma parte essencial do fluxo de trabalho de aprendizado de máquina, permitindo que os dados sejam preparados e transformados de maneira eficiente antes de serem alimentados aos modelos. A biblioteca scikit-learn oferece uma ampla variedade de Transformers para diferentes tarefas de pré-processamento e transformação de dados.
Predictors: Fazendo Previsões
Predictors são objetos em machine learning que, após serem treinados sobre um conjunto de dados, são capazes de fazer previsões sobre novos dados. Eles são a concretização de um modelo que aprendeu padrões nos dados de treinamento e agora pode aplicar esse aprendizado para prever resultados em dados não vistos anteriormente.
Método .predict()
O método .predict()
é central para a funcionalidade de um Predictor. Após o treinamento do modelo com um conjunto de dados (usando o método .fit()
), o .predict()
é usado para aplicar o modelo treinado a novos dados, gerando previsões baseadas no aprendizado anterior.
Exemplo de uso de um Predictor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
from sklearn.linear_model import LinearRegression # Dados de exemplo X_train = [[0, 0], [1, 1], [2, 2]] y_train = [0, 1, 2] # Instanciação de um Predictor LinearRegression regressor = LinearRegression() # Treinando o modelo com .fit() regressor.fit(X_train, y_train) # Fazendo previsões com .predict() X_test = [[3, 3]] y_pred = regressor.predict(X_test) print(y_pred) |
Neste caso, o LinearRegression
é um Predictor. Ele é treinado com .fit()
usando o conjunto de treinamento e, em seguida, faz previsões para novos dados com o método .predict()
.
O exemplo fornecido ilustra o uso de um Predictor no contexto de regressão linear, utilizando a biblioteca Scikit-Learn, uma das ferramentas mais populares para machine learning em Python.
- Preparação dos Dados: Inicialmente, os dados de treinamento (
X_train
,y_train
) são definidos. Eles representam, respectivamente, as variáveis independentes e a variável dependente que o modelo tentará prever. - Instanciação do Modelo: Um objeto
LinearRegression
é instanciado. Este objeto é o Predictor, capaz de realizar a regressão linear, um método estatístico que visa modelar a relação entre uma variável dependente e uma ou mais variáveis independentes. - Treinamento do Modelo: O método
.fit()
é chamado com os dados de treinamento, permitindo que o modelo “aprenda” a relação entreX_train
ey_train
. - Previsão: Com o modelo treinado, novos dados (
X_test
) são introduzidos ao modelo através do método.predict()
, que gera as previsões (y_pred
) baseadas no aprendizado obtido durante o treinamento.
O entendimento destes três tipos de objetos — Estimators, Transformers e Predictors — e de seus métodos associados é essencial para utilizar a biblioteca Scikit-Learn de forma eficaz no desenvolvimento de soluções de machine learning. Eles formam a espinha dorsal de como os algoritmos são aplicados e interagem com os dados no ecossistema de machine learning com Python. A habilidade de articular esses componentes juntos na construção de um pipeline de machine learning é o que permite aos praticantes lidar com problemas reais e criar sistemas preditivos eficientes.
Pre-processamento de Dados com Scikit-Learn: Técnicas Essenciais e Exemplos Práticos
O pre-processamento de dados é uma etapa crucial no pipeline de machine learning. O Scikit-Learn oferece ferramentas robustas para preparar seus dados antes de treinar modelos. Vamos criar um exemplo prático usando um conjunto de dados hipotético de um estudo de saúde, que acompanha a frequência de exercícios, dieta, parâmetros biológicos e uma avaliação de risco de doenças cardíacas.
Criação do Conjunto de Dados de Exemplo
Imagine que temos dados coletados de um aplicativo de monitoramento de saúde com as seguintes colunas: Idade (contínua), Gênero (categórica), Colesterol (contínuo, com valores faltantes), Pressão sanguínea (contínua) e Fumante (categórica, com ‘Sim' ou ‘Não'), com uma coluna target indicando Risco de doença cardíaca (baixo, médio, alto).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import numpy as np import pandas as pd # Dados de exemplo data = { 'Idade': [25, 35, 45, np.nan, 55, 65, 75, np.nan, 85, 95], 'Gênero': ['F', 'M', 'F', 'F', 'M', 'M', 'F', 'M', 'F', 'M'], 'Colesterol': [190, np.nan, 240, 225, 210, np.nan, 180, 195, 220, np.nan], 'Pressão Sanguínea': [70, 80, 78, 75, 72, 130, 60, 85, 90, 77], 'Fumante': ['Não', 'Sim', 'Não', 'Não', 'Sim', 'Não', 'Sim', 'Não', 'Não', 'Sim'], 'Risco': ['baixo', 'médio', 'alto', 'baixo', 'alto', 'médio', 'baixo', 'médio', 'baixo', 'alto'] } df = pd.DataFrame(data) |
Tratando Dados Faltantes (Handling Missing Data)
Dados faltantes podem comprometer a análise se não forem tratados adequadamente. No Scikit-Learn, a classe SimpleImputer
é utilizada para lidar com esses valores.
1 2 3 4 5 6 7 |
from sklearn.impute import SimpleImputer # Imputação de dados faltantes na coluna 'Idade' e 'Colesterol' imputer = SimpleImputer(missing_values=np.nan, strategy='mean') df['Idade'] = imputer.fit_transform(df[['Idade']]) df['Colesterol'] = imputer.fit_transform(df[['Colesterol']]) |
Nesse trecho, estamos lidando com o problema de dados faltantes nas colunas ‘Idade' e ‘Colesterol'. Dados faltantes são valores ausentes no conjunto de dados, representados por np.nan
(valor nulo do NumPy).
Primeiro, importamos a classe SimpleImputer
do módulo sklearn.impute
. Essa classe é usada para preencher os valores faltantes de acordo com uma estratégia especificada.
1 |
from sklearn.impute import SimpleImputer |
Em seguida, criamos uma instância do SimpleImputer
chamada imputer
. Passamos dois parâmetros:
missing_values=np.nan
: Indica que os valores faltantes são representados pornp.nan
.strategy='mean'
: Especifica a estratégia usada para preencher os valores faltantes. Nesse caso, usamos a média dos valores presentes na coluna.
1 |
imputer = SimpleImputer(missing_values=np.nan, strategy='mean') |
Agora, aplicamos o imputer
nas colunas ‘Idade' e ‘Colesterol' do DataFrame df
. Usamos o método fit_transform()
para ajustar o imputer
aos dados e transformá-los de uma só vez.
1 2 |
df['Idade'] = imputer.fit_transform(df[['Idade']]) df['Colesterol'] = imputer.fit_transform(df[['Colesterol']]) |
Vamos ver o que acontece com os dados de exemplo:
1 2 3 4 5 6 |
data = { 'Idade': [25, 35, 45, np.nan, 55, 65, 75, np.nan, 85, 95], ... 'Colesterol': [190, np.nan, 240, 225, 210, np.nan, 180, 195, 220, np.nan], ... } |
Na coluna ‘Idade', temos dois valores faltantes (np.nan
). Quando aplicamos o imputer
com a estratégia ‘mean', esses valores faltantes serão substituídos pela média das idades presentes. Nesse caso, a média das idades é calculada considerando apenas os valores não nulos: (25 + 35 + 45 + 55 + 65 + 75 + 85 + 95) / 8 = 60. Portanto, os valores faltantes na coluna ‘Idade' serão preenchidos com 60.
Na coluna ‘Colesterol', também temos três valores faltantes. Aplicando o mesmo processo, a média dos valores de colesterol presentes é calculada: (190 + 240 + 225 + 210 + 180 + 195 + 220) / 7 ≈ 208.57. Os valores faltantes na coluna ‘Colesterol' serão preenchidos com 208.57.
Após a aplicação do imputer
, o DataFrame df
terá os valores faltantes preenchidos com as médias calculadas:
1 2 3 4 5 6 7 8 9 10 11 |
Idade Gênero Colesterol Pressão Sanguínea Fumante Risco 0 25.0 F 190.0 70 Não baixo 1 35.0 M 208.57 80 Sim médio 2 45.0 F 240.0 78 Não alto 3 60.0 F 225.0 75 Não baixo 4 55.0 M 210.0 72 Sim alto 5 65.0 M 208.57 130 Não médio 6 75.0 F 180.0 60 Sim baixo 7 60.0 M 195.0 85 Não médio 8 85.0 F 220.0 90 Não baixo 9 95.0 M 208.57 77 Sim alto |
Essa técnica de imputação de dados faltantes usando a média é simples e eficaz em muitos casos. No entanto, existem outras estratégias disponíveis no SimpleImputer
, como 'median'
(mediana) e 'most_frequent'
(valor mais frequente), que podem ser mais apropriadas dependendo das características dos seus dados.
Convertendo Dados Categóricos em Números (Encoding Categorical Data)
Dados categóricos devem ser convertidos para um formato numérico. Usamos LabelEncoder
para transformar a coluna target e OneHotEncoder
para as características categóricas.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
from sklearn.preprocessing import LabelEncoder, OneHotEncoder from sklearn.compose import ColumnTransformer # Encoding da coluna 'Gênero' e 'Fumante' column_transformer = ColumnTransformer( [('encoder', OneHotEncoder(), ['Gênero', 'Fumante'])], remainder='passthrough' ) # Aplicando o ColumnTransformer aos dados, excluindo a coluna 'Risco' x = column_transformer.fit_transform(df.drop('Risco', axis=1)) # Encoding da coluna 'Risco' usando LabelEncoder label_encoder = LabelEncoder() y = label_encoder.fit_transform(df['Risco']) |
Depois de lidar com os dados faltantes, precisamos tratar as variáveis categóricas presentes no conjunto de dados. Variáveis categóricas são aquelas que representam categorias ou rótulos, como ‘Gênero' (Feminino/Masculino) e ‘Fumante' (Sim/Não). Como a maioria dos algoritmos de aprendizado de máquina trabalha com dados numéricos, precisamos converter essas variáveis categóricas para um formato numérico.
Vamos analisar o código passo a passo:
- Importamos as classes necessárias do Scikit-Learn:
LabelEncoder
eOneHotEncoder
do módulosklearn.preprocessing
para codificar as variáveis categóricas.ColumnTransformer
do módulosklearn.compose
para aplicar transformações em colunas específicas do DataFrame.
1 2 |
from sklearn.preprocessing import LabelEncoder, OneHotEncoder from sklearn.compose import ColumnTransformer |
- Criamos uma instância do
ColumnTransformer
chamadacolumn_transformer
para codificar as colunas ‘Gênero' e ‘Fumante' usando oOneHotEncoder
:- O primeiro argumento é uma lista de tuplas, onde cada tupla especifica uma transformação a ser aplicada em um conjunto de colunas.
- Nesse caso, temos apenas uma tupla:
('encoder', OneHotEncoder(), ['Gênero', 'Fumante'])
, que aplica oOneHotEncoder
nas colunas ‘Gênero' e ‘Fumante'. - O parâmetro
remainder='passthrough'
indica que as colunas não especificadas devem ser mantidas inalteradas.
1 2 3 4 |
column_transformer = ColumnTransformer( [('encoder', OneHotEncoder(), ['Gênero', 'Fumante'])], remainder='passthrough' ) |
- Aplicamos o
column_transformer
nos dados, excluindo a coluna ‘Risco', e atribuímos o resultado à variávelX
:- Usamos o método
fit_transform()
para ajustar ocolumn_transformer
aos dados e transformá-los de uma só vez. - O método
drop('Risco', axis=1)
é usado para excluir a coluna ‘Risco' do DataFrame antes de aplicar a transformação, pois ela é a variável target e não deve ser incluída nas features.
- Usamos o método
1 |
x = column_transformer.fit_transform(df.drop('Risco', axis=1)) |
- Criamos uma instância do
LabelEncoder
chamadalabel_encoder
para codificar a coluna ‘Risco':- O
LabelEncoder
é usado para converter os rótulos categóricos em valores numéricos inteiros. - Aplicamos o
label_encoder
na coluna ‘Risco' usando o métodofit_transform()
e atribuímos o resultado à variávely
.
- O
1 2 |
label_encoder = LabelEncoder() y = label_encoder.fit_transform(df['Risco']) |
Após a execução desse código, teremos:
X
: um array NumPy contendo as features codificadas:- As colunas ‘Gênero' e ‘Fumante' serão transformadas em colunas binárias usando o
OneHotEncoder
. Cada categoria será representada por uma coluna binária. - As colunas numéricas ‘Idade', ‘Colesterol' e ‘Pressão Sanguínea' serão mantidas inalteradas.
- As colunas ‘Gênero' e ‘Fumante' serão transformadas em colunas binárias usando o
y
: um array NumPy contendo os rótulos da variável target ‘Risco' codificados numericamente usando oLabelEncoder
.
Por exemplo, supondo que após a codificação tenhamos:
- ‘Gênero_F' e ‘Gênero_M' representando as categorias de gênero.
- ‘Fumante_Não' e ‘Fumante_Sim' representando as categorias de fumante.
- ‘baixo' codificado como 0, ‘médio' como 1 e ‘alto' como 2 na variável target ‘Risco'.
O array X
terá a seguinte estrutura:
1 2 3 4 5 |
[[1.0, 0.0, 1.0, 0.0, 25.0, 190.0, 70.0], [0.0, 1.0, 0.0, 1.0, 35.0, 208.57, 80.0], ... [1.0, 0.0, 1.0, 0.0, 85.0, 220.0, 90.0], [0.0, 1.0, 0.0, 1.0, 95.0, 208.57, 77.0]] |
e o array y
será:
1 |
[0, 1, 2, 0, 2, 1, 0, 1, 0, 2] |
Agora, com as variáveis categóricas codificadas e a variável target transformada, os dados estão prontos para serem usados em algoritmos de aprendizado de máquina que requerem entrada numérica.
Essa etapa de codificação de variáveis categóricas é fundamental para muitos algoritmos, pois permite que eles processem e aprendam com dados não numéricos de maneira eficaz.
Escalonamento de Características (Feature Scaling)
O escalonamento de características é importante para muitos algoritmos de machine learning. No nosso exemplo, podemos usar StandardScaler
para padronizar as features.
1 2 3 4 5 6 7 8 |
from sklearn.preprocessing import StandardScaler # Instanciando o objeto StandardScaler scaler = StandardScaler() # Aplicando o escalonamento no nosso array de características 'X' x_scaled = scaler.fit_transform(x) |
Vamos detalhar a etapa de escalonamento de características (feature scaling) usando o StandardScaler
do Scikit-Learn.
O escalonamento de características é uma técnica de pré-processamento que visa transformar as variáveis numéricas para que tenham uma escala similar. Isso é importante porque muitos algoritmos de aprendizado de máquina são sensíveis à escala das features. Se uma feature tiver uma escala muito maior do que as outras, ela pode dominar o algoritmo e prejudicar o desempenho do modelo.
O StandardScaler
é uma classe do Scikit-Learn que padroniza as features, subtraindo a média e dividindo pelo desvio padrão de cada feature. Isso resulta em features com média zero e desvio padrão igual a um.
Vamos analisar o código passo a passo:
- Importamos a classe
StandardScaler
do módulosklearn.preprocessing
:
1 |
from sklearn.preprocessing import StandardScaler |
- Criamos uma instância do
StandardScaler
chamadascaler
:
1 |
scaler = StandardScaler() |
- Aplicamos o escalonamento no array de características
X
usando o métodofit_transform()
doscaler
:- O método
fit_transform()
ajusta oscaler
aos dados, calculando a média e o desvio padrão de cada feature, e então aplica a transformação nos dados. - O resultado é atribuído à variável
X_scaled
.
- O método
1 |
X_scaled = scaler.fit_transform(X) |
Após a execução desse código, x_scaled
será um array NumPy contendo as features escalonadas.
Para entender melhor o que o StandardScaler
faz, vamos considerar um exemplo simples com apenas duas features numéricas: ‘Idade' e ‘Pressão Sanguínea'.
Suponha que temos os seguintes valores para essas features:
1 2 3 |
Idade: [25, 35, 45, 55, 65] Pressão Sanguínea: [120, 130, 140, 150, 160] |
Ao aplicar o StandardScaler
, ele calcula a média e o desvio padrão de cada feature:
- ‘Idade': média = 45, desvio padrão = 15.81
- ‘Pressão Sanguínea': média = 140, desvio padrão = 15.81
Em seguida, o StandardScaler
subtrai a média de cada valor e divide pelo desvio padrão:
- ‘Idade' escalonada: [-1.26, -0.63, 0.0, 0.63, 1.26]
- ‘Pressão Sanguínea' escalonada: [-1.26, -0.63, 0.0, 0.63, 1.26]
Observe que, após o escalonamento, ambas as features têm média zero e desvio padrão igual a um. Isso coloca as features em uma escala similar, o que pode melhorar o desempenho de muitos algoritmos de aprendizado de máquina.
É importante ressaltar que o escalonamento deve ser aplicado apenas nas features numéricas. No código que aplicamos como exemplo, as colunas “Gênero” e “Fumante”, que são categóricas, são transformadas em variáveis numéricas por meio do processo de One-Hot Encoding antes de qualquer escalonamento ser aplicado.
No entanto, é importante notar que, embora essas colunas binárias passem pelo escalonamento, o impacto dessa transformação é limitado devido à natureza binária dos dados. O escalonamento pode ajustar essas colunas para que tenham média 0 e desvio padrão 1, mas, dado que os valores originais são 0 e 1, essa etapa não altera a interpretação dessas variáveis da mesma forma que altera para variáveis contínuas.
Além do StandardScaler
, o Scikit-Learn oferece outras técnicas de escalonamento, como o MinMaxScaler
(que escala as features para um intervalo específico, geralmente entre 0 e 1) e o RobustScaler
(que é menos sensível a outliers nos dados).
O escalonamento de características é uma etapa importante no pré-processamento de dados para muitos algoritmos de aprendizado de máquina, pois ajuda a garantir que todas as features tenham uma influência equilibrada no modelo e pode melhorar significativamente o desempenho e a convergência do algoritmo.
Com o nosso conjunto de dados agora devidamente pré-processado, estamos prontos para avançar para as próximas etapas do pipeline de machine learning, como seleção de modelo e validação cruzada.
Este exemplo destacou a importância do pre-processamento de dados para criar modelos de machine learning robustos e confiáveis com o Scikit-Learn. Ao lidar com dados faltantes, aplicar codificação a dados categóricos e aplicar escalonamento de features, garantimos que nossos modelos possam performar da melhor maneira possível quando aplicados a dados do mundo real.
Introdução aos Pipelines: Simplificando o Processo de Machine Learning
Ao trabalharmos com projetos de machine learning, enfrentamos frequentemente a complexidade de pré-processar nossos dados antes de aplicar algum algoritmo de aprendizado. Um Pipeline no Scikit-Learn é uma ferramenta que nos auxilia a encadear vários passos de transformação e modelagem de maneira a simplificar esse processo.
O Exemplo Prático de um DataFrame
Vamos começar com um DataFrame que simula um conjunto de dados médicos, como segue:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import numpy as np import pandas as pd data = { 'Idade': [25, 35, 45, np.nan, 55, 65, 75, np.nan, 85, 95], 'Gênero': ['F', 'M', 'F', 'F', 'M', 'M', 'F', 'M', 'F', 'M'], 'Colesterol': [190, np.nan, 240, 225, 210, np.nan, 180, 195, 220, np.nan], 'Pressão Sanguínea': [70, 80, 78, 75, 72, 130, 60, 85, 90, 77], 'Fumante': ['Não', 'Sim', 'Não', 'Não', 'Sim', 'Não', 'Sim', 'Não', 'Não', 'Sim'], 'Risco': ['baixo', 'médio', 'alto', 'baixo', 'alto', 'médio', 'baixo', 'médio', 'baixo', 'alto'] } df = pd.DataFrame(data) |
Neste DataFrame, temos features com tipos de dados variados e também alguns valores ausentes. A necessidade de tratar esses valores ausentes, converter features categóricas e escalar as numéricas é um processo comum e que pode ser bastante trabalhoso.
Simplificação com Pipeline
O uso de um pipeline nos permite automatizar o pré-processamento dos dados. Ele agrupa tarefas que precisam ser executadas em sequência, reduzindo o esforço manual e os erros que podem ocorrer ao realizar essas tarefas separadamente. Vejamos como isso é feito na prática:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
from sklearn.pipeline import Pipeline from sklearn.impute import SimpleImputer from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.compose import ColumnTransformer from sklearn.linear_model import LogisticRegression # Definição do pré-processador para o ColumnTransformer preprocessor = ColumnTransformer( transformers=[ ('num', Pipeline(steps=[ ('imputer', SimpleImputer(strategy='mean')), # Preenchendo valores ausentes ('scaler', StandardScaler())]), # Escalonando as características numéricas ['Idade', 'Colesterol', 'Pressão Sanguínea']), ('cat', OneHotEncoder(), ['Gênero', 'Fumante']) # Convertendo as características categóricas ] ) # Criação do pipeline completo com o ColumnTransformer e o modelo pipeline = Pipeline(steps=[ ('preprocessor', preprocessor), ('classifier', LogisticRegression()) # Modelo final que será treinado ]) # Separando as features e o target X = df.drop('Risco', axis=1) y = df['Risco'] # Treinando o pipeline completo pipeline.fit(X, y) |
Vamos analisar o código passo a passo:
- Importações necessárias:
Pipeline
do módulosklearn.pipeline
para criar o pipeline.SimpleImputer
do módulosklearn.impute
para preencher valores ausentes.StandardScaler
eOneHotEncoder
do módulosklearn.preprocessing
para escalonar as características numéricas e converter as características categóricas, respectivamente.ColumnTransformer
do módulosklearn.compose
para aplicar diferentes transformações em diferentes subconjuntos de colunas.LogisticRegression
do módulosklearn.linear_model
como o modelo final a ser treinado.
- Definição do pré-processador usando o
ColumnTransformer
:- O
ColumnTransformer
permite aplicar diferentes transformações em diferentes subconjuntos de colunas. - Neste caso, temos dois transformadores:
'num'
: Um pipeline que lida com as colunas numéricas (‘Idade', ‘Colesterol', ‘Pressão Sanguínea'). Ele consiste em duas etapas:SimpleImputer
comstrategy='mean'
para preencher os valores ausentes com a média da coluna.StandardScaler
para escalonar as características numéricas, subtraindo a média e dividindo pelo desvio padrão.
'cat'
: UmOneHotEncoder
para converter as colunas categóricas (‘Gênero', ‘Fumante') em variáveis binárias (one-hot encoding).
- O
- Criação do pipeline completo:
- O pipeline completo é criado usando a classe
Pipeline
do Scikit-Learn. - Ele consiste em duas etapas:
'preprocessor'
: OColumnTransformer
definido anteriormente, que aplica as transformações de pré-processamento nos dados.'classifier'
: O modelo final a ser treinado, neste caso, uma regressão logística (LogisticRegression
).
- O pipeline completo é criado usando a classe
- Separação das features e do target:
- As features (variáveis independentes) são atribuídas à variável
X
usandodf.drop('Risco', axis=1)
, que remove a coluna ‘Risco' do DataFramedf
. - O target (variável dependente) é atribuído à variável
y
usandodf['Risco']
.
- As features (variáveis independentes) são atribuídas à variável
- Treinamento do pipeline completo:
- O método
fit(X, y)
é chamado no pipeline completo para treinar o modelo. - Internamente, o pipeline aplica as seguintes etapas:
- O pré-processador (
preprocessor
) é ajustado aos dadosX
usando oColumnTransformer
. Isso significa que:- Os valores ausentes nas colunas numéricas são preenchidos com a média da coluna usando o
SimpleImputer
. - As colunas numéricas são escalonadas usando o
StandardScaler
. - As colunas categóricas são convertidas em variáveis binárias usando o
OneHotEncoder
.
- Os valores ausentes nas colunas numéricas são preenchidos com a média da coluna usando o
- O modelo final (
classifier
) é treinado nos dados pré-processados usando a regressão logística.
- O pré-processador (
- O método
Após o treinamento, o pipeline está pronto para ser usado para fazer previsões em novos dados. Você pode chamar o método predict(X_new)
no pipeline para obter as previsões para um novo conjunto de dados X_new
.
Para fazer previsões usando o pipeline que você definiu, você pode simplesmente chamar o método predict()
no pipeline treinado, passando os novos dados como argumento. Aqui está um exemplo de como você pode fazer isso:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Suponha que você tenha novos dados em um DataFrame chamado 'new_data' new_data = pd.DataFrame({ 'Idade': [30, 40, 50], 'Gênero': ['M', 'F', 'M'], 'Colesterol': [200, 180, 220], 'Pressão Sanguínea': [120, 110, 130], 'Fumante': ['Não', 'Sim', 'Não'] }) # Fazendo previsões usando o pipeline treinado predictions = pipeline.predict(new_data) # Imprimindo as previsões print(predictions) |
Neste exemplo:
- Supomos que você tenha novos dados em um DataFrame chamado
new_data
. Esses dados devem ter as mesmas colunas que foram usadas para treinar o pipeline, exceto pela coluna ‘Risco', que é a variável target. - Chamamos o método
predict()
no pipeline treinado (pipeline
), passando o DataFramenew_data
como argumento. O pipeline aplicará automaticamente as mesmas etapas de pré-processamento que foram definidas durante o treinamento (preenchimento de valores ausentes, escalonamento de características numéricas e codificação one-hot de características categóricas) antes de fazer as previsões usando o modelo treinado. - As previsões são retornadas como um array NumPy e atribuídas à variável
predictions
. - Imprimimos as previsões usando
print(predictions)
.
O resultado será um array contendo as previsões do modelo para cada amostra nos novos dados. As previsões serão baseadas no modelo treinado (regressão logística, no exemplo fornecido) e nas etapas de pré-processamento definidas no pipeline.
Por exemplo, a saída pode ser algo como:
1 |
['baixo' 'médio' 'alto'] |
Isso indica que o modelo previu as classes de risco ‘baixo', ‘médio' e ‘alto' para as três amostras nos novos dados, respectivamente.
Lembre-se de que as previsões serão baseadas no modelo treinado e nas etapas de pré-processamento definidas no pipeline. Certifique-se de que os novos dados tenham a mesma estrutura e as mesmas colunas que foram usadas durante o treinamento do pipeline.
A principal vantagem de usar um pipeline é que ele encapsula todas as etapas de pré-processamento e o modelo em um único objeto, tornando o código mais legível, modular e fácil de manter. Além disso, ao usar o pipeline, você garante que as mesmas etapas de pré-processamento sejam aplicadas consistentemente tanto no treinamento quanto na previsão.
Vantagens do Pipeline
A grande vantagem de utilizar o Pipeline é que ele encapsula todas as etapas de tratamento dos dados e modelagem, evitando que tenhamos que manualmente aplicar transformações a cada vez que manipulamos ou dividimos os dados em conjuntos de treino e teste. Além disso, o pipeline evita o vazamento de dados do conjunto de teste para o conjunto de treino, pois garante que o pré-processamento seja aplicado separadamente em cada fase. Essa abordagem não só simplifica o código, mas também fortalece a integridade do processo de modelagem.
Portanto, o Pipeline é um recurso poderoso que traz eficiência e segurança ao processo de construção de modelos de machine learning, ao mesmo tempo que mantém um código mais limpo, mais legível e com manutenção mais fácil.
ColumnTransformer
Embora os pipelines sejam extremamente úteis para sequenciar etapas de processamento e modelagem, o ColumnTransformer
tem seu próprio poder: permite aplicar transformações distintas a colunas específicas dentro de um DataFrame. Entender as diferenças e complementariedades entre um pipeline e o ColumnTransformer
é fundamental para criar um processo de pré-processamento eficaz.
Entendendo o ColumnTransformer
O ColumnTransformer
é uma ferramenta do Scikit-Learn projetada para combinar várias transformações de pré-processamento para colunas distintas de um DataFrame. Enquanto um pipeline é ideal para definir uma sequência de passos que serão aplicados à totalidade dos dados, o ColumnTransformer
permite que diferentes colunas ou grupos de colunas recebam tratamentos individuais.
Demonstração com um DataFrame Existente
Tomemos como exemplo o DataFrame a seguir, que poderia representar um estudo clínico:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import numpy as np import pandas as pd # DataFrame de exemplo data = { 'Idade': [25, 35, 45, np.nan, 55, 65, 75, np.nan, 85, 95], 'Gênero': ['F', 'M', 'F', 'F', 'M', 'M', 'F', 'M', 'F', 'M'], 'Colesterol': [190, np.nan, 240, 225, 210, np.nan, 180, 195, 220, np.nan], 'Pressão Sanguínea': [70, 80, 78, 75, 72, 130, 60, 85, 90, 77], 'Fumante': ['Não', 'Sim', 'Não', 'Não', 'Sim', 'Não', 'Sim', 'Não', 'Não', 'Sim'], 'Risco': ['baixo', 'médio', 'alto', 'baixo', 'alto', 'médio', 'baixo', 'médio', 'baixo', 'alto'] } df = pd.DataFrame(data) |
Diferenças Chave entre Pipeline e ColumnTransformer
A principal diferença entre o ColumnTransformer
e os pipelines tradicionais é que, com o ColumnTransformer
, podemos realizar ações como:
- Preencher valores faltantes apenas em algumas colunas.
- Escalar apenas as colunas numéricas.
- Codificar apenas as colunas categóricas.
Essas ações podem ser realizadas simultaneamente, mas de forma independente para cada grupo de colunas, o que seria mais complexo se estivéssemos utilizando um pipeline simples.
Aplicação do ColumnTransformer
Aplicar o ColumnTransformer
no nosso DataFrame poderia ser feito da seguinte maneira:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
from sklearn.compose import ColumnTransformer from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.impute import SimpleImputer # Instanciando o ColumnTransformer column_transformer = ColumnTransformer( transformers=[ ('num', Pipeline(steps=[ ('imputer', SimpleImputer(strategy='mean')), # Tratamento de dados numéricos faltantes ('scaler', StandardScaler()) # Escalonamento dos dados numéricos ]), ['Idade', 'Colesterol', 'Pressão Sanguínea']), ('cat', OneHotEncoder(), ['Gênero', 'Fumante']) # Codificação de variáveis categóricas ], remainder='drop' # Colunas não listadas serão descartadas ) # Pré-processamento das colunas com transformações específicas X_transformed = column_transformer.fit_transform(df) |
Conclusão
O Pipeline e o ColumnTransformer são duas ferramentas poderosas do scikit-learn que trabalham de forma complementar para simplificar e automatizar o processo de pré-processamento de dados e construção de modelos de aprendizado de máquina.
O Pipeline permite encadear várias etapas de transformação e estimação em uma única objeto, tornando o fluxo de trabalho mais organizado e fácil de gerenciar. Ele é especialmente útil quando você tem uma sequência fixa de etapas que precisam ser aplicadas consistentemente aos dados, como pré-processamento, seleção de recursos e treinamento do modelo. O Pipeline garante que as etapas sejam executadas na ordem correta e permite que você trate o fluxo de trabalho como um único objeto, facilitando a aplicação de técnicas de validação cruzada e ajuste de hiperparâmetros.
Por outro lado, o ColumnTransformer é uma ferramenta flexível que permite aplicar diferentes transformações em diferentes subconjuntos de colunas de um conjunto de dados. Ele é particularmente útil quando você tem dados heterogêneos, com colunas de diferentes tipos (por exemplo, numéricas, categóricas, de texto) que requerem tratamentos distintos. O ColumnTransformer permite especificar transformações específicas para cada subconjunto de colunas, como imputação de valores ausentes, escalonamento, codificação one-hot, entre outros. Isso elimina a necessidade de pré-processar manualmente cada tipo de coluna e torna o código mais legível e mantível.
A combinação do Pipeline e do ColumnTransformer oferece uma abordagem poderosa e flexível para o pré-processamento de dados e a construção de modelos. O ColumnTransformer pode ser usado dentro de um Pipeline como uma etapa de pré-processamento, permitindo que você aplique transformações específicas em diferentes subconjuntos de colunas antes de passar os dados para as etapas subsequentes do Pipeline, como a seleção de recursos e o treinamento do modelo.
Essa abordagem combinada traz várias vantagens:
1. Código mais limpo e organizado: O Pipeline e o ColumnTransformer ajudam a estruturar o código de forma mais clara e modular, separando as etapas de pré-processamento e treinamento do modelo.
2. Consistência no pré-processamento: O ColumnTransformer garante que as mesmas transformações sejam aplicadas consistentemente em diferentes subconjuntos de colunas, evitando erros e inconsistências manuais.
3. Facilidade de experimentação: O Pipeline permite experimentar facilmente diferentes combinações de etapas de pré-processamento e modelos, simplificando a comparação e a seleção das melhores abordagens.
4. Prevenção de vazamento de dados: Ao usar o Pipeline, você evita o vazamento de informações do conjunto de teste para o conjunto de treinamento, garantindo que as transformações sejam ajustadas apenas nos dados de treinamento e aplicadas aos dados de teste.
5. Simplicidade na implantação: O Pipeline e o ColumnTransformer podem ser serializados e implantados como um único objeto, facilitando a colocação do modelo em produção.
Em resumo, o Pipeline e o ColumnTransformer são ferramentas complementares que trabalham em conjunto para simplificar e aprimorar o processo de pré-processamento de dados e construção de modelos de aprendizado de máquina. Eles promovem um código mais organizado, consistente e fácil de manter, além de facilitar a experimentação e a implantação dos modelos. A combinação dessas ferramentas é uma prática recomendada para projetos de aprendizado de máquina, permitindo um fluxo de trabalho mais eficiente e produtivo.
Avaliação de Modelos com Scikit-Learn: Métricas para Classificação e Regressão
Avaliar um modelo de machine learning é uma etapa crucial para entender o seu desempenho em tarefas de previsão. O Scikit-Learn, uma das bibliotecas mais populares para aprendizado de máquina em Python, oferece uma gama de métricas específicas para avaliar modelos de classificação e de regressão. Vamos explorar essas métricas e entender como elas podem nos ajudar a quantificar a eficácia dos modelos.
Métricas de Classificação
Accuracy (Acurácia)
A acurácia é uma métrica que mede a proporção de previsões corretas realizadas por um modelo de classificação. No Scikit-Learn, podemos usar a função accuracy_score()
para calcular facilmente essa taxa, passando como argumentos as listas dos valores verdadeiros e das previsões feitas pelo modelo.
Exemplificando a Utilização da accuracy_score()
no Cálculo da Acurácia
Preparando os Dados de Exemplo
Imagine que estamos trabalhando com um modelo simples de classificação que tenta prever se um email é ‘spam' ou ‘não spam'. Após o treino e as predições, temos as seguintes listas: uma com os rótulos verdadeiros (y_true
) e outra com os rótulos previstos pelo modelo (y_pred
).
1 2 3 4 5 6 |
# Lista dos rótulos verdadeiros y_true = ['spam', 'não spam', 'spam', 'não spam', 'spam', 'não spam', 'não spam', 'spam', 'spam', 'não spam'] # Lista das predições do modelo y_pred = ['spam', 'não spam', 'spam', 'spam', 'não spam', 'não spam', 'não spam', 'spam', 'spam', 'spam'] |
Aqui, temos um conjunto de 10 e-mails, onde o modelo fez as suas previsões, acertando algumas e errando outras.
Cálculo da Acurácia
Agora, vamos calcular a acurácia do modelo usando a função accuracy_score()
do Scikit-Learn:
1 2 3 4 5 6 7 8 |
from sklearn.metrics import accuracy_score # Calculando a acurácia accuracy = accuracy_score(y_true, y_pred) # Imprimindo a acurácia print(f"A acurácia do modelo de classificação é: {accuracy:.2f}") |
Suponha que, após executar o código acima, obtemos uma saída indicando uma acurácia de 0.70, ou 70%. Isso significa que o modelo acertou 70% das suas previsões.
Interpretação da Acurácia
O valor de 0.70 de acurácia indica que, em termos gerais, o modelo é razoavelmente bom em diferenciar e-mails ‘spam' de ‘não spam'. No entanto, é sempre importante considerar o contexto e a aplicação prática. Se, por exemplo, o custo de classificar um ‘não spam' como ‘spam' (perder um e-mail importante) for muito alto, outras métricas como a precisão e o recall devem ser avaliadas conjuntamente.
Conclusão
A função accuracy_score()
é uma maneira eficiente de obter uma visão rápida da performance de um modelo de classificação. Essa métrica é útil em conjuntos de dados bem balanceados, mas deve ser usada em conjunto com outras métricas em casos de desbalanceamento de classes para que se tenha uma avaliação de desempenho mais completa e confiável.
Precisão e Recall
Entender e aplicar corretamente as métricas de precisão e recall é fundamental para avaliar modelos de classificação, especialmente em contextos onde o equilíbrio entre o reconhecimento correto de classes e a minimização de erros específicos é crucial.
Precisão (Precision)
A precisão mede a exatidão do modelo quando ele faz uma previsão positiva. Em outras palavras, é a proporção de previsões positivas que foram efetivamente corretas. Essa métrica é particularmente importante em situações onde o custo de um falso positivo é alto. Por exemplo, enviar uma promoção para um cliente não interessado pode ser um desperdício de recursos.
Recall (Sensibilidade)
O recall, por sua vez, avalia a capacidade do modelo de encontrar todas as instâncias relevantes dentro de uma classe. É a proporção de positivos reais que foram identificados corretamente. Ele é essencial quando o custo de um falso negativo é elevado, como no diagnóstico de uma doença grave onde falhar em identificar um caso positivo pode ter consequências sérias.
Cálculo de Precisão e Recall
Para calcular essas métricas, utilizamos as funções precision_score()
e recall_score()
do Scikit-Learn. Continuando com nosso exemplo anterior de classificação de e-mails em ‘spam' ou ‘não spam', podemos usar as mesmas listas de valores verdadeiros e predições do modelo.
1 2 3 4 5 6 7 8 9 10 |
from sklearn.metrics import precision_score, recall_score # Calculando a precisão e o recall precision = precision_score(y_true, y_pred, pos_label='spam') recall = recall_score(y_true, y_pred, pos_label='spam') # Imprimindo os resultados print(f"Precisão do modelo: {precision:.2f}") print(f"Recall do modelo: {recall:.2f}") |
Interpretação das Métricas
Se a precisão for alta (por exemplo, 0.90 ou 90%), isso indica que, quando o modelo prevê um e-mail como ‘spam', é muito provável que realmente seja. No entanto, uma precisão alta não necessariamente significa que o modelo é eficaz em identificar todos os e-mails ‘spam' que recebe.
Por outro lado, um recall alto (também por exemplo, 0.90 ou 90%) sugere que o modelo é habilidoso em capturar a grande maioria dos e-mails ‘spam'. No entanto, um recall alto pode vir acompanhado de um número maior de falsos positivos (e-mails ‘não spam' incorretamente classificados como ‘spam').
Balanceamento entre Precisão e Recall
Em muitos casos, existe uma troca entre precisão e recall. Melhorar um geralmente reduz o desempenho do outro. Uma forma de buscar um equilíbrio é através da métrica F1-Score, que é a média harmônica entre precisão e recall.
Aplicando a F1-Score para Avaliação Equilibrada de Modelos de Classificação
A F1-Score é uma métrica que combina precisão e recall em um único número, oferecendo uma visão equilibrada do desempenho de um classificador. É particularmente útil em situações onde é preciso balancear a importância de minimizar falsos positivos e falsos negativos. A F1-Score é a média harmônica da precisão e do recall e tende a ser mais baixa do que as métricas de precisão e recall individuais se uma delas for muito menor que a outra.
Cálculo da F1-Score
Para calcular a F1-Score, usamos a função f1_score()
do Scikit-Learn. Considerando nosso exemplo contínuo sobre a classificação de e-mails, vamos aplicar a F1-Score ao conjunto de previsões feitas pelo nosso modelo.
1 2 3 4 5 6 7 8 9 10 11 12 |
from sklearn.metrics import f1_score # Supondo que 'y_true' contém os rótulos verdadeiros e 'y_pred' as previsões do modelo y_true = ['spam', 'não spam', 'spam', 'não spam', 'spam', 'não spam', 'não spam', 'spam', 'spam', 'não spam'] y_pred = ['spam', 'não spam', 'spam', 'spam', 'não spam', 'não spam', 'não spam', 'spam', 'spam', 'spam'] # Calculando a F1-Score f1 = f1_score(y_true, y_pred, pos_label='spam') # Imprimindo o resultado print(f"A F1-Score do modelo é: {f1:.2f}") |
Ao executar o código acima, obteremos um valor numérico que indica a F1-Score do modelo. Por exemplo, uma F1-Score de 0.80 indica um bom equilíbrio entre precisão e recall, considerando que o valor pode variar de 0 (pior) a 1 (melhor).
Quando Utilizar a F1-Score
A F1-Score é particularmente valiosa quando precisamos de um equilíbrio entre precisão e recall. Em outras palavras, quando não queremos privilegiar a minimização de um tipo de erro em detrimento do outro. Ela é ideal para cenários em que tanto falsos positivos quanto falsos negativos têm consequências significativas.
A F1-Score é uma métrica robusta para avaliar modelos de classificação, principalmente em conjuntos de dados com classes desbalanceadas ou quando é fundamental manter um equilíbrio entre precisão e recall. Ela fornece uma única métrica que resume a capacidade do modelo de classificar com precis
No entanto, a escolha de focar em precisão, recall ou um equilíbrio entre ambos deve sempre ser guiada pelas necessidades específicas do problema de negócios que o modelo visa resolver.
Conclusão
Precisão e recall são métricas que oferecem um olhar detalhado sobre a performance de um modelo de classificação, cada uma enfatizando um aspecto diferente do desempenho. Ao usá-las em conjunto, é possível ter uma compreensão mais completa sobre onde o modelo está acertando e onde precisa ser aprimorado, permitindo ajustes mais precisos e uma tomada de decisão mais informada na escolha ou no desenvolvimento de modelos de machine learning.
Métricas de Regressão
No universo do aprendizado de máquina, compreender a performance de modelos de regressão é essencial, pois eles são amplamente utilizados para prever valores contínuos. Vamos nos aprofundar em duas métricas centrais: o Erro Quadrático Médio (MSE) e o Coeficiente de Determinação (R²), explorando como eles são calculados e o que realmente representam para a análise do desempenho de modelos de regressão.
Erro Quadrático Médio (MSE)
O Erro Quadrático Médio (MSE) é uma das métricas mais comuns para avaliar modelos de regressão. O MSE é calculado tomando a média das diferenças ao quadrado entre os valores previstos pelo modelo e os valores reais. Esse procedimento penaliza mais os erros grandes, devido ao quadrado, tornando essa métrica bastante sensível a outliers no conjunto de dados.
1 2 3 4 5 6 7 8 9 10 11 12 |
from sklearn.metrics import mean_squared_error # Supondo que temos os valores reais 'y_true' e as previsões 'y_pred' do modelo de regressão y_true = [3, -0.5, 2, 7] y_pred = [2.5, 0.0, 2, 8] # Calculando o MSE mse = mean_squared_error(y_true, y_pred) # Apresentando o MSE print(f"O Erro Quadrático Médio (MSE) do modelo é: {mse:.2f}") |
Um MSE baixo indica que o modelo tem um bom desempenho na previsão dos valores, com uma menor variação dos erros. Um alto MSE, por outro lado, sugere que o modelo pode estar inadequado ou que há variabilidade significativa nos dados que não está sendo capturada pelo modelo.
O RMSE (Root Mean Squared Error) é uma métrica comumente usada para avaliar o desempenho de modelos de regressão no contexto de machine learning. O Scikit-Learn, uma popular biblioteca de machine learning em Python, fornece uma função chamada mean_squared_error
que nos permite calcular facilmente o RMSE.
Exemplo prático usando Scikit-Learn: Suponha que você tenha um modelo de regressão para prever o preço de casas com base em características como área, número de quartos, localização, etc. Você treinou o modelo usando um conjunto de dados de treinamento e agora deseja avaliar seu desempenho em um conjunto de dados de teste.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error import numpy as np # Gerar dados sintéticos para regressão X, y = make_regression(n_samples=100, n_features=1, noise=10, random_state=42) # Dividir os dados em conjuntos de treinamento e teste X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # Criar e treinar o modelo de regressão linear model = LinearRegression() model.fit(X_train, y_train) # Fazer previsões no conjunto de teste y_pred = model.predict(X_test) # Calcular o RMSE rmse = np.sqrt(mean_squared_error(y_test, y_pred)) print("RMSE:", rmse) |
Neste exemplo:
- Usamos a função
make_regression
do Scikit-Learn para gerar dados sintéticos para um problema de regressão. Especificamos o número de amostras (n_samples
), o número de características (n_features
), o nível de ruído (noise
) e uma semente aleatória (random_state
) para reprodutibilidade. - Dividimos os dados gerados em conjuntos de treinamento e teste usando a função
train_test_split
. Especificamos que 20% dos dados devem ser usados para teste (test_size=0.2
). - Criamos uma instância do modelo de regressão linear usando a classe
LinearRegression
do Scikit-Learn e treinamos o modelo usando o métodofit
, passando os dados de treinamento (X_train
ey_train
). - Fazemos previsões no conjunto de teste usando o método
predict
do modelo treinado, passandoX_test
. - Calculamos o RMSE usando a função
mean_squared_error
do Scikit-Learn, passando os valores reais (y_test
) e as previsões (y_pred
). Em seguida, aplicamos a raiz quadrada usandonp.sqrt
para obter o RMSE final. - Por fim, imprimimos o valor do RMSE.
O Scikit-Learn simplifica o processo de cálculo do RMSE, fornecendo a função mean_squared_error
que realiza internamente os cálculos necessários. Além disso, a biblioteca oferece uma ampla gama de modelos de regressão e recursos para pré-processamento de dados, treinamento de modelos e avaliação de desempenho.
Ao usar o Scikit-Learn, podemos facilmente experimentar diferentes modelos de regressão, ajustar hiperparâmetros e comparar seus desempenhos usando métricas como o RMSE para selecionar o modelo mais adequado para o problema em questão.
Interpretação do RMSE
O valor de RMSE deve sempre ser interpretado no contexto dos dados. Por estar na mesma unidade dos valores observados, o RMSE oferece uma compreensão direta do erro típico que o modelo comete em suas previsões. Quanto menor o RMSE, melhor o modelo é em prever sem grandes erros, e um RMSE de zero indicaria previsões perfeitas.
Comparando Modelos: Em muitas situações, o RMSE é utilizado para comparar diferentes modelos ou configurações de um modelo sobre um mesmo conjunto de dados. O modelo com o menor RMSE é considerado o que tem melhor ajuste.
Sensibilidade a Outliers: Assim como o MSE, o RMSE é bastante sensível a outliers. Erros maiores são mais penalizados, elevando o valor do RMSE. Isso pode ser bom ou ruim, dependendo de se os outliers representam ou não informações valiosas.
Cautela na Interpretação: Mesmo um modelo com um RMSE baixo pode não ser ideal. Se o RMSE é significativamente menor do que a variância dos dados, por exemplo, o modelo pode estar superajustando (overfitting) e não generalizar bem para novos dados.
Coeficiente de Determinação (R² Score)
O Coeficiente de Determinação, também conhecido como R² (R-squared) ou R² Score, é outra métrica comumente usada para avaliar o desempenho de modelos de regressão no contexto de machine learning. O Scikit-Learn fornece a função r2_score
para calcular facilmente o R² Score.
O R² Score mede a proporção da variância na variável dependente que é explicada pelas variáveis independentes no modelo de regressão. Ele fornece uma indicação de quão bem o modelo se ajusta aos dados. O valor do R² varia entre 0 e 1, onde:
- Um R² de 0 indica que o modelo não explica nenhuma variação nos dados.
- Um R² de 1 indica que o modelo explica toda a variação nos dados.
Imagine que você está tentando prever as notas de matemática dos alunos com base no número de horas que eles estudam por semana. Você cria um modelo matemático que tenta explicar essa relação entre as horas de estudo e as notas.
O R² Score é uma medida que nos diz o quão bem o seu modelo explica as variações nas notas de matemática. Ele é como uma nota que você dá para o seu modelo, indicando o quanto ele é bom em fazer previsões.
O R² Score varia de 0 a 1:
- Se o R² Score for 0, significa que o seu modelo não explica nada sobre as variações nas notas. É como se você estivesse tentando adivinhar as notas sem nenhuma informação útil.
- Se o R² Score for 1, significa que o seu modelo explica perfeitamente todas as variações nas notas. É como se você tivesse encontrado uma fórmula mágica que prevê as notas com 100% de precisão.
Na prática, o R² Score geralmente fica entre 0 e 1. Quanto mais próximo de 1, melhor o seu modelo é em explicar as variações nas notas.
Por exemplo, se o R² Score for 0.75, significa que o seu modelo explica 75% das variações nas notas de matemática. Isso indica que o número de horas de estudo é um bom indicador das notas, mas ainda há outros fatores que influenciam as notas e que não estão incluídos no modelo.
É importante lembrar que um R² Score alto não significa necessariamente que o modelo é perfeito. Ele apenas indica que o modelo explica bem as variações nos dados que você usou para criá-lo. Para ter certeza de que o modelo é bom, você também precisa testá-lo com novos dados e ver se ele ainda faz previsões precisas.
Em resumo, o R² Score é como uma nota que você dá para o seu modelo matemático, indicando o quão bem ele explica as variações nos dados. Quanto mais próximo de 1, melhor o modelo é em fazer previsões. Mas lembre-se de que um R² Score alto não é garantia de um modelo perfeito e que outros fatores também devem ser considerados.
Exemplo prático usando Scikit-Learn: Vamos continuar com o exemplo anterior de previsão de preços de casas usando um modelo de regressão linear. Após treinar o modelo e fazer previsões no conjunto de teste, podemos calcular o R² Score para avaliar o desempenho do modelo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.metrics import r2_score # Gerar dados sintéticos para regressão X, y = make_regression(n_samples=100, n_features=1, noise=10, random_state=42) # Dividir os dados em conjuntos de treinamento e teste X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # Criar e treinar o modelo de regressão linear model = LinearRegression() model.fit(X_train, y_train) # Fazer previsões no conjunto de teste y_pred = model.predict(X_test) # Calcular o R² Score r2 = r2_score(y_test, y_pred) print("R² Score:", r2) |
Um R² próximo a 1 sugere que o modelo se ajusta bem aos dados, enquanto um valor próximo a 0 indica que o modelo não explica a variância da variável dependente melhor do que um modelo muito simples ou constante.
Neste exemplo:
- Usamos a função
make_regression
do Scikit-Learn para gerar dados sintéticos para um problema de regressão, da mesma forma que no exemplo anterior. - Dividimos os dados em conjuntos de treinamento e teste usando a função
train_test_split
. - Criamos uma instância do modelo de regressão linear usando a classe
LinearRegression
do Scikit-Learn e treinamos o modelo usando o métodofit
, passando os dados de treinamento. - Fazemos previsões no conjunto de teste usando o método
predict
do modelo treinado. - Calculamos o R² Score usando a função
r2_score
do Scikit-Learn, passando os valores reais (y_test
) e as previsões (y_pred
). - Por fim, imprimimos o valor do R² Score.
O R² Score fornece uma medida intuitiva da qualidade do ajuste do modelo aos dados. Quanto mais próximo de 1, melhor o modelo explica a variação nos dados. No entanto, é importante ter em mente que um R² alto não necessariamente indica que o modelo é bom em fazer previsões precisas, especialmente se o modelo estiver sobreajustado (overfitting) aos dados de treinamento.
Além disso, o R² Score tem algumas limitações:
- Ele não indica se os coeficientes do modelo são estatisticamente significativos.
- Ele não considera a complexidade do modelo, ou seja, um modelo com mais variáveis independentes tende a ter um R² maior, mesmo que essas variáveis não contribuam significativamente para a previsão.
Portanto, é recomendado usar o R² Score em conjunto com outras métricas de avaliação, como o RMSE, e também considerar a interpretabilidade e a complexidade do modelo ao tomar decisões.
O Scikit-Learn simplifica o cálculo do R² Score com a função r2_score
, tornando fácil avaliar e comparar diferentes modelos de regressão.
Interpretação e Uso Prático
Ambos, MSE e R², são fundamentais na avaliação de modelos de regressão, mas devem ser interpretados em contexto. Um MSE alto pode ser aceitável em uma variável com alta variabilidade inerente, enquanto um R² alto pode ser enganoso se o modelo estiver superajustado aos dados de treino (overfitting).
Por isso, é importante usar essas métricas em conjunto com uma análise cuidadosa dos resíduos (diferença entre valores previstos e reais), testes de validação cruzada e uma compreensão profunda do domínio do problema para avaliar adequadamente a qualidade das previsões de um modelo de regressão.
Conclusão
MSE e R² são métricas chave para avaliar a qualidade de modelos de regressão. Enquanto o MSE oferece uma visão direta dos erros de previsão do modelo, o R² fornece um olhar sobre quão bem esses valores previstos se ajustam aos valores reais numa escala relativa. Compreender e utilizar essas métricas permite não apenas avaliar o desempenho dos modelos de forma quantitativa, mas também ajuda na melhoria e na escolha da melhor abordagem de modelagem para tarefas preditivas específicas.
Métricas Adicionais
Além dessas métricas padrão, existem outras, como F1-Score, que combina precisão e recall em uma única métrica que busca um equilíbrio entre as duas. Para regressão, temos também o Erro Absoluto Médio (Mean Absolute Error – MAE), que é a média do valor absoluto dos erros.
Importância de Métricas Apropriadas
A escolha da métrica de avaliação adequada é fundamental para garantir que estamos capturando o aspecto do desempenho que mais valorizamos. Por exemplo, em um modelo que prevê doenças graves, um alto recall pode ser mais desejável do que uma alta precisão. Da mesma forma, um modelo de avaliação de riscos financeiros pode exigir uma análise mais detalhada do R² para entender completamente a variabilidade dos retornos.
Modelos de Seleção com Scikit-Learn
A seleção e validação adequadas de modelos são etapas cruciais no desenvolvimento de modelos de aprendizado de máquina eficazes e confiáveis. Neste artigo, exploraremos duas técnicas amplamente utilizadas para avaliar o desempenho de modelos: o Train Test Split e a Kfold Cross-Validation.
Utilizaremos a biblioteca Scikit-Learn em Python para demonstrar a aplicação dessas técnicas em um exemplo prático usando o conjunto de dados California Housing.
Train Test Split
O Train Test Split é uma abordagem simples e direta para dividir um conjunto de dados em duas partes: uma parte para treinar o modelo e outra parte para testar seu desempenho. Essa divisão nos permite avaliar como o modelo generaliza para dados não vistos durante o treinamento.
Vamos ver um exemplo de como aplicar o Train Test Split usando o Scikit-Learn:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
from sklearn.model_selection import train_test_split from sklearn.datasets import fetch_california_housing from sklearn.ensemble import RandomForestRegressor # Carregando o California Housing dataset california = fetch_california_housing() X, y = california.data, california.target # Dividindo o dataset em 80% treino e 20% teste X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # Criando o modelo de regressão com Random Forest model = RandomForestRegressor() # Treinando o modelo com os dados de treino model.fit(X_train, y_train) # Avaliando o desempenho do modelo com os dados de teste score = model.score(X_test, y_test) print(f"Desempenho do Modelo (R² Score): {score:.2f}") |
Neste exemplo, carregamos o conjunto de dados California Housing usando a função fetch_california_housing()
. Em seguida, dividimos o conjunto de dados em 80% para treinamento e 20% para teste usando a função train_test_split()
. Criamos um modelo de regressão Random Forest e o treinamos com os dados de treinamento. Por fim, avaliamos o desempenho do modelo nos dados de teste usando o R² Score.
Vamos detalhar o processo para ficar claro a cada passo.
1 2 3 |
from sklearn.model_selection import train_test_split from sklearn.datasets import fetch_california_housing from sklearn.ensemble import RandomForestRegressor |
Nesta parte, estamos importando as bibliotecas necessárias do Scikit-Learn:
train_test_split
: função para dividir o conjunto de dados em conjuntos de treinamento e teste.fetch_california_housing
: função para carregar o conjunto de dados California Housing.RandomForestRegressor
: classe para criar um modelo de regressão Random Forest.
1 2 3 |
# Carregando o California Housing dataset california = fetch_california_housing() X, y = california.data, california.target |
Aqui, estamos carregando o conjunto de dados California Housing usando a função fetch_california_housing()
. Esse conjunto de dados contém informações sobre habitações na Califórnia, como população, renda média, preço médio das casas, entre outros.
california.data
contém os recursos (features) do conjunto de dados, que são as variáveis de entrada.california.target
contém os valores alvo (target), que é a variável que queremos prever (preço médio das casas).
1 2 |
# Dividindo o dataset em 80% treino e 20% teste X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) |
Nesta etapa, estamos usando a função train_test_split()
para dividir o conjunto de dados em conjuntos de treinamento e teste.
X
ey
são os recursos e valores alvo do conjunto de dados, respectivamente.test_size=0.2
especifica que 20% dos dados serão usados para teste e os 80% restantes para treinamento.random_state=42
é uma semente aleatória para garantir a reprodutibilidade dos resultados.- A função retorna quatro conjuntos de dados:
X_train
(recursos de treinamento),X_test
(recursos de teste),y_train
(valores alvo de treinamento) ey_test
(valores alvo de teste).
1 2 |
# Criando o modelo de regressão com Random Forest model = RandomForestRegressor() |
Aqui, estamos criando uma instância do modelo de regressão Random Forest usando a classe RandomForestRegressor()
. O Random Forest é um algoritmo de aprendizado de máquina que combina várias árvores de decisão para fazer previsões.
1 2 |
# Treinando o modelo com os dados de treino model.fit(X_train, y_train) |
Nesta linha, estamos treinando o modelo Random Forest usando os dados de treinamento. O método fit()
ajusta o modelo aos dados de treinamento, encontrando os melhores parâmetros para fazer previsões.
1 2 3 |
# Avaliando o desempenho do modelo com os dados de teste score = model.score(X_test, y_test) print(f"Desempenho do Modelo (R² Score): {score:.2f}") |
Por fim, estamos avaliando o desempenho do modelo treinado usando os dados de teste. O método score()
calcula o coeficiente de determinação (R² Score) entre as previsões do modelo e os valores reais dos dados de teste.
- O R² Score varia de 0 a 1, onde 1 indica um ajuste perfeito e 0 indica que o modelo não explica nenhuma variação nos dados.
- Imprimimos o R² Score formatado com duas casas decimais usando a sintaxe de f-string do Python.
Esse código demonstra o fluxo básico de carregamento de dados, divisão em conjuntos de treinamento e teste, criação e treinamento de um modelo de regressão Random Forest e avaliação do desempenho usando o R² Score nos dados de teste.
Kfold Cross-Validation
Embora o Train Test Split seja uma técnica útil, ele pode não fornecer uma estimativa robusta do desempenho do modelo, especialmente quando lidamos com conjuntos de dados pequenos ou quando queremos uma avaliação mais abrangente. É aí que entra a Kfold Cross-Validation.
Na Kfold Cross-Validation, dividimos o conjunto de dados em “k” partes (geralmente 5 ou 10) e realizamos “k” iterações de treinamento e teste. Em cada iteração, uma parte diferente é usada como conjunto de teste, enquanto as partes restantes são usadas para treinamento.
Ao final, temos “k” resultados de desempenho do modelo, que podem ser combinados para obter uma estimativa mais confiável.
Vamos ver um exemplo de como aplicar a Kfold Cross-Validation usando o Scikit-Learn:
1 2 3 4 5 6 7 8 9 10 11 12 |
from sklearn.model_selection import cross_val_score # O modelo RandomForestRegressor já foi instanciado no exemplo anterior # Executando a validação cruzada Kfold com 10 folds scores = cross_val_score(model, X, y, cv=10) # Mostrando o R² Score para cada fold print("R² Score de cada fold:", scores) # E a média dos R² Scores print("Média dos R² Scores:", scores.mean()) |
Vamos explicar o código em detalhes:
1 |
from sklearn.model_selection import cross_val_score |
Nesta linha, estamos importando a função cross_val_score
do módulo model_selection
do Scikit-Learn. Essa função é usada para realizar a validação cruzada Kfold.
1 |
# O modelo RandomForestRegressor já foi instanciado no exemplo anterior |
Este comentário indica que o modelo Random Forest já foi criado anteriormente, provavelmente usando o código model = RandomForestRegressor()
, como vimos no exemplo anterior.
1 2 |
# Executando a validação cruzada Kfold com 10 folds scores = cross_val_score(model, X, y, cv=10) |
Aqui, estamos usando a função cross_val_score()
para realizar a validação cruzada Kfold com 10 folds.
model
é o modelo Random Forest que já foi instanciado anteriormente.X
são os recursos (features) do conjunto de dados completo.y
são os valores alvo (target) do conjunto de dados completo.cv=10
especifica o número de folds (dobras) a serem usados na validação cruzada. Neste caso, estamos usando 10 folds.
A validação cruzada Kfold divide o conjunto de dados em 10 partes (folds) e realiza 10 iterações de treinamento e teste. Em cada iteração, uma parte diferente é usada como conjunto de teste, enquanto as outras 9 partes são usadas para treinamento. O modelo é treinado e avaliado em cada iteração, e no final, temos 10 pontuações de desempenho (R² Scores) do modelo.
1 2 |
# Mostrando o R² Score para cada fold print("R² Score de cada fold:", scores) |
Nesta linha, estamos imprimindo os R² Scores obtidos para cada fold da validação cruzada. A variável scores
é um array que contém os R² Scores de cada iteração.
1 2 |
# E a média dos R² Scores print("Média dos R² Scores:", scores.mean()) |
Por fim, estamos calculando e imprimindo a média dos R² Scores obtidos na validação cruzada. A função mean()
é usada para calcular a média dos valores no array scores
.
A validação cruzada Kfold é uma técnica mais robusta para avaliar o desempenho de um modelo, pois fornece uma estimativa mais confiável de como o modelo se generaliza para dados não vistos. Ao realizar várias iterações de treinamento e teste com diferentes subconjuntos dos dados, obtemos uma avaliação mais abrangente do desempenho do modelo.
Neste exemplo, estamos usando a validação cruzada Kfold com 10 folds para avaliar o desempenho do modelo Random Forest. Os R² Scores obtidos em cada fold nos dão uma ideia da consistência do desempenho do modelo, enquanto a média dos R² Scores fornece uma estimativa geral do desempenho esperado do modelo em dados não vistos.
Interpretação e Seleção do Método
Exploramos duas técnicas importantes para a seleção e validação de modelos: o Train Test Split e a Kfold Cross-Validation. O Train Test Split é uma abordagem simples para avaliar o desempenho do modelo em um subconjunto específico de dados, enquanto a Kfold Cross-Validation fornece uma avaliação mais robusta, considerando diferentes subconjuntos dos dados.
A escolha entre essas técnicas depende de fatores como o tamanho do conjunto de dados, a diversidade dos dados e os recursos computacionais disponíveis. É importante considerar esses aspectos ao selecionar a técnica mais adequada para o seu problema.
O Scikit-Learn oferece uma implementação fácil e eficiente dessas técnicas, permitindo que os desenvolvedores avaliem e comparem diferentes modelos de maneira rápida e confiável.
Ao utilizar essas técnicas de seleção e validação de modelos, podemos garantir que nossos modelos de aprendizado de máquina sejam robustos, generalizáveis e capazes de fornecer resultados precisos e confiáveis em dados não vistos anteriormente.
Conclusão
Este artigo cobriu as bases do machine learning usando Scikit-Learn em Python. Recomendamos a documentação oficial e tutoriais online para continuar sua jornada de aprendizado.
Incluímos diversos exemplos de código Python para ilustrar os conceitos e técnicas discutidos. Agora é a sua vez de explorar o mundo do machine learning e praticar com o Scikit-Learn. Boa sorte!