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

Criado em 30 jul. 2020  ·  37Comentários  ·  Fonte: dmlc/xgboost

As exceções de NPE ocorrem quando previstas por meio da API JAVA.

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

Comentários muito úteis

Tudo bem, acho que vou ter pronto até amanhã.

Todos 37 comentários

Como o modelo é treinado por meio do Python Sklearn, ocorrem incompatibilidades posteriormente. Para economizar tempo, a equipe de algoritmos moveu o modelo XGB treinado pelo Sklearn uma camada sobre o pacote Python XgBoost.

image

Qual versão do XGBoost você está usando? Anteriormente, corrigimos um bug em que o pacote jvm não lança uma exceção corretamente quando a previsão falha e continua com um buffer de previsão vazio.

Qual versão do XGBoost você está usando? Anteriormente, corrigimos um bug em que o pacote jvm não lança uma exceção corretamente quando a previsão falha e continua com um buffer de previsão vazio.

A versão 1.0 da plataforma de algoritmo da empresa é usada e a versão 0.9.0 do projeto de algoritmo é usada devido a problemas de compatibilidade de versão. Os colegas do algoritmo usaram Python para converter o arquivo de modelo 1.0 para 0.9.0. Eu me pergunto se isso é causado por essa transformação

Eu sugiro esperar por 1.2 (https://github.com/dmlc/xgboost/issues/5734) e tentar novamente, temos algumas correções de bugs importantes nesta versão. Também sugiro usar a mesma versão xgboost ou posterior para previsão. O modelo binário do XGBoost é compatível com versões anteriores, seguindo em frente, o modelo baseado em JSON é recomendado.

Eu bati o mesmo problema com 1.2.0. Então o problema ainda está aqui.

Eu também tenho o mesmo problema.
Eu usei xgboost4j para criar o modelo.

existe uma solução alternativa?

Este é um grande problema para mim, ele falhou em trabalhos de produção.

@ranInc Você está usando a versão mais recente do XGBoost? Até agora, não sabemos a causa exata desse problema. Iremos resolvê-lo da melhor forma possível e, como não há garantia de quando o problema poderá ser resolvido, sugiro que você investigue uma alternativa enquanto isso.

@ranInc Você pode nos ajudar fornecendo um pequeno programa de exemplo que nós (desenvolvedores) podemos executar em nossa própria máquina.

Estou executando o 1.2.0, o jar mais recente no repositório maven.
A alternativa para mim é voltar ao saprk 2.4.5 e usar o xgboost 0.9 - e é isso que estou fazendo agora.

Por exemplo: vou tentar identificar o modelo/dados específicos que estão causando a falha do trabalho mais tarde.

Oi,
Encontrei o modelo/dados específicos.
Estou anexando neste comentário.
xgb1.2_bug.zip

é assim que você recria o bug (lembre-se de que se você não fizer a repartição aqui, funciona - então tem algo a ver com a quantidade de dados ou tipo de dados em cada partição):

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()

Você tem alguma ideia de quando isso pode ser resolvido?
Isso me impede de usar o spark 3.0 ...

@ranInc Ainda não. Avisaremos quando conseguirmos corrigir o bug. Além disso, você pode postar o código em Scala? Acho que nunca apoiamos oficialmente o uso do PySpark com o XGBoost.

      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()

Outro ponteiro,
parece que o problema é devido a todos os recursos enviados para serem previstos serem zeros/ausentes.

Acho que ninguém está trabalhando nisso?
Isso basicamente significa que o xgboost não funciona no spark 3.

Sim, desculpe, nossas mãos estão bastante cheias agora. Em algum momento, abordaremos essa questão. Peço respeitosamente sua paciência. Obrigado.

@ranInc Eu tive algum tempo hoje, então tentei executar o script que você forneceu aqui. Eu reproduzi o erro java.lang.NullPointerException .

Estranhamente, a versão de desenvolvimento mais recente ( master branch) não trava da mesma maneira. Em vez disso, produz erro

Exceção no encadeamento "principal" org.apache.spark.SparkException: Trabalho abortado devido a falha de estágio: Tarefa 0 no estágio 7.0 falhou 1 vez, falha mais recente: Tarefa perdida 0.0 no estágio 7.0 (TID 11, d04389c5babb, driver executor): ml.dmlc.xgboost4j.java.XGBoostError: [00:36:10] /workspace/src/learner.cc:1179: Falha na verificação: learner_model_param_.num_feature >= p_fmat->Info().num_col_ (1 vs. 2) : O número de colunas não corresponde ao número de recursos no booster.

Vou investigar mais.

Acho que a mensagem de erro faz sentido agora, sua entrada tem mais recursos do que o modelo de previsão.

Antes, o pacote jvm continuará após a falha do xgboost, resultando em um buffer de previsão vazio. Eu adicionei um guarda de verificação recentemente.

Apenas certifique-se de que o número de colunas em seu conjunto de dados de treinamento seja maior ou igual ao seu conjunto de dados de previsão.

Oi,
O modelo foi criado usando a mesma quantidade de recursos.
No spark, ele usa uma coluna de vetor e não várias colunas.
Em qualquer caso, o tamanho do vetor é sempre o mesmo, para ajuste e previsão - 100% de certeza disso.

Isso tem algo a ver com linhas com todos os recursos zero/ausentes.
Você pode ver que, se filtrar do dataframe as linhas com todos os recursos zero - funciona muito bem.

@ranInc Você pode postar o programa Scala completo que gerou o modelo? A mensagem de erro parece sugerir que seu modelo foi treinado com um único recurso.

Acho que não vai ajudar muito pois o código é muito genérico e tem alguns transformadores propiciatórios,
O código em si é principalmente pyspark e não scala.

A melhor maneira de ver que o número de recursos não é um problema é apenas filtrar as linhas com todos os recursos zero e usar o modelo - isso funciona sem problemas.
Você também pode manter todas as linhas e reparticionar o dataframe para usar uma partição, e isso também funciona.

@ranInc Eu filtrei as linhas com zero e ainda estou enfrentando o mesmo erro ( java.lang.NullPointerException ):

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

Esta não é a maneira correta de fazer isso?

Acho que não vai ajudar muito pois o código é muito genérico e tem alguns transformadores propiciatórios

Quero ver quantos recursos estão sendo usados ​​no treinamento e no tempo de previsão. A mensagem de erro

ml.dmlc.xgboost4j.java.XGBoostError: [00:36:10] /workspace/src/learner.cc:1179: Falha na verificação: learner_model_param_.num_feature >= p_fmat->Info().num_col_ (1 vs. 2) : O número de colunas não corresponde ao número de recursos no booster.

sugere que o modelo foi treinado com um único recurso e a previsão está sendo feita com dois recursos.

No momento, só tenho acesso ao quadro de dados e ao modelo serializado que você carregou. Não tenho informações sobre o que aconteceu no treinamento do modelo e o que deu errado, o que me impede de solucionar o problema ainda mais. Se o seu programa tem alguma informação proprietária, é possível produzir um exemplo limpo?

  1. não, você pode fazer isso:
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")

você também pode apenas re-particionar o dataframe assim:

....
df = df.repartition(1)
....
  1. Eu entendo, mas o código não vai te dar muito, porque ele usa VectorAssembler, e você não poderá saber quantos recursos foram realmente usados,
    Mas tenho 100% de certeza de que usou a mesma quantidade de recursos.

Mas tenho 100% de certeza de que usou a mesma quantidade de recursos.

Como você garantiu isso, se o VectorAssembler causa um número variável de recursos?

VectorAssembler sempre cria a mesma quantidade de recursos, ele só precisa de nomes de colunas para pegar.
O próprio código é usado para criar milhares de modelos, então é bem genérico e basicamente obtém uma lista de nomes para usar.

Talvez eu possa executar a criação do modelo novamente e enviar o dataframe usado para o modelo - ou qualquer outro dado necessário.
Isso levará tempo para mim e se você usar o que eu mostrei antes, você verá que o modelo funciona bem com 2 recursos.

@ranInc Deixe-me fazer mais uma pergunta: é correto dizer que os dados de exemplo têm uma coluna esparsa (VectorAssembler) que possui no máximo dois recursos ?

Não.
VectorAssembler é um Trasformer que pega várias colunas e as coloca em uma coluna Vector.
Os vetores são sempre usados ​​para ajustar e prever modelos no spark.

O dataframe de exemplo aqui tem uma coluna de vetor.
Algumas linhas são esparsas, outras densas - todas têm dois recursos.

@ranInc Portanto, todas as linhas têm dois recursos, alguns valores estão ausentes e outros não. Entendi. Vou tentar sua sugestão sobre como filtrar linhas vazias.

Como você deve ter adivinhado, sou bastante novo no ecossistema Spark, portanto, o esforço de depuração pode ser bastante difícil. No momento, precisamos de mais desenvolvedores que saibam mais sobre a programação Spark e Scala em geral. Se você conhece pessoalmente alguém que gostaria de nos ajudar a melhorar o pacote JVM do XGBoost, por favor nos avise.

@ranInc Tentei filtrar linhas vazias de acordo com sua sugestão:

Programa A: script de exemplo, sem filtrar linhas vazias

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()
}

