Xgboost: [R] Bester Iterationsindex vom frĂŒhen Stoppen wird verworfen, wenn das Modell auf der Festplatte gespeichert wird

Erstellt am 15. Jan. 2020  Â·  33Kommentare  Â·  Quelle: dmlc/xgboost

Diese Werte werden nach xgboost::xgb.train vorhergesagt:
247367.2 258693.3 149572.2 201675.8 250493.9 292349.2 414828.0 296503.2 260851.9 190413.3

Diese Werte werden nach xgboost::xgb.save und xgboost::xgb.load des VorgÀngermodells vorhergesagt:
247508.8 258658.2 149252.1 201692.6 250458.1 292313.4 414787.2 296462.5 260879.0 190430.1

Sie sind nah, aber nicht gleich. Die Unterschiede zwischen diesen beiden Vorhersagen reichen von -1317.094 bis 1088.859 bei einem Satz von 25.000 Stichproben. Beim Vergleich mit wahren Labels unterscheiden sich die MAE/RMSE dieser beiden Vorhersagen nicht wesentlich.

Ich vermute also, dass dies mit Rundungsfehlern beim Laden/Speichern zu tun hat, da sich MAE/RMSE nicht so stark unterscheiden. Trotzdem finde ich das seltsam, da das binĂ€re Speichern des Modells keine Rundungsfehler einfĂŒhren sollte?

Jemand eine Ahnung?

PS Das Hochladen und Dokumentieren des Schulungsprozesses scheint mir hier nicht wichtig. Ich könnte bei Bedarf Details liefern oder eine Simulation mit Dummy-Daten durchfĂŒhren, um das zu beweisen.

Blocking bug

Hilfreichster Kommentar

Geheimnis gelĂŒftet. Ich habe die wahre Ursache identifiziert. Beim Speichern des Modells auf der Festplatte werden Informationen zum vorzeitigen Stoppen verworfen. Im Beispiel fĂŒhrt XGBoost 6381 Boosting-Runden aus und findet das beste Modell bei 6378 Runden. Das Modellobjekt im Speicher enthĂ€lt 6381 BĂ€ume, nicht 6378 BĂ€ume, da kein Baum entfernt wird. Es gibt ein zusĂ€tzliches Feld best_iteration , das sich daran erinnert, welche Iteration die beste war:

> fit$best_iteration
[1] 6378

Dieses zusĂ€tzliche Feld wird stillschweigend verworfen, wenn wir das Modell auf der Festplatte speichern. So verwendet predict() mit dem ursprĂŒnglichen Modell 6378 BĂ€ume, wĂ€hrend predict() mit dem wiederhergestellten Modell 6381 BĂ€ume verwendet.

> x <- predict(fit, newdata = dtrain2, predleaf = TRUE)
> x2 <- predict(fit.loaded, newdata = dtrain2, predleaf = TRUE)
> dim(x)
[1] 5000 6378
> dim(x2)
[1] 5000 6381

Alle 33 Kommentare

Es sollte kein Rundungsfehler sowohl fĂŒr BinĂ€r als auch fĂŒr JSON auftreten. Benutzt du Dart?

Nein, bin ich nicht:

params <- list(objective = 'reg:squarederror',
               max_depth = 10, eta = 0.02, subsammple = 0.5,
               base_score = median(xgboost::getinfo(xgb.train, 'label'))
)

xgboost::xgb.train(
  params = params, data = xgb.train,
  watchlist = list('train' = xgb.train, 'test' = xgb.test),
  nrounds = 10000, verbose = TRUE, print_every_n = 25,
  eval_metric = 'mae',
  early_stopping_rounds = 3, maximize = FALSE)

Können Sie uns Dummy-Daten zur VerfĂŒgung stellen, wo dieses PhĂ€nomen auftritt?

Los geht's (Quick & Dirty):

N <- 100000
set.seed(2020)
X <- data.frame('X1' = rnorm(N), 'X2' = runif(N), 'X3' = rpois(N, lambda = 1))
Y <- with(X, X1 + X2 - X3 + X1*X2^2 - ifelse(X1 > 0, 2, X3))

params <- list(objective = 'reg:squarederror',
               max_depth = 5, eta = 0.02, subsammple = 0.5,
               base_score = median(Y)
)

dtrain <- xgboost::xgb.DMatrix(data = data.matrix(X), label = Y)

fit <- xgboost::xgb.train(
  params = params, data = dtrain,
  watchlist = list('train' = dtrain),
  nrounds = 10000, verbose = TRUE, print_every_n = 25,
  eval_metric = 'mae',
  early_stopping_rounds = 3, maximize = FALSE
)

pred <- stats::predict(fit, newdata = dtrain)

xgboost::xgb.save(fit, 'booster.raw')
fit.loaded <- xgboost::xgb.load('booster.raw')

pred.loaded <- stats::predict(fit.loaded, newdata = dtrain)

identical(pred, pred.loaded)
pred[1:10]
pred.loaded[1:10]

sqrt(mean((Y - pred)^2))
sqrt(mean((Y - pred.loaded)^2))

Auf meinem Computer ist identical(pred, pred.loaded) FALSE (dh sollte WAHR sein). Hier die Ausgabe der letzten Befehle:

> identical(pred, pred.loaded)
[1] FALSE
> pred[1:10]
 [1] -4.7971768 -2.5070562 -0.8889422 -4.9199696 -4.4374819 -0.2739395 -0.9825708  0.4579227  1.3667605 -4.3333349
> pred.loaded[1:10]
 [1] -4.7971768 -2.5070562 -0.8889424 -4.9199696 -4.4373770 -0.2739397 -0.9825710  0.4579227  1.3667605 -4.3333349
> 
> sqrt(mean((Y - pred)^2))
[1] 0.02890702
> sqrt(mean((Y - pred.loaded)^2))
[1] 0.02890565

Sie sehen, dass die Vorhersagen manchmal leicht abweichen. Können Sie den Beispielcode auf Ihrem Computer erneut ausfĂŒhren und sehen, ob das gleiche Problem auftritt?

Einige zusÀtzliche Informationen zu R und xgboost:

> sessionInfo()
R version 3.6.1 (2019-07-05)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252    LC_MONETARY=English_United States.1252 LC_NUMERIC=C                          
[5] LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
 [1] compiler_3.6.1    magrittr_1.5      Matrix_1.2-17     tools_3.6.1       yaml_2.2.0        xgboost_0.90.0.2  stringi_1.4.3     grid_3.6.1       
 [9] data.table_1.12.4 lattice_0.20-38 

Beachten Sie auch:

> identical(fit$raw, fit.loaded$raw)
[1] TRUE

Danke fĂŒr das Skript. Nur ein Update, ich habe es sowohl in der Json- als auch in der BinĂ€rdatei gespeichert mit:

xgboost::xgb.save(fit, 'booster.json')
fit.loaded <- xgboost::xgb.load('booster.json')

xgboost::xgb.save(fit.loaded, 'booster-1.json')

Die Hashwerte (via sha256sum ./booster.json ) von booster.json und booster-1.json sind genau gleich, also vermute ich, dass es irgendwo eine Diskrepanz gibt, die durch Gleitkommaarithmetik verursacht wird.

Warum das Problem schließen, ohne die Ursache zu kennen?

@trivialfis Hast du True fĂŒr identical(pred, pred.loaded) ? Das OP fragt, warum die Vorhersagen nicht ĂŒbereinstimmen, obwohl zwei Modelle dieselbe binĂ€re Signatur haben.

Ich werde versuchen, es selbst zu reproduzieren.

Oh, das tut mir leid. Die Ursache, die ich gefunden habe, ist der Vorhersage-Cache. Nach dem Laden des Modells stammen die Vorhersagewerte aus der echten Vorhersage und nicht aus dem zwischengespeicherten Wert:

Ich vermute also, dass es irgendwo eine Diskrepanz gibt, die durch Gleitkommaarithmetik verursacht wird.

Der Vorhersage-Cache interagiert also auf destruktive Weise mit Gleitkomma-Arithmetik?

@ hcho3 Es ist ein Problem, das ich bei der Implementierung der neuen

Rekonstruieren Sie die DMatrix vor der Vorhersage, um den Cache aus dem Weg zu rÀumen:

dtrain_2 <- xgboost::xgb.DMatrix(data = data.matrix(X), label = Y)

pred <- stats::predict(fit, newdata = dtrain_2)

Es wird den identical Test bestehen. Andernfalls schlÀgt es fehl.

Bei mehr BĂ€umen weist der identische Test immer noch kleine Unterschiede auf (1e-7 fĂŒr 2000 BĂ€ume). Aber mĂŒssen wir auch in einer Multithread-Umgebung nach und nach identische Ergebnisse erzielen?

Da die Gleitkomma-Summierung nicht assoziativ ist, können wir sie als Aufgabe verwenden, um eine starke Garantie fĂŒr die Berechnungsreihenfolge zu haben, wenn dies gewĂŒnscht wird.

TatsĂ€chlich wird es nicht funktionieren, eine starke Garantie fĂŒr die Bestellung zu geben (wird viel helfen, aber es wird trotzdem Diskrepanzen geben). Ein Gleitkommawert im CPU-FPU-Register kann eine höhere Genauigkeit haben, als er im Speicher gespeichert wird. (Die Hardwareimplementierung kann eine höhere Genauigkeit fĂŒr Zwischenwerte verwenden, https://en.wikipedia.org/wiki/Extended_precision). Mein Punkt ist, wenn das Ergebnis fĂŒr 1000 BĂ€ume innerhalb von 32-Bit-Float genau reproduzierbar ist, ist es unwahrscheinlich, dass es sich um einen Programmierfehler handelt.

Ich stimme zu, dass die Gleitkomma-Summierung nicht assoziativ ist. Ich werde das Skript selbst ausfĂŒhren und sehen, ob der Unterschied klein genug ist, um ihn der Gleitkommaarithmetik zuzuschreiben.

Im Allgemeinen verwende ich normalerweise np.testing.assert_almost_equal mit decimal=5 , um zu testen, ob zwei Float-Arrays fast gleich sind.

Jep. Entschuldigung fĂŒr das Schließen ohne detaillierte Hinweise.

@hcho3 Irgendein Update?

Ich bin noch nicht drum herum gekommen. Lass mich diese Woche mal nachschauen.

@trivialfis Ich habe es geschafft, den Fehler zu reproduzieren. Ich habe das bereitgestellte Skript ausgefĂŒhrt und FALSE fĂŒr identical(pred, pred.loaded) . Ich habe versucht, eine neue DMatrix dtrain_2 erstellen, wie Sie es vorgeschlagen haben, und habe immer noch FALSE fĂŒr den Test erhalten.

Ausgabe aus dem Skript von

[1] FALSE     # identical(pred, pred.loaded)
 [1] -4.7760534 -2.5083885 -0.8860036 -4.9163256 -4.4455137 -0.2548684
 [7] -0.9745615  0.4646015  1.3602829 -4.3288369     # pred[1:10]
 [1] -4.7760534 -2.5083888 -0.8860038 -4.9163256 -4.4454765 -0.2548686
 [7] -0.9745617  0.4646015  1.3602829 -4.3288369     # pred.loaded[1:10]
[1] 0.02456085   # MSE on pred
[1] 0.02455945   # MSE on pred.loaded

Ausgabe vom modifizierten Skript mit dtrain_2 <- xgboost::xgb.DMatrix(data = data.matrix(X), label = Y) :

[1] FALSE     # identical(pred, pred.loaded)
 [1] -4.7760534 -2.5083885 -0.8860036 -4.9163256 -4.4455137 -0.2548684
 [7] -0.9745615  0.4646015  1.3602829 -4.3288369     # pred[1:10]
 [1] -4.7760534 -2.5083888 -0.8860038 -4.9163256 -4.4454765 -0.2548686
 [7] -0.9745617  0.4646015  1.3602829 -4.3288369     # pred.loaded[1:10]
[1] 0.02456085   # MSE on pred
[1] 0.02455945   # MSE on pred.loaded

Also muss etwas anderes passieren.

Ich habe auch versucht, einen Round-Trip-Test durchzufĂŒhren:

xgboost::xgb.save(fit, 'booster.raw')
fit.loaded <- xgboost::xgb.load('booster.raw')
xgboost::xgb.save(fit.loaded, 'booster.raw.roundtrip')

und die beiden BinÀrdateien booster.raw und booster.raw.roundtrip waren identisch.

Der maximale Unterschied zwischen pred und pred.loaded betrÀgt 0,0008370876.

Ein kleineres Beispiel, das schneller lÀuft:

library(xgboost)

N <- 5000
set.seed(2020)
X <- data.frame('X1' = rnorm(N), 'X2' = runif(N), 'X3' = rpois(N, lambda = 1))
Y <- with(X, X1 + X2 - X3 + X1*X2^2 - ifelse(X1 > 0, 2, X3))

params <- list(objective = 'reg:squarederror',
               max_depth = 5, eta = 0.02, subsammple = 0.5,
               base_score = median(Y)
)

dtrain <- xgboost::xgb.DMatrix(data = data.matrix(X), label = Y)

fit <- xgboost::xgb.train(
  params = params, data = dtrain,
  watchlist = list('train' = dtrain),
  nrounds = 10000, verbose = TRUE, print_every_n = 25,
  eval_metric = 'mae',
  early_stopping_rounds = 3, maximize = FALSE
)

pred <- stats::predict(fit, newdata = dtrain)

invisible(xgboost::xgb.save(fit, 'booster.raw'))
fit.loaded <- xgboost::xgb.load('booster.raw')
invisible(xgboost::xgb.save(fit.loaded, 'booster.raw.roundtrip'))

pred.loaded <- stats::predict(fit.loaded, newdata = dtrain)

identical(pred, pred.loaded)
pred[1:10]
pred.loaded[1:10]
max(abs(pred - pred.loaded))

sqrt(mean((Y - pred)^2))
sqrt(mean((Y - pred.loaded)^2))

Ausgabe:

[1] FALSE
 [1] -2.4875379 -0.9452241 -6.9658904 -2.9985323 -4.2192593 -0.8505422
 [7] -0.3928839 -1.6886091 -1.3611379 -3.1278882
 [1] -2.4875379 -0.9452239 -6.9658904 -2.9985323 -4.2192593 -0.8505420
 [7] -0.3928837 -1.6886090 -1.3611377 -3.1278882
[1] 0.0001592636
[1] 0.01370754
[1] 0.01370706

Ich habe gerade versucht, eine zusÀtzliche Rundreise zu machen, und jetzt Àndern sich die Vorhersagen nicht mehr.

library(xgboost)

N <- 5000
set.seed(2020)
X <- data.frame('X1' = rnorm(N), 'X2' = runif(N), 'X3' = rpois(N, lambda = 1))
Y <- with(X, X1 + X2 - X3 + X1*X2^2 - ifelse(X1 > 0, 2, X3))

params <- list(objective = 'reg:squarederror',
               max_depth = 5, eta = 0.02, subsammple = 0.5,
               base_score = median(Y)
)

dtrain <- xgboost::xgb.DMatrix(data = data.matrix(X), label = Y)

fit <- xgboost::xgb.train(
  params = params, data = dtrain,
  watchlist = list('train' = dtrain),
  nrounds = 10000, verbose = TRUE, print_every_n = 25,
  eval_metric = 'mae',
  early_stopping_rounds = 3, maximize = FALSE
)

pred <- stats::predict(fit, newdata = dtrain)

invisible(xgboost::xgb.save(fit, 'booster.raw'))
fit.loaded <- xgboost::xgb.load('booster.raw')
invisible(xgboost::xgb.save(fit.loaded, 'booster.raw.roundtrip'))
fit.loaded2 <- xgboost::xgb.load('booster.raw.roundtrip')

pred.loaded <- stats::predict(fit.loaded, newdata = dtrain)
pred.loaded2 <- stats::predict(fit.loaded2, newdata = dtrain)

identical(pred, pred.loaded)
identical(pred.loaded, pred.loaded2)
pred[1:10]
pred.loaded[1:10]
pred.loaded2[1:10]
max(abs(pred - pred.loaded))
max(abs(pred.loaded - pred.loaded2))

sqrt(mean((Y - pred)^2))
sqrt(mean((Y - pred.loaded)^2))
sqrt(mean((Y - pred.loaded2)^2))

Ergebnis:

[1] FALSE
[1] TRUE
 [1] -2.4875379 -0.9452241 -6.9658904 -2.9985323 -4.2192593 -0.8505422
 [7] -0.3928839 -1.6886091 -1.3611379 -3.1278882
 [1] -2.4875379 -0.9452239 -6.9658904 -2.9985323 -4.2192593 -0.8505420
 [7] -0.3928837 -1.6886090 -1.3611377 -3.1278882
 [1] -2.4875379 -0.9452239 -6.9658904 -2.9985323 -4.2192593 -0.8505420
 [7] -0.3928837 -1.6886090 -1.3611377 -3.1278882
[1] 0.0001592636
[1] 0
[1] 0.01370754
[1] 0.01370706
[1] 0.01370706

Vielleicht ist der Vorhersage-Cache also tatsÀchlich ein Problem.

Ich habe das Skript mit deaktiviertem Vorhersage-Caching erneut ausgefĂŒhrt:

diff --git a/src/predictor/cpu_predictor.cc b/src/predictor/cpu_predictor.cc
index ebc15128..c40309bc 100644
--- a/src/predictor/cpu_predictor.cc
+++ b/src/predictor/cpu_predictor.cc
@@ -259,7 +259,7 @@ class CPUPredictor : public Predictor {
     // delta means {size of forest} * {number of newly accumulated layers}
     uint32_t delta = end_version - beg_version;
     CHECK_LE(delta, model.trees.size());
-    predts->Update(delta);
+    //predts->Update(delta);

     CHECK(out_preds->Size() == output_groups * dmat->Info().num_row_ ||
           out_preds->Size() == dmat->Info().num_row_);

(Das Deaktivieren des Vorhersage-Caching fĂŒhrt zu einem sehr langsamen Training.)

Ausgabe:

[1] FALSE
[1] TRUE
 [1] -2.4908853 -0.9507379 -6.9615889 -2.9935317 -4.2165089 -0.8543566
 [7] -0.3940181 -1.6930715 -1.3572118 -3.1403396
 [1] -2.4908853 -0.9507380 -6.9615889 -2.9935317 -4.2165089 -0.8543567
 [7] -0.3940183 -1.6930716 -1.3572119 -3.1403399
 [1] -2.4908853 -0.9507380 -6.9615889 -2.9935317 -4.2165089 -0.8543567
 [7] -0.3940183 -1.6930716 -1.3572119 -3.1403399
[1] 0.0001471043
[1] 0
[1] 0.01284297
[1] 0.01284252
[1] 0.01284252

Der Vorhersage-Cache ist also definitiv NICHT die Ursache fĂŒr diesen Fehler.

Auch die Blattvorhersagen gehen auseinander:

invisible(xgboost::xgb.save(fit, 'booster.raw'))
fit.loaded <- xgboost::xgb.load('booster.raw')
invisible(xgboost::xgb.save(fit.loaded, 'booster.raw.roundtrip'))
fit.loaded2 <- xgboost::xgb.load('booster.raw.roundtrip')

x <- predict(fit, newdata = dtrain2, predleaf = TRUE)
x2 <- predict(fit.loaded, newdata = dtrain2, predleaf = TRUE)
x3 <- predict(fit.loaded2, newdata = dtrain2, predleaf = TRUE)

identical(x, x2)
identical(x2, x3)

Ausgabe:

[1] FALSE
[1] TRUE

Geheimnis gelĂŒftet. Ich habe die wahre Ursache identifiziert. Beim Speichern des Modells auf der Festplatte werden Informationen zum vorzeitigen Stoppen verworfen. Im Beispiel fĂŒhrt XGBoost 6381 Boosting-Runden aus und findet das beste Modell bei 6378 Runden. Das Modellobjekt im Speicher enthĂ€lt 6381 BĂ€ume, nicht 6378 BĂ€ume, da kein Baum entfernt wird. Es gibt ein zusĂ€tzliches Feld best_iteration , das sich daran erinnert, welche Iteration die beste war:

> fit$best_iteration
[1] 6378

Dieses zusĂ€tzliche Feld wird stillschweigend verworfen, wenn wir das Modell auf der Festplatte speichern. So verwendet predict() mit dem ursprĂŒnglichen Modell 6378 BĂ€ume, wĂ€hrend predict() mit dem wiederhergestellten Modell 6381 BĂ€ume verwendet.

> x <- predict(fit, newdata = dtrain2, predleaf = TRUE)
> x2 <- predict(fit.loaded, newdata = dtrain2, predleaf = TRUE)
> dim(x)
[1] 5000 6378
> dim(x2)
[1] 5000 6381

@trivialfis Ich neige dazu, BĂ€ume physisch zu entfernen. Wenn das Training bei 6381 Runden endete und die beste Iteration bei 6378 Runden war, erwarten Benutzer, dass das endgĂŒltige Modell 6378 BĂ€ume enthĂ€lt.

@hcho3 Ich denke, es ist ein Àhnliches Problem in https://github.com/dmlc/xgboost/issues/4052 .

Die bset_iteration sollten in Learner::attributes_ gespeichert werden, auf das ĂŒber xgboost::xgb.attr zugegriffen werden kann.

@hcho3 , schöner Fund!

Beachten Sie auch die Dokumentation von xgboost:::predict.xgb.Booster() :

image

Wenn ich das richtig verstehe, ist die Dokumentation nicht ganz korrekt? Basierend auf der Dokumentation hatte ich erwartet, dass die Vorhersage bereits alle BĂ€ume verwendet. Dies hatte ich leider nicht verifiziert.

@DavorJ Wenn das frĂŒhe Stoppen aktiviert ist, verwendet predict() das Feld best_iteration , um eine Vorhersage zu erhalten.

@trivialfis Die Situation ist auf Python-Seite schlimmer, da xgb.predict() keine Informationen aus einem frĂŒhen Stoppen verwendet:

import xgboost as xgb
import numpy as np
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split

X, y = load_boston(return_X_y=True)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

dtrain = xgb.DMatrix(X_train, label=y_train)
dtest = xgb.DMatrix(X_test, label=y_test)

params = {'objective': 'reg:squarederror'}

bst = xgb.train(params, dtrain, 100, [(dtrain, 'train'), (dtest, 'test')],
                early_stopping_rounds=5)

x = bst.predict(dtrain, pred_leaf=True)
x2 = bst.predict(dtrain, pred_leaf=True, ntree_limit=bst.best_iteration)
print(x.shape)
print(x2.shape)

pred = bst.predict(dtrain)
pred2 = bst.predict(dtrain, ntree_limit=bst.best_iteration)

print(np.max(np.abs(pred - pred2)))

Ausgabe:

Will train until test-rmse hasn't improved in 5 rounds.
[1]     train-rmse:12.50316     test-rmse:11.92709
...
[25]    train-rmse:0.56720      test-rmse:2.56874
[26]    train-rmse:0.54151      test-rmse:2.56722
[27]    train-rmse:0.51842      test-rmse:2.56124
[28]    train-rmse:0.47489      test-rmse:2.56640
[29]    train-rmse:0.45489      test-rmse:2.58780
[30]    train-rmse:0.43093      test-rmse:2.59385
[31]    train-rmse:0.41865      test-rmse:2.59364
[32]    train-rmse:0.40823      test-rmse:2.59465
Stopping. Best iteration:
[27]    train-rmse:0.51842      test-rmse:2.56124
(404, 33)
(404, 27)
0.81269073

Benutzer mĂŒssen daran denken, bst.best_iteration zu holen und es als ntree_limit Argument zu ĂŒbergeben, wenn sie predict() aufrufen. Dies ist fehleranfĂ€llig und sorgt fĂŒr eine unangenehme Überraschung.

Wir haben zwei Möglichkeiten zur Behebung:

  1. BÀume physisch löschen, die hinter best_iteration .
  2. Behalten Sie die best_iteration Informationen bei, wenn Sie das Modell serialisieren, und lassen Sie sie von der predict() Funktion verwenden.

@hcho3 Ich habe eine halbfertige Idee dazu, die auch mit unserer Option process_type = update und Wald zusammenhÀngt.

Hintergrund

FĂŒr eine kurze Zusammenfassung der Probleme, die wir mit update , wenn num_boost_round das mit update wird, kleiner ist als die Anzahl der bereits vorhandenen BĂ€ume, werden die nicht aktualisierten BĂ€ume entfernt .

FĂŒr eine kurze EinfĂŒhrung in die Probleme mit dem Wald: best_iteration gilt nicht fĂŒr den Wald, da die Funktion predict eine bestimmte Anzahl von BĂ€umen anstelle einer Iteration erfordert, also gibt es in Python etwas namens best_ntree_limit , was mich sehr verwirrt. Ich habe ntree_limit in inplace_predict explizit durch ntree_limit iteration_range , um dieses Attribut zu vermeiden.

Idee

Ich möchte slice und concat booster hinzufĂŒgen, die die BĂ€ume in 2 Modelle extrahieren und BĂ€ume aus 2 Modellen in 1 verketten. Wenn wir diese 2 Methoden haben :

  • base_margin_ wird nicht mehr benötigt und ich glaube, es ist fĂŒr andere Benutzer intuitiver.
  • ntree_limit in der Vorhersage wird nicht mehr benötigt, wir schneiden einfach das Modell und fĂŒhren die Vorhersage auf den Slices aus.
  • update Prozess ist in sich abgeschlossen, aktualisieren Sie einfach die BĂ€ume in Slices auf einmal, kein num_boost_rounds .

Weiter

Ich glaube auch, dass dies irgendwie mit Multi-Target-BĂ€umen verbunden ist. Als ob wir Multi-Class - Multi-Target - BĂ€ume in der Zukunft unterstĂŒtzen können, gibt es mehr Möglichkeiten , um BĂ€ume zu arrangieren, wie mit output_groups fĂŒr jede Klasse oder jedes Ziel, mit Wald und Vektor - Blatt Paarung. ntree_limit wird nicht ausreichen.

Auch #5531.

Aber die Idee ist noch ziemlich frĂŒh, also hatte ich nicht das Vertrauen, sie zu teilen. Jetzt sind wir bei diesem Thema, vielleicht kann ich einige Anregungen dazu bekommen.

Können wir angesichts des Zeitplans von 1.1 die Dokumentation erweitern, um zu verdeutlichen, wie Benutzer diese beste Iteration bei der Vorhersage manuell erfassen und verwenden mĂŒssen?
Und es zu bekannten Problemen in den Versionshinweisen hinzufĂŒgen?

@trivialfis klingt interessant, solange wir Konfigurationsprobleme dadurch nicht weiter verkomplizieren.

Das Löschen der zusĂ€tzlichen BĂ€ume aus dem Modell, wie von @hcho3 vorgeschlagen, ist ansprechend, da wir uns nicht mit Inkonsistenzen durch die gleichzeitige Verwendung einer tatsĂ€chlichen ModelllĂ€nge auseinandersetzen mĂŒssen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen