Xgboost: [jvm-пакеты] java.lang.NullPointerException: ноль в ml.dmlc.xgboost4j.java.Booster.predict

Созданный на 30 июл. 2020  ·  37Комментарии  ·  Источник: dmlc/xgboost

Исключения NPE возникают при прогнозировании через JAVA API.

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

Самый полезный комментарий

Ладно, думаю, к завтрашнему дню все будет готово.

Все 37 Комментарий

Поскольку модель обучается с помощью Python Sklearn, позже возникают несовместимости. Чтобы сэкономить время, команда алгоритмов переместила обученную Sklearn модель XGB на один уровень поверх пакета Python XgBoost. Интересно, не это ли это вызвало?

image

Какую версию XGBoost вы используете? Ранее мы исправили ошибку, из-за которой пакет jvm неправильно выдавал исключение при сбое прогнозирования и продолжал работу с пустым буфером прогнозирования.

Какую версию XGBoost вы используете? Ранее мы исправили ошибку, из-за которой пакет jvm неправильно выдавал исключение при сбое прогнозирования и продолжал работу с пустым буфером прогнозирования.

Используется версия 1.0 платформы алгоритма компании, а версия 0.9.0 проекта алгоритма используется из-за проблем с совместимостью версий. Коллеги по алгоритму использовали Python для преобразования файла модели 1.0 в 0.9.0. Интересно, вызвано ли это этой трансформацией