Programa B: Exemplo com filtragem de linha vazia

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()
}

Algumas observações

  • Com a versão estável 1.2.0, o Programa A apresenta erros com java.lang.NullPointerException . Pouco antes do NPE, o seguinte aviso é exibido no log de execução do Spark:
WARNING: /xgboost/src/learner.cc:979: Number of columns does not match number of features in booster. Columns: 0 Features: 1
  • Com a versão 1.2.0 estável, o Programa B é concluído com êxito sem erros.
  • Com a versão de desenvolvimento (ramificação master mais recente, commit 42d31d9dcb6f7c1cb7d0545e9ab3a305ecad0816), tanto o Programa A quanto o Programa B falham com o seguinte erro:
[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]

o que é estranho porque, de acordo com @ranInc , o modelo foi treinado com dados com dois recursos.

  • Eu construí a versão 1.2.0-SNAPSHOT da fonte (commit 71197d1dfa27c80add9954b10284848c1f165c40). Desta vez, tanto o Programa A quanto o Programa B falham com o erro de incompatibilidade de recurso ( learner_model_param_.num_feature >= p_fmat->Info().num_col_ (1 vs. 2) : Number of columns does not match number of features in booster ).
  • A diferença de comportamento entre a versão estável 1.2.0 e 1.2.0-SNAPSHOT foi inesperada e me deixou bastante nervoso. Em particular, a mensagem de aviso de 1.2.0
WARNING: /xgboost/src/learner.cc:979: Number of columns does not match number of features in booster. Columns: 0 Features: 1

não é encontrado na versão 1.2.0 da base de código C++. Em vez disso, o aviso é encontrado na ramificação release_1.0.0 :
https://github.com/dmlc/xgboost/blob/ea6b117a5737f5beb2533fc89b3f3fcd72ecc04e/src/learner.cc#L972 -L982
Então, isso significa que o arquivo JAR 1.2.0 no Maven Central tem libxgboost4j.so de 1.0.0 ?? 🤯 😱

  • De fato, o arquivo JAR 1.2.0 do Maven Central contém libxgboost4j.so que na verdade é 1.0.0 (!!!). Para descobrir, baixe xgboost4j_2.12-1.2.0.jar do Maven Central e extraia o arquivo libxgboost4j.so . Em seguida, execute o seguinte script Python para verificar a versão do arquivo de biblioteca:
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
  • Deixando de lado o problema 1.0.0, vemos claramente que o modelo XGBoost treinado reconheceu apenas um único recurso ( learner_model_param_.num_feature == 1 ). Talvez os dados de treinamento tivessem um recurso 100% vazio? @ranInc

Você quer que eu pegue o dataframe usado para criar o modelo?
Se eu conseguir pegá-lo, acho que posso criar um código scala simples que cria o modelo.

@ranInc Minha suspeita é que um dos dois recursos nos dados de treinamento consistia inteiramente em valores ausentes, definindo learner_model_param_.num_feature como 1. Então, sim, ver os dados de treinamento será muito útil.

Tudo bem, acho que vou ter pronto até amanhã.

Criado #6426 para acompanhar o problema de libxgboost4j.so incompatíveis. Aqui (#5957) vamos manter a discussão sobre por que learner_model_param_.num_feature está sendo definido como 1.

Parece que você está errado, os dados de treinamento não têm valores ausentes.
no código de exemplo aqui, em vez de retransmitir a repartição para reproduzir a falha, usei apenas uma linha (que tem apenas zero recursos) para previsão.

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()
Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

lizsz picture lizsz  ·  3Comentários

nnorton24 picture nnorton24  ·  3Comentários

nicoJiang picture nicoJiang  ·  4Comentários

XiaoxiaoWang87 picture XiaoxiaoWang87  ·  3Comentários

wenbo5565 picture wenbo5565  ·  3Comentários