Une histoire déroutante avec deux façons d'implémenter XGBoost en Python + notes générales

introduction

XGBoost est une méthode de GBDT et peut être implémentée en python. Cependant, lorsque j'ai examiné les exemples d'implémentation, j'étais confus car il y avait plusieurs façons de les décrire même s'ils utilisaient la même bibliothèque. Par conséquent, le but de cet article est d'essayer la même chose dans chaque notation avec la signification mémorable de l'auteur. (Veuillez noter que l'explication détaillée de XGBoost sera omise.)

Environnement de montage

pip install xgboost

Détails d'implémentation

Mise en œuvre ~ Partie commune ~

Charger le jeu de données

import_boston_datasets.py


#Importez d'abord la bibliothèque à utiliser cette fois
import pandas as pd
import numpy as np
import xgboost
import matplotlib.pyplot as plt
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

boston = load_boston()

df_boston = pd.DataFrame(boston.data, columns=boston.feature_names)

#Attachez la variable objectif à la fin de la trame de données en tant que prix pour les afficher tous ensemble.
df_boston['PRICE'] = boston.target
print(df_boston.head())
CRIM ZN INDUS CHAS NOX RM AGE DIS RAD TAX PTRATIO B LSTAT PRICE
0 0.00632 18.0 2.31 0.0 0.538 6.575 65.2 4.0900 1.0 296.0 15.3 396.90 4.98 24.0
1 0.02731 0.0 7.07 0.0 0.469 6.421 78.9 4.9671 2.0 242.0 17.8 396.90 9.14 21.6
2 0.02729 0.0 7.07 0.0 0.469 7.185 61.1 4.9671 2.0 242.0 17.8 392.83 4.03 34.7
3 0.03237 0.0 2.18 0.0 0.458 6.998 45.8 6.0622 3.0 222.0 18.7 394.63 2.94 33.4
4 0.06905 0.0 2.18 0.0 0.458 7.147 54.2 6.0622 3.0 222.0 18.7 396.90 5.33 36.2

Création de données de train et de données de test

make_train_test.py


#Divisez les données en fonction x et variable objectif y
x = df_boston.loc[:,'CRIM':'LSTAT']
y = df_boston['PRICE']

#7:Divisé en données de train et données de test à 3
trainX, testX, trainY, testY = train_test_split(x, y, test_size=0.3)

#Essayez de sortir chaque forme
print('x.shape = {}'.format(x.shape))
print('y.shape = {}'.format(y.shape))
print('trainX.shape = {}'.format(trainX.shape))
print('trainY.shape = {}'.format(trainY.shape))
print('testX.shape = {}'.format(testX.shape))
print('testY.shape = {}'.format(testY.shape))
# x.shape = (506, 13)
# y.shape = (506,)
# trainX.shape = (354, 13)
# trainY.shape = (354,)
# testX.shape = (152, 13)
# testY.shape = (152,)

Mise en œuvre ~ Formation ~

Méthode 1

La méthode 1 est une méthode utilisant une interface avec ** l'API compatible scikit-learn **. Je vais le décrire à partir d'ici, que vous connaissez peut-être. Tout d'abord, de l'implémentation la plus simple sans spécifier de paramètres.

regression1-1.py


#Utilisez XGB Regressor car il s'agit d'une régression
reg = xgb.XGBRegressor()

#eval_Définir les données de vérification dans l'ensemble
reg.fit(trainX, trainY,
        eval_set=[(trainX, trainY),(testX, testY)])
#[0]	validation_0-rmse:21.5867	validation_1-rmse:21.7497
#[1]	validation_0-rmse:19.5683	validation_1-rmse:19.7109
#[2]	validation_0-rmse:17.7456	validation_1-rmse:17.8998
#réduction
#[97]	validation_0-rmse:1.45198	validation_1-rmse:2.7243
#[98]	validation_0-rmse:1.44249	validation_1-rmse:2.72238
#[99]	validation_0-rmse:1.43333	validation_1-rmse:2.7233

#Exécution prédictive
predY = reg.predict(testX)

#Affichage de MSE
print(mean_squared_error(testY, predY))
#7.4163707577050655

Si vous spécifiez les paramètres un peu plus correctement, ce sera comme suit.

regression1-2.py


reg = xgb.XGBRegressor(#Spécification de la fonction objectif La valeur initiale est également l'erreur carrée
                       objective='reg:squarederror',
                       #Nombre de cycles d'apprentissage tôt_Puisque l'arrêt est utilisé, spécifiez plus
                       n_estimators=50000,
                       #Quoi utiliser pour booster La valeur initiale est également gbtree
                       booster='gbtree',
                       #Taux d'apprentissage
                       learning_rate=0.01,
                       #Profondeur maximale de l'arbre
                       max_depth=6,
                       #Valeur de la graine
                       random_state=2525)

#Préparer des variables pour afficher le processus d'apprentissage
evals_result = {}
reg.fit(trainX, trainY,
        eval_set=[(trainX, trainY),(testX, testY)],
        #Index d'évaluation utilisé pour l'apprentissage
        eval_metric='rmse',
        #Spécifiez le nombre de tours pour arrêter l'apprentissage lorsque la fonction objectif ne s'améliore pas
        early_stopping_rounds=15,
        #Utilisez l'API de rappel pour enregistrer le processus d'apprentissage et spécifier les variables ci-dessus
        callbacks=[xgb.callback.record_evaluation(evals_result)])

#[1]	validation_0-rmse:19.5646	validation_1-rmse:19.7128
#[2]	validation_0-rmse:17.7365	validation_1-rmse:17.9048
#[3]	validation_0-rmse:16.0894	validation_1-rmse:16.2733
#réduction
#[93]	validation_0-rmse:0.368592	validation_1-rmse:2.47429
#[94]	validation_0-rmse:0.3632	validation_1-rmse:2.47945
#[95]	validation_0-rmse:0.356932	validation_1-rmse:2.48028
#Stopping. Best iteration:
#[80]	validation_0-rmse:0.474086	validation_1-rmse:2.46597

predY = reg.predict(testX)
print(mean_squared_error(testY, predY))
#6.080995445035289

La perte s'est un peu améliorée par rapport au moment où rien n'était précisé. Il existe d'autres paramètres qui peuvent être spécifiés, mais pour plus de détails Référence de l'API Python XGBoost Voir ** API Scikit-Learn ** dans.

Cependant, il existe des paramètres qui ne sont pas écrits dans cette API, ce qui est souvent déroutant. Par exemple, si vous sortez le modèle alors que rien n'est spécifié

ex.py


reg = xgb.XGBRegressor()
print(reg)
#XGBRegressor(base_score=0.5, booster='gbtree', colsample_bylevel=1,
#             colsample_bynode=1, colsample_bytree=1, gamma=0,
#             importance_type='gain', learning_rate=0.1, max_delta_step=0,
#             max_depth=3, min_child_weight=1, missing=None, n_estimators=100,
#             n_jobs=1, nthread=None, objective='reg:linear', random_state=0,
#             reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None,
#             silent=None, subsample=1, verbosity=1)

Vous pouvez vérifier la valeur initiale du modèle comme ceci. Mais au fond

silent=None

Même si vous vérifiez avec l'API, un tel paramètre n'existe pas en premier lieu. Certains sites le décrivent comme un paramètre de présence ou d'absence de sortie lors de la formation, mais même s'il a été spécifié, rien n'a changé.

Méthode 2

Vient ensuite la deuxième méthode. Il s'agit de l '** API d'origine ** de la bibliothèque xgboost. Par conséquent, il existe une légère différence dans la gestion des ensembles de données.

regression2-1.py


#xgb.Rendez-le utilisable dans l'API d'origine de DMatrix
#feature_Vous n'êtes pas obligé de spécifier des noms, mais vous pouvez les ajouter en toute sécurité car cela sera pratique plus tard.
dtrain = xgb.DMatrix(trainX, label=trainY, feature_names = x.columns)
dtest = xgb.DMatrix(testX, label=testY, feature_names = x.columns)

reg = xgb.train(#Spécifiez une liste vide car l'entraînement est effectué avec la valeur initiale sans spécifier intentionnellement de paramètres
                params=[],
                dtrain=dtrain,
                #Définir les données de vérification dans eval
                evals=[(dtrain, 'train'), (dtest, 'eval')])
#[0]	train-rmse:17.1273	eval-rmse:17.3433
#[1]	train-rmse:12.3964	eval-rmse:12.7432
#[2]	train-rmse:9.07831	eval-rmse:9.44546
#[3]	train-rmse:6.6861	eval-rmse:7.16429
#[4]	train-rmse:5.03358	eval-rmse:5.70227
#[5]	train-rmse:3.88521	eval-rmse:4.7088
#[6]	train-rmse:3.03311	eval-rmse:4.09655
#[7]	train-rmse:2.44077	eval-rmse:3.6657
#[8]	train-rmse:2.0368	eval-rmse:3.40768
#[9]	train-rmse:1.72258	eval-rmse:3.29363

predY = reg.predict(dtest)
print(mean_squared_error(testY, predY))
#10.847961069710934

Vous pouvez voir que le nombre de cycles d'apprentissage est défini pour être assez petit par défaut. Ce n'est pas un meilleur résultat que la méthode 1. Définissons les paramètres de la même manière et exécutons-le.

regression2-2.py


#xgb.Rendez-le utilisable dans l'API d'origine de DMatrix
dtrain = xgb.DMatrix(trainX, label=trainY, feature_names = x.columns)
dtest = xgb.DMatrix(testX, label=testY, feature_names = x.columns)

#XGB d'abord_Définissez les paramètres en tant que paramètres
xgb_params = {#Fonction objective
              'objective': 'reg:squarederror',
              #Index d'évaluation utilisé pour l'apprentissage
              'eval_metric': 'rmse',
              #Quoi utiliser pour booster
              'booster': 'gbtree',
              #learning_Synonyme de taux
              'eta': 0.1,
              #Profondeur maximale de l'arbre
              'max_depth': 6,
              #random_Synonyme d'état
              'seed': 2525}

#Préparez des variables pour obtenir le processus d'apprentissage
evals_result = {}
reg = xgb.train(#Utilisez les paramètres d'apprentissage définis ci-dessus
                params=xgb_params,
                dtrain=dtrain,
                #Nombre de cycles d'apprentissage
                num_boost_round=50000,
                #Nombre de tours d'arrêt anticipé u
                early_stopping_rounds=15,
                #Données de vérification
                evals=[(dtrain, 'train'), (dtest, 'eval')],
                #Définissez les variables préparées ci-dessus
                evals_result=evals_result)
#[1]	train-rmse:19.5646	eval-rmse:19.7128
#[2]	train-rmse:17.7365	eval-rmse:17.9048
#[3]	train-rmse:16.0894	eval-rmse:16.2733
#réduction
#[93]	train-rmse:0.368592	eval-rmse:2.47429
#[94]	train-rmse:0.3632	eval-rmse:2.47945
#[95]	train-rmse:0.356932	eval-rmse:2.48028
#Stopping. Best iteration:
#[80]	train-rmse:0.474086	eval-rmse:2.46597

predY = reg.predict(dtest)
print(mean_squared_error(testY, predY))
#6.151798278561384

La perte affichée pendant le processus d'apprentissage est exactement la même que dans la méthode 1. Cependant, si vous prédisez et sortez MSE après cela, la valeur sera différente ... Je ne connais pas la cause, donc je vais la transmettre. Comme vous pouvez le voir en comparant les codes, les noms des paramètres et les endroits où ils sont écrits sont légèrement différents, alors soyez prudent. Par exemple, si le taux d'apprentissage eta est défini comme learning_rate comme dans la méthode 1, il peut être exécuté mais la valeur n'est pas reflétée. À propos de ce paramètre XGBoost Parameters Quand Référence de l'API Python XGBoost Découvrez l '** API d'apprentissage **.

Implémentation ~ Représentation graphique du processus d'apprentissage ~

Puisque la valeur est stockée dans ** evals_result ** préparé au moment de l'apprentissage, la transition est représentée graphiquement en l'utilisant.

Méthode 1

plot_validation1.py


#tracer la transition de perte pour les données de train
plt.plot(evals_result['validation_0']['rmse'], label='train rmse')
#tracer la transition de perte pour les données de test
plt.plot(evals_result['validation_1']['rmse'], label='eval rmse')
plt.grid()
plt.legend()
plt.xlabel('rounds')
plt.ylabel('rmse')
plt.show()

img.png

Méthode 2

Pour une raison quelconque, le nom stocké dans evals_result est différent de celui de la méthode 1.

plot_validation2.py


#tracer la transition de perte pour les données de train
plt.plot(evals_result['train']['rmse'], label='train rmse')
#tracer la transition de perte pour les données de test
plt.plot(evals_result['eval']['rmse'], label='eval rmse')
plt.grid()
plt.legend()
plt.xlabel('rounds')
plt.ylabel('rmse')
plt.savefig("img.png ", bbox_inches='tight')
plt.show()

img.png

Mise en œuvre ~ Affichage de l'importance des fonctionnalités ~

xgboost a une méthode appelée ** xgb.plot_importance () ** qui trace FeatureImportance, qui peut être utilisée dans les deux méthodes 1 et 2.

plot_importance.py


xgb.plot_importance(reg)

img.png

Vous pouvez également spécifier importance_type comme argument. API description et importance_type Si vous vous référez à cet article

Vous pouvez en utiliser trois (il semble que vous puissiez également utiliser la valeur totale du gain et de la couverture au lieu de la valeur moyenne pour lire l'API) La valeur initiale semble être le poids, par exemple, si vous spécifiez le gain et le sortez, ce sera comme suit.

plot_importance.py


xgb.plot_importance(reg,importance_type='gain')

img.png

Il existe également une méthode appelée ** xgb.get_score () **, qui vous permet d'obtenir les valeurs utilisées dans le graphique sous forme de dictionnaire. Cependant, cette méthode n'est disponible que dans la méthode 2 **, et je ne suis pas sûr qu'il existe un moyen de faire quelque chose de similaire dans la méthode 1 ... Je m'inquiète des incohérences ici.

print_importance.py


print(reg.get_score(importance_type='weight'))
#{'LSTAT': 251,
# 'RM': 363,
# 'CRIM': 555,
# 'DIS': 295,
# 'B': 204,
# 'INDUS': 81,
# 'NOX': 153,
# 'AGE': 290,
# 'PTRATIO': 91,
# 'RAD': 41,
# 'ZN': 36,
# 'TAX': 91,
# 'CHAS': 13}

print(reg.get_score(importance_type='gain'))
#{'LSTAT': 345.9503342748026,
# 'RM': 67.2338906183525,
# 'CRIM': 9.066383988597524,
# 'DIS': 20.52948739887609,
# 'B': 5.704856272869067,
# 'INDUS': 6.271976581219753,
# 'NOX': 17.48982672038596,
# 'AGE': 3.396609941187381,
# 'PTRATIO': 15.018738197646142,
# 'RAD': 5.182013825021951,
# 'ZN': 2.7426182845938896,
# 'TAX': 12.025571026275834,
# 'CHAS': 1.172155851074923}

Je pense que feature_names a été spécifié lors de la création de DMatrix, mais si vous ne le spécifiez pas, le nom du montant de la fonctionnalité ne sera pas affiché sur le graphique etc., donc ce sera très difficile à comprendre. Il est bon de le définir.

Autres caractéristiques de chaque méthode

Méthode 1

Je pense que le point le plus pratique de la méthode 1 est que la recherche de paramètres est possible en utilisant GridSerchCV de sklearn. Autant que j'ai vérifié, la méthode 1 a été utilisée dans tous les articles utilisant XGBoost pour la recherche de paramètres. Le code du CV de recherche aléatoire est affiché pour référence.

randomized_search.py


from sklearn.model_selection import RandomizedSearchCV

params = {
          'n_estimators':[50000],
          'objective':['reg:squarederror'],
          'eval_metric': ['rmse'],
          'booster': ['gbtree'],
          'learning_rate':[0.1,0.05,0.01],
          'max_depth':[5,7,10,15],
          'random_state':[2525]
         }

mod = xgb.XGBRegressor()
#n_Iter a un nombre de recherche aléatoire
rds = RandomizedSearchCV(mod,params,random_state=2525,scoring='r2',n_jobs=1,n_iter=50)
rds.fit(trainX,
        trainY,
        eval_metric='rmse',
        early_stopping_rounds=15,
        eval_set=[(testX, testY)])
print(rds.best_params_)
#{'seed': 2525,
# 'objective': 'reg:squarederror',
# 'n_estimators': 50000,
# 'max_depth': 5,
# 'learning_rate': 0.1,
# 'eval_metric': 'rmse',
# 'booster': 'gbtree'}

Méthode 2

Pour être honnête, je pense que l'API d'origine n'est pas familière et que vous n'avez pas à vous soucier de l'utiliser. Cependant, il peut y avoir d'autres exemples de ce type, car certaines méthodes ne peuvent être utilisées qu'avec la méthode ci-dessus. Le basique est-il implémenté par la méthode 1? Je pense qu'il serait préférable de mettre en œuvre celui-ci ici si vous ne pouvez pas le faire.

en conclusion

Cette fois, en étudiant XGBoost, j'ai résumé aussi facilement que possible les points peu clairs dus au mélange de méthodes. J'espère que quelqu'un dans une situation similaire arrivera ici et résoudra le problème. Il existe de nombreuses autres méthodes utiles dans la bibliothèque xgboost, comme une méthode qui peut afficher l'arborescence générée sous forme de diagramme, il est donc recommandé de jeter un coup d'œil rapide à l'API et de l'implémenter de différentes manières. C'est le premier article de Qiita de ma vie, et je pense que ce n'est pas suffisant, mais merci d'avoir lu jusqu'ici.

Article de référence

Python: essayez d'utiliser XGBoost Comment utiliser xgboost: classification multi-classes par données d'iris Utilisation de XGBoost avec Python Xgboost: Comment calculer importance_type de feature_importance xgboost: modèle d'apprentissage automatique efficace pour les données de table

Recommended Posts

Une histoire déroutante avec deux façons d'implémenter XGBoost en Python + notes générales
Une histoire sur la tentative d'implémentation de variables privées en Python.
[Note] Une histoire sur la tentative de remplacer une méthode de classe avec deux barres inférieures dans la série Python 3.
Je veux facilement implémenter le délai d'expiration en python
J'ai essayé d'implémenter un pseudo pachislot en Python
Je veux travailler avec un robot en python.
J'ai essayé d'implémenter un automate cellulaire unidimensionnel en Python
Une histoire sur la façon de spécifier un chemin relatif en python.
6 façons d'enchaîner des objets en Python
5 façons de créer un chatbot Python
Une histoire sur l'ajout d'une API REST à un démon créé avec Python
Implémenter un automate fini déterministe en Python pour déterminer des multiples de 3
J'ai essayé de mettre en œuvre un jeu de dilemme de prisonnier mal compris en Python
Deux façons d'afficher plusieurs graphiques dans une seule image avec matplotlib
Une histoire qui n'a pas fonctionné lorsque j'ai essayé de me connecter avec le module de requêtes Python
J'ai essayé d'implémenter PLSA en Python
Livre en spirale en Python! Python avec un livre en spirale! (Chapitre 14 ~)
Essayez de vous connecter à qiita avec Python
[Petite histoire] Comment enregistrer des graphiques matplotlib dans un lot avec Jupyter
J'ai essayé d'implémenter la permutation en Python
J'ai essayé d'implémenter PLSA dans Python 2
Comment utiliser BigQuery en Python
Comment obtenir stacktrace en python
Notez que le serveur d'exécution de Django est moss en Python 2.7.11 fourni avec Homebrew
J'ai essayé d'implémenter ADALINE en Python
J'ai essayé d'implémenter PPO en Python
Pour faire fonctionner la station d'horodatage en Python
J'ai essayé d'implémenter le jeu de cartes de Trump en Python
Différentes façons de lire la dernière ligne d'un fichier csv en Python
J'ai essayé d'implémenter le tri par fusion en Python avec le moins de lignes possible
[Python] A créé une classe pour jouer des vagues de péché en arrière-plan avec pyaudio
Une histoire qui est devenue bleu clair en 4 mois après avoir démarré AtCoder avec python
Comment déposer Google Docs dans un dossier dans un fichier .txt avec python
Recherche d'un moyen efficace d'écrire un Dockerfile avec Python avec de la poésie
J'ai essayé d'implémenter ce qui semble être un outil de snipper Windows avec Python
Une histoire à laquelle j'étais accro après la communication SFTP avec python
Tapez des notes sur les scripts Python pour exécuter le modèle PyTorch en C ++ avec libtorch
Comment obtenir une liste de fichiers dans le même répertoire avec python
[Python] Compréhension de liste Différentes façons de créer une liste
Comment lire un fichier CSV avec Python 2/3
Essayez d'implémenter Oni Mai Tsuji Miserable avec python
Envoyer un message à LINE avec Python (LINE Notify)
3 façons d'analyser les chaînes de temps avec python [Note]
[Python] Récupérez les fichiers dans le dossier avec Python
Calculons en fait le problème statistique avec Python
[REAPER] Comment jouer à Reascript avec Python
Comment effacer un taple dans une liste (Python)
Comment incorporer des variables dans des chaînes python
Convertissez des PDF en images en masse avec Python
[Python3] Une histoire bloquée avec la conversion du fuseau horaire
Je veux créer une fenêtre avec Python
Comment implémenter la mémoire partagée en Python (mmap.mmap)
Comment créer un fichier JSON en Python
Essayez de dessiner une courbe de vie avec python
Je veux faire un jeu avec Python
Notes personnelles sur le code doc Python dans Sphinx
Créer un environnement virtuel avec conda avec Python
Essayez de créer un code de "décryptage" en Python