Marcos Kalinowski e Tatiana Escovedo
Para voltar a atividade 2 link text https://colab.research.google.com/drive/1MCCMFdsGaXIQjdAYpFrqTyw0bvtXhuYb#scrollTo=3UTQu_c6g3Ut
# Imports
import pandas as pd
import numpy as np
from numpy import set_printoptions
import matplotlib.pyplot as plt
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import ExtraTreesClassifier
# Novos imports
from sklearn.feature_selection import SelectKBest # para a Seleção Univariada
from sklearn.feature_selection import f_classif # para o teste ANOVA da Seleção Univariada
from sklearn.feature_selection import RFE # para a Eliminação Recursiva de Atributos
# importando dados de um arquvo crv para dataframe vinhoreddados : VINHO TINTO
# url a importar
url_dados_wred = 'https://wdz.eng.br/Curso/Atividade2/arquivos/winequality-red.csv'
#rotulos dos atributos do dadtaset
atributosred = ['acidezfixa', 'acidezvolátil', 'ácidocítrico', 'acucarresidual', 'cloretos', 'dióxidoenxofrelivre', 'dióxidoenxofretotal', 'densidade', 'pH', 'sulfatos', 'alcool']
#carga do dataset
vinhoreddados = pd.read_csv(url_dados_wred, delimiter=';')
# Carrega arquivo csv usando Pandas usando uma URL
# Informa a URL de importação do dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv"
# Informa o cabeçalho das colunas
colunas = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
# Lê o arquivo utilizando as colunas informadas
dataset = pd.read_csv(url, names=colunas, skiprows=0, delimiter=',')
# separando os atributos e a classe do dataset
array = vinhoreddados.values
X = array[:,0:8]
y = array[:,8]
# A semente (seed) pode ser qualquer número, e garante que os resultados possam ser reproduzidos de forma idêntica toda vez que o script for rodado.
# Isto é muito importante quando trabalhamos com modelos ou métodos que utilizam de algum tipo de aleatoriedade.
seed = 7
print (X)
print (y)
[[7.400e+00 7.000e-01 0.000e+00 ... 1.100e+01 3.400e+01 9.978e-01] [7.800e+00 8.800e-01 0.000e+00 ... 2.500e+01 6.700e+01 9.968e-01] [7.800e+00 7.600e-01 4.000e-02 ... 1.500e+01 5.400e+01 9.970e-01] ... [6.300e+00 5.100e-01 1.300e-01 ... 2.900e+01 4.000e+01 9.957e-01] [5.900e+00 6.450e-01 1.200e-01 ... 3.200e+01 4.400e+01 9.955e-01] [6.000e+00 3.100e-01 4.700e-01 ... 1.800e+01 4.200e+01 9.955e-01]] [3.51 3.2 3.26 ... 3.42 3.57 3.39]
https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectKBest.html
A função SelectKBest() pode ser usada com diversos testes estatísticos para selecionar os atributos. Vamos usar o teste ANOVA F-value e selecionar os 4 melhores atributos que podem ser usados como variáveis preditoras.
Neste contexto, o teste ANOVA F-value estima o quanto cada característica de X é dependente da classe y.
Para saber mais: https://www.statisticshowto.com/probability-and-statistics/f-statistic-value-test/
# Função para seleção de atributos
best_var = SelectKBest(score_func=f_classif, k=4)
# Executa a função de pontuação em (X, y) e obtém os atributos selecionados
fit = best_var.fit(X, y)
# Reduz X para os atributos selecionados
features = fit.transform(X)
# Resultados
print('\nNúmero original de atributos:', X.shape[1])
print('\nNúmero reduzido de atributos:', features.shape[1])
# Exibe os atributos orginais
print("\nAtributos Originais:", vinhoreddados.columns[0:8])
# Exibe as pontuações de cada atributos e os 4 escolhidas (com as pontuações mais altas): fixed acidity' 'citric acid' 'chlorides' 'density'.
set_printoptions(precision=3) # 3 casas decimais
print("\nScores dos Atributos Originais:", fit.scores_)
print("\nAtributos Selecionados:", best_var.get_feature_names_out(input_features=vinhoreddados.columns[0:8]))
# Imprime o dataset apenas com as colunas selecionadas
print("\n", features)
Número original de atributos: 8 Número reduzido de atributos: 4 Atributos Originais: Index(['fixed acidity', 'volatile acidity', 'citric acid', 'residual sugar', 'chlorides', 'free sulfur dioxide', 'total sulfur dioxide', 'density'], dtype='object') Scores dos Atributos Originais: [20.561 2.816 8.934 1.219 6.36 1.388 1.573 5.109] Atributos Selecionados: ['fixed acidity' 'citric acid' 'chlorides' 'density'] [[7.4 0. 0.076 0.998] [7.8 0. 0.098 0.997] [7.8 0.04 0.092 0.997] ... [6.3 0.13 0.076 0.996] [5.9 0.12 0.075 0.995] [6. 0.47 0.067 0.995]]
https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.RFE.html
Iremos aplicar a técnica de eliminação recursiva de atributos com um algoritmo de Regressão Logística (poderia ser qualquer classificador) para selecionar as 4 melhores variáveis preditoras.
# Criação do modelo
modelo = LogisticRegression(max_iter=200)
# Eliminação Recursiva de Variáveis
rfe = RFE(modelo, n_features_to_select=4)
fit = rfe.fit(X, y)
# Print dos resultados
print("Atributos Originais:", vinhoreddados.columns[0:8])
# Exibe os atributos selecionados (marcados como True em "Atributos Selecionados"
# e com valor 1 em "Ranking dos Atributos"): fixed acidity' 'citric acid' 'chlorides' 'density'.
# (Basta mapear manualmente o índice dos nomes dos respectivos atributos)
print("\nAtributos Selecionados: %s" % fit.support_)
print("\nRanking de atributos: %s" % fit.ranking_)
print("\nQtd de melhores Atributos: %d" % fit.n_features_)
print("\nNomes dos Atributos Selecionados: %s" % fit.get_feature_names_out(input_features=vinhoreddados.columns[0:8]))
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-7-1e36d9a882e0> in <module> 4 # Eliminação Recursiva de Variáveis 5 rfe = RFE(modelo, n_features_to_select=4) ----> 6 fit = rfe.fit(X, y) 7 8 # Print dos resultados /usr/local/lib/python3.8/dist-packages/sklearn/feature_selection/_rfe.py in fit(self, X, y, **fit_params) 220 Fitted estimator. 221 """ --> 222 return self._fit(X, y, **fit_params) 223 224 def _fit(self, X, y, step_score=None, **fit_params): /usr/local/lib/python3.8/dist-packages/sklearn/feature_selection/_rfe.py in _fit(self, X, y, step_score, **fit_params) 281 print("Fitting estimator with %d features." % np.sum(support_)) 282 --> 283 estimator.fit(X[:, features], y, **fit_params) 284 285 # Get importance and rank them /usr/local/lib/python3.8/dist-packages/sklearn/linear_model/_logistic.py in fit(self, X, y, sample_weight) 1514 accept_large_sparse=solver not in ["liblinear", "sag", "saga"], 1515 ) -> 1516 check_classification_targets(y) 1517 self.classes_ = np.unique(y) 1518 /usr/local/lib/python3.8/dist-packages/sklearn/utils/multiclass.py in check_classification_targets(y) 195 "multilabel-sequences", 196 ]: --> 197 raise ValueError("Unknown label type: %r" % y_type) 198 199 ValueError: Unknown label type: 'continuous'
http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.ExtraTreesClassifier.html
Iremos construir um classificador ExtraTreesClassifier.
# Criação do modelo para seleção de atributos
modelo = ExtraTreesClassifier(n_estimators=100)
modelo.fit(X,y)
# Exibe os atributos orginais
print("\nAtributos Originais:", vinhoreddados.columns[0:8])
# Exibe a pontuação de importância para cada atributo (quanto maior a pontuação, mais importante é o atributo).
# Atributos selecionados: plas, mass, pedi, age.
print(modelo.feature_importances_)
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-9-609783d10c8b> in <module> 1 # Criação do modelo para seleção de atributos 2 modelo = ExtraTreesClassifier(n_estimators=100) ----> 3 modelo.fit(X,y) 4 5 # Exibe os atributos orginais /usr/local/lib/python3.8/dist-packages/sklearn/ensemble/_forest.py in fit(self, X, y, sample_weight) 365 self.n_outputs_ = y.shape[1] 366 --> 367 y, expanded_class_weight = self._validate_y_class_weight(y) 368 369 if getattr(y, "dtype", None) != DOUBLE or not y.flags.contiguous: /usr/local/lib/python3.8/dist-packages/sklearn/ensemble/_forest.py in _validate_y_class_weight(self, y) 732 733 def _validate_y_class_weight(self, y): --> 734 check_classification_targets(y) 735 736 y = np.copy(y) /usr/local/lib/python3.8/dist-packages/sklearn/utils/multiclass.py in check_classification_targets(y) 195 "multilabel-sequences", 196 ]: --> 197 raise ValueError("Unknown label type: %r" % y_type) 198 199 ValueError: Unknown label type: 'continuous'
Curiosidade: no próximo notebook, após tratarmos os missings, ficaremos com as colunas: preg, plas, pres, mass, pedi, age - a única que não foi selecionada por algum método de feature selection foi pres
OBS: É possível utilizar técnicas de Feature selection como parte de um pipeline. Veja um exemplo no trecho de código a seguir:
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_classif
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
pipeline = Pipeline([
('feature_selection', SelectKBest(score_func=f_classif, k=4)),
('classification', RandomForestClassifier(n_estimators=100, max_features=3, random_state=7))
])
print (pipeline)
Pipeline(steps=[('feature_selection', SelectKBest(k=4)), ('classification', RandomForestClassifier(max_features=3, random_state=7))])