Eine verwirrende Geschichte mit zwei Möglichkeiten, XGBoost in Python + zu implementieren

Einführung

XGBoost ist eine GBDT-Methode und kann in Python implementiert werden. Als ich jedoch die Implementierungsbeispiele untersuchte, war ich verwirrt, weil es mehrere Möglichkeiten gab, sie zu beschreiben, obwohl sie dieselbe Bibliothek verwendeten. Daher besteht der Zweck dieses Artikels darin, in jeder Notation dasselbe mit der einprägsamen Bedeutung des Autors zu versuchen. (Bitte beachten Sie, dass eine ausführliche Erläuterung von XGBoost weggelassen wird.)

Montageumgebung

pip install xgboost

Implementierungsdetails

Implementierung ~ Gemeinsamer Teil ~

Datensatz laden

import_boston_datasets.py


#Importieren Sie zuerst die Bibliothek, die dieses Mal verwendet werden soll
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)

#Fügen Sie die Zielvariable als Preis an das Ende des Datenrahmens an, um sie alle zusammen anzuzeigen.
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

Erstellung von Zugdaten und Testdaten

make_train_test.py


#Teilen Sie die Daten in Merkmal x und Zielvariable y
x = df_boston.loc[:,'CRIM':'LSTAT']
y = df_boston['PRICE']

#7:Unterteilt in Zugdaten und Testdaten bei 3
trainX, testX, trainY, testY = train_test_split(x, y, test_size=0.3)

#Versuchen Sie, jede Form auszugeben
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,)

Implementierung ~ Schulung ~

Methode 1

Methode 1 ist eine Methode, die eine Schnittstelle mit ** scikit-learn-kompatibler API ** verwendet. Ich werde es von hier aus beschreiben, mit dem Sie vielleicht vertraut sind. Zunächst von der einfachsten Implementierung ohne Angabe von Parametern.

regression1-1.py


#Verwenden Sie XGB Regressor, da es sich um eine Regression handelt
reg = xgb.XGBRegressor()

#eval_Stellen Sie die Verifizierungsdaten im Set ein
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
#Kürzung
#[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

#Vorausschauende Ausführung
predY = reg.predict(testX)

#Anzeige von MSE
print(mean_squared_error(testY, predY))
#7.4163707577050655

Wenn Sie die Parameter etwas genauer angeben, ist dies wie folgt.

regression1-2.py


reg = xgb.XGBRegressor(#Festlegen der Zielfunktion Der Anfangswert ist auch der quadratische Fehler
                       objective='reg:squarederror',
                       #Anzahl der frühen Lernrunden_Geben Sie mehr an, da das Stoppen verwendet wird
                       n_estimators=50000,
                       #Was für Booster zu verwenden ist Der Anfangswert ist auch gbtree
                       booster='gbtree',
                       #Lernrate
                       learning_rate=0.01,
                       #Maximale Tiefe des Baumes
                       max_depth=6,
                       #Startwert
                       random_state=2525)

#Bereiten Sie Variablen vor, um den Lernprozess anzuzeigen
evals_result = {}
reg.fit(trainX, trainY,
        eval_set=[(trainX, trainY),(testX, testY)],
        #Bewertungsindex zum Lernen
        eval_metric='rmse',
        #Geben Sie die Anzahl der Runden an, um das Lernen zu beenden, wenn sich die Zielfunktion nicht verbessert
        early_stopping_rounds=15,
        #Verwenden Sie die Rückruf-API, um den Lernprozess aufzuzeichnen und die oben genannten Variablen anzugeben
        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
#Kürzung
#[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

Der Verlust hat sich ein wenig verbessert, als wenn nichts angegeben wurde. Es gibt andere Parameter, die angegeben werden können, jedoch für Details XGBoost Python API-Referenz Siehe ** Scikit-Learn API ** in.

Es gibt jedoch Parameter, die nicht in diese API geschrieben sind, was häufig verwirrend ist. Zum Beispiel, wenn Sie das Modell ausgeben, wenn nichts angegeben ist

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)

Sie können den Anfangswert des Modells folgendermaßen überprüfen. Aber ganz unten

silent=None

Selbst wenn Sie dies mit der API überprüfen, ist ein solcher Parameter überhaupt nicht vorhanden. Einige Websites beschreiben es als Parameter für das Vorhandensein oder Nichtvorhandensein von Ausgaben während des Trainings, aber selbst wenn es angegeben wurde, hat sich nichts geändert.

Methode 2

Als nächstes folgt die zweite Methode: Dies ist die ** ursprüngliche API ** der xgboost-Bibliothek. Daher gibt es einen kleinen Unterschied im Umgang mit Datensätzen.

regression2-1.py


#xgb.Machen Sie es in der ursprünglichen API von DMatrix verwendbar
#feature_Sie müssen keine Namen angeben, aber es ist sicher, sie hinzuzufügen, da dies später bequem sein wird.
dtrain = xgb.DMatrix(trainX, label=trainY, feature_names = x.columns)
dtest = xgb.DMatrix(testX, label=testY, feature_names = x.columns)

reg = xgb.train(#Geben Sie eine leere Liste an, da das Training mit dem Anfangswert durchgeführt wird, ohne absichtlich Parameter anzugeben
                params=[],
                dtrain=dtrain,
                #Stellen Sie die Verifizierungsdaten in eval ein
                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

Sie können sehen, dass die Anzahl der Lernrunden standardmäßig sehr gering eingestellt ist. Das ist kein besseres Ergebnis als Methode 1. Lassen Sie uns die Parameter auf die gleiche Weise einstellen und ausführen.

regression2-2.py


#xgb.Machen Sie es in der ursprünglichen API von DMatrix verwendbar
dtrain = xgb.DMatrix(trainX, label=trainY, feature_names = x.columns)
dtest = xgb.DMatrix(testX, label=testY, feature_names = x.columns)

#Xgb zuerst_Stellen Sie die Parameter als Parameter ein
xgb_params = {#Zielfunktion
              'objective': 'reg:squarederror',
              #Bewertungsindex zum Lernen
              'eval_metric': 'rmse',
              #Was für Booster zu verwenden
              'booster': 'gbtree',
              #learning_Synonym für Rate
              'eta': 0.1,
              #Maximale Tiefe des Baumes
              'max_depth': 6,
              #random_Synonym für Staat
              'seed': 2525}

#Bereiten Sie Variablen vor, um den Lernprozess zu erhalten
evals_result = {}
reg = xgb.train(#Verwenden Sie die oben festgelegten Lernparameter
                params=xgb_params,
                dtrain=dtrain,
                #Anzahl der Lernrunden
                num_boost_round=50000,
                #Anzahl der Runden des frühen Stopps u
                early_stopping_rounds=15,
                #Überprüfungsdaten
                evals=[(dtrain, 'train'), (dtest, 'eval')],
                #Stellen Sie die oben vorbereiteten Variablen ein
                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
#Kürzung
#[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

Der während des Lernprozesses angezeigte Verlust ist genau der gleiche wie in Methode 1. Wenn Sie jedoch danach MSE vorhersagen und ausgeben, ist der Wert anders ... Ich kenne die Ursache nicht, daher werde ich sie weitergeben. Wie Sie beim Vergleich der Codes sehen können, unterscheiden sich die Namen der Parameter und die Stellen, an denen sie geschrieben sind, geringfügig. Seien Sie also vorsichtig. Wenn beispielsweise die Lernrate eta wie in Methode 1 als Lernrate festgelegt ist, kann sie ausgeführt werden, der Wert wird jedoch nicht wiedergegeben. Über diesen Parameter XGBoost Parameters Wann XGBoost Python API-Referenz Schauen Sie sich die ** Lern-API ** an.

Implementierung ~ Grafische Darstellung des Lernprozesses ~

Da der Wert in ** evals_result ** gespeichert ist, das zum Zeitpunkt des Lernens erstellt wurde, wird der Übergang damit grafisch dargestellt.

Methode 1

plot_validation1.py


#Zeichnen Sie den Verlustübergang für Zugdaten
plt.plot(evals_result['validation_0']['rmse'], label='train rmse')
#Plotverlustübergang für Testdaten
plt.plot(evals_result['validation_1']['rmse'], label='eval rmse')
plt.grid()
plt.legend()
plt.xlabel('rounds')
plt.ylabel('rmse')
plt.show()

img.png

Methode 2

Aus irgendeinem Grund unterscheidet sich der Name in evals_result von dem in Methode 1.

plot_validation2.py


#Zeichnen Sie den Verlustübergang für Zugdaten
plt.plot(evals_result['train']['rmse'], label='train rmse')
#Plotverlustübergang für Testdaten
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

Implementierung ~ Anzeige der Funktionsbedeutung ~

xgboost verfügt über eine Methode namens ** xgb.plot_importance () **, die FeatureImportance darstellt, die in beiden Methoden 1 und 2 verwendet werden kann.

plot_importance.py


xgb.plot_importance(reg)

img.png

Sie können auch important_type als Argument angeben. API Beschreibung und Wichtigkeitstyp Wenn Sie auf [diesen Artikel] verweisen (https://qiita.com/hand10ryo/items/ed1e511b5236f7bfe606)

Sie können drei davon verwenden. (Es scheint, dass Sie anstelle des Durchschnittswerts zum Lesen der API auch den Gesamtwert für Gewinn und Deckung verwenden können.) Der Anfangswert scheint Gewicht zu sein. Wenn Sie beispielsweise die Verstärkung angeben und ausgeben, sieht dies wie folgt aus.

plot_importance.py


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

img.png

Es gibt auch eine Methode namens ** xgb.get_score () **, mit der Sie die im Diagramm verwendeten Werte als Wörterbuch abrufen können. Diese Methode ist jedoch nur in Methode 2 ** verfügbar, und ich bin mir nicht sicher, ob es in Methode 1 eine Möglichkeit gibt, etwas Ähnliches zu tun ... Ich mache mir Sorgen über die Inkonsistenzen hier.

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}

Ich denke, dass feature_names beim Erstellen der DMatrix angegeben wurde, aber wenn Sie es nicht angeben, wird der Name des Feature-Betrags nicht in der Grafik usw. angezeigt, so dass es sehr schwer zu verstehen ist. Es ist gut, ihn festzulegen.

Andere Merkmale jeder Methode

Methode 1

Ich denke, der bequemste Punkt von Methode 1 ist, dass die Parametersuche mit GridSerchCV von sklearn möglich ist. Soweit ich dies überprüft habe, wurde Methode 1 in allen Artikeln verwendet, die XGBoost für die Parametersuche verwendeten. Der Code des Lebenslaufs für die zufällige Suche wird als Referenz angegeben.

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 hat eine zufällige Suchanzahl
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'}

Methode 2

Um ehrlich zu sein, bin ich der Meinung, dass die ursprüngliche API nicht bekannt ist und Sie sich nicht die Mühe machen müssen, sie zu verwenden. Es kann jedoch auch andere solche Beispiele geben, da einige Methoden nur mit dieser Methode oben verwendet werden können. Wird das Basic nach Methode 1 implementiert? Ich denke, es wäre besser, dieses hier zu implementieren, wenn Sie dies nicht tun können.

abschließend

Dieses Mal habe ich bei der Untersuchung von XGBoost die unklaren Punkte aufgrund der Methodenmischung so einfach wie möglich zusammengefasst. Ich hoffe, dass jemand in einer ähnlichen Situation hierher kommt und das Problem löst. Es gibt viele andere nützliche Methoden in der xgboost-Bibliothek, z. B. eine Methode, mit der der generierte Baum als Diagramm angezeigt werden kann. Es wird daher empfohlen, einen kurzen Blick auf die API zu werfen und sie auf verschiedene Arten zu implementieren. Dies ist der erste Qiita-Artikel in meinem Leben, und ich denke, es ist nicht genug, aber danke, dass Sie so weit gelesen haben.

Referenzartikel

Python: Versuchen Sie es mit XGBoost Verwendung von xgboost: Klassifizierung mehrerer Klassen nach Irisdaten Verwenden von XGBoost mit Python Xgboost: Berechnen des Wichtigkeitstyps von feature_importance xgboost: Effektives Modell für maschinelles Lernen für Tabellendaten

Recommended Posts

Eine verwirrende Geschichte mit zwei Möglichkeiten, XGBoost in Python + zu implementieren
Eine Geschichte über den Versuch, private Variablen in Python zu implementieren.
[Hinweis] Eine Geschichte über den Versuch, eine Klassenmethode mit zwei Unterbalken in der Python 3-Serie zu überschreiben.
Ich möchte Timeout einfach in Python implementieren
Ich habe versucht, einen Pseudo-Pachislot in Python zu implementieren
Ich möchte mit einem Roboter in Python arbeiten.
Ich habe versucht, einen eindimensionalen Zellautomaten in Python zu implementieren
Eine Geschichte darüber, wie man einen relativen Pfad in Python angibt.
6 Möglichkeiten zum Stringen von Objekten in Python
5 Möglichkeiten zum Erstellen eines Python-Chatbots
Eine Geschichte über das Hinzufügen einer REST-API zu einem mit Python erstellten Daemon
Implementieren Sie einen deterministischen endlichen Automaten in Python, um Vielfache von 3 zu bestimmen
Ich habe versucht, ein missverstandenes Gefangenendilemma in Python zu implementieren
Zwei Möglichkeiten, mit matplotlib mehrere Grafiken in einem Bild anzuzeigen
Eine Geschichte, die nicht funktioniert hat, als ich versucht habe, mich mit dem Python-Anforderungsmodul anzumelden
Ich habe versucht, PLSA in Python zu implementieren
Spiralbuch in Python! Python mit einem Spiralbuch! (Kapitel 14 ~)
Versuchen Sie, sich mit Python bei qiita anzumelden
[Kleine Geschichte] So speichern Sie Matplotlib-Diagramme in einem Stapel mit Jupyter
Ich habe versucht, Permutation in Python zu implementieren
Ich habe versucht, PLSA in Python 2 zu implementieren
So arbeiten Sie mit BigQuery in Python
Wie bekomme ich Stacktrace in Python?
Beachten Sie, dass Djangos Runserver in Python 2.7.11, das mit Homebrew geliefert wird, Moos ist
Ich habe versucht, ADALINE in Python zu implementieren
Ich habe versucht, PPO in Python zu implementieren
So betreiben Sie die Zeitstempelstation in Python
Ich habe versucht, Trumps Kartenspiel in Python zu implementieren
Verschiedene Möglichkeiten, die letzte Zeile einer CSV-Datei in Python zu lesen
Ich habe versucht, die Zusammenführungssortierung in Python mit möglichst wenigen Zeilen zu implementieren
[Python] Erstellt eine Klasse, um mit pyaudio Sinuswellen im Hintergrund zu spielen
Eine Geschichte, die in 4 Monaten nach dem Start von AtCoder mit Python hellblau wurde
So legen Sie Google Text & Tabellen in einem Ordner zusammen in einer TXT-Datei mit Python ab
Auf der Suche nach einer effizienten Möglichkeit, eine Docker-Datei mit Python mit Gedichten zu schreiben
Ich habe versucht, ein scheinbar Windows-Snipper-Tool mit Python zu implementieren
Eine Geschichte, der ich nach der SFTP-Kommunikation mit Python verfallen war
Geben Sie Notizen zu Python-Skripten ein, um das PyTorch-Modell in C ++ mit libtorch auszuführen
So erhalten Sie mit Python eine Liste der Dateien im selben Verzeichnis
[Python] Listenverständnis Verschiedene Möglichkeiten zum Erstellen einer Liste
Lesen einer CSV-Datei mit Python 2/3
Versuchen Sie, Oni Mai Tsuji Miserable mit Python zu implementieren
Senden Sie eine Nachricht mit Python an LINE (LINE Notify)
3 Möglichkeiten, Zeitzeichenfolgen mit Python zu analysieren [Hinweis]
[Python] Holen Sie sich die Dateien mit Python in den Ordner
Berechnen wir das statistische Problem mit Python
[REAPER] Wie man Reascript mit Python spielt
So löschen Sie einen Taple in einer Liste (Python)
Einbetten von Variablen in Python-Strings
Konvertieren Sie PDFs mit Python in Massenbilder
[Python3] Eine Geschichte, die bei der Zeitzonenkonvertierung steckt
Ich möchte mit Python ein Fenster erstellen
So implementieren Sie Shared Memory in Python (mmap.mmap)
So erstellen Sie eine JSON-Datei in Python
Versuchen Sie, mit Python eine Lebenskurve zu zeichnen
Ich möchte ein Spiel mit Python machen
Persönliche Notizen zum Dokumentieren von Python-Code in Sphinx
Erstellen Sie eine virtuelle Umgebung mit conda in Python
Versuchen Sie, in Python einen "Entschlüsselungs" -Code zu erstellen