Introdução
Este laboratório demonstra como realizar a afinação de hiperparâmetros com validação cruzada utilizando a biblioteca scikit-learn. O objetivo é classificar imagens de dígitos manuscritos usando uma classificação binária para facilitar a compreensão: identificar se um dígito é 8 ou não. O conjunto de dados utilizado é o conjunto de dados de dígitos. O desempenho dos hiperparâmetros selecionados e do modelo treinado é então medido em um conjunto de avaliação dedicado que não foi utilizado durante a etapa de seleção do modelo.
Dicas da Máquina Virtual
Após o início da VM, clique no canto superior esquerdo para mudar para a aba Notebook para acessar o Jupyter Notebook para a prática.
Às vezes, pode ser necessário aguardar alguns segundos para que o Jupyter Notebook termine de carregar. A validação das operações não pode ser automatizada devido a limitações no Jupyter Notebook.
Se você enfrentar problemas durante o aprendizado, sinta-se à vontade para perguntar ao Labby. Forneça feedback após a sessão e resolveremos prontamente o problema para você.
Carregar Dados
Vamos carregar o conjunto de dados de dígitos e achatá-los em vetores. Cada imagem de 8 por 8 pixels precisa ser transformada em um vetor de 64 pixels. Assim, obteremos um array de dados final com forma (n_imagens, n_pixels). Também dividiremos os dados em um conjunto de treinamento e um conjunto de teste de tamanho igual.
from sklearn import datasets
from sklearn.model_selection import train_test_split
digits = datasets.load_digits()
n_samples = len(digits.images)
X = digits.images.reshape((n_samples, -1))
y = digits.target == 8
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)
Definir Estratégia de Busca em Grade
Vamos definir uma função a ser passada para o parâmetro refit da instância GridSearchCV. Ela implementará a estratégia personalizada para selecionar o melhor candidato a partir do atributo cv_results_ do GridSearchCV. Uma vez selecionado o candidato, ele é automaticamente retrabalhado pela instância GridSearchCV.
Aqui, a estratégia é criar uma lista curta dos modelos que são os melhores em termos de precisão e revocação. A partir dos modelos selecionados, finalmente selecionamos o modelo mais rápido na previsão. Observe que essas escolhas personalizadas são completamente arbitrárias.
import pandas as pd
from sklearn.metrics import classification_report
def print_dataframe(filtered_cv_results):
"""Imprime o DataFrame filtrado de forma organizada."""
for mean_precision, std_precision, mean_recall, std_recall, params in zip(
filtered_cv_results["mean_test_precision"],
filtered_cv_results["std_test_precision"],
filtered_cv_results["mean_test_recall"],
filtered_cv_results["std_test_recall"],
filtered_cv_results["params"],
):
print(
f"Precisão: {mean_precision:0.3f} (±{std_precision:0.03f}),"
f" Revocação: {mean_recall:0.3f} (±{std_recall:0.03f}),"
f" para {params}"
)
print()
def refit_strategy(cv_results):
"""Define a estratégia para selecionar o melhor estimador.
A estratégia definida aqui é filtrar todos os resultados abaixo de um limiar de precisão
de 0,98, classificar os restantes por revocação e manter todos os modelos com um desvio
padrão do melhor em revocação. Uma vez que esses modelos são selecionados, podemos selecionar
o modelo mais rápido para prever.
Parâmetros
----------
cv_results : dict de numpy (masked) ndarrays
Resultados de validação cruzada retornados pelo `GridSearchCV`.
Retorna
-------
best_index : int
O índice do melhor estimador conforme aparece em `cv_results`.
"""
## Imprime as informações sobre a busca em grade para as diferentes pontuações
threshold_precision = 0.98
cv_results_ = pd.DataFrame(cv_results)
print("Todos os resultados da busca em grade:")
print_dataframe(cv_results_)
## Filtra todos os resultados abaixo do limiar
resultados_alta_precisao = cv_results_[
cv_results_["mean_test_precision"] > threshold_precision
]
print(f"Modelos com precisão superior a {threshold_precision}:")
print_dataframe(resultados_alta_precisao)
resultados_alta_precisao = resultados_alta_precisao[
[
"mean_score_time",
"mean_test_recall",
"std_test_recall",
"mean_test_precision",
"std_test_precision",
"rank_test_recall",
"rank_test_precision",
"params",
]
]
## Seleciona os modelos mais eficientes em termos de revocação
## (dentro de 1 desvio padrão do melhor)
desvio_padrao_melhor_revocacao = resultados_alta_precisao["mean_test_recall"].std()
melhor_revocacao = resultados_alta_precisao["mean_test_recall"].max()
limiar_melhor_revocacao = melhor_revocacao - desvio_padrao_melhor_revocacao
resultados_alta_revocacao = resultados_alta_precisao[
resultados_alta_precisao["mean_test_recall"] > limiar_melhor_revocacao
]
print(
"Dos modelos de alta precisão selecionados anteriormente, mantemos todos os\n"
"modelos dentro de um desvio padrão do modelo de maior revocação:"
)
print_dataframe(resultados_alta_revocacao)
## A partir dos melhores candidatos, seleciona o modelo mais rápido para prever
indice_modelo_mais_rapido = resultados_alta_revocacao[
"mean_score_time"
].idxmin()
print(
"\nO modelo final selecionado é o mais rápido para prever entre o subconjunto\n"
"selecionado de melhores modelos com base em precisão e revocação.\n"
"Seu tempo de pontuação é:\n\n"
f"{resultados_alta_revocacao.loc[indice_modelo_mais_rapido]}"
)
return indice_modelo_mais_rapido
Definir Hiperparâmetros
Vamos definir os hiperparâmetros e criar a instância GridSearchCV.
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC
tuned_parameters = [
{"kernel": ["rbf"], "gamma": [1e-3, 1e-4], "C": [1, 10, 100, 1000]},
{"kernel": ["linear"], "C": [1, 10, 100, 1000]},
]
grid_search = GridSearchCV(
SVC(), tuned_parameters, scoring=["precision", "recall"], refit=refit_strategy
)
Ajustar o Modelo e Fazer Previsões
Vamos ajustar o modelo e fazer previsões no conjunto de avaliação.
grid_search.fit(X_train, y_train)
## Os parâmetros selecionados pela busca em grade com nossa estratégia personalizada são:
grid_search.best_params_
## Finalmente, avaliamos o modelo afinado no conjunto de avaliação deixado de fora: o
## objeto `grid_search` **foi automaticamente reapresentado** em todo o conjunto de treinamento
## com os parâmetros selecionados pela nossa estratégia de reapresentação personalizada.
y_pred = grid_search.predict(X_test)
print(classification_report(y_test, y_pred))
Resumo
Neste laboratório, aprendemos como realizar a afinação de hiperparâmetros com validação cruzada usando a biblioteca scikit-learn. Usamos o conjunto de dados dígitos e definimos uma estratégia de reapresentação personalizada para selecionar o melhor candidato do atributo cv_results_ da instância GridSearchCV. Finalmente, avaliamos o modelo afinado no conjunto de avaliação deixado de fora.