<jupyter_start><jupyter_text>**Hands-on Sintonia de Hiperparâmetros**---Sintonia de Hiperparâmetros com sklearn  Vamos começar a olhar para alguns hiperparâmetros diversos e também para algumas tecnicas de otimização de hiperparâmetros.Vamos seguir utilizando a base de dados **diabetes.csv**  que pode ser encontrada no OpenML em: https://www.openml.org/d/37. Essa base descreve o problema de predizer o resultado positivo ou negativo de um teste para diabetes aplicado em um conjunto específico de pacientes na Índia.  Para a primeira etapa, vamos utilizar a divisão treino e teste e olhar para os dois dos três classificadores que usamos durante o hands-on de Classificação.Note que, o processo é equivalente para as demais tarefas, tanto a de regressão quanto a de clusterização. Aqui, usaremos a classificação devido a simplicidade de interpretação do resultadoo. Mais informações sobre os classificadores podem ser encontradas na documentação do sklearn nos links abaixo. *    Support Vector Machine (SVM)*    Random Forest Na segunda etapa, vamos aplicar a técnica de cross validation para o processo de validação dos modelos e, em conjunto, vamos usar os métodos de grid search e random search para otimização dos hiperparâmetros.   *Importando* bibliotecas<jupyter_code>import pandas as pd #biblioteca para manipulação de dados
import numpy as np #biblioteca para utilizacao de vetores e matrizes
import matplotlib.pyplot as plt #bibloteca para plotar graficos
#liberando acesso do colab aos arquivos no drive
from google.colab import drive
drive.mount('/content/gdrive')<jupyter_output>Mounted at /content/gdrive<jupyter_text>Carregamento dos dados<jupyter_code>#lendo o csv que contem a base de dados e armazanando em um df
df = pd.read_csv('/content/gdrive/My Drive/IGTI/Aulas Práticas/diabetes.csv')
#imprimindo as 5 primeiras linhas do df para confirmação
df.head(5)<jupyter_output><empty_output><jupyter_text>*   preg: number of times pregnant*   plas: Plasma glucose concentration a 2 hours in an oral glucose tolerance test*   pres: Diastolic blood pressure (mm Hg)*   skin: Triceps skin fold thickness (mm)*   insu: 2-Hour serum insulin (mu U/ml)*   mass: Body mass index (weight in kg/(height in m)^2)*   pedi: Diabetes pedigree function*   age: Age (years)*   class: Class variable (tested_positive or tested_negative)<jupyter_code># Verificando o numero de amostras (linhas) e features (colunas) do dataset. 
print('Amostras e Features:', df.shape)
# Verificando quais são os tipos das features
df.columns<jupyter_output><empty_output><jupyter_text>Pré processamento Nesse problema, o único atributo categórico é a classe. Alguns modelos podem ter dificuldade de lidar com esse atributo. Nesse caso, precisamos transformar os valores de "tested_negative" e "tested_positivo" para 0 e 1.Para isso, vamos fazer uma função bem simples.<jupyter_code>#criando um dicionario de dados para o mapeamento
name_to_class = {
    'tested_negative': 0,
    'tested_positive': 1
}

#substituindo os valores categóricos pelo mapeamento
df['class'] = df['class'].map(name_to_class)

#check
df.head(5)<jupyter_output><empty_output><jupyter_text>Uma outra etapa importante do pré-processamento consiste na avaliação de dados faltantes.<jupyter_code># Analisando o resumo da base
df.describe()<jupyter_output><empty_output><jupyter_text>Os modelos implementados no sklearn recebem como entrada para a modelagam um ou mais arrays. Dessa forma, precisamos modificar o df original para que seja possível a modelagem correta. Para isso, vamos separar o label das amotras, armazenar o nome das featues já que os arrays não fazem isso e depois retirar a coluna de labels do df original. Em seguida, vamos converter o df para array usando o numpy!<jupyter_code># armazenando os labels em um array
labels = np.array(df['class'])

# salvando a ordem das features
feature_list = list(df.columns)
# removendo a coluna de labels do df original
df = df.drop('class', axis = 1)

# check
df.columns
# convertendo df para array
data = np.array(df)<jupyter_output><empty_output><jupyter_text>Agora estamos quase prontos para a modelagem em si! Vamos usar a função  train_test_split  e olhar para para algumas combinações de parâmetros dos modelos que selecionamos.<jupyter_code># importar train_test_split do scikitlearn 
from sklearn.model_selection import train_test_split

