Blog

Postado em em 2 de maio de 2023

Seleção de Recursos em Ciência de Dados – (Feature Selection)

Hoje eu quero te mostrar algumas formas de fazer a seleção de recursos em ciência de dados para trabalhar de forma eficiente!

Caso prefira esse conteúdo no formato de vídeo-aula, assista ao vídeo abaixo ou acesse o nosso canal do YouTube!

Para receber por e-mail o(s) arquivo(s) utilizados na aula, preencha:

Fala Impressionadores! Você já ouviu falar em seleção de recursos em projetos de Ciência de Dados? Vou te mostrar as seguintes técnicas avançadas para seleção de features:

  • Remoção de features com baixa variância
  • Select from model (seleção por meio de um modelo)
  • RFE (Recursive Features Elimination).

E aí, vamos aprender como fazer a seleção de recursos (feature selection) em projetos de ciência de dados?

O ponto principal desta aula é que, se na nossa base de dados tiver um elevado número de informações, vamos ter que usar técnicas para priorizar qual informação é mais relevante para o modelo conseguir ser generalizável.

Seleção de Recursos (Feature Selection)

Este é o processo de selecionar as colunas (recursos / features) mais importantes para o modelo, ele vai eliminar tudo que for desnecessário, porém, quanto mais recursos:

  • Maior o tempo de processamento
  • Maior a chance de o modelo sofrer overfitting (não ser generalizável)
  • Adicionar ruído devido a alguma feature
  • Mais informações para monitorar em produção (aumento do custo de monitoramento)

O próprio Scikit-Learn já oferece ferramentas para fazermos a seleção de features:

https://scikit-learn.org/stable/modules/feature_selection.html

Podemos fazer a seleção das features:

  • Selecionando aquelas mais relacionadas ao target por meio de métodos estatísticos
  • Utilizando modelos que já possuem métodos de penalização e seleção de features
  • Separando subsets contendo parte das features e testando seu desempenho no próprio modelo

Por exemplo, pego metade das features e vejo o resultado, depois pego metade + 1 e assim sucessivamente…

Vamos começar falando da remoção de features com baixa variância, segue abaixo a biblioteca:

https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.VarianceThreshold.html#sklearn.feature_selection.VarianceThreshold

Variância:

Mede o quanto os dados estão dispersos em relação à média

  • Se a variância for zero, todos os registros possuem o mesmo valor. Então podemos começar eliminando todas as colunas com o mesmo valor, afinal, se os valores são iguais isso não vai fazer diferença na previsão e vão apenas tornar o seu modelo mais lento e mais trabalhoso de fazer.
  • É importante saber que o desvio padrão (std) é a raiz quadrada da variância.
  • O VarianceThreshold vai remover todos os recursos em que a variância não chegue até um certo limite, então o que ele vai fazer é estabelecer um valor para a variância, considerando os valores, com uma diferença maior que 15%, por exemplo. Por padrão ele remove tudo que a variância for igual a zero

Analisa apenas os recursos (X), sem considerar o target (y)

  • Pode ser usado em aprendizado não supervisionado

Exemplo prático

# Sendo o dataset

import pandas as pd
Seleção de Recursos em Ciência de Dados
verificando a base
# Podemos visualizar as informações estatísticas

X.describe()
Seleção de Recursos em Ciência de Dados
informações estatísticas

Observe que a coluna 3 não está trazendo nenhuma informação, então ela será diretamente eliminada.

Para executar basta seguir os passos da biblioteca:

# Importando o VarianceThreshold

from sklearn.feature_selection import VarianceThreshold

# Criando o seletor

selector = VarianceThreshold()

# Fazendo o fit com os dados

selector = selector.fit(X)

# Fazendo a transformação

selector.transform(X)
transformação
transformação
# Criando o seletor com limite de 0.15

selector = VarianceThreshold(threshold=0.15)

# Fazendo o fit com os dados

selector = selector.fit(X)

# Fazendo a transformação

selector.transform(X)
Seleção de Recursos em Ciência de Dados
colunas com a variância acima de 15%

