CSI 4506 - Automne 2024
Version: oct. 5, 2024 13h02
GridSearchCV
dans scikit-learn.OpenML est une plateforme ouverte pour partager des ensembles de données, des algorithmes et des expériences - pour apprendre à mieux apprendre, ensemble.
Author: Vincent Sigillito
Source: Obtained from UCI
Please cite: UCI citation policy
Title: Pima Indians Diabetes Database
Sources:
Past Usage:
Smith,J.W., Everhart,J.E., Dickson,W.C., Knowler,W.C., & Johannes,R.S. (1988). Using the ADAP learning algorithm to forecast the onset of diabetes mellitus. In {it Proceedings of the Symposium on Computer Applications and Medical Care} (pp. 261–265). IEEE Computer Society Press.
The diagnostic, binary-valued variable investigated is whether the patient shows signs of diabetes according to World Health Organization criteria (i.e., if the 2 hour post-load plasma glucose was at least 200 mg/dl at any survey examination or if found during routine medical care). The population lives near Phoenix, Arizona, USA.
Results: Their ADAP algorithm makes a real-valued prediction between 0 and 1. This was transformed into a binary decision using a cutoff of 0.448. Using 576 training instances, the sensitivity and specificity of their algorithm was 76% on the remaining 192 instances.
Relevant Information: Several constraints were placed on the selection of these instances from a larger database. In particular, all patients here are females at least 21 years old of Pima Indian heritage. ADAP is an adaptive learning routine that generates and executes digital analogs of perceptron-like devices. It is a unique algorithm; see the paper for details.
Number of Instances: 768
Number of Attributes: 8 plus class
For Each Attribute: (all numeric-valued)
Missing Attribute Values: None
Class Distribution: (class value 1 is interpreted as “tested positive for diabetes”)
Class Value Number of instances 0 500 1 268
Brief statistical analysis:
Attribute number: Mean: Standard Deviation:
3.8 3.4
120.9 32.0
69.1 19.4
20.5 16.0
79.8 115.2
32.0 7.9
0.5 0.3
33.2 11.8
Relabeled values in attribute ‘class’ From: 0 To: tested_negative
From: 1 To: tested_positive
Downloaded from openml.org.
return_X_y
fetch_openml
renvoie un Bunch
, un DataFrame
ou X
et y
Déséquilibre modéré (rapport inférieur à 3 ou 4)
Parfois appelée holdout method.
Recommandation: Allouer 80% de votre ensemble de données pour l’entraînement et réserver les 20% restants pour les tests.
Ensemble d’entraînement: Sous-ensemble de données utilisé pour entraîner votre modèle.
Ensemble de test: Sous-ensemble indépendant utilisé exclusivement lors de l’étape finale pour évaluer les performances du modèle.
Erreur d’entraînement :
Erreur de généralisation : L’erreur observée lorsque le modèle est évalué sur des données nouvelles, non vues.
Sous-apprentissage :
Sur-apprentissage :
La validation croisée (cross-validation) est une méthode utilisée pour évaluer et améliorer les performances des modèles d’apprentissage automatique.
Elle consiste à partitionner l’ensemble de données en plusieurs sous-ensembles, en entraînant le modèle sur certains sous-ensembles tout en le validant sur les autres.
cross_val_score
from sklearn import tree
clf = tree.DecisionTreeClassifier()
from sklearn.model_selection import cross_val_score
clf_scores = cross_val_score(clf, X, y, cv=5)
print("\nScores:", clf_scores)
print(f"\nMoyenne: {clf_scores.mean():.2f}")
print(f"\nÉcart-type: {clf_scores.std():.2f}")
Scores: [0.71428571 0.66883117 0.71428571 0.79738562 0.73202614]
Moyenne: 0.73
Écart-type: 0.04
Un hyperparamètre est une configuration externe au modèle qui est définie avant le processus d’apprentissage et qui régit le processus d’apprentissage, influençant les performances et la complexité du modèle.
criterion
: gini
, entropy
, log_loss
, mesure la qualité d’une scission.max_depth
: limite le nombre de niveaux dans l’arbre pour éviter le sur-apprentissage.penalty
: l1
ou l2
, aide à éviter le sur-apprentissage.solver
: liblinear
, newton-cg
, lbfgs
, sag
, saga
.max_iter
: nombre maximal d’itérations pour que les solveurs convergent.tol
: critère d’arrêt, les petites valeurs signifient une plus grande précision.n_neighbors
: nombre de voisins à utiliser pour les requêtes de \(k\)-voisins.weights
: uniform
ou distance
, poids égal ou basé sur la distance.max_depth
for value in [3, 5, 7, None]:
clf = tree.DecisionTreeClassifier(max_depth=value)
clf_scores = cross_val_score(clf, X_train, y_train, cv=10)
print("\nmax_depth = ", value)
print(f"Moyenne: {clf_scores.mean():.2f}")
print(f"Écart-type: {clf_scores.std():.2f}")
max_depth = 3
Moyenne: 0.74
Écart-type: 0.04
max_depth = 5
Moyenne: 0.76
Écart-type: 0.04
max_depth = 7
Moyenne: 0.73
Écart-type: 0.04
max_depth = None
Moyenne: 0.71
Écart-type: 0.05
criterion
for value in ["gini", "entropy", "log_loss"]:
clf = tree.DecisionTreeClassifier(max_depth=5, criterion=value)
clf_scores = cross_val_score(clf, X_train, y_train, cv=10)
print("\ncriterion = ", value)
print(f"Moyenne: {clf_scores.mean():.2f}")
print(f"Écart-type: {clf_scores.std():.2f}")
criterion = gini
Moyenne: 0.76
Écart-type: 0.04
criterion = entropy
Moyenne: 0.75
Écart-type: 0.05
criterion = log_loss
Moyenne: 0.75
Écart-type: 0.05
n_neighbors
from sklearn.neighbors import KNeighborsClassifier
for value in range(1, 11):
clf = KNeighborsClassifier(n_neighbors=value)
clf_scores = cross_val_score(clf, X_train, y_train, cv=10)
print("\nn_neighbors = ", value)
print(f"Moyenne: {clf_scores.mean():.2f}")
print(f"Écart-type: {clf_scores.std():.2f}")
n_neighbors
n_neighbors = 1
Moyenne: 0.67
Écart-type: 0.05
n_neighbors = 2
Moyenne: 0.71
Écart-type: 0.03
n_neighbors = 3
Moyenne: 0.69
Écart-type: 0.05
n_neighbors = 4
Moyenne: 0.73
Écart-type: 0.03
n_neighbors = 5
Moyenne: 0.72
Écart-type: 0.03
n_neighbors = 6
Moyenne: 0.73
Écart-type: 0.05
n_neighbors = 7
Moyenne: 0.74
Écart-type: 0.04
n_neighbors = 8
Moyenne: 0.75
Écart-type: 0.04
n_neighbors = 9
Moyenne: 0.73
Écart-type: 0.05
n_neighbors = 10
Moyenne: 0.73
Écart-type: 0.04
weights
from sklearn.neighbors import KNeighborsClassifier
for value in ["uniform", "distance"]:
clf = KNeighborsClassifier(n_neighbors=5, weights=value)
clf_scores = cross_val_score(clf, X_train, y_train, cv=10)
print("\nweights = ", value)
print(f"Moyenne: {clf_scores.mean():.2f}")
print(f"Écart-type: {clf_scores.std():.2f}")
weights = uniform
Moyenne: 0.72
Écart-type: 0.03
weights = distance
Moyenne: 0.73
Écart-type: 0.04
De nombreux hyperparamètres nécessitent un ajustement
L’exploration manuelle des combinaisons est fastidieuse
La recherche en grille est plus systématique
Énumérer toutes les combinaisons possibles d’hyperparamètres
Entraîner sur l’ensemble d’entraînement, évaluer sur l’ensemble de validation
GridSearchCV
from sklearn.model_selection import GridSearchCV
param_grid = [
{'max_depth': range(1, 10),
'criterion': ["gini", "entropy", "log_loss"]}
]
clf = tree.DecisionTreeClassifier()
grid_search = GridSearchCV(clf, param_grid, cv=5)
grid_search.fit(X_train, y_train)
(grid_search.best_params_, grid_search.best_score_)
({'criterion': 'gini', 'max_depth': 5}, 0.7481910124074653)
GridSearchCV
param_grid = [
{'n_neighbors': range(1, 16),
'weights': ["uniform", "distance"]}
]
clf = KNeighborsClassifier()
grid_search = GridSearchCV(clf, param_grid, cv=5)
grid_search.fit(X_train, y_train)
(grid_search.best_params_, grid_search.best_score_)
({'n_neighbors': 14, 'weights': 'uniform'}, 0.7554165363361485)
GridSearchCV
from sklearn.linear_model import LogisticRegression
# 2 * 5 * 5 * 3 = 150 tests!
param_grid = [
{'penalty': ["l1", "l2", None],
'solver' : ['liblinear', 'newton-cg', 'lbfgs', 'sag', 'saga'],
'max_iter' : [100, 200, 400, 800, 1600],
'tol' : [0.01, 0.001, 0.0001]}
]
clf = LogisticRegression()
grid_search = GridSearchCV(clf, param_grid, cv=5)
grid_search.fit(X_train, y_train)
(grid_search.best_params_, grid_search.best_score_)
({'max_iter': 100, 'penalty': 'l2', 'solver': 'newton-cg', 'tol': 0.001},
0.7756646856427901)
clf = LogisticRegression(max_iter=100, penalty='l2', solver='newton-cg', tol=0.001)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred))
precision recall f1-score support
0 0.83 0.83 0.83 52
1 0.64 0.64 0.64 25
accuracy 0.77 77
macro avg 0.73 0.73 0.73 77
weighted avg 0.77 0.77 0.77 77
Marcel Turcotte
École de science informatique et de génie électrique (SIGE)
Université d’Ottawa