# aplicando a funcao train_test_split para separar os conjuntos de treino e 
# teste segundo uma porcentagem de separação definida. 
train_data, test_data, train_labels, test_labels = train_test_split(data, labels, test_size = 0.25, random_state = 42)<jupyter_output><empty_output><jupyter_text>Support Vector Machine SVM Vamos dar uma olhada agora no comportamento do SVM<jupyter_code>#importar o modelo SVM
from sklearn.svm import SVC
# treinando o SVM com kernel RBF
classifier1 = SVC(kernel='rbf').fit(train_data,train_labels)

# aplicando o modelo treinado 
predictions1_labels = classifier1.predict(test_data)

# Exibindo dataframe com valores 10 reais e suas respectivas previsões
#p = pd.DataFrame({'Real': test_labels, 'Previsto': predictions1_labels})  
#p.head(10)
#avaliando o modelo 
from sklearn import metrics
 
print('Matriz de Confusão\n', metrics.confusion_matrix(test_labels, predictions1_labels)) 
print('\nAcurácia\n', metrics.accuracy_score(test_labels, predictions1_labels)) 
print('\nF1\n', metrics.f1_score(test_labels, predictions1_labels)) 
print('\nAUCROC\n', metrics.roc_auc_score(test_labels, predictions1_labels))<jupyter_output>Matriz de Confusão
 [[106  17]
 [ 35  34]]

Acurácia
 0.7291666666666666

F1
 0.5666666666666667

AUCROC
 0.6772711205372923<jupyter_text>Vamos tentar melhorar o SVM? Vamos trocar o kernel gaussiano pelo sigmoidal<jupyter_code># treinando o SVM com kernel sigmoidal
classifier2 = SVC(kernel='sigmoid').fit(train_data,train_labels)

# aplicando o modelo treinado 
predictions2_labels = classifier2.predict(test_data)

# Exibindo dataframe com valores 10 reais e suas respectivas previsões
#p = pd.DataFrame({'Real': test_labels, 'Previsto': predictions2_labels})  
#p.head(10)
#avaliando o modelo 
from sklearn import metrics
 
print('Matriz de Confusão\n', metrics.confusion_matrix(test_labels, predictions2_labels)) 
print('\nAcurácia\n', metrics.accuracy_score(test_labels, predictions2_labels)) 
print('\nF1\n', metrics.f1_score(test_labels, predictions2_labels)) 
print('\nAUCROC\n', metrics.roc_auc_score(test_labels, predictions2_labels))<jupyter_output>Matriz de Confusão
 [[94 29]
 [57 12]]

Acurácia
 0.5520833333333334

F1
 0.21818181818181817

AUCROC
 0.46907034287734173<jupyter_text>Vamos tentar outra opção!<jupyter_code># treinando o SVM com kernel rbf, com largura da gaussiana alterada
classifier3 = SVC(kernel='rbf', gamma = 'auto').fit(train_data,train_labels)

# aplicando o modelo treinado 
predictions3_labels = classifier3.predict(test_data)

# Exibindo dataframe com valores 10 reais e suas respectivas previsões
#p = pd.DataFrame({'Real': test_labels, 'Previsto': predictions3_labels})  
#p.head(10)
#avaliando o modelo 
from sklearn import metrics
 
print('Matriz de Confusão\n', metrics.confusion_matrix(test_labels, predictions3_labels)) 
print('\nAcurácia\n', metrics.accuracy_score(test_labels, predictions3_labels)) 
print('\nF1\n', metrics.f1_score(test_labels, predictions3_labels)) 
print('\nAUCROC\n', metrics.roc_auc_score(test_labels, predictions3_labels))<jupyter_output>Matriz de Confusão
 [[123   0]
 [ 69   0]]

Acurácia
 0.640625

F1
 0.0

AUCROC
 0.5<jupyter_text>Ultimo teste!<jupyter_code># treinando o SVM com kernel rbf, com largura da gaussiana alterada
classifier4 = SVC(C = 0.1, kernel='rbf', gamma = 0.0001).fit(train_data,train_labels)

# aplicando o modelo treinado 
predictions4_labels = classifier4.predict(test_data)

# Exibindo dataframe com valores 10 reais e suas respectivas previsões
#p = pd.DataFrame({'Real': test_labels, 'Previsto': predictions4_labels})  
#p.head(10)
#avaliando o modelo 
from sklearn import metrics
 
print('Matriz de Confusão\n', metrics.confusion_matrix(test_labels, predictions4_labels)) 
print('\nAcurácia\n', metrics.accuracy_score(test_labels, predictions4_labels)) 
print('\nF1\n', metrics.f1_score(test_labels, predictions4_labels)) 
print('\nAUCROC\n', metrics.roc_auc_score(test_labels, predictions4_labels))<jupyter_output>Matriz de Confusão
 [[112  11]
 [ 43  26]]

Acurácia
 0.71875

F1
 0.49056603773584906

AUCROC
 0.6436903499469776<jupyter_text>Random Forest Classifiers Vamos agora modelar o nosso problema utilizando o Random Forest Classifier e testar algumas combinações de hiperparâmetros!<jupyter_code># importar o modelo Random Forest Regressor
from sklearn.ensemble import RandomForestClassifier

# treinando o modelo 
classifier5 = RandomForestClassifier(n_estimators= 10, random_state=42).fit(train_data, train_labels);

# aplicando o modelo treinado para a previsão do resultado do teste
predictions5_labels = classifier5.predict(test_data)

# Exibindo dataframe com valores 10 reais e suas respectivas previsões
#p = pd.DataFrame({'Real': test_labels, 'Previsto': predictions5_labels})  
#p.head(10)
#avaliando o modelo
print('Matriz de Confusão\n', metrics.confusion_matrix(test_labels, predictions5_labels)) 
print('\nAcurácia\n', metrics.accuracy_score(test_labels, predictions5_labels)) 
print('\nF1\n', metrics.f1_score(test_labels, predictions5_labels)) 
print('\nAUCROC\n', metrics.roc_auc_score(test_labels, predictions5_labels))<jupyter_output>Matriz de Confusão
 [[97 26]
 [24 45]]

Acurácia
 0.7395833333333334

F1
 0.6428571428571428

AUCROC
 0.72039589961117<jupyter_text>Eita...Será que o nosso resultado pode ser melhor?Vamos trocar random_state e dar uma olhada em como a característica aleatoria do RF influencia no resultado.<jupyter_code># treinando o modelo 
classifier6 = RandomForestClassifier(n_estimators= 10, random_state = 124).fit(train_data, train_labels);

# aplicando o modelo treinado para a previsão do resultado do teste
predictions6_labels = classifier6.predict(test_data)

# Exibindo dataframe com valores 10 reais e suas respectivas previsões
#p = pd.DataFrame({'Real': test_labels, 'Previsto': predictions5_labels})  
#p.head(10)
#avaliando o modelo
print('Matriz de Confusão\n', metrics.confusion_matrix(test_labels, predictions6_labels)) 
print('\nAcurácia\n', metrics.accuracy_score(test_labels, predictions6_labels)) 
print('\nF1\n', metrics.f1_score(test_labels, predictions6_labels)) 
print('\nAUCROC\n', metrics.roc_auc_score(test_labels, predictions6_labels))<jupyter_output>Matriz de Confusão
 [[100  23]
 [ 24  45]]

Acurácia
 0.7552083333333334

F1
 0.656934306569343

AUCROC
 0.7325910215623894<jupyter_text>Vamos tentar aumentar o número de estimadores<jupyter_code># treinando o modelo 
classifier7 = RandomForestClassifier(n_estimators= 100, random_state = 42).fit(train_data, train_labels);

# aplicando o modelo treinado para a previsão do resultado do teste
predictions7_labels = classifier7.predict(test_data)

# Exibindo dataframe com valores 10 reais e suas respectivas previsões
#p = pd.DataFrame({'Real': test_labels, 'Previsto': predictions5_labels})  
#p.head(10)
#avaliando o modelo
print('Matriz de Confusão\n', metrics.confusion_matrix(test_labels, predictions7_labels)) 
print('\nAcurácia\n', metrics.accuracy_score(test_labels, predictions7_labels)) 
print('\nF1\n', metrics.f1_score(test_labels, predictions7_labels)) 
print('\nAUCROC\n', metrics.roc_auc_score(test_labels, predictions7_labels))
# importar o modelo Random Forest Regressor
from sklearn.ensemble import RandomForestClassifier

# treinando o modelo 
classifier8 = RandomForestClassifier(n_estimators= 100, bootstrap = False, random_state = 42).fit(train_data, train_labels);

# aplicando o modelo treinado para a previsão do resultado do teste
predictions8_labels = classifier8.predict(test_data)

# Exibindo dataframe com valores 10 reais e suas respectivas previsões
#p = pd.DataFrame({'Real': test_labels, 'Previsto': predictions8_labels})  
#p.head(10)
#avaliando o modelo
print('Matriz de Confusão\n', metrics.confusion_matrix(test_labels, predictions8_labels)) 
print('\nAcurácia\n', metrics.accuracy_score(test_labels, predictions8_labels)) 
print('\nF1\n', metrics.f1_score(test_labels, predictions8_labels)) 
print('\nAUCROC\n', metrics.roc_auc_score(test_labels, predictions8_labels))<jupyter_output>Matriz de Confusão
 [[93 30]
 [24 45]]

Acurácia
 0.71875

F1
 0.6250000000000001

AUCROC
 0.704135737009544<jupyter_text>Qual seria o custo, isto é, qual o tempo que nós perdiaríamos ao ter que calibrar manualmente, de forma aleatória ou sistemática, todos os modelos que criamos?  Só não! Vamos dar uma olhada em como funciona o Random Search e o Grid Search aplicados? SIIIIIIIIIIIMVamos aproveitar para usar a validação cruzada estratificada! O sklearn tem funções de Grid Search e Random Search implementadas que já fazem o processo de validação cruzada do modelo. Mais informações sobre esses métodos podem ser encontradas nos links abaixo!*    Grid Search CV *    Random Search CVVamos testa-las?  Grid Search **Vamos testar o Grid Search com kfold estratificado e o SVM**<jupyter_code>from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import f1_score, make_scorer
#definindo hiperparâmetros
hiperparam = {'kernel':('sigmoid', 'rbf'), 'C':[0.01, 1, 10]}

#definindo o tipo de validacao cruzada e o numero de folds
cv_strat = StratifiedKFold(n_splits = 10)

#instânciando meu classificador
classifier = SVC()

#definindo a estrategia de score a partir da metrica f1
f1 = make_scorer(f1_score)

#instanciando e modelando o grid search com os hiperparametros e a validação definidas.
grid_cv = GridSearchCV(classifier, hiperparam, cv = cv_strat, scoring = f1)
grid_cv.fit(data, labels)
#vamos olhar para todos os resultados encontrados!
print('Resumo de todos os resultados encontrados:\n\n', grid_cv.cv_results_)

#vamos olhar para os melhores resultados encontrados pelo Grid Search
print('Melhor resultado f1:', grid_cv.best_score_)
print('\n\nMelhor configuração de hiperparâmetros:', grid_cv.best_params_)

print( '\n\nConfigurações de todos os hiperparâmetros do melhor estimado encontrado pelo GridSearch: \n', grid_cv.best_estimator_)<jupyter_output>Melhor resultado f1: 0.6086487385278134


Melhor configuração de hiperparâmetros: {'C': 10, 'kernel': 'rbf'}


Configurações de todos os hiperparâmetros do melhor estimado encontrado pelo GridSearch: 
 SVC(C=10, break_ties=False, cache_size=200, class_weight=None, coef0=0.0,
    decision_function_shape='ovr', degree=3, gamma='scale', kernel='rbf',
    max_iter=-1, probability=False, random_state=None, shrinking=True,
    tol=0.001, verbose=False)<jupyter_text>**Vamos agora repetir o processo para o Random Forest**<jupyter_code>#definindo hiperparâmetros
#hiperparam1 = {'n_estimators':[10, 100, 1000]}
hiperparam1 = {'n_estimators':[10, 100, 1000], 'bootstrap': (True, False)}
#hiperparam1 = {'n_estimators':[10, 100, 1000], 'bootstrap': (True, False), 'criterion': ('gini', 'entropy')}

#instânciando meu classificador
classifier1 = RandomForestClassifier()

#instanciando e modelando o grid search com os hiperparametros e a validação definidas.
grid_cv1 = GridSearchCV(classifier1, hiperparam1, cv = cv_strat, scoring = f1)
grid_cv1.fit(data, labels)
#vamos olhar para todos os resultados encontrados!
print('Resumo de todos os resultados encontrados:\n\n', grid_cv1.cv_results_)

#vamos olhar para os melhores resultados encontrados pelo Grid Search
print('Melhor resultado f1:', grid_cv1.best_score_)
print('\n\nMelhor configuração de hiperparâmetros:', grid_cv1.best_params_)
print( '\n\nConfigurações de todos os hiperparâmetros do melhor estimado encontrado pelo GridSearch: \n', grid_cv1.best_estimator_)<jupyter_output>Melhor resultado f1: 0.631712870537294


Melhor configuração de hiperparâmetros: {'bootstrap': True, 'n_estimators': 100}


Configurações de todos os hiperparâmetros do melhor estimado encontrado pelo GridSearch: 
 RandomForestClassifier(bootstrap=True, ccp_alpha=0.0, class_weight=None,
                       criterion='gini', max_depth=None, max_features='auto',
                       max_leaf_nodes=None, max_samples=None,
                       min_impurity_decrease=0.0, min_impurity_split=None,
                       min_samples_leaf=1, min_samples_split=2,
                       min_weight_fraction_leaf=0.0, n_estimators=100,
                       n_jobs=None, oob_score=False, random_state=None,
                       verbose=0, warm_start=False)<jupyter_text>Random Search<jupyter_code>from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import uniform

#definindo o tipo de validacao cruzada e o numero de folds
cv_strat = StratifiedKFold(n_splits = 10)

#definindo a estrategia de score a partir da metrica f1
f1 = make_scorer(f1_score)

#definindo hiperparâmetros
distributions = dict(kernel = ['sigmoid', 'rbf'], 
                     C = uniform(loc=0, scale=10))

#instânciando meu classificador
classifier = SVC()

#instanciando e modelando o grid search com os hiperparametros e a validação definidas.
random_cv = RandomizedSearchCV(classifier, distributions, cv = cv_strat, scoring = f1, random_state = 42, n_iter = 10)
random_cv.fit(data, labels)
#vamos olhar para todos os resultados encontrados!
print('Resumo de todos os resultados encontrados:\n\n', random_cv.cv_results_)
#vamos olhar para os melhores resultados encontrados pelo Grid Search
print('Melhor resultado f1:', random_cv.best_score_)
print('\n\nMelhor configuração de hiperparâmetros:', random_cv.best_params_)
print( '\n\nConfigurações de todos os hiperparâmetros do melhor estimado encontrado pelo GridSearch: \n', random_cv.best_estimator_)<jupyter_output>Melhor resultado f1: 0.6065838014605637


Melhor configuração de hiperparâmetros: {'C': 8.324426408004218, 'kernel': 'rbf'}


Configurações de todos os hiperparâmetros do melhor estimado encontrado pelo GridSearch: 
 SVC(C=8.324426408004218, break_ties=False, cache_size=200, class_weight=None,
    coef0=0.0, decision_function_shape='ovr', degree=3, gamma='scale',
    kernel='rbf', max_iter=-1, probability=False, random_state=None,
    shrinking=True, tol=0.001, verbose=False)<jupyter_text>Vamos testar agora o mesmo processo para o RF<jupyter_code>from scipy.stats import randint
#definindo o tipo de validacao cruzada e o numero de folds
cv_strat = StratifiedKFold(n_splits = 10)

#definindo a estrategia de score a partir da metrica f1
f1 = make_scorer(f1_score)

#definindo hiperparâmetros
distributions1 = dict(n_estimators = randint(10, 100),
                      bootstrap = [True, False],
                      criterion = ['gini', 'entropy'])

#instânciando meu classificador
classifier1 = RandomForestClassifier(random_state = 42)

#instanciando e modelando o grid search com os hiperparametros e a validação definidas.
random_cv1 = RandomizedSearchCV(classifier1, distributions1, cv = cv_strat, scoring = f1, random_state = 42, n_iter = 10)
random_cv1.fit(data, labels)
#vamos olhar para todos os resultados encontrados!
print('Resumo de todos os resultados encontrados:\n\n', random_cv1.cv_results_)
#vamos olhar para os melhores resultados encontrados pelo Grid Search
print('Melhor resultado f1:', random_cv1.best_score_)
print('\n\nMelhor configuração de hiperparâmetros:', random_cv1.best_params_)
print( '\n\nConfigurações de todos os hiperparâmetros do melhor estimado encontrado pelo GridSearch: \n', random_cv1.best_estimator_)<jupyter_output>Melhor resultado f1: 0.6336649387264222


Melhor configuração de hiperparâmetros: {'bootstrap': False, 'criterion': 'gini', 'n_estimators': 42}


Configurações de todos os hiperparâmetros do melhor estimado encontrado pelo GridSearch: 
 RandomForestClassifier(bootstrap=False, ccp_alpha=0.0, class_weight=None,
                       criterion='gini', max_depth=None, max_features='auto',
                       max_leaf_nodes=None, max_samples=None,
                       min_impurity_decrease=0.0, min_impurity_split=None,
                       min_samples_leaf=1, min_samples_split=2,
                       min_weight_fraction_leaf=0.0, n_estimators=42,
                       n_jobs=None, oob_score=False, random_state=42, verbose=0,
                       warm_start=False)
{'fraction_non_alphanumeric': 0.08475325313037073, 'fraction_numerical': 0.03795727964645225, 'mean_word_length': 5.790930310103368, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 61, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 7, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '18', 'dir': 'jupyter-structured-clean-dedup', 'id': '402410', 'license': 'CC0-1.0', 'n_tokens_mistral': 7536, 'n_tokens_neox': 6958, 'n_words': 1935, 'path': 'Mod3/IGTI/Hands_on_Sintonia_Hiperparametros.ipynb', 'repo_name': 'spedison/Curso_igti_ML', 'size': '20365'}