Neste modelo só mantemos as colunas de índice 1 e 2 por terem valores relevantes, também podemos verificar qual a variância, se o desvio padrão é o quadrado da variância, podemos fazer o cálculo e verificar os valores:

# Visualizando a variância

(X.std())**2

verificando a variância
verificando a variância

Observe que só foi mantido as variâncias que estavam acima de 15%.

2ª Técnica – SelectKBest

Biblioteca:

https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectKBest.html#sklearn.feature_selection.SelectKBest

Vamos analisar cada uma das features de forma separada, considerando sua relação com o target por meio de testes estatísticos e selecionar os K recursos de maior pontuação (também podemos selecionar um percentual dos recursos, considerar a taxa de falsos positivos / falsos negativos ou até criar nossa própria estratégia de seleção)

Precisamos selecionar qual vai ser a função estatística usada, essa função irá retornar uma pontuação para cada um dos recursos.

Neste modelo estamos olhando cada features de forma isolada, este é um ponto muito importante de destacar!

Métodos baseados no teste F vão analisar o grau de dependência linear entre duas variáveis aleatórias, temos diversos métodos disponíveis nesta biblioteca:

  • Regressão: f_regression
  • Classificação: f_classif

Os métodos de informação mútua conseguem analisar qualquer tipo de dependência estatística, mas precisam de mais dados para serem mais precisos, eles também trabalham bem com dados esparsos.

  • Regressão: mutual_info_regression
  • Classificação: mutual_info_classif

Métodos quadráticos só podem ser aplicados para valores não negativos:

  • Classificação: chi2 (também serve para trabalharmos com dados esparsos)

“Aviso Cuidado para não usar uma função de pontuação de regressão com um problema de classificação, pois vai te gerar um resultado, porém, você obterá resultados inúteis.”

Exemplo prático:

# Importando o dataset iris

from sklearn.datasets import load_iris

# Importando X e y

X, y = load_iris(return_X_y=True,as_frame=True)

# Visualizando X

X.head(3)
verificando a base
verificando a base
# Importando o SelectKBest

from sklearn.feature_selection import SelectKBest

# Criando o nosso seletor

seletor = SelectKBest(k=2)

# Fazendo o fit com os dados

seletor.fit(X,y)

SelectKBest(k=2)

# Visualizando os scores

seletor.scores_

array([ 119.26450218,   49.16004009, 1180.16118225,  960.0071468 ])

Neste caso quanto maior a pontuação mais essa coluna é relacionada a nossa variável target. Vamos visualizar os dados:

# Visualizando graficamente a distribuição dos dados

import seaborn as sns

import matplotlib.pyplot as plt

fig, ax = plt.subplots(ncols=4,figsize=(16,6))

sns.kdeplot(X.iloc[:,0],hue=y,ax=ax[0])

sns.kdeplot(X.iloc[:,1],hue=y,ax=ax[1])

sns.kdeplot(X.iloc[:,2],hue=y,ax=ax[2])

sns.kdeplot(X.iloc[:,3],hue=y,ax=ax[3])

plt.show()
Visualizando graficamente
Visualizando graficamente

Veja que a partir da terceira imagem fica muito fácil classificar os dados, a distinção entre as colunas é muito maior e isso indica maior capacidade desta coluna de separar e classificar os dados.

# Visualizando os valores gerados

seletor.get_feature_names_out()

array(['petal length (cm)', 'petal width (cm)'], dtype=object)

Usando o seletor vamos extrair as colunas que melhor separam e classificam os dados.

3ª Forma – SelectFromModel

https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectFromModel.html#sklearn.feature_selection.SelectFromModel

Neste exemplo também é feito uma seleção dos recursos baseado em algum modelo utilizando algoritmos que já possuem cálculos da importância das features (como coef_ e feature_importances_), porém não é feito de forma recursiva (melhorando o tempo de processamento)

Quanto melhor for o modelo que usarmos no seletor, melhor será nossa seleção (porém aumenta o tempo de processamento)

Podemos selecionar tanto o número de features (max_features) quanto o coeficiente de corte (threshold).

Neste caso vamos utilizar a Árvore de Decisão para calcular a importância de cada recurso

https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html#sklearn.tree.DecisionTreeClassifier

# Importando a Árvore de Decisão

from sklearn.tree import DecisionTreeClassifier

# Criando o classificador

clf = DecisionTreeClassifier(random_state=0)

# Fazendo o fit com os dados

clf = clf.fit(X,y)

# Verificando a importância de cada uma das features

clf.feature_importances_
percentuais
percentuais

Observe que a última features é a que tem maior importância para os dados, quando criamos a árvore de decisão e vamos abrindo os valores esse é o primeiro que irá aparecer.

# Somando essas importâncias

clf.feature_importances_.sum()

1.0

A soma dos percentuais é sempre 1 por isso, na imagem acima temos a importância de cada features considerando o todo como 1.

Agora vamos utilizar o SelectFromModel

Para usar o SelectFromModel vamos precisar de um estimador, observe que é umas das primeiras informações da biblioteca.

# Importando o SelectFromModel

from sklearn.feature_selection import SelectFromModel

# Selecionando a árvore de decisão como estimador

estimator = DecisionTreeClassifier(random_state=0)

# Criando o seletor

seletor = SelectFromModel(estimator,threshold=0,max_features=2)

# Fazendo o fit com os dados

seletor = seletor.fit(X,y)

# Visualizando as features selecionadas

seletor.get_feature_names_out()

array(['petal length (cm)', 'petal width (cm)'], dtype=object)

# Visualizando a importância dos recursos

seletor.estimator_.feature_importances_
percentuais
percentuais

O percentual também funciona para a árvore de decisão.

# Tirando a média

seletor.estimator_.feature_importances_.mean()

0.25

# Visualizando o threshold

seletor.threshold_

0.0

RFE (Recursive feature elimination)

https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.RFE.html#sklearn.feature_selection.RFE

Esta aplicação começa treinando o estimador na base completa, depois vai eliminando recursivamente os recursos até chegar na quantidade de recursos desejados, ou seja, ele elimina o menos importante, lê novamente a base, elimina novamente o menos importante até chegar nos recursos mais desejados.

O processo que ele executa basicamente é:

  • Faz o fit do modelo com a base completa
  • Elimina aquele recurso com menor importância (menor coeficiente)
  • Faz um novo fit agora com a nova base
  • Repete os passos 2 e 3 até chegar no número de recursos desejados

Para grandes bases de dados, o tempo de processamento aumenta muito, então, vai utilizar um estimador externo que atribui pesos aos recursos.

Vamos utilizar algoritmos que já possuem cálculos da importância das features (como coef_ e feature_importances_)

Se quisermos utilizar estimadores que não possuem o cálculo da importância das features, podemos utilizar o SFS (SequentialFeatureSelector)

Cuidado com o tempo de processamento muito grande para não inviabilizar o seu processo!

Exemplo prático

# Importando o RFE

from sklearn.feature_selection import RFE

Podemos utilizar o mesmo estimador visto anteriormente!

# Criando nosso seletor

selector = RFE(estimator, n_features_to_select=2, step=1)

# Fazendo o fit com os dados

selector = selector.fit(X,y)

# Verificando o ranking

selector.ranking_

array([3, 2, 1, 1])

“As features selecionadas (ou seja, as mais bem estimadas) recebem classificação 1”

Conclusão – Seleção de Recursos em Projetos de Ciência de Dados

Nesta aula passamos por alguns métodos se seleção de features que podem ajudar nos seus projetos de ciências de dados.

Recomendo que leiam as bibliotecas e que escolham a que faz mais sentido para o seu projeto, lembrando de considerar sempre o tempo de execução com métodos mais complexos para não inviabilizar o projeto.

Eu fico por aqui! Até a próxima! Um abraço,

Hashtag Treinamentos

Para acessar outras publicações de Ciência de Dados, clique aqui!


Quer aprender mais sobre Python com um minicurso básico gratuito?

Quer sair do zero no Python e virar uma referência na sua empresa? Inscreva-se agora mesmo no Python Impressionador