Fundamentos do Machine Learning com Python
Introdução à Engenharia e Seleção de Features
Aprenda sobre introdução à engenharia e seleção de features
Introdução à Engenharia e Seleção de Features
Olá, futuros especialistas em Machine Learning! 👋 Nesta aula, vamos mergulhar em dois pilares cruciais para o sucesso de qualquer projeto de Machine Learning: a Engenharia de Features (Feature Engineering) e a Seleção de Features (Feature Selection).
Imagine que seus dados são a matéria-prima e seu modelo de ML é o chef. A qualidade do prato final (o desempenho do modelo) não depende apenas da receita (o algoritmo), mas também da qualidade e do preparo dos ingredientes. É exatamente isso que a Engenharia e a Seleção de Features nos ajudam a fazer: transformar dados brutos em ingredientes de alta qualidade para nossos modelos. 🚀
1. Introdução: Por que Features são tão Importantes?
No Machine Learning, "features" (ou características) são as variáveis de entrada que um modelo usa para fazer previsões. Elas são a representação numérica dos dados que descrevem cada observação no seu dataset.
A performance de um modelo de Machine Learning é altamente dependente da qualidade e da relevância das features que ele recebe. Modelos ruins podem ser salvos por boas features, enquanto modelos avançados podem falhar miseravelmente com features inadequadas.
- Engenharia de Features (Feature Engineering): É a arte e a ciência de criar novas features a partir de dados brutos ou existentes para melhorar o desempenho do modelo. É um processo criativo e iterativo, muitas vezes impulsionado pelo conhecimento do domínio.
- Seleção de Features (Feature Selection): É o processo de selecionar um subconjunto das features mais relevantes e úteis para o modelo, descartando as irrelevantes ou redundantes.
Ambos os processos são vitais para:
- ✅ Melhorar a performance preditiva do modelo.
- ✅ Reduzir o overfitting (sobreajuste).
- ✅ Diminuir o tempo de treinamento do modelo.
- ✅ Aumentar a interpretabilidade do modelo.
- ✅ Lidar com a maldição da dimensionalidade (curse of dimensionality).
Vamos explorar cada um em detalhes!
2. Engenharia de Features (Feature Engineering)
A Engenharia de Features é o processo de usar o conhecimento do domínio para criar features que tornam os algoritmos de Machine Learning mais eficazes. É a etapa onde transformamos dados brutos em informações mais úteis para o modelo.
Por que fazer Engenharia de Features?
- Melhorar a Representação dos Dados: Algoritmos de ML funcionam melhor com dados numéricos e bem estruturados. A engenharia de features ajuda a transformar dados categóricos, textuais ou de tempo em formatos utilizáveis.
- Capturar Relações Complexas: Criar features que representam interações entre variáveis ou padrões não lineares pode ajudar o modelo a aprender relações mais complexas nos dados.
- Lidar com Dados Ausentes/Ruidosos: Embora não seja o foco principal, a engenharia de features pode ser combinada com técnicas de tratamento de dados ausentes ou ruidosos.
Técnicas Comuns de Engenharia de Features
2.1. Codificação de Variáveis Categóricas (Categorical Encoding)
Variáveis categóricas (como "cor": vermelho, azul, verde) precisam ser convertidas em representações numéricas.
- One-Hot Encoding: Cria uma nova coluna binária para cada categoria única. É ideal para categorias nominais (sem ordem).
- Exemplo:
cor->cor_vermelho,cor_azul,cor_verde.
- Exemplo:
- Label Encoding: Atribui um número inteiro único a cada categoria. Adequado para categorias ordinais (com ordem, e.g.,
pequeno,médio,grande).
Exemplo com scikit-learn:
import pandas as pd
from sklearn.preprocessing import OneHotEncoder, LabelEncoder
# Dados de exemplo
data = {
'cor': ['vermelho', 'azul', 'verde', 'vermelho', 'azul'],
'tamanho': ['P', 'M', 'G', 'P', 'M'],
'preço': [10, 15, 20, 12, 18]
}
df = pd.DataFrame(data)
print("DataFrame Original:")
print(df)
print("-" * 30)
# --- One-Hot Encoding para 'cor' ---
ohe = OneHotEncoder(handle_unknown='ignore', sparse_output=False)
# Ajusta e transforma a coluna 'cor'
encoded_cols = ohe.fit_transform(df[['cor']])
# Cria um DataFrame com as novas colunas
ohe_df = pd.DataFrame(encoded_cols, columns=ohe.get_feature_names_out(['cor']))
print("One-Hot Encoded (cor):")
print(ohe_df)
print("-" * 30)
# --- Label Encoding para 'tamanho' (se assumirmos uma ordem P < M < G) ---
# É importante definir a ordem se ela for significativa
size_mapping = {'P': 0, 'M': 1, 'G': 2}
df['tamanho_encoded'] = df['tamanho'].map(size_mapping)
print("Label Encoded (tamanho):")
print(df[['tamanho', 'tamanho_encoded']])2.2. Binning / Discretização (para Variáveis Numéricas)
Converte variáveis numéricas contínuas em variáveis categóricas (bins ou intervalos). Pode ajudar a lidar com outliers e capturar relações não lineares.
- Exemplo:
idade(0-10, 11-20, 21-30, etc.).
Exemplo com scikit-learn:
import numpy as np
from sklearn.preprocessing import KBinsDiscretizer
# Dados de exemplo
idades = np.array([5, 12, 23, 35, 42, 50, 61, 75, 88]).reshape(-1, 1)
# Discretização em 3 bins usando quantis (bins de tamanhos iguais)
# strategy='uniform': bins de largura igual
# strategy='quantile': bins com o mesmo número de amostras
# strategy='kmeans': bins baseados em centroids de K-Means
kbd = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='quantile')
idades_binned = kbd.fit_transform(idades)
print("Idades Originais:")
print(idades.flatten())
print("\nIdades Discretizadas (3 bins por quantil):")
print(idades_binned.flatten())2.3. Features Polinomiais e de Interação
- Features Polinomiais: Criam novas features elevando as features existentes a potências (e.g.,
x,x^2,x^3). Isso permite que modelos lineares capturem relações não lineares. - Features de Interação: Criam novas features multiplicando duas ou mais features existentes (e.g.,
x1 * x2). Isso permite que o modelo capture como as features interagem entre si.
Exemplo com scikit-learn:
from sklearn.preprocessing import PolynomialFeatures
import numpy as np
# Dados de exemplo (duas features)
X = np.array([[2, 3],
[0, 1],
[4, 0]])
print("Features Originais (X):")
print(X)
print("-" * 30)
# Criar features polinomiais de grau 2
# include_bias=False para não adicionar a coluna de uns (intercept)
poly = PolynomialFeatures(degree=2, include_bias=False)
X_poly = poly.fit_transform(X)
print("Features Polinomiais (grau 2):")
print(X_poly)
print("Nomes das novas features:", poly.get_feature_names_out(['feature1', 'feature2']))
# As colunas são: feature1, feature2, feature1^2, feature1*feature2, feature2^22.4. Features de Data e Hora (Datetime Features)
Extrair informações úteis de colunas de data e hora é crucial em muitos problemas.
- Exemplos:
ano,mês,dia do mês,dia da semana,hora,minuto,semana do ano,é_fim_de_semana,diferença_dias_desde_evento.
Exemplo com pandas:
import pandas as pd
# Dados de exemplo com timestamp
df_time = pd.DataFrame({
'timestamp': pd.to_datetime(['2023-01-15 10:30:00', '2023-01-16 14:00:00', '2023-02-01 08:00:00'])
})
print("DataFrame Original (timestamp):")
print(df_time)
print("-" * 30)
# Extrair features de data/hora
df_time['ano'] = df_time['timestamp'].dt.year
df_time['mes'] = df_time['timestamp'].dt.month
df_time['dia_do_mes'] = df_time['timestamp'].dt.day
df_time['dia_da_semana'] = df_time['timestamp'].dt.dayofweek # 0=Segunda, 6=Domingo
df_time['hora'] = df_time['timestamp'].dt.hour
df_time['eh_fim_de_semana'] = df_time['timestamp'].dt.dayofweek.isin([5, 6]).astype(int)
print("DataFrame com Features de Data/Hora:")
print(df_time)2.5. Outras Técnicas (Mencionar)
- Agregação de Features: Criar features como média, soma, contagem, mínimo, máximo de grupos de dados.
- Features Baseadas em Texto: Para dados textuais, técnicas como TF-IDF (Term Frequency-Inverse Document Frequency) ou Word Embeddings (Word2Vec, GloVe) convertem texto em vetores numéricos.
- Transformações Matemáticas: Aplicar logaritmo, raiz quadrada, etc., para normalizar distribuições ou estabilizar variâncias.
3. Seleção de Features (Feature Selection)
A Seleção de Features é o processo de escolher um subconjunto das features mais relevantes do seu dataset. Isso é fundamental para:
- Reduzir Overfitting: Menos features irrelevantes ou redundantes ajudam o modelo a generalizar melhor.
- Melhorar a Velocidade de Treinamento: Menos dados para processar significam treinamento mais rápido.
- Reduzir a Complexidade do Modelo: Modelos mais simples são mais fáceis de entender e manter.
- Melhorar a Interpretabilidade: Focar nas features mais importantes torna o modelo mais transparente.
- Evitar a Maldição da Dimensionalidade: Em datasets com muitas features, a seleção ajuda a mitigar problemas de esparsidade e aumento do espaço de busca.
Métodos de Seleção de Features
Existem três categorias principais de métodos de seleção de features:
3.1. Métodos de Filtro (Filter Methods)
Avaliam a relevância das features com base em suas propriedades estatísticas (correlação, chi-quadrado, ANOVA) em relação à variável alvo, independentemente do modelo de Machine Learning.
- Vantagens: Rápidos, computacionalmente baratos, independentes do modelo.
- Desvantagens: Não consideram a interação entre features ou o desempenho do modelo.
Exemplos de Métricas:
- Correlação: Para features numéricas e alvo numérico.
- Teste Qui-Quadrado (
chi2): Para features categóricas e alvo categórico. - ANOVA (
f_classif): Para features numéricas e alvo categórico.
Exemplo com scikit-learn (SelectKBest):
from sklearn.feature_selection import SelectKBest, f_classif, chi2
from sklearn.datasets import load_iris
import pandas as pd
import numpy as np
# Carregar dataset Iris para exemplo (classificação)
iris = load_iris()
X, y = iris.data, iris.target
feature_names = iris.feature_names
# Criar um DataFrame para melhor visualização
df_iris = pd.DataFrame(X, columns=feature_names)
df_iris['target'] = y
print("DataFrame Iris Original (primeiras 5 linhas):")
print(df_iris.head())
print("-" * 30)
# --- Usando f_classif para features numéricas e alvo categórico ---
# Selecionar as 2 melhores features usando f_classif
selector_f_classif = SelectKBest(f_classif, k=2)
X_new_f_classif = selector_f_classif.fit_transform(X, y)
print("Features selecionadas por f_classif (as 2 melhores):")
print(np.array(feature_names)[selector_f_classif.get_support()])
print("Shape dos dados transformados:", X_new_f_classif.shape)
print("-" * 30)
# --- Exemplo com chi2 (requer features não-negativas, idealmente categóricas) ---
# Vamos simular features categóricas para o chi2 discretizando uma das features numéricas
# Nota: chi2 é mais adequado para features categóricas.
# Aqui, discretizamos 'sepal length (cm)' para ilustrar.
from sklearn.preprocessing import KBinsDiscretizer
kbd = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='uniform')
X_categorical = kbd.fit_transform(X[:, 0].reshape(-1, 1)) # Apenas uma feature para simplificar
selector_chi2 = SelectKBest(chi2, k=1)
X_new_chi2 = selector_chi2.fit_transform(X_categorical, y)
print("Features selecionadas por chi2 (simulando categóricas):")
# Como usamos apenas uma feature discretizada, o output será essa mesma feature.
# Em um cenário real, você aplicaria isso a múltiplas features categóricas.
print("Score Chi2 para a feature discretizada:", selector_chi2.scores_)
print("Shape dos dados transformados:", X_new_chi2.shape)3.2. Métodos Wrapper (Wrapper Methods)
Usam um algoritmo de Machine Learning para avaliar a performance de diferentes subconjuntos de features. O modelo é treinado e testado repetidamente com diferentes combinações de features.
- Vantagens: Podem encontrar subconjuntos de features que interagem bem com o modelo, geralmente resultam em melhor performance.
- Desvantagens: Computacionalmente caros, podem ser lentos em datasets grandes.
Exemplos:
- Recursive Feature Elimination (RFE): Treina um modelo, remove a feature menos importante, repete até atingir o número desejado de features.
Exemplo com scikit-learn (RFE):
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
import numpy as np
# Carregar dataset Iris
iris = load_iris()
X, y = iris.data, iris.target
feature_names = iris.feature_names
# Usar Regressão Logística como estimador
estimator = LogisticRegression(max_iter=200)
# Selecionar as 2 melhores features usando RFE
selector_rfe = RFE(estimator=estimator, n_features_to_select=2, step=1)
selector_rfe.fit(X, y)
print("Rankings das features por RFE (1 = selecionado):")
print(dict(zip(feature_names, selector_rfe.ranking_)))
print("\nFeatures selecionadas por RFE:")
print(np.array(feature_names)[selector_rfe.support_])
print("Shape dos dados transformados:", selector_rfe.transform(X).shape)3.3. Métodos Embarcados (Embedded Methods)
Realizam a seleção de features como parte do processo de treinamento do próprio algoritmo de Machine Learning.
- Vantagens: Combinam a precisão dos métodos wrapper com a eficiência dos métodos de filtro.
- Desvantagens: A seleção é específica do modelo usado.
Exemplos:
- Regularização L1 (Lasso): Modelos lineares com regularização L1 tendem a reduzir os coeficientes de features menos importantes a zero, efetivamente selecionando features.
- Modelos Baseados em Árvores (Random Forest, Gradient Boosting): Podem fornecer uma medida de importância das features.
Exemplo com scikit-learn (SelectFromModel com Lasso):
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegressionCV # LogisticRegression com validação cruzada para Lasso
from sklearn.datasets import load_iris
import numpy as np
# Carregar dataset Iris
iris = load_iris()
X, y = iris.data, iris.target
feature_names = iris.feature_names
# Usar LogisticRegressionCV com penalidade L1 (Lasso) como estimador
# cv=5: 5-fold cross-validation para encontrar o melhor C (inverso da força de regularização)
# solver='liblinear' ou 'saga' suporta L1
estimator_l1 = LogisticRegressionCV(Cs=10, penalty='l1', solver='liblinear', cv=5, random_state=42, max_iter=500)
estimator_l1.fit(X, y)
# Selecionar features com base nos coeficientes do modelo L1
# threshold='1e-5*mean' seleciona features cujos coeficientes são maiores que um pequeno múltiplo da média.
# Ou podemos usar um número fixo de features, como k=2.
sfm = SelectFromModel(estimator_l1, threshold='mean') # Seleciona features com coeficientes > média dos coeficientes
X_new_l1 = sfm.fit_transform(X, y)
print("Coeficientes do modelo L1 para cada feature:")
print(dict(zip(feature_names, estimator_l1.coef_[0]))) # Exemplo para a primeira classe
print("\nFeatures selecionadas por SelectFromModel (com base em L1):")
print(np.array(feature_names)[sfm.get_support()])
print("Shape dos dados transformados:", X_new_l1.shape)4. Integração: Onde a Engenharia e a Seleção de Features se Encontram?
Em um pipeline de Machine Learning, a Engenharia de Features e a Seleção de Features geralmente são etapas sequenciais e complementares:
- Pré-processamento de Dados: Tratamento de valores ausentes, escalonamento.
- Engenharia de Features: Criação de novas features a partir das existentes.
- Seleção de Features: Escolha do melhor subconjunto de features (originais e recém-criadas).
- Treinamento do Modelo: Uso das features selecionadas para treinar o modelo.
É comum usar Pipeline do scikit-learn para orquestrar essas etapas de forma eficiente e evitar vazamento de dados (data leakage).
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_breast_cancer
# Carregar um dataset de exemplo
cancer = load_breast_cancer()
X, y = cancer.data, cancer.target
feature_names = cancer.feature_names
# Dividir os dados em treino e teste
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# Criar um pipeline que inclui:
# 1. Escalonamento das features
# 2. Criação de features polinomiais
# 3. Seleção das 10 melhores features
# 4. Treinamento de um modelo de Regressão Logística
pipeline = Pipeline([
('scaler', StandardScaler()),
('poly', PolynomialFeatures(degree=2, include_bias=False)),
('selector', SelectKBest(f_classif, k=10)), # Seleciona 10 melhores features
('model', LogisticRegression(max_iter=1000, solver='liblinear'))
])
# Treinar o pipeline
pipeline.fit(X_train, y_train)
# Fazer previsões no conjunto de teste
y_pred = pipeline.predict(X_test)
# Avaliar o modelo
accuracy = accuracy_score(y_test, y_pred)
print(f"Acurácia do modelo com pipeline: {accuracy:.4f}")
# Para ver as features selecionadas (um pouco mais complexo com pipeline)
# Você precisaria acessar o passo 'selector' e então 'get_support()'
# e mapear de volta para os nomes das features após PolynomialFeatures.
# Por simplicidade, vamos apenas mostrar a acurácia.5. Exercícios Conceituais
Para consolidar seu aprendizado, reflita sobre as seguintes questões:
- Um dataset possui uma coluna
data_nascimento. Que tipo de features você poderia criar a partir dela usando Engenharia de Features para um modelo que prevê a probabilidade de compra de um produto? - Você está construindo um modelo de classificação e tem 100 features. O tempo de treinamento é muito longo e o modelo está overfitando. Que tipo de método de Seleção de Features você consideraria e por quê?
- Qual a principal diferença entre os métodos de filtro e os métodos wrapper na Seleção de Features? Quando você usaria um em vez do outro?
- Considere um dataset com features
rendaeanos_experiencia. Se você suspeita que o impacto derendana variável alvo muda dependendo deanos_experiencia, que tipo de feature engenharia você poderia aplicar?
6. Resumo e Próximos Passos
Nesta aula, exploramos a importância vital da Engenharia e Seleção de Features no Machine Learning.
- Engenharia de Features é a arte de criar novas features a partir de dados brutos para melhorar a performance do modelo. Vimos exemplos como One-Hot Encoding, Binning, Features Polinomiais e extração de informações de datas.
- Seleção de Features é o processo de escolher o subconjunto mais relevante de features para reduzir a complexidade, melhorar a velocidade e prevenir overfitting. Discutimos os métodos de Filtro (e.g.,
SelectKBest), Wrapper (e.g.,RFE) e Embarcados (e.g.,SelectFromModelcom L1).
Lembre-se: "Garbage In, Garbage Out" — a qualidade das suas features impacta diretamente a qualidade do seu modelo. Investir tempo na Engenharia e Seleção de Features é um dos retornos mais altos que você pode ter em um projeto de Machine Learning.
No próximo módulo, começaremos a explorar os algoritmos de Machine Learning em si, como Regressão Linear e Logística, onde aplicaremos muitos dos conceitos de pré-processamento e engenharia de features que aprendemos até agora.
Até lá! 🎓