Xgboost: [jvm-packages] java.lang.NullPointerException: null bei ml.dmlc.xgboost4j.java.Booster.predict

Erstellt am 30. Juli 2020  ·  37Kommentare  ·  Quelle: dmlc/xgboost

NPE-Ausnahmen treten auf, wenn sie von der JAVA-API vorhergesagt werden.

java.lang.NullPointerException: null
bei ml.dmlc.xgboost4j.java.Booster.predict(Booster.java:309)
bei ml.dmlc.xgboost4j.java.Booster.predict(Booster.java:375)
bei com.tuhu.predict.predict.BaseModelPredict.predict(BaseModelPredict.java:71)
bei com.tuhu.predict.predict.XgboostFindPageModelPredict.predict(XgboostFindPageModelPredict.java:53)
at com.tuhu.predict.service.impl.MlpFindPageFeatureServiceImpl.featureProcess(MlpFindPageFeatureServiceImpl.java:65)
bei com.tuhu.predict.api.controller.MlpFindPageController.recommendPredict(MlpFindPageController.java:49)
at com.tuhu.predict.api.controller.MlpFindPageController$$FastClassBySpringCGLIB$$f694b9ff.invoke()
unter org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
unter org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746)
unter org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:163)
unter org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke (MethodBeforeAdviceInterceptor.java:52)
unter org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:174)
unter org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:47)
unter org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:174)
unter org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:52)
unter org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:174)
unter org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
unter org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:174)
bei org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed (MethodInvocationProceedingJoinPoint.java:88)
at com.tuhu.springcloud.common.annotation.AbstractControllerLogAspect.doAround(AbstractControllerLogAspect.java:104)
bei sun.reflect.NativeMethodAccessorImpl.invoke0 (native Methode)
at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
bei java.lang.reflect.Method.invoke (Method.java:498)
unter org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
unter org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
unter org.springframework.aop.aspectj.AspectJroundAdvice.invoke(AspectJroundAdvice.java:70)
unter org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:174)
bei org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
unter org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:185)
unter org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
at com.tuhu.predict.api.controller.MlpFindPageController$$EnhancerBySpringCGLIB$$560ed775.recommendPredict()
bei sun.reflect.NativeMethodAccessorImpl.invoke0 (native Methode)
at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
bei java.lang.reflect.Method.invoke (Method.java:498)
unter org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
unter org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest (InvocableHandlerMethod.java:136)
bei org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
bei org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod (RequestMappingHandlerAdapter.java:877)
bei org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal (RequestMappingHandlerAdapter.java:783)
bei org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle (AbstractHandlerMethodAdapter.java:87)
unter org.springframework.web.servlet.DispatcherServlet.doDispatch (DispatcherServlet.java:991)
bei org.springframework.web.servlet.DispatcherServlet.doService (DispatcherServlet.java:925)
bei org.springframework.web.servlet.FrameworkServlet.processRequest (FrameworkServlet.java:974)
unter org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877)
unter javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
unter org.springframework.web.servlet.FrameworkServlet.service (FrameworkServlet.java:851)
unter javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
unter org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
unter org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
bei org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
unter org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
unter org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.tuhu.soter.starter.filter.SoterDefaultFilter.doFilter(SoterDefaultFilter.java:79)
unter org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
unter org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
bei com.tuhu.boot.logback.filter.LogFilter.doFilter(LogFilter.java:54)
unter org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
unter org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
bei org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:158)
bei org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:126)
unter org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:111)
bei org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
unter org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
unter org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
unter org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:90)
bei org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
unter org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
unter org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.tuhu.boot.common.filter.HeartbeatFilter.doFilter(HeartbeatFilter.java:42)
unter org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
unter org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
bei com.tuhu.boot.common.filter.MDCFilter.doFilter(MDCFilter.java:47)
unter org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
unter org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
bei org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
bei org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
unter org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
unter org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
unter org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109)
bei org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
unter org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
unter org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
unter org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
bei org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
unter org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
unter org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
bei org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
bei org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
unter org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
unter org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
unter org.apache.catalina.core.StandardWrapperValve.invoke (StandardWrapperValve.java:198)
unter org.apache.catalina.core.StandardContextValve.invoke (StandardContextValve.java:96)
bei org.apache.catalina.authenticator.AuthenticatorBase.invoke (AuthenticatorBase.java:496)
unter org.apache.catalina.core.StandardHostValve.invoke (StandardHostValve.java:140)
bei org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
unter org.apache.catalina.core.StandardEngineValve.invoke (StandardEngineValve.java:87)
unter org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:677)
unter org.apache.catalina.connector.CoyoteAdapter.service (CoyoteAdapter.java:342)
unter org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
bei org.apache.coyote.AbstractProcessorLight.process (AbstractProcessorLight.java:66)
bei org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
unter org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468)
unter org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
bei java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1149)
bei java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
bei org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
bei java.lang.Thread.run(Thread.java:748)

Hilfreichster Kommentar

Okay, ich denke, ich werde es bis morgen fertig haben.

Alle 37 Kommentare

Da das Modell durch Python Sklearn trainiert wird, treten später Inkompatibilitäten auf. Um Zeit zu sparen, hat das Algorithmus-Team das mit Sklearn trainierte XGB-Modell um eine Ebene über das Python XgBoost-Paket verschoben. Ich frage mich, ob es daran lag

image

Welche Version von XGBoost verwendest du? Zuvor haben wir einen Fehler behoben, bei dem das jvm-Paket eine Ausnahme nicht korrekt auslöst, wenn die Vorhersage fehlschlägt und mit einem leeren Vorhersagepuffer fortfährt.

Welche Version von XGBoost verwendest du? Zuvor haben wir einen Fehler behoben, bei dem das jvm-Paket eine Ausnahme nicht korrekt auslöst, wenn die Vorhersage fehlschlägt und mit einem leeren Vorhersagepuffer fortfährt.

Version 1.0 der Algorithmusplattform des Unternehmens wird verwendet, und Version 0.9.0 des Algorithmusprojekts wird aufgrund von Versionskompatibilitätsproblemen verwendet. Algorithmuskollegen verwendeten Python, um die 1.0-Modelldatei in 0.9.0 zu konvertieren. Ich frage mich, ob es durch diese Transformation verursacht wird

Ich würde vorschlagen, auf 1.2 (https://github.com/dmlc/xgboost/issues/5734) zu warten und es erneut zu versuchen, wir haben einige wichtige Fehlerbehebungen in dieser Version. Außerdem würde ich vorschlagen, dieselbe oder eine neuere xgboost-Version für die Vorhersage zu verwenden. Das binäre Modell von XGBoost ist abwärtskompatibel, für die Zukunft wird ein JSON-basiertes Modell empfohlen.

Ich habe das gleiche Problem mit 1.2.0. Das Problem ist also immer noch da.

Ich habe auch das gleiche Problem.
Ich habe xgboost4j verwendet, um das Modell zu erstellen.

gibt es eine Abhilfe?

Das ist ein großes Problem für mich, es sind Jobs in der Produktion ausgefallen.

@ranInc Verwenden Sie die neueste Version von XGBoost? Bisher ist uns die genaue Ursache dieses Problems nicht bekannt. Wir werden uns nach besten Kräften darum kümmern, und da es keine Garantie dafür gibt, wann das Problem behoben werden kann, schlage ich vor, dass Sie in der Zwischenzeit nach einer Alternative suchen.

@ranInc Sie können uns helfen, indem Sie ein kleines Beispielprogramm bereitstellen, das wir (Entwickler) auf unserem eigenen Computer ausführen können.

Ich verwende 1.2.0, das neueste JAR im Maven-Repository.
Die Alternative für mich ist, zu saprk 2.4.5 zurückzukehren und dann xgboost 0.9 zu verwenden - und das mache ich jetzt.

Zum Beispiel: Ich werde versuchen, das spezifische Modell/die spezifischen Daten zu lokalisieren, die dazu führen, dass der Job später fehlschlägt.

Hallo,
Ich habe das spezifische Modell/Daten gefunden.
Ich hänge es in diesem Kommentar an.
xgb1.2_bug.zip

So erstellen Sie den Fehler neu (denken Sie daran, dass es funktioniert, wenn Sie die Neupartitionierung hier nicht vornehmen - es hat also etwas mit der Datenmenge oder dem Datentyp in jeder Partition zu tun):

from pyspark.ml.pipeline import PipelineModel
from pyspark.sql import SparkSession
from pyspark.sql.dataframe import DataFrame

df = spark.read.parquet("/tmp/6620294785024229130_features").repartition(200).persist()
df.count()

model = PipelineModel.read().load("/tmp/6620294785024229130_model_xg_only")

predictions = model.transform(df)

predictions.persist()
predictions.count()
predictions.show()

Haben Sie eine Ahnung, wann dies behoben werden kann?
Dies hindert mich daran, Spark 3.0 zu verwenden ...

@ranInc Noch nicht. Wir werden Sie informieren, wenn wir den Fehler behoben haben. Kannst du den Code auch in Scala posten? Ich glaube nicht, dass wir die Verwendung von PySpark mit XGBoost jemals offiziell unterstützt haben.

      import org.apache.spark.ml.{Pipeline, PipelineModel}
      val df = spark.read.parquet("/tmp/6620294785024229130_features").repartition(200).persist()
      df.count()

      val model = PipelineModel.read.load("/tmp/6620294785024229130_model_xg_only")

      val predictions = model.transform(df)

      predictions.persist()
      predictions.count()
      predictions.show()

Ein weiterer Hinweis,
Es scheint, dass das Problem darauf zurückzuführen ist, dass alle Merkmale, die zur Vorhersage gesendet werden, Nullen sind/fehlen.

Ich nehme an, niemand arbeitet daran?
Dies bedeutet im Grunde, dass xgboost auf Spark 3 überhaupt nicht funktioniert.

Ja, tut mir leid, unsere Hände sind gerade ziemlich voll. Irgendwann kommen wir auf dieses Problem zurück. Ich bitte Sie respektvoll um Geduld. Danke.

@ranInc Ich hatte heute etwas Zeit, also habe ich versucht, das Skript auszuführen, das Sie hier bereitgestellt haben. Ich habe den Fehler java.lang.NullPointerException reproduziert.

Seltsamerweise stürzt die neueste Entwicklungsversion ( master -Zweig) nicht auf die gleiche Weise ab. Stattdessen erzeugt es einen Fehler

Ausnahme im Thread „main“ org.apache.spark.SparkException: Job abgebrochen wegen Stage-Fehler: Task 0 in Stage 7.0 ist 1 Mal fehlgeschlagen, letzter Fehler: Task 0.0 in Stage 7.0 verloren (TID 11, d04389c5babb, Executor-Treiber): ml.dmlc.xgboost4j.java.XGBoostError: [00:36:10] /workspace/src/learner.cc:1179: Prüfung fehlgeschlagen: learner_model_param_.num_feature >= p_fmat->Info().num_col_ (1 vs. 2) : Die Anzahl der Spalten stimmt nicht mit der Anzahl der Features im Booster überein.

Ich werde weiter recherchieren.

Ich denke, die Fehlermeldung macht jetzt Sinn, Ihre Eingabe hat mehr Funktionen als das Modell für die Vorhersage.

Bevor das jvm-Paket nach einem xgboost-Fehler fortgesetzt wird, was zu einem leeren Vorhersagepuffer führt. Ich habe kürzlich einen Kontrollwächter hinzugefügt.

Stellen Sie einfach sicher, dass die Anzahl der Spalten in Ihrem Trainingsdatensatz größer oder gleich Ihrem Vorhersagedatensatz ist.

Hallo,
Das Modell wurde mit der gleichen Menge an Features erstellt.
In Spark wird eine Vektorspalte und nicht mehrere Spalten verwendet.
In jedem Fall ist die Größe des Vektors für Anpassung und Vorhersage immer gleich - da ist 100% sicher.

Das hat etwas mit Zeilen zu tun, die alle null/fehlende Merkmale enthalten.
Sie können sehen, dass, wenn Sie aus dem Datenrahmen die Zeilen mit allen Null-Features filtern, es gut funktioniert.

@ranInc Können Sie das vollständige Scala-Programm posten, das das Modell generiert hat? Die Fehlermeldung scheint darauf hinzudeuten, dass Ihr Modell mit einem einzigen Feature trainiert wurde.

Ich glaube nicht, dass es viel helfen wird, da der Code sehr generisch ist und einige versöhnliche Transformatoren enthält,
Der Code selbst ist meistens pyspark und nicht scala.

Der beste Weg, um zu sehen, dass die Anzahl der Features kein Problem ist, besteht darin, einfach die Zeilen mit allen Null-Features herauszufiltern und das Modell zu verwenden - das funktioniert problemlos.
Sie können auch alle Zeilen beibehalten und den Datenrahmen neu partitionieren, um eine Partition zu verwenden, und das funktioniert auch.

@ranInc Ich habe Zeilen mit Null herausgefiltert und habe immer noch den gleichen Fehler ( java.lang.NullPointerException ):

...
df.na.drop(minNonNulls = 1)
...

Ist das nicht der richtige Weg?

Ich glaube nicht, dass es viel helfen wird, da der Code sehr generisch ist und einige versöhnliche Transformatoren enthält

Ich möchte sehen, wie viele Funktionen beim Training und zur Vorhersagezeit verwendet werden. Die Fehlermeldung

ml.dmlc.xgboost4j.java.XGBoostError: [00:36:10] /workspace/src/learner.cc:1179: Prüfung fehlgeschlagen: learner_model_param_.num_feature >= p_fmat->Info().num_col_ (1 vs. 2) : Die Anzahl der Spalten stimmt nicht mit der Anzahl der Features im Booster überein.

schlägt vor, dass das Modell mit einem einzigen Merkmal trainiert wurde und die Vorhersage mit zwei Merkmalen gemacht wird.

Im Moment habe ich nur Zugriff auf den Datenrahmen und das serialisierte Modell, das Sie hochgeladen haben. Mir fehlt der Einblick in das, was in das Modelltraining eingeflossen ist und was schief gelaufen ist, was mich daran hindert, das Problem weiter zu beheben. Wenn Ihr Programm einige proprietäre Informationen enthält, ist es möglich, ein sauberes Beispiel zu erstellen?

  1. nein, das kannst du machen:
import org.apache.spark.ml.linalg.{SparseVector, Vector}
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions.{callUDF, col}
.......
 val isVectorAllZeros = (col: Vector) => {
        col match {
          case sparse: SparseVector =>
            if(sparse.indices.isEmpty){
              true
            }else{
              false
            }
          case _ => false
        }
      }

      spark.udf.register("isVectorAllZeros", isVectorAllZeros)
      df = df.withColumn("isEmpty",callUDF("isVectorAllZeros",
        col("features_6620294785024229130"))).where("isEmpty == false")

Sie können den Datenrahmen auch einfach so neu partitionieren:

....
df = df.repartition(1)
....
  1. Ich verstehe, aber der Code gibt Ihnen nicht viel, weil er VectorAssembler verwendet und Sie nicht wissen können, wie viele Funktionen tatsächlich verwendet wurden.
    Aber ich bin mir 100% sicher, dass es die gleiche Menge an Funktionen verwendet hat.

Aber ich bin mir 100% sicher, dass es die gleiche Menge an Funktionen verwendet hat.

Wie haben Sie dies sichergestellt, wenn VectorAssembler eine variable Anzahl von Funktionen hat?

VectorAssembler erstellt immer die gleiche Menge an Features, es braucht nur die Namen der Spalten, aus denen man greifen kann.
Der Code selbst wird verwendet, um Tausende von Modellen zu erstellen, daher ist er sehr generisch und erhält im Grunde eine Liste von zu verwendenden Namen.

Möglicherweise kann ich die Modellerstellung erneut ausführen und Ihnen den für das Modell verwendeten Datenrahmen oder andere Daten senden, die Sie benötigen.
Das wird jedoch einige Zeit dauern, und wenn Sie das verwenden, was ich zuvor gezeigt habe, werden Sie sehen, dass das Modell mit 2 Funktionen einwandfrei funktioniert.

@ranInc Lassen Sie mich noch eine Frage stellen: Ist es richtig zu sagen, dass die Beispieldaten eine Spalte mit geringer Dichte (VectorAssembler) haben, die höchstens zwei Funktionen hat?

Nein.
VectorAssembler ist ein Trasformer, der mehrere Spalten erfasst und sie in eine Vektorspalte einfügt.
Vektoren werden immer zum Anpassen und Vorhersagen von Modellen in Spark verwendet.

Der Beispieldatenrahmen hier hat eine Vektorspalte.
Einige Zeilen sind spärlich, andere dicht – alle haben zwei Merkmale.

@ranInc Alle Zeilen haben also zwei Merkmale, einige Werte fehlen und andere nicht. Habe es. Ich werde Ihren Vorschlag zum Filtern leerer Zeilen ausprobieren.

Wie Sie vielleicht erraten haben, bin ich ziemlich neu im Spark-Ökosystem, daher kann sich der Debugging-Aufwand als ziemlich schwierig erweisen. Wir brauchen derzeit mehr Entwickler, die mehr über Spark- und Scala-Programmierung im Allgemeinen wissen. Wenn Sie persönlich jemanden kennen, der uns helfen möchte, das JVM-Paket von XGBoost zu verbessern, lassen Sie es uns bitte wissen.

@ranInc Ich habe versucht, leere Zeilen gemäß Ihrem Vorschlag zu filtern:

Programm A: Beispielskript, ohne nach leeren Zeilen zu filtern

import org.apache.spark.sql.SparkSession
import org.apache.spark.ml.{Pipeline, PipelineModel}
import org.apache.spark.ml.linalg.{SparseVector, Vector}
import org.apache.spark.sql.functions.{callUDF, col}

object Main extends App {
  val spark = SparkSession
      .builder()
      .appName("XGBoost4J-Spark Pipeline Example")
      .getOrCreate()

  val df = spark.read.parquet("/home/ubuntu/data/6620294785024229130_features").repartition(200).persist()
  df.show()

  val model = PipelineModel.read.load("/home/ubuntu/data/6620294785024229130_model_xg_only")

  val predictions = model.transform(df)

  predictions.persist()
  predictions.count()
  predictions.show()
}

Programm B: Beispiel mit Leerzeilenfilterung

import org.apache.spark.sql.SparkSession
import org.apache.spark.ml.{Pipeline, PipelineModel}
import org.apache.spark.ml.linalg.{SparseVector, Vector}
import org.apache.spark.sql.functions.{callUDF, col}

object Main extends App {
  val spark = SparkSession
      .builder()
      .appName("XGBoost4J-Spark Pipeline Example")
      .getOrCreate()

  val isVectorAllZeros = (col: Vector) => {
    col match {
      case sparse: SparseVector => (sparse.indices.isEmpty)
      case _ => false
    }
  }
  spark.udf.register("isVectorAllZeros", isVectorAllZeros)

  val df = spark.read.parquet("/home/ubuntu/data/6620294785024229130_features").repartition(200).persist()
                .withColumn("isEmpty", callUDF("isVectorAllZeros", col("features_6620294785024229130")))
                .where("isEmpty == false")
  df.show()

  val model = PipelineModel.read.load("/home/ubuntu/data/6620294785024229130_model_xg_only")

  val predictions = model.transform(df)

  predictions.persist()
  predictions.count()
  predictions.show()
}

Einige Beobachtungen

  • Mit der stabilen Version 1.2.0 gibt Programm A einen Fehler mit java.lang.NullPointerException aus. Unmittelbar vor der NPE wird die folgende Warnung im Spark-Ausführungsprotokoll angezeigt:
WARNING: /xgboost/src/learner.cc:979: Number of columns does not match number of features in booster. Columns: 0 Features: 1
  • Mit der stabilen Version 1.2.0 wird Programm B erfolgreich ohne Fehler abgeschlossen.
  • Bei der Entwicklungsversion (neuester master -Zweig, Commit 42d31d9dcb6f7c1cb7d0545e9ab3a305ecad0816) schlagen sowohl Programm A als auch Programm B mit dem folgenden Fehler fehl:
[12:44:57] /home/ubuntu/xgblatest/src/learner.cc:1179: Check failed: learner_model_param_.num_feature >= p_fmat->Info().num_col_ (1 vs. 2) : Number of columns does not match number of features in booster.                                                                                                        
Stack trace:                                                                                                                                   
  [bt] (0) /tmp/libxgboost4j14081654332866852928.so(dmlc::LogMessageFatal::~LogMessageFatal()+0x79) [0x7f7ef62c4e19]                             [bt] (1) /tmp/libxgboost4j14081654332866852928.so(xgboost::LearnerImpl::ValidateDMatrix(xgboost::DMatrix*, bool) const+0x20b) [0x7f7ef63f5f0b]                                                                                                                                              
  [bt] (2) /tmp/libxgboost4j14081654332866852928.so(xgboost::LearnerImpl::Predict(std::shared_ptr<xgboost::DMatrix>, bool, xgboost::HostDeviceVector<float>*, unsigned int, bool, bool, bool, bool, bool)+0x3c3) [0x7f7ef6400233]                                                             
  [bt] (3) /tmp/libxgboost4j14081654332866852928.so(XGBoosterPredict+0xec) [0x7f7ef62caa3c]                                                      [bt] (4) /tmp/libxgboost4j14081654332866852928.so(Java_ml_dmlc_xgboost4j_java_XGBoostJNI_XGBoosterPredict+0x47) [0x7f7ef62befd7]             
  [bt] (5) [0x7f80908a8270]

Das ist seltsam, da das Modell laut @ranInc mit Daten mit zwei Merkmalen trainiert wurde.

  • Ich habe Version 1.2.0-SNAPSHOT aus der Quelle erstellt (commit 71197d1dfa27c80add9954b10284848c1f165c40). Dieses Mal schlagen sowohl Programm A als auch Programm B mit dem Fehler „Feature Mismatched“ ( learner_model_param_.num_feature >= p_fmat->Info().num_col_ (1 vs. 2) : Number of columns does not match number of features in booster ) fehl.
  • Der Verhaltensunterschied zwischen der stabilen Version 1.2.0 und 1.2.0-SNAPSHOT war unerwartet und machte mich ziemlich nervös. Insbesondere die Warnmeldung von 1.2.0
WARNING: /xgboost/src/learner.cc:979: Number of columns does not match number of features in booster. Columns: 0 Features: 1

wird in der Version 1.2.0 der C++-Codebasis nicht gefunden. Stattdessen befindet sich die Warnung im Zweig release_1.0.0 :
https://github.com/dmlc/xgboost/blob/ea6b117a5737f5beb2533fc89b3f3fcd72ecc04e/src/learner.cc#L972 -L982
Bedeutet das also, dass die JAR-Datei 1.2.0 auf Maven Central libxgboost4j.so von 1.0.0 enthält? 🤯 😱

  • Tatsächlich enthält die 1.2.0-JAR-Datei von Maven Central libxgboost4j.so , das ist eigentlich 1.0.0 (!!!). Um dies herauszufinden, laden Sie xgboost4j_2.12-1.2.0.jar von Maven Central herunter und extrahieren Sie die Datei libxgboost4j.so . Führen Sie dann das folgende Python-Skript aus, um die Version der Bibliotheksdatei zu überprüfen:
import ctypes

lib = ctypes.cdll.LoadLibrary('./libxgboost4j.so')

major = ctypes.c_int()
minor = ctypes.c_int()
patch = ctypes.c_int()

lib.XGBoostVersion(ctypes.byref(major), ctypes.byref(minor), ctypes.byref(patch))
print((major.value, minor.value, patch.value))  # prints (1, 0, 2), indicating version 1.0.2
  • Abgesehen vom 1.0.0-Problem sehen wir deutlich, dass das trainierte XGBoost-Modell nur ein einziges Feature erkannt hat ( learner_model_param_.num_feature == 1 ). Vielleicht hatten die Trainingsdaten ein Feature, das zu 100 % leer war?? @ranInc

Soll ich den Datenrahmen abrufen, der zum Erstellen des Modells verwendet wurde?
Wenn ich es greifen kann, denke ich, dass ich einen einfachen Scala-Code erstellen kann, der das Modell erstellt.

@ranInc Mein Verdacht ist, dass eines der beiden Merkmale in den Trainingsdaten vollständig aus fehlenden Werten bestand und learner_model_param_.num_feature auf 1 gesetzt wurde. Also ja, das Anzeigen der Trainingsdaten wird sehr hilfreich sein.

Okay, ich denke, ich werde es bis morgen fertig haben.

#6426 erstellt, um das Problem der nicht übereinstimmenden libxgboost4j.so zu verfolgen. Lassen Sie uns hier (#5957) die Diskussion darüber fortsetzen, warum learner_model_param_.num_feature auf 1 gesetzt wird.

Anscheinend liegen Sie falsch, Trainingsdaten haben keine fehlenden Werte.
Im Beispielcode hier habe ich, anstatt mich auf die Neupartitionierung zu verlassen, um den Fehler zu reproduzieren, stattdessen nur eine Zeile (die nur null Features hat) für die Vorhersage verwendet.

features_creation.zip

import ml.dmlc.xgboost4j.scala.spark.XGBoostRegressor
import org.apache.spark.ml.Pipeline
import org.apache.spark.sql.SparkSession
import org.apache.spark.ml.PipelineModel
import org.apache.spark.sql.DataFrame

val df = spark.read.parquet("/tmp/6620294785024229130_only_features_creation").persist()
df.count()

val regressor = new XGBoostRegressor()
    .setFeaturesCol("features_6620294785024229130")
    .setLabelCol("label_6620294785024229130")
    .setPredictionCol("prediction")
    .setMissing(0.0F)
    .setMaxDepth(3)
    .setNumRound(100)
    .setNumWorkers(1)

val pipeline = new Pipeline().setStages(Array(regressor))
val model = pipeline.fit(df)

val pred = spark.read.parquet("/tmp/6620294785024229130_features").persist()
pred.count()
pred.where("account_code == 4011593987").show()
model.transform(pred.where("account_code == 4011593987")).show()
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

trivialfis picture trivialfis  ·  3Kommentare

FabHan picture FabHan  ·  4Kommentare

matthewmav picture matthewmav  ·  3Kommentare

frankzhangrui picture frankzhangrui  ·  3Kommentare

uasthana15 picture uasthana15  ·  4Kommentare