Exemple de classification binaire – Vers la science des données
Enfin, nous devons mettre à l’échelle les entités afin d’avoir toutes leurs valeurs sur la même plage ou amplitude. Cette étape doit être effectuée car la plupart des classificateurs ML utilisent la distance euclidienne et les caractéristiques avec des amplitudes ou une plage plus élevées auraient plus d’influence sur la prédiction. Par exemple, la température, 32 degrés Fahrenheit est identique à 273,15 degrés Kelvin et si nous devions utiliser les deux caractéristiques dans un modèle, Kelvin aurait plus de poids ou influencerait la prédiction.
scaler = RobustScaler()scaler.fit(X_train_clean)# transform train and test sets using training parameters
X_train_scaled = scaler.transform(X_train_clean)
X_test_scaled = scaler.transform(X_test_clean)X_train_scaled
col_names = X_train_clean.columns
X_train_clean_df = pd.DataFrame(X_train_scaled, columns=col_names)
X_test_clean_df = pd.DataFrame(X_test_scaled, columns=col_names)X_train_clean_df.head()
Nous avons utilisé RobustScaler car il est très robuste ou robuste contre les valeurs aberrantes. Notez que le résultat est un tableau numpy, transformons-le en une trame de données. Enfin, notez comment le détartreur a modifié les valeurs de nos fonctionnalités pour qu’elles soient à la même échelle ou amplitude.
Les ensembles de données modernes dans des domaines tels que le traitement du langage naturel et l’IoT sont généralement très dimensionnels. Il n’est pas rare de voir des centaines voire des milliers de fonctionnalités. Savoir réduire les fonctionnalités à quelques-uns non seulement améliore nos changements de recherche d’un modèle généralisable, mais diminue également la dépendance à une puissance de calcul coûteuse. En réduisant avec précision le nombre de fonctionnalités / dimensions dans nos données, nous supprimons finalement le bruit inutile de nos données.
Il est important de noter que la sélection d’entités consiste non seulement à réduire l’espace des entités mais également à créer des entités. Comprendre comment trouver les tendances dans votre ensemble de données et les relations entre les entités (c’est-à-dire les entités polynomiales) demande de nombreuses années de pratique, mais apporte de gros dividendes en termes de pouvoir prédictif. Il existe des cours collégiaux entiers dédiés à la sélection / ingénierie de fonctionnalités, mais ceux qui s’intéressent davantage au sujet, veuillez rechercher les méthodes Filter, Wrapper et Enbedded comme introduction.
RandomForestClassifier de Scikit-Learn possède un attribut «feature_importances_» qui est utilisé pour déterminer l’importance relative de chaque entité dans votre jeu de données. Nous utiliserons cette méthode dans notre exemple ci-dessous. La forêt aléatoire est une méthode d’ensemble qui utilise de nombreux arbres de décision individuels et agrège leurs résultats individuels pour produire une prédiction plus précise. Plus d’informations sur les méthodes d’ensemble plus tard.
rf_selector = RandomForestClassifier(n_estimators=100, random_state=SEED, n_jobs=-1)rf_selector.fit(X_train_clean_df, y_train)
feature_imp = pd.Series(rf_selector.feature_importances_,index=X_train_clean_df.columns).sort_values(ascending=False)feature_imp
feature_imp[0:20].index
sum(feature_imp[0:20])
Nous avons réussi à éliminer la plupart des fonctionnalités d’origine jusqu’à seulement 20, ce qui représente presque 76% de l’écart de performance. Toutes les fonctionnalités supplémentaires ajouteraient seulement une très petite puissance prédictive supplémentaire.
X_train_rf = X_train_clean_df[['NDC Class - Muscle Relaxants', 'CPT Category - Medicine', 'ICD Group 13', 'CPT Category - Eval_Mgmt', 'CPT Category - Surgery', 'CPT Category - Radiology', 'CPT Category - Path_Lab', 'HCPCS E Codes', 'HCPCS J Codes', 'Weekly Wage_sqrt', 'HCPCS A Codes', 'Accident DateID_rec', 'ICD Group 19', 'ICD Group 21', 'HCPCS G Codes', 'Claimant Age', 'CPT Category - Anesthesia', 'Percent Impairment', 'HCPCS L Codes', 'ICD Group 6']]X_test_rf = X_test_clean_df[['NDC Class - Muscle Relaxants', 'CPT Category - Medicine', 'ICD Group 13', 'CPT Category - Eval_Mgmt', 'CPT Category - Surgery', 'CPT Category - Radiology', 'CPT Category - Path_Lab', 'HCPCS E Codes', 'HCPCS J Codes', 'Weekly Wage_sqrt', 'HCPCS A Codes', 'Accident DateID_rec', 'ICD Group 19', 'ICD Group 21', 'HCPCS G Codes', 'Claimant Age', 'CPT Category - Anesthesia', 'Percent Impairment', 'HCPCS L Codes', 'ICD Group 6']]plt.figure(figsize=(12,8))
sns.barplot(x=feature_imp[0:20], y=feature_imp.index[0:20])
# Add labels to your graph
plt.xlabel('Feature Importance Score')
plt.ylabel('Features')
plt.title("Visualizing Important Features")
plt.grid(b=False, which='major', color='#666666', linestyle='-', alpha=0.2)
plt.show()
y_train.value_counts()sm = SMOTE(sampling_strategy='auto', k_neighbors=5, random_state=SEED)X_train_rf_smote, y_train_rf_smote = sm.fit_sample(X_train_rf, y_train)pd.Series(y_train_rf_smote).value_counts().plot.bar()
Si vous vous souvenez de notre examen initial de l’ensemble de données, la variable cible était déséquilibrée. Nous avions significativement plus d’observations qui n’ont pas entraîné d’abus d’opioïdes (89%) par rapport à celles qui ont entraîné d’abus d’opioïdes (10%). Nous avons également décidé d’utiliser la méthode SMOTE car elle crée de nouvelles observations synthétiques au lieu de copier les observations existantes. SMOTE utilise KNN (généralement k = 5) où une observation aléatoire de la classe minoritaire est sélectionnée et k des voisins les plus proches se trouvent. Ensuite, l’un des k voisins est sélectionné au hasard et un échantillon synthétique est construit à partir d’un point sélectionné au hasard entre l’observation d’origine et le voisin sélectionné au hasard.
En appliquant SMOTE, nous avons pu créer des cas minoritaires supplémentaires pour avoir un objectif équilibré.
Lors de l’évaluation des divers classificateurs formés, nous devons vraiment réfléchir à la mesure de performance que nous voulons utiliser. La métrique que nous utilisons pour évaluer notre classificateur dépend vraiment de la nature de notre problème ou des conséquences potentielles d’une erreur de prédiction. Examinons un exemple très courant de diagnostic du cancer (c.-à-d. Diagnostiqué avec un cancer ou non diagnostiqué avec un cancer). Nous voulons évidemment que notre modèle prédit autant de diagnostics de cancer réels que possible, mais nous savons également qu’il est statistiquement impossible d’identifier correctement tous les vrais diagnostics de cancer. Notre modèle finira par prédire qu’une personne aura un cancer alors qu’elle n’a pas réellement de cancer (faux positif) et prédira qu’une personne n’aura pas de cancer alors qu’elle a effectivement un cancer (faux négatif). La question que nous devons nous poser est «Qu’est-ce qui est pire? Prédire qu’une personne aura un cancer alors qu’elle n’en souffre pas ou prédire qu’une personne n’aura pas de cancer alors qu’elle en a réellement? ». La réponse dans cet exemple est évidente car les conséquences de dire à une personne qu’elle n’a pas de cancer quand elle l’emporte de loin sur le contraire. Gardons cet exemple à l’esprit, mais examinons les mesures de performances de classification couramment utilisées.
Mesures de performance de classification
Matrice de confusion
Une matrice de confusion fournira un décompte des prédictions pour chacun des 4 quadrants (TP, FP, FN, TN). Nous voudrions en fin de compte que notre modèle prédit autant de diagnostics Vrai Positif (TP) et Vrai Négatif (TN) et aussi peu de diagnostics Faux Positif (FP) et Faux Négatif (FN). La plupart des mesures de performances restantes sont dérivées de ce graphique, il est donc impératif que vous ayez une bonne compréhension.
Précision
En termes plus simples, la précision détaille la fréquence à laquelle le classificateur est correct. En d’autres termes, le nombre de prédictions correctes (TP, TF) est divisé par le nombre total de prédictions. La précision est importante lorsque vous n’êtes intéressé que par TP et TN. La précision est généralement la première mesure, mais elle ne raconte qu’un côté de l’histoire et ne prend pas en compte les conséquences du cancer dont nous avons discuté ci-dessus.
(TP + TN) / (TP + FP + FN + TN)
Précision
La précision nous indique quel pourcentage de la classe positive prédite était correct. En d’autres termes, quel pourcentage de diagnostics positifs de cancer prédits avaient effectivement un cancer. La précision ne tient qu’à ce que notre modèle prédit avec précision la classe positive. La haute précision concerne les faibles taux de PF.
TP / (TP + FP)
Rappel (également appelé sensibilité)
Le rappel ne peut être considéré comme une précision qu’en arrière. En d’autres termes, quel pourcentage de positifs réels notre modèle prévoyait être positif. Quel pourcentage de personnes effectivement diagnostiquées avec un cancer (par un médecin) notre modèle prévoyait avoir un cancer. Rappel se soucie moins de prédire avec précision les cas positifs mais de s’assurer que nous avons capturé tous les cas positifs. Un rappel élevé se rapporte à de faibles taux de FN.
TP / (TP + FN)
Score F1
Il est mathématiquement impossible d’avoir à la fois une haute précision et un rappel élevé et c’est là que le score f1 est utile. Le score F1 est la moyenne harmonique ou pondérée de la précision et du rappel. Si vous essayez de produire un modèle qui équilibre la précision et le rappel, le score f1 est une excellente option. Le score F1 est également une bonne option lorsque vous avez un ensemble de données déséquilibré. Un bon score f1 signifie que votre FP et votre FN sont faibles.
2 * (Rappel * Précision) / (Rappel + Précision)
Courbe ROC / Score AUC
La courbe des caractéristiques de fonctionnement du récepteur (ROC) trace le vrai taux positif contre le taux de faux positifs à n’importe quel seuil de probabilité. Le seuil est le seuil spécifié pour une observation à classer soit 0 (pas de cancer) ou 1 (a un cancer). Avant de discuter de la courbe ROC et du score AUC, examinons un exemple de régression logistique essayant de prédire si un individu est obèse ou non. Cela nous aidera à mieux comprendre ce qu’est un seuil et comment ajuster la prédiction du modèle en modifiant le seuil. Cet exemple apportera également les concepts de TP, TN, FN et FP que vous avez appris ci-dessus.
Suivez tout ce qui est logique, je vous le promets 🙂
Une régression logistique est un classificateur binaire et dans l’exemple ci-dessus, nous essayons de prédire correctement l’obésité en fonction d’une seule caractéristique / prédicteur, le poids. Nous avons un ensemble de données de 9 observations, où 4 observations (vertes) ne sont pas obèses et 5 (rouges) sont réellement obèses. Sur la base de la fonction sigmoïde (la ligne sinueuse) produite par la régression logarithmique, les 3 premières observations vertes non obèses ont 0% de chances d’être prédites comme obèses en fonction de leur poids. Les 3 dernières observations obèses rouges ont également une probabilité de 100% d’être prédites comme obèses. La deuxième observation d’obésité rouge a environ 70% de chances d’être prédite comme obèse.
Cependant, la 4ème observation verte non obèse a environ 85% de chances d’être prédite comme obèse en fonction de son poids (doit être très musclé), ce qui est évidemment la mauvaise prédiction. De plus, la première observation d’obésité a environ 15% de chances d’être obèse, ce qui, encore une fois, est une mauvaise prédiction. Gardez à l’esprit que le seuil est de 0,5
Supposons que les conséquences d’une prédiction incorrecte d’une personne qui ne sera pas obèse alors qu’elle est réellement obèse sont importantes. En d’autres termes, nous voulons ajuster le modèle de manière à ce qu’il capture ou prédise autant de personnes obèses réelles que possible. Pour accomplir cette tâche, nous devons changer notre seuil. Avec le seuil abaissé à 0,2, notre modèle prédira correctement les 5 observations obèses comme obèses.
Cependant, en abaissant le seuil à 0,2, la quatrième observation non obèse était désormais prédite comme obèse. C’est le compromis que nous faisons lors de l’ajustement du seuil du modèle.
Prenons encore une fois notre exemple de cancer. Nous serions d’accord avec un modèle avec un seuil de 0,2 car il prédirait correctement tous les diagnostics de cancer réels (c’est-à-dire les vrais positifs). Cependant, le modèle ferait un compromis car il prédirait en fin de compte plus de personnes qui n’avaient pas réellement de cancer comme ayant un cancer (c’est-à-dire, les faux positifs). Les conséquences des faux positifs sont moins graves que de prévoir à tort qu’une personne n’aura pas de cancer alors qu’elle le fait réellement.
Maintenant, un modèle avec un seuil de 0,9 ferait le contraire d’un seuil de 0,2. Cela garantirait de prédire les 4 individus non obèses comme non obèses, cependant, les deux premiers individus obèses seraient finalement prédits comme non obèses. Maintenant que nous comprenons le seuil et son objectif, revenons à la courbe ROC.
Alors, où la courbe ROC entre-t-elle en jeu?
C’était un exemple simple avec seulement 9 points de données où le seuil était facile à voir et à interpréter. Et si vous avez un million d’observations et une situation plus compliquée par rapport à notre exemple d’obésité ou de cancer. Quel serait le meilleur seuil dans cette situation? Faut-il faire un tas de ces graphiques pour trouver un seuil qui convienne le mieux à nos besoins? ». La réponse est non. Une courbe ROC est un excellent moyen de résumer rapidement ces données afin que vous puissiez choisir votre seuil.
Voici un exemple de courbe ROC, notez le vrai taux positif (réellement obèse et prédit comme obèse) sur l’axe y et le faux taux positif (non obèse mais prédit comme obèse) sur l’axe x. Enfin, n’oubliez pas qu’un ROC est utilisé pour résumer le taux de TP et le taux de FP à différents seuils.
Vrai taux positif
Taux de faux positifs
Comparons rapidement 3 seuils distincts sur la courbe ROC. Un seuil de 0,9 a la matrice de confusion suivante à partir de laquelle nous pouvons calculer un taux de TP de 0,6 et un taux de FP de 0,2.
Représentons le taux de TP et les points de taux de FP sur notre courbe ROC. Trouvons également les taux TP et FP pour des seuils de 0,6 et 0,2 pour la démonstration.
La ligne pointillée verte représente la courbe ROC, mais ignorons cela pour le moment. Les points bleus individuels sont le résultat de 4 matrices de confusion distinctes où le seuil a été ajusté. Maintenant, posez-vous la question: «Si c’était l’exemple du cancer et que vous vouliez vous assurer d’avoir saisi / prédit tous les diagnostics de cancer réels, quel seuil choisiriez-vous?» …………………………………………… ……………………………………………………………………………………………………………………………… .. Si vous avez dit 0,2, vous avez raison! À ce seuil, votre taux de TP est de 100%, ce qui signifie que vous capturez / prédisez tous les diagnostics de cancer réels. Votre taux de PF est d’environ 0,33, ce qui signifie que votre modèle classe incorrectement certains diagnostics non cancéreux comme ayant un cancer, mais ça va. Effrayer quelqu’un et lui faire dépenser de l’argent pour se faire tester a moins de conséquences que de dire à une personne qu’elle n’a pas de cancer alors qu’elle le fait.
Maintenant, le ROC connecte simplement chaque point afin d’aider à visualiser le passage du seuil de très conservateur à plus indulgent. Enfin, la courbe ROC aide à visualiser l’AUC.
Alors, quelle est la zone sous la courbe (AUC)?
Vous verrez souvent un graphique ROC avec de nombreuses courbes ROC et chaque courbe est un classificateur différent (c.-à-d. Régression logarithmique, SVC, arbre de décision, etc.). L’AUC est une grande métrique simple qui fournit un nombre décimal de 0 à 1 où plus le nombre est élevé, meilleur est le classificateur. L’AUC mesure la qualité des prévisions du modèle, quel que soit le seuil. Nous verrons les courbes ROC ainsi que leurs scores AUC pour notre problème d’opioïdes ci-dessous.
Évaluation de nos classificateurs
Maintenant que nous comprenons mieux les paramètres utilisés pour évaluer les modèles de classification, revenons à notre problème actuel. Nous évaluerons 6 classificateurs; régression logistique, forêt aléatoire, knn, classificateur de renforcement de gradient, bayes naïfs et machine à vecteurs de support. En termes de paramètres, nous concentrerons notre attention principalement sur le rappel, car nous voulons désespérément prédire / capturer autant de personnes qui abusent d’opioïdes que possible. De plus, nous explorerons la précision, l’exactitude et le score F1 au moyen d’un rapport de classification.
Souvenons-nous de nos jeux de données finalisés:
X_train_rf_smote: ne contenant que des fonctionnalités importantes avec application de smote
y_train_rf_smote: smote appliqué pour équilibrer la cible
X_test_rf: contenant uniquement des fonctionnalités importantes
y_test: fonction cible intacte
models = []models.append(('logReg', LogisticRegression(max_iter=10000, random_state=SEED)))
models.append(('rf_classifer',RandomForestClassifier(random_state=SEED)))
models.append(('knn', KNeighborsClassifier()))
models.append(('gbm',GradientBoostingClassifier(random_state=SEED)))models.append(('bayes', GaussianNB()))
models.append(('svc', svm.SVC()))training_results = []
testing_results = []
classifiers = []for name, classifier in models:
scores = cross_val_score(classifier, X_train_rf_smote,
y_train_rf_smote, cv=3, scoring='recall')
training_results.append(scores)
classifiers.append(name)
print('{}: avg recall using cv w/ RF features on training data:
{}'.format(name, scores.mean().round(3)))classifier.fit(X_train_rf_smote, y_train_rf_smote)
y_preds = classifier.predict(X_test_rf)
test_recall = recall_score(y_test, y_preds, average='binary')
testing_results.append(test_recall)
test_class = classification_report(y_test, y_preds)
print('{}: recall w/ RF features on testing data
{}:'.format(name, test_recall.round(3)))print(test_class)
Avant de continuer, examinons le rapport de classification pour chaque modèle illustré ci-dessus. Au moment de produire un rapport de classification, vous devriez avoir une bonne idée de la mesure de performance que vous souhaitez utiliser. Concentrez votre attention sur cette ou ces mesures.
Notez que le rapport de classification a été créé pour l’ensemble de test PAS pour l’ensemble de formation.
Soyons précis (c.-à-d. Quel pourcentage de nos prévisions étaient correctes?), Rappelons (c.-à-d. Pour toutes les observations qui étaient réellement positives, quel pourcentage a été prédit correctement?), F1-score et support. Notez que nous avons une précision, un rappel et un score F1 à la fois pour 0 et 1, où 0 est sans abus d’opioïdes et 1 avec abus d’opioïdes. En regardant le classificateur SVC, nous voyons que le modèle a correctement prédit la classe zéro (0) 90% du temps, mais il n’a correctement prédit que la classe un (1) 17% du temps.
Pour rappel, sur l’ensemble de la classe zéro (0) (c’est-à-dire les non-utilisateurs), le modèle a prédit correctement 91%. Cependant, sur l’ensemble d’une (une) classe (c’est-à-dire les utilisateurs), le modèle ne prédit que 17% correctement. Cela est dû au déséquilibre de classe car le classificateur est plus susceptible de prédire la classe zéro (0) sur la base de la simple probabilité.
F1-score est le moyen harmonique de précision et de rappel qui est facile à comprendre. Le support est le nombre total d’observations de classe pour la cible. En d’autres termes, l’ensemble de données de test présentait un déséquilibre entre les non-utilisateurs d’opioïdes et les utilisateurs. Nous n’avons pas appliqué SMOTE à l’ensemble de test, si vous vous en souvenez.
Examinons les moyennes macro et pondérées car leur interprétation est spécifiquement orientée vers la présence ou non d’un déséquilibre de classe (support). La moyenne des macros est une moyenne simple entre les classes zéro (0) et (1). Il pèse chaque classe également ou en d’autres termes, comme s’il n’y avait pas de déséquilibre de classe. Macro avg interprète le classificateur avec une pénalité plus importante lorsqu’il n’effectue pas / ne prévoit pas bien la classe minoritaire. En d’autres termes, si les classes étaient équilibrées, quelle serait votre moyenne. En cas de déséquilibre de classe, la macro moyenne fournit une meilleure estimation de votre classificateur.
Moyenne pondérée, calcule la moyenne de chaque classe indépendamment et ajoute un poids à chaque moyenne en fonction du nombre de la vraie (1) classe cible. Le problème avec les moyennes pondérées est le fait que les performances de la classe minoritaire reçoivent moins de poids. Par conséquent, les moyennes pondérées masquent la performance de la classe minoritaire. Ceci est particulièrement indésirable car la classe minoritaire (c’est-à-dire les utilisateurs d’opioïdes) est très souvent la classe qui nous intéresse le plus.
Retour à notre évaluation
En regardant nos classificateurs formés, il semble que GradientBoostingClassifier soit le plus performant. Nous avons spécifiquement choisi de concentrer notre attention sur le rappel. Nous voulons nous assurer que nous capturons autant de personnes qui abusent des opioïdes que possible, même si cela signifie que notre classificateur incorrecte certains faux positifs. De tous les utilisateurs d’opioïdes réels dans l’ensemble de test, le classificateur a correctement prédit 85% d’entre eux. Le rappel moyen macro était de 91%, ce qui signifie que le modèle est bon pour prédire à la fois les non-utilisateurs réels et les utilisateurs.
Construisons un modèle GradientBoostingClassifier et ajustons ses paramètres.
Nous vous laisserons le graphique ROC / AUC pour les classificateurs testés (omettant SVC en raison de son temps de formation prolongé).
classifiers = [
{'name': 'Log Regression', 'classifier': LogisticRegression(max_iter=10000, random_state=SEED)},
{'name': 'Random Forest', 'classifier': RandomForestClassifier()},
{'name': 'Gradient Boosting Classifier', 'classifier': GradientBoostingClassifier(random_state=SEED)},
{'name': 'KNN', 'classifier': KNeighborsClassifier()},
{'name': 'Naive Bayes', 'classifier': GaussianNB()}]results = pd.DataFrame(columns =['classifier', 'FPR', 'TPR', 'AUC'])plt.figure(figsize=(13,8))for clf in classifiers:
model = clf['classifier']
model.fit(X_train_rf_smote, y_train_rf_smote)
y_preds = model.predict(X_test_rf)
y_proba = model.predict_proba(X_test_rf)[:,1]
fpr, tpr, thresholds = roc_curve(y_test, y_proba)
auc = roc_auc_score(y_test, model.predict(X_test_rf))
plt.plot(fpr, tpr, label='%s ROC (AUC = %0.2f)' % (clf['name'],
auc))plt.plot([0, 1], [0, 1],'r--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate', fontsize=15)
plt.ylabel('True Positive Rate', fontsize=15)
plt.title('ROC Curves', fontsize=20)
plt.legend(loc="lower right")
plt.show()
Quels sont les modèles d’ensemble tels que GradientBoostingClassifier?
Nous n’entrerions pas dans les détails des modèles d’ensemble, mais ils utilisent essentiellement plusieurs modèles pour améliorer leur prédiction. Imaginez que vous êtes à la recherche d’une nouvelle voiture, une toute nouvelle voiture de sport. Allez-vous acheter la première voiture de sport que vous voyez? Bien sûr que non, vous allez faire vos recherches. Vous lirez d’innombrables critiques, regardez des heures de vidéos YouTube et demandez l’avis des autres propriétaires de la voiture avant de prendre votre décision. Eh bien, les modèles d’ensemble fonctionnent de la même manière. Chaque examen / opinion différent est un modèle différent et, ensemble, ils fournissent une perspective / prédiction holistique.
Que sont les hyperparamètres?
Pensez aux hyperparamètres comme des boutons de réglage. Imaginez que vous éditez une image afin d’obtenir un certain effet. Vous pouvez régler l’image à l’aide de «boutons» tels que l’exposition, les hautes lumières, les ombres, le contraste, la luminosité, la saturation, la chaleur, la teinte, etc. Eh bien, les hyperparamètres sont le même type de «boutons», mais pour les classificateurs.
clf_gbc = GradientBoostingClassifier(random_state=SEED)clf_gbc.fit(X_train_rf_smote, y_train_rf_smote)
Tous les hyperparamètres sont mis en évidence et leur explication est hors de portée de ce blog. Nous pouvons ajuster tout ou seulement quelques-uns, mais attention à essayer de régler trop de paramètres en même temps prendra plusieurs heures voire plusieurs jours en fonction de la puissance de votre ordinateur et de la taille de l’ensemble de données. Notez que chaque hyperparamètre a des valeurs par défaut.
Hyperparamètres utilisés: taux d’apprentissage, max_depth et n_estimators.
Nous utiliserons la bibliothèque GridSearchCV de Sklearn. GridSearchCV prend en compte les hyperparamètres spécifiés (en créant le modèle) tels que ‘learning_rate’ ainsi que la plage de valeurs pour chaque hyperparamètre. Il itérera ensuite sur toutes les combinaisons possibles de tous les hyperparamètres et de leurs plages de valeurs, entraînant le modèle à chaque itération. Encore une fois, en fonction du nombre d’hyperparamètres et de la taille de vos données, ce processus peut prendre très longtemps. Une fois terminé, GridSearchCV vous fournira la meilleure combinaison de paramètres pour la métrique de notation choisie qui dans notre cas est le rappel. N’oubliez pas que la meilleure combinaison sélectionnée par l’algorithme sera hors des hyperparamètres et des plages que vous avez spécifiées. En d’autres termes, il pourrait y avoir une meilleure combinaison d’hyperparamètres. Il s’agit souvent d’un processus itératif où nous testions des combinaisons uniques avec des plages de valeurs de plus en plus strictes pour chaque hyperparamètre.
learning_rates = [0.01, 0.05, 0.1, 0.25, 0.5, 1]
n_estimators = [1, 2, 4, 8, 16, 32]
max_depths = np.linspace(1, 15, 15, endpoint=True)param_grid = dict(learning_rate=learning_rates, n_estimators=n_estimators, max_depth=max_depths)grid = GridSearchCV(estimator = GradientBoostingClassifier(random_state=SEED), param_grid=param_grid, scoring='recall', verbose=1, n_jobs=-1, cv=2)grid_results = grid.fit(X_train_rf_smote, y_train_rf_smote)
print('Best Score: ', grid_results.best_score_)
print('Best Params: ', grid_results.best_params_)
GridSearchCV a révélé qu’un learning_rate de 0,01, max_depth de 2,0 et n_estimators de 1 produiront le meilleur modèle. Il a réussi à améliorer notre score de rappel de formation initiale de 96% à 98%.
Modèle de formation avec hyperparamètres optimisés
Entraînons notre modèle GradientBoostingClassifier mais cette fois en utilisant les hyperparamètres fournis par GridSearchCV.
gbc_clf = GradientBoostingClassifier(learning_rate=0.01, max_depth=2.0, n_estimators=1, random_state=SEED)gbc_scores = cross_val_score(gbc_clf, X_train_rf_smote, y_train_rf_smote ,cv=3, scoring='recall')
gbc_clf.fit(X_train_rf_smote, y_train_rf_smote)y_preds = gbc_clf.predict(X_test_rf)test_recall = recall_score(y_test, y_preds, average='binary').round(3)
print('Gradient Boosting: avg recall using cv w/ RF features on training data:', gbc_scores.mean().round(3))
test_class = classification_report(y_test, y_preds)
cm = confusion_matrix(y_test, y_preds)
print('Gradient Boosting: recall w/ RF features on testing data:', test_recall)
print(test_class)
print(cm)
Rappelez-vous notre formation initiale avec les hyperparamètres par défaut a donné un rappel de 96% sur l’ensemble d’entraînement et 85% de rappel sur l’ensemble de test. En appliquant les hyperparamètres optimisés, nous avons pu augmenter notre rappel à 98% sur l’ensemble d’entraînement. Ce qui est plus impressionnant, c’est le fait que nous avons augmenté notre rappel sur l’ensemble de test de 85% à 95%! En d’autres termes, nous avons pu prédire correctement 95% des utilisateurs réels d’opioïdes.
Examinons le rapport de classification plus en détail. Lorsque le modèle a prédit que quelqu’un ne serait pas un utilisateur d’opioïdes, c’était correct dans 99% des cas (précision) mais seulement 32% dans le cas où quelqu’un était un utilisateur d’opioïdes. En revanche, le modèle a correctement prédit 77% des utilisateurs réels non opioïdes et 95% des utilisateurs réels opioïdes. Étant donné que l’ensemble de test était déséquilibré, notre moyenne macro de précision était de 66% et 86% pour le rappel.
Jetons un coup d’œil à la matrice de confusion (située juste en dessous du rapport de classification), car elle montre vraiment ce qui se passe lorsque nous privilégions une métrique par rapport à une autre. Si vous vous souvenez, nous étions déterminés à prédire / capturer autant d’utilisateurs d’opioïdes que possible, même si cela signifiait que nous avions des faux positifs (pas un utilisateur mais prévu d’être un utilisateur). Notre modèle a correctement prédit près de 33 000 utilisateurs réels d’opioïdes et 4 724 non-utilisateurs. Il a prédit que plus de 10 000 personnes seraient des utilisateurs d’opioïdes alors qu’en réalité ils ne l’étaient pas. Cependant, le nombre sur lequel nous devrions vraiment nous concentrer est les 248 personnes qui sont des utilisateurs d’opioïdes, mais notre modèle a prédit qu’elles ne le seraient pas. Ce sont les patients qui se sont «infiltrés» malheureusement.
gbc_clf = GradientBoostingClassifier(learning_rate=0.01, max_depth=2.0, n_estimators=1, random_state=SEED)
gbc_clf.fit(X_train_rf_smote, y_train_rf_smote)y_preds = gbc_clf.predict(X_test_rf)fpr, tpr, thresholds = roc_curve(y_test, gbc_clf.predict_proba(X_test_rf)[:,1])
roc_auc = roc_auc_score(y_test, y_preds).round(3)
plt.figure(figsize=(13,8))
plt.plot(fpr, tpr, label= 'AUC = %0.2f' % roc_auc)
plt.plot([0, 1], [0, 1],'r--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate', fontsize=15)
plt.ylabel('True Positive Rate', fontsize=15)
plt.title('Gradient Boosting Classifier ROC Curve', fontsize=20)
plt.legend(loc="lower right")
plt.show()
Comprendre la nature complète d’un problème de classification de la science des données est essentiel dans votre maturité en tant que scientifique des données. J’espère que vous avez trouvé ce tutoriel informatif et facile à comprendre. Je me réjouis de tout commentaire et suggestion, car nous ne faisons que perfectionner notre métier.