Я бы посоветовал дождаться версии 1.2 (https://github.com/dmlc/xgboost/issues/5734) и попробовать еще раз, в этом выпуске исправлены некоторые важные ошибки. Также я бы предложил использовать ту же или более позднюю версию xgboost для прогнозирования. Двоичная модель XGBoost обратно совместима, в дальнейшем рекомендуется модель на основе JSON.

Я столкнулся с той же проблемой с 1.2.0. Так что проблема все еще здесь.

У меня тоже такая же проблема.
Я использовал xgboost4j для создания модели.

есть обходной путь?

Это большая проблема для меня, это провал работы в производстве.

@ranInc Вы используете последнюю версию XGBoost? Пока мы не знаем точную причину этой проблемы. Мы приложим все усилия, чтобы решить эту проблему, и, поскольку нет никаких гарантий относительно того, когда проблема может быть решена, я предлагаю вам тем временем изучить альтернативу.

@ranInc Вы можете помочь нам, предоставив небольшой пример программы, которую мы (разработчики) можем запустить на нашей собственной машине.

Я использую 1.2.0, последнюю банку в репозитории maven.
Альтернативой для меня является возврат к saprk 2.4.5 и использование xgboost 0.9 - чем я сейчас и занимаюсь.

Например: я попытаюсь определить конкретную модель/данные, из-за которых задание не работает позже.

Привет,
Я нашел конкретную модель/данные.
Прикрепляю к этому комментарию.
xgb1.2_bug.zip

вот как вы воссоздаете ошибку (имейте в виду, что если вы не сделаете здесь переразбиение , оно сработает, так что это как-то связано с объемом данных или типом данных в каждом разделе):

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

Есть ли у вас какие-либо идеи, когда это может быть решено?
Это мешает мне использовать искру 3.0...

@ranInc Еще нет. Мы сообщим вам, когда исправим ошибку. Кроме того, вы можете опубликовать код на Scala? Я не думаю, что мы когда-либо официально поддерживали использование PySpark с 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()

Другой указатель,
кажется, что проблема связана с тем, что все функции, отправляемые для прогнозирования, являются нулями/отсутствуют.

Я так понимаю, что этим никто не занимается?
Это в основном означает, что xgboost вообще не работает на искре 3.

Да, жаль, что у нас сейчас заняты руки. Когда-нибудь мы вернемся к этому вопросу. С уважением прошу вашего терпения. Спасибо.

@ranInc Сегодня у меня было немного времени, поэтому я попытался запустить сценарий, который вы предоставили здесь. Я воспроизвел ошибку java.lang.NullPointerException .

Как ни странно, последняя разрабатываемая версия (ветвь master ) не падает так же. Вместо этого выдает ошибку

Исключение в потоке «основной» org.apache.spark.SparkException: задание прервано из-за сбоя этапа: задача 0 на этапе 7.0 не удалась 1 раз, последний сбой: потеряна задача 0.0 на этапе 7.0 (TID 11, d04389c5babb, драйвер исполнителя): ml.dmlc.xgboost4j.java.XGBoostError: [00:36:10] /workspace/src/learner.cc:1179: Ошибка проверки: Learner_model_param_.num_feature >= p_fmat->Info().num_col_ (1 против 2) : Количество столбцов не соответствует количеству функций в бустере.

Я буду исследовать дальше.

Я думаю, что сообщение об ошибке теперь имеет смысл, ваш ввод имеет больше возможностей, чем модель для прогнозирования.

До того, как пакет jvm продолжит работу после сбоя xgboost, что приведет к пустому буферу прогнозирования. Недавно я добавил чек-гвард.

Просто убедитесь, что количество столбцов в вашем наборе данных для обучения больше или равно вашему набору данных для прогнозирования.

Привет,
Модель была создана с использованием того же количества признаков.
В искре используется один векторный столбец, а не несколько столбцов.
В любом случае размер вектора всегда один и тот же, для подгонки и предсказания - в этом уверен на 100%.

Это как-то связано со строками со всеми нулевыми/отсутствующими функциями.
Вы можете видеть, что если вы отфильтруете из фрейма данных строки со всеми нулевыми функциями - все работает отлично.

@ranInc Можете ли вы опубликовать полную программу Scala, сгенерировавшую модель? Сообщение об ошибке, по-видимому, предполагает, что ваша модель была обучена с помощью одной функции.

Я не думаю, что это сильно поможет, так как код очень общий и содержит несколько умилостивляющих преобразователей,
Сам код в основном pyspark, а не scala.

Лучший способ убедиться, что количество признаков не является проблемой, — просто отфильтровать строки со всеми нулевыми признаками и использовать модель — это работает без проблем.
Вы также можете сохранить все строки и перераспределить фрейм данных, чтобы использовать один раздел, и это тоже работает.

@ranInc Я отфильтровал строки с нулем и все еще сталкиваюсь с той же ошибкой ( java.lang.NullPointerException ):

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

Разве это не правильный способ сделать это?

Я не думаю, что это сильно поможет, так как код очень общий и содержит несколько умилостивляющих преобразователей.

Я хочу посмотреть, сколько функций используется при обучении и во время прогнозирования. Сообщение об ошибке

ml.dmlc.xgboost4j.java.XGBoostError: [00:36:10] /workspace/src/learner.cc:1179: Ошибка проверки: Learner_model_param_.num_feature >= p_fmat->Info().num_col_ (1 против 2) : Количество столбцов не соответствует количеству функций в бустере.

предполагает, что модель была обучена с одной функцией, а прогноз делается с двумя функциями.

Прямо сейчас у меня есть доступ только к фрейму данных и сериализованной модели, которую вы загрузили. Мне не хватает понимания того, что происходило при обучении модели и что пошло не так, что мешает мне продолжать устранение неполадок. Если в вашей программе есть какая-то конфиденциальная информация, можно ли создать чистый пример?

  1. нет, можно так:
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")

вы также можете просто переразбить фрейм данных следующим образом:

....
df = df.repartition(1)
....
  1. Я понимаю, но код вам многого не даст, потому что он использует VectorAssembler, и вы не сможете узнать, сколько фич было использовано на самом деле,
    Но я на 100% уверен, что он использовал то же количество функций.

Но я на 100% уверен, что он использовал то же количество функций.

Как вы добились этого, если VectorAssembler имеет переменное количество функций?

VectorAssembler всегда создает одинаковое количество функций, ему просто нужны имена столбцов, из которых можно получить.
Сам код используется для создания тысяч моделей, поэтому он очень общий и в основном содержит список имен для использования.

Возможно, я смогу снова запустить создание модели и отправить вам кадр данных, используемый для модели, или любые другие данные, которые вам нужны.
Однако для меня это займет время, и если вы используете то, что я показал ранее, вы увидите, что модель отлично работает с двумя функциями.

@ranInc Позвольте мне задать еще один вопрос: правильно ли говорить, что данные примера имеют разреженный столбец (VectorAssembler), который имеет не более двух функций ?

Нет.
VectorAssembler — это Trasformer, который захватывает несколько столбцов и помещает их в один столбец Vector.
Векторы всегда используются для подгонки и прогнозирования моделей в искре.

Пример фрейма данных здесь имеет векторный столбец.
У одних ряды разреженные, у других плотные - у всех по две особенности.

@ranInc Итак, все строки имеют две функции: некоторые значения отсутствуют, а другие нет. Понятно. Я попробую ваше предложение о фильтрации пустых строк.

Как вы, наверное, догадались, я новичок в экосистеме Spark, поэтому усилия по отладке могут оказаться довольно сложными. В настоящее время нам нужно больше разработчиков, которые больше знают о Spark и программировании на Scala в целом. Если вы лично знаете кого-то, кто хотел бы помочь нам улучшить JVM-пакет XGBoost, сообщите нам об этом.

@ranInc Я попытался отфильтровать пустые строки в соответствии с вашим предложением:

Программа A: Пример сценария без фильтрации пустых строк

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

Программа B: пример с фильтрацией пустых строк

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

Некоторые наблюдения

  • В стабильной версии 1.2.0 программа A выдает ошибку java.lang.NullPointerException . Непосредственно перед NPE в журнале выполнения Spark отображается следующее предупреждение:
WARNING: /xgboost/src/learner.cc:979: Number of columns does not match number of features in booster. Columns: 0 Features: 1
  • В стабильной версии 1.2.0 программа B успешно завершается без ошибок.
  • В разрабатываемой версии (последняя ветка master , коммит 42d31d9dcb6f7c1cb7d0545e9ab3a305ecad0816) и программа A , и программа B завершаются со следующей ошибкой:
[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]

что странно, потому что, по словам @ranInc , модель обучалась на данных с двумя функциями.

  • Я собрал версию 1.2.0-SNAPSHOT из исходников (коммит 71197d1dfa27c80add9954b10284848c1f165c40). На этот раз и программа A , и программа B завершаются ошибкой несовпадения функций ( learner_model_param_.num_feature >= p_fmat->Info().num_col_ (1 vs. 2) : Number of columns does not match number of features in booster ).
  • Разница в поведении между стабильной версией 1.2.0 и 1.2.0-SNAPSHOT была неожиданной и заставила меня сильно понервничать. В частности, предупреждающее сообщение от 1.2.0
WARNING: /xgboost/src/learner.cc:979: Number of columns does not match number of features in booster. Columns: 0 Features: 1

отсутствует в версии 1.2.0 кодовой базы C++. Вместо этого предупреждение находится в ветке release_1.0.0 :
https://github.com/dmlc/xgboost/blob/ea6b117a5737f5beb2533fc89b3f3fcd72ecc04e/src/learner.cc#L972 -L982
Значит ли это, что файл JAR версии 1.2.0 на Maven Central содержит libxgboost4j.so из версии 1.0.0?? 🤯 😱

  • Действительно, JAR-файл версии 1.2.0 из Maven Central содержит libxgboost4j.so , что на самом деле соответствует версии 1.0.0 (!!!). Чтобы узнать это, загрузите xgboost4j_2.12-1.2.0.jar с Maven Central и извлеките файл libxgboost4j.so . Затем запустите следующий скрипт Python, чтобы проверить версию файла библиотеки:
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
  • Помимо проблемы 1.0.0, мы ясно видим, что обученная модель XGBoost распознала только одну функцию ( learner_model_param_.num_feature == 1 ). Может быть, в тренировочных данных была функция, которая была на 100% пустой?? @ranInc

Вы хотите, чтобы я захватил фрейм данных, используемый для создания модели?
Если я смогу его ухватить, думаю, я смогу написать простой код Scala, создающий модель.

@ranInc Я подозреваю, что одна из двух функций в обучающих данных полностью состояла из пропущенных значений, установив для learner_model_param_.num_feature значение 1. Так что да, просмотр обучающих данных будет очень полезен.

Ладно, думаю, к завтрашнему дню все будет готово.

Создан #6426, чтобы отслеживать проблему несоответствия libxgboost4j.so . Здесь (#5957) давайте продолжим обсуждение того, почему learner_model_param_.num_feature устанавливается в 1.

Кажется, вы ошибаетесь, данные обучения не имеют пропущенных значений.
в приведенном здесь примере кода вместо того, чтобы повторять переразбиение для воспроизведения сбоя, я вместо этого использовал только одну строку (которая имеет только нулевые функции) для прогнозирования.

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()
Была ли эта страница полезной?
0 / 5 - 0 рейтинги