Ich habe einige Anfragen zur Unterstützung monotoner Einschränkungen für bestimmte Funktionen in Bezug auf die Ausgabe erhalten.
dh wenn andere Merkmale festgelegt sind, erzwingen Sie eine monoton ansteigende Vorhersage bezüglich des bestimmten spezifizierten Merkmals. Ich öffne diese Ausgabe, um das allgemeine Interesse an dieser Funktion zu erfahren. Ich kann dies hinzufügen, wenn genügend Interesse besteht,
Ich benötige die Hilfe von Freiwilligen aus der Community, um die Beta-Funktion zu testen und ein Dokument und ein Tutorial zur Verwendung dieser Funktion beizutragen. Bitte beantworten Sie das Problem, wenn Sie interessiert sind
Eine experimentelle Version wird unter https://github.com/dmlc/xgboost/pull/1516 bereitgestellt https://github.com/tqchen/xgboost .
Schalten Sie die folgenden Optionen ein (wahrscheinlich über Python, r API möglich)
monotone_constraints = "(0,1,1,0)"
Es gibt zwei Argumente
monotone_constraints
ist eine Liste in der Länge der Anzahl von Features, 1 bedeutet monoton ansteigend, - 1 bedeutet abnehmend, 0 bedeutet keine Einschränkung. Wenn es kürzer als die Anzahl der Merkmale ist, wird 0 aufgefüllt.Unterstützt derzeit nur den exakten gierigen Algorithmus auf Multi-Core. Noch nicht in der verteilten Version verfügbar
@tqchen Ich habe heute bei der Arbeit eine Anfrage erhalten, einige GBMs mit monotonen Einschränkungen zu bauen, um die Leistung einiger anderer Modelle zu testen. Dies wäre mit einem Tweedie-Abweichungsverlust, also müsste ich mit einer benutzerdefinierten Verlustfunktion gehen, wie sie heute steht.
Auf jeden Fall scheint es eine gute Gelegenheit zu sein, zu helfen und gleichzeitig etwas zu erledigen.
Basierend auf der Diskussion hier erzwingt GBM(R Package) Monotonie nur lokal.
Könnten Sie klarstellen, wie XGBoost monotone Einschränkungen erzwingt?
Es wäre großartig, wenn XGBoost globale Einschränkungen durchsetzen könnte.
Ich verstehe nicht, was Sie mit lokaler oder globaler Einschränkung meinen, können Sie das näher erläutern?
Entschuldigung, ich habe den falschen Link eingefügt, hier ist der richtige (Link)
Jeder Baum kann nur in einer bestimmten Teilmenge des interessierenden Merkmals einer monotonen Beschränkung folgen, so dass viele Baumensembles zusammen eine Verletzung der Gesamtmonotonie im gesamten Bereich dieses Merkmals verursachen können.
OK, nach meinem Verständnis wird es global durchgesetzt. Sie sind herzlich eingeladen, es auszuprobieren.
Habe gerade einige einfache Tests der Monotonie-Beschränkung im Kontext einer univariaten Regression durchgeführt. Den Code und eine sehr kurze Dokumentation finden Sie hier:
Einige erste Beobachtungen:
Es stellte sich heraus, dass ich im Fall von Constraint = -1 einen Fehler einführe. Ich habe einen Fix verschoben, bitte sehen Sie, ob die neueste Version gut funktioniert. Bitte überprüfen Sie auch, ob es funktioniert, wenn mehrere Einschränkungen vorliegen
@tqchen Ich habe Ihren Fix auf den abnehmenden Fehler getestet, scheint jetzt zu funktionieren.
Lassen Sie uns bestätigen, ob bei einigen Standarddatensätzen die Geschwindigkeit gegenüber der Originalversion abnimmt, dann können wir sie zusammenführen
@tqchen Ich habe ein Modell mit zwei Variablen getestet, eines mit einer zunehmenden Einschränkung und eines mit einer abnehmenden:
params_constrained = params.copy()
params_constrained['updater'] = "grow_monotone_colmaker,prune"
params_constrained['monotone_constraints'] = "(1,-1)"
Die Ergebnisse sind gut
Ich werde versuchen, heute Nachmittag ein wenig Zeit zu finden, um ein paar Timing-Tests zu machen.
Ich habe ein Update auf #1516 vorgenommen, um die automatische Erkennung von Montone-Optionen zu ermöglichen. Jetzt muss der Benutzer nur noch monotone_constraints = "(0,1,1,0)"
eingeben, bitte überprüfen Sie, ob es funktioniert.
Ich werde dies einbinden, wenn die Geschwindigkeitstests in Ordnung sind, und lassen Sie uns zur nächsten Phase des Hinzufügens von Tutorials übergehen
@madrury @XiaoxiaoWang87
Tests für den multivariaten Fall hier hinzugefügt:
no constraint: 964.9 microseconds per iteration
with constraint: 861.7 microseconds per iteration
(bitte kommentieren, wenn Sie eine bessere Möglichkeit haben, den Geschwindigkeitstest durchzuführen)
Check failed: (wleft) <= (wright)
beim Spielen mit verschiedenen Hyperparametern zu sehen.Ich habe ein paar Timing-Experimente in einem Jupyter-Notebook durchgeführt.
Erster Test: einige einfache simulierte Daten. Es gibt zwei Merkmale, eine ansteigende und eine abnehmende, aber mit einer kleinen Sinuswelle überlagert, so dass jede Funktion nicht wirklich monoton ist
X = np.random.random(size=(N, K))
y = (5*X[:, 0] + np.sin(5*2*pi*X[:, 0])
- 5*X[:, 1] - np.cos(5*2*pi*X[:, 1])
+ np.random.normal(loc=0.0, scale=0.01, size=N))
Hier sind Timing-Ergebnisse von xgboosts mit und ohne monotone Einschränkungen. Ich habe das frühe Stoppen deaktiviert und für jeden eine bestimmte Anzahl von Iterationen erhöht.
Zuerst ohne monotone Einschränkungen:
%%timeit -n 100
model_no_constraints = xgb.train(params, dtrain,
num_boost_round = 2500,
verbose_eval = False)
100 loops, best of 3: 246 ms per loop
Und hier mit Monotonie-Einschränkungen
%%timeit -n 100
model_with_constraints = xgb.train(params_constrained, dtrain,
num_boost_round = 2500,
verbose_eval = False)
100 loops, best of 3: 196 ms per loop
Zweiter Test: Kalifornische Wohnungsdaten von sklearn. Ohne Einschränkungen
%%timeit -n 10
model_no_constraints = xgb.train(params, dtrain,
num_boost_round = 2500,
verbose_eval = False)
10 loops, best of 3: 5.9 s per loop
Hier sind die Einschränkungen, die ich verwendet habe
print(params_constrained['monotone_constraints'])
(1,1,1,0,0,1,0,0)
Und das Timing für das eingeschränkte Modell
%%timeit -n 10
model_no_constraints = xgb.train(params, dtrain,
num_boost_round = 2500,
verbose_eval = False)
10 loops, best of 3: 6.08 s per loop
@XiaoxiaoWang87 Ich habe einen anderen PR gedrängt, den Scheck auf wleft und wright zu verlieren, bitte sehen Sie, dass es funktioniert.
@madrury Können Sie auch ohne die Einschränkungsfunktion mit einer früheren Version von XGBoost vergleichen?
@tqchen Klar. Können Sie einen Commit-Hash zum Vergleich empfehlen? Soll ich einfach den Commit verwenden, bevor Sie die monotonen Einschränkungen hinzufügen?
Ja der vorherige wird reichen
@tqchen Beim erhalte ich einige Fehler, die ich vorher nicht hatte. Ich hoffe, der Grund fällt Ihnen klar auf.
Wenn ich versuche, denselben Code wie zuvor auszuführen, erhalte ich eine Ausnahme, hier ist der vollständige Traceback:
XGBoostError Traceback (most recent call last)
<ipython-input-14-63a9f6e16c9a> in <module>()
8 model_with_constraints = xgb.train(params, dtrain,
9 num_boost_round = 1000, evals = evallist,
---> 10 early_stopping_rounds = 10)
/Users/matthewdrury/anaconda/lib/python2.7/site-packages/xgboost-0.6-py2.7.egg/xgboost/training.pyc in train(params, dtrain, num_boost_round, evals, obj, feval, maximize, early_stopping_rounds, evals_result, verbose_eval, learning_rates, xgb_model, callbacks)
201 evals=evals,
202 obj=obj, feval=feval,
--> 203 xgb_model=xgb_model, callbacks=callbacks)
204
205
/Users/matthewdrury/anaconda/lib/python2.7/site-packages/xgboost-0.6-py2.7.egg/xgboost/training.pyc in _train_internal(params, dtrain, num_boost_round, evals, obj, feval, xgb_model, callbacks)
72 # Skip the first update if it is a recovery step.
73 if version % 2 == 0:
---> 74 bst.update(dtrain, i, obj)
75 bst.save_rabit_checkpoint()
76 version += 1
/Users/matthewdrury/anaconda/lib/python2.7/site-packages/xgboost-0.6-py2.7.egg/xgboost/core.pyc in update(self, dtrain, iteration, fobj)
804
805 if fobj is None:
--> 806 _check_call(_LIB.XGBoosterUpdateOneIter(self.handle, iteration, dtrain.handle))
807 else:
808 pred = self.predict(dtrain)
/Users/matthewdrury/anaconda/lib/python2.7/site-packages/xgboost-0.6-py2.7.egg/xgboost/core.pyc in _check_call(ret)
125 """
126 if ret != 0:
--> 127 raise XGBoostError(_LIB.XGBGetLastError())
128
129
XGBoostError: [14:08:41] src/tree/tree_updater.cc:18: Unknown tree updater grow_monotone_colmaker
Wenn ich alles für das von Ihnen implementierte Schlüsselwortargument auswechsele, erhalte ich ebenfalls eine Fehlermeldung:
TypeError Traceback (most recent call last)
<ipython-input-15-ef7671f72925> in <module>()
8 monotone_constraints="(1)",
9 num_boost_round = 1000, evals = evallist,
---> 10 early_stopping_rounds = 10)
TypeError: train() got an unexpected keyword argument 'monotone_constraints'
Entfernen Sie das Updater-Argument und behalten Sie die monotonen Einschränkungsargumente in Parametern bei, da der monotone Einschränkungs-Updater jetzt automatisch aktiviert wird, wenn monotone Einschränkungen angezeigt werden
@tqchen Mein Kumpel @amontz hat mir sofort nach dem monotone_constraints
als Kwarg an .train
.
Es funktioniert mit diesen Anpassungen. Danke.
@madrury kannst du die Geschwindigkeit bestätigen?
Auch @madrury und @XiaoxiaoWang87 Da diese Funktion jetzt kurz vor der Zusammenführung steht, wäre es großartig, wenn Sie sich koordinieren könnten, um ein Tutorial zu erstellen, das den Benutzern diese Funktion vorstellt.
Wir können ipy notebook nicht direkt zum Hauptrepo bringen. Bilder können jedoch auf https://github.com/dmlc/web-data/tree/master/xgboost und Markdown zum Hauptrepo verschoben werden.
Wir müssen auch die Stringkonvertierung der Front-End-Schnittstelle ändern, damit das int-Tupel in das String-Tupelformat konvertiert werden kann, das vom Backend akzeptiert wird.
@hetong007 für Änderungen in R und @slundberg für Julia
@tqchen Julia ist derzeit an die 0.4-Version von XGBoost angehängt, also wenn ich es das nächste Mal verwenden muss und Zeit habe, werde ich die Bindungen aktualisieren, wenn bis dahin niemand anderes hat. An diesem Punkt kann diese Änderung auch hinzugefügt werden.
Hier ist der Vergleich zwischen Modellen _ohne_ einer monotonen Einschränkung von vor der Implementierung bis nachher.
Commit 8cac37 : Vor der Implementierung der monotonen Einschränkung.'
Simulierte Daten : 100 loops, best of 3: 232 ms per loop
Kalifornien-Daten : 10 loops, best of 3: 5.89 s per loop
Commit b1c224 : Nach der Implementierung der monotonen Einschränkung.
Simulierte Daten : 100 loops, best of 3: 231 ms per loop
Kalifornien-Daten : 10 loops, best of 3: 5.61 s per loop
Die Beschleunigung für Kalifornien nach der Implementierung erscheint mir verdächtig, aber ich habe es zweimal versucht, und es ist konsistent.
Ich würde gerne versuchen, ein Tutorial zu schreiben. Ich werde mich in der vorhandenen Dokumentation umschauen und in den nächsten Tagen etwas zusammenstellen.
Das ist toll, die PR ist jetzt offiziell mit dem Master verschmolzen. Freue mich auf das Tutorial
Danke @madrury. Ich freue mich auf. Lassen Sie mich wissen, was ich helfen kann. Über weitere Studien zu diesem Thema würde ich mich auf jeden Fall freuen.
Ich werde es morgen verbessern. Ich bin nur neugierig auf den Grund der Kommunikation mit C++ über einen String anstelle eines Arrays.
Ich teste von R. Ich habe zufällig Daten mit zwei Variablen generiert und versuche, Vorhersagen zu treffen.
Das habe ich jedoch gefunden
monotone_constraints
macht die Vorhersage etwas anders.Bitte weisen Sie darauf hin, wenn ich Fehler gemacht habe.
Der Code, um es zu reproduzieren (getestet auf der neuesten Github-Version , nicht von drat
):
set.seed(1024)
x1 = rnorm(1000, 10)
x2 = rnorm(1000, 10)
y = -1*x1 + rnorm(1000, 0.001) + 3*sin(x2)
train = cbind(x1, x2)
bst = xgboost(data = train, label = y, max_depth = 2,
eta = 0.1, nthread = 2, nrounds = 10,
monotone_constraints = '(1,-1)')
pred = predict(bst, train)
ind = order(train[,1])
pred.ord = pred[ind]
plot(train[,1], y, main = 'with constraint')
pred.ord = pred[order(train[,1])]
lines(pred.ord)
bst = xgboost(data = train, label = y, max_depth = 2,
eta = 0.1, nthread = 2, nrounds = 10)
pred = predict(bst, train)
ind = order(train[,1])
pred.ord = pred[ind]
plot(train[,1], y, main = 'without constraint')
pred.ord = pred[order(train[,1])]
lines(pred.ord)
Die Einschränkung wurde für die Teilbestellung durchgeführt. Die Beschränkung wird also nur erzwungen, wenn wir die Montonachse bewegen und die andere Achse festhalten
@hetong007 Um meine Pläne zu machen, habe ich
seq
in R verwenden.colmeans
in R.Hier ist der Python-Code, den ich für die oben eingefügten Plots verwendet habe. Er sollte ziemlich leicht in einen entsprechenden R-Code konvertiert werden.
def plot_one_feature_effect(model, X, y, idx=1):
x_scan = np.linspace(0, 1, 100)
X_scan = np.empty((100, X.shape[1]))
X_scan[:, idx] = x_scan
left_feature_means = np.tile(X[:, :idx].mean(axis=0), (100, 1))
right_feature_means = np.tile(X[:, (idx+1):].mean(axis=0), (100, 1))
X_scan[:, :idx] = left_feature_means
X_scan[:, (idx+1):] = right_feature_means
X_plot = xgb.DMatrix(X_scan)
y_plot = model.predict(X_plot, ntree_limit=bst.best_ntree_limit)
plt.plot(x_scan, y_plot, color = 'black')
plt.plot(X[:, idx], y, 'o', alpha = 0.25)
So mache ich die partiellen Abhängigkeitsdiagramme (für ein beliebiges Modell):
Code:
def plot_partial_dependency(bst, X, y, f_id):
X_temp = X.copy()
x_scan = np.linspace(np.percentile(X_temp[:, f_id], 0.1), np.percentile(X_temp[:, f_id], 99.5), 50)
y_partial = []
for point in x_scan:
X_temp[:, f_id] = point
dpartial = xgb.DMatrix(X_temp[:, feature_ids])
y_partial.append(np.average(bst.predict(dpartial)))
y_partial = np.array(y_partial)
# Plot partial dependence
fig, ax = plt.subplots()
fig.set_size_inches(5, 5)
plt.subplots_adjust(left = 0.17, right = 0.94, bottom = 0.15, top = 0.9)
ax.plot(x_scan, y_partial, '-', color = 'black', linewidth = 1)
ax.plot(X[:, f_id], y, 'o', color = 'blue', alpha = 0.02)
ax.set_xlim(min(x_scan), max(x_scan))
ax.set_xlabel('Feature X', fontsize = 10)
ax.set_ylabel('Partial Dependence', fontsize = 12)
Danke für die Anleitung! Mir wurde klar, dass ich einen dummen Fehler in der Handlung gemacht hatte. Hier ist ein weiterer Test für univariate Daten, der Plot scheint in Ordnung zu sein:
set.seed(1024)
x = rnorm(1000, 10)
y = -1*x + rnorm(1000, 0.001) + 3*sin(x)
train = matrix(x, ncol = 1)
bst = xgboost(data = train, label = y, max_depth = 2,
eta = 0.1, nthread = 2, nrounds = 100,
monotone_constraints = '(-1)')
pred = predict(bst, train)
ind = order(train[,1])
pred.ord = pred[ind]
plot(train[,1], y, main = 'with constraint', pch=20)
lines(train[ind,1], pred.ord, col=2, lwd = 5)
bst = xgboost(data = train, label = y, max_depth = 2,
eta = 0.1, nthread = 2, nrounds = 100)
pred = predict(bst, train)
ind = order(train[,1])
pred.ord = pred[ind]
plot(train[,1], y, main = 'without constraint', pch=20)
lines(train[ind,1], pred.ord, col=2, lwd = 5)
@hetong007 Das Ziel in der R-Schnittstelle besteht also darin, dem Benutzer die Möglichkeit zu geben, neben den Strings das R-Array zu übergeben
monotone_constraints=c(1,-1)
Bitte lassen Sie es uns wissen, wenn Sie PR für das Tutorial machen
@hetong007 Sie sind auch mehr als willkommen, eine R-Blogger-Version zu
@tqchen Sorry Leute, ich war die Woche auf Dienstreise.
Ich habe ein paar Pull-Requests mit für ein Tutorial zu monotonen Einschränkungen gesendet. Bitte teilen Sie mir Ihre Meinung mit, ich freue mich über jede Kritik oder Kritik.
Hoffentlich ist es angebracht, dies hier zu fragen: Funktioniert das jetzt, wenn wir mit den üblichen git clone --recursive https://github.com/dmlc/xgboost
aktualisieren?
Ich frage, wie ich das neue Tutorial gesehen habe, aber nichts Neues über eine Änderung des Codes selbst. Danke euch allen!
Ja, die neue Funktion wird zusammengeführt, bevor das Tutorial zusammengeführt wird
Hallo,
Ich bin mir nicht sicher, ob Sie die globale Monotonie erfolgreich implementiert haben, von dem, was ich in Ihrem Code gesehen habe, entspricht es eher einer lokalen Monotonie.
Hier ist ein einfaches Beispiel, das Monotonie bricht:
`
df <- data.frame(y = c(2,rep(6,100),1,rep(11,100)),
x1= c(rep(1,101),rep(2,101)),x2 = c(1,rep(2,100),1,rep(2,100)))
Bibliothek (xgboost)
set.saat(0)
XGB <- xgboost(data=data.matrix(df[,-1]),label=df[,1],
objektiv=" reg:linear ",
bag.fraction=1,nround=100,monotone_constraints=c(1,0),
eta=0,1 )
sans_corr <- data.frame(x1=c(1,2,1,2),x2=c(1,1,2,2))
sans_corr$prediction <- Predict(XGB,data.matrix(sans_corr))
`
Ich hoffe, mein Verständnis Ihres Codes und meines Beispiels ist nicht falsch
Derzeit ist diese Funktion nicht in der Sklearn-API enthalten. Können Sie oder jemand bitte helfen, es hinzuzufügen? Danke!
Ist es möglich, einer Variablen eine allgemeine Monotonie zu erzwingen, ohne anzugeben, ob sie steigend oder fallend sein soll?
@davidADSP Sie können eine Spearman-Korrelationsprüfung für den gewünschten Prädiktor und das gewünschte Ziel durchführen, um zu sehen, ob eine Erhöhung oder Verringerung richtig ist.
Diese Funktion scheint ungültig zu sein, wenn 'tree_method':'hist'. @tqchen Hilfe? Danke an alle.
Wie funktioniert die Einschränkung für ein Mehrklassenziel wie mlogloss? Wird die Einschränkung der Monotonie für Mehrklassenverluste unterstützt? Wenn ja, wie wird es durchgesetzt. (Für jede Klasse gibt es einen Baum)
Gibt es ein Whitepaper zum Monotizitätsalgorithmus, der in XGBOOST erzwungen wird? Ist es global oder lokal? Lokal bedeutet spezifisch für bestimmte Knoten, aber Knoten in anderen Teilen des Baums können eine Verletzung der Gesamtmonotonie verursachen. Kann mir bitte auch jemand helfen, die Zeile L412-417 zu verstehen. Warum "w" begrenzt ist - nach oben und unten. Wie dies hilft, die Monotonie aufrechtzuerhalten. Zeile 457 - Warum wird "mid" verwendet?
Hilfreichster Kommentar
Derzeit ist diese Funktion nicht in der Sklearn-API enthalten. Können Sie oder jemand bitte helfen, es hinzuzufügen? Danke!