Xgboost: [ОБСУЖДЕНИЕ] Интеграция с PySpark

Созданный на 25 окт. 2016  ·  53Комментарии  ·  Источник: dmlc/xgboost

Я только что заметил, что есть запросы на интеграцию с PySpark http://dmlc.ml/2016/03/14/xgboost4j-portable-distributed-xgboost-in-spark-flink-and-dataflow.html

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

Я хотел бы начать обсуждение здесь о том, начнем ли мы эту работу и когда.

@tqchen @terrytangyuan

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

@CodingCat @tqchen Сообщество Data Science определенно выиграет от внедрения XGboost в PySpark, потому что:

  • В целом Python является языком № 3 по состоянию на март 2017 года с 10,2% популярности (против 1,8% для Scala).
    http://redmonk.com/sogrady/2017/03/17/language-rankings-1-17/
    https://jobsquery.it/stats/language/group;
  • Что касается производительности PySpark против Scala, я полагаю, это не так уж важно, потому что это почти весь Scala под капотом для Spark, верно?
  • Я знаю, по крайней мере, 3 стартапа AI, которые используют PySpark для производства, и, в более общем плане, Python гораздо более популярен среди специалистов по данным и пользуется спросом на рынке труда (
    http://r4stats.com/articles/popularity/)
    Мой вывод: XGboost, реализованный в PySpark, окажет наибольшее влияние на DataScience среди всех других реализаций.
    (PS после стабильной работы убедитесь, что Cloudera это реализует)

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

@CodingCat Знаете ли вы, насколько велико сообщество PySpark? Большинство людей просто используют Scala API. Похоже, что многие вещи нужно заново реализовать в Python - пожалуйста, поправьте меня, если я ошибаюсь.

Я думаю, что PySpark довольно распространен в сообществе специалистов по данным, то есть в сценариях быстрого прототипирования и т. Д. Я слышал о многих случаях, когда специалисты по обработке данных используют pySpark для анализа больших объемов данных.

С другой стороны, большинство сценариев производственного уровня основаны на Scala API (я знаю только один случай, когда люди используют PySpark в крупномасштабном производстве).

Да, я просто чувствую, что текущий API Python должен быть в состоянии удовлетворить большинство потребностей в прототипировании. Лично меня больше волнует Spark, когда нам нужно больше готового к производству материала. Возможно, нам следует оставить обсуждение здесь, чтобы люди могли обсудить свои потребности. А пока было бы здорово, если бы вы могли предоставить некоторые подробности о подходах / оценках / этапах интеграции.

только что заметил какие-то обсуждения в сообществе

http://apache-spark-developers-list.1001551.n3.nabble.com/Blocked-PySpark-changes-td19712.html

похоже, что разработка PySpark отстает ... как нижележащую библиотеку, я голосую за hold on чтобы посвятить его интеграции PySpark .....

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

В дорожной карте (№ 873) сказано, что реализован распределенный питон. Означает ли это, что xgboost может работать в кластере hadoop с Python? (Я не имею в виду pyspark)

да, см. пример, размещенный по ссылке

В чем разница между запуском xgboost в кластере hadoop с python и запуском xgboost на кластере hadoop с scala api? Есть ли существенные различия в производительности?
Я думаю, что есть еще много людей, использующих pyspark для серийных моделей.

@ yiming-chen цель xgboost4j-spark - объединить ETL и обучение модели в одном конвейере.

вопрос сводится к тому, какой язык используют пользователи при выполнении ETL? на основании моих наблюдений и опыта 95% пользователей создают свою систему ETL с помощью scala.

@CodingCat Я не знаю, откуда у вас 95% -ный показатель, но, по моему опыту, PySpark определенно широко используется. Например, мы пытаемся интегрировать Airflow для планирования работы для нашего конвейера, и Python подойдет в этой ситуации.

@berch PySpark широко используется вами, и вы собираетесь интегрировать его с воздушным потоком ... имеет ли это отношение к тому, что я сказал?

@CodingCat @tqchen Сообщество Data Science определенно выиграет от внедрения XGboost в PySpark, потому что:

  • В целом Python является языком № 3 по состоянию на март 2017 года с 10,2% популярности (против 1,8% для Scala).
    http://redmonk.com/sogrady/2017/03/17/language-rankings-1-17/
    https://jobsquery.it/stats/language/group;
  • Что касается производительности PySpark против Scala, я полагаю, это не так уж важно, потому что это почти весь Scala под капотом для Spark, верно?
  • Я знаю, по крайней мере, 3 стартапа AI, которые используют PySpark для производства, и, в более общем плане, Python гораздо более популярен среди специалистов по данным и пользуется спросом на рынке труда (
    http://r4stats.com/articles/popularity/)
    Мой вывод: XGboost, реализованный в PySpark, окажет наибольшее влияние на DataScience среди всех других реализаций.
    (PS после стабильной работы убедитесь, что Cloudera это реализует)

не стесняйтесь присылать PR, вы узнаете стоимость

чтобы не возвращаться к теме снова и снова, я закрою обсуждение выводом, что

  • Я лично не буду голосовать за продолжение этих усилий по интеграции PySpark (пока)

  • Мы приглашаем всех желающих внести свой вклад в это дело, однако мы должны учитывать по крайней мере следующие моменты:

    • не вводите другой пакет Python

    • обратная совместимость с текущим API Python при реализации интеграции

    • справиться с отстающими функциями pyspark's ML

Значит, мы не можем использовать pyspark для загрузки модели XGBoost-spark? @CodingCat

так что на самом деле scala XGBoost может быть менее болезненно обернут в PySpark JavaEstimator API. Немного поиграл и у меня есть такой прототип:

from pyspark.ml.wrapper import JavaEstimator, JavaModel
from pyspark.ml.param.shared import *
from pyspark.ml.util import *
from pyspark.context import SparkContext

class XGBoost(JavaEstimator, JavaMLWritable, JavaMLReadable, HasRegParam, HasElasticNetParam):

    def __init__(self, paramMap = {}):
        super(XGBoost, self).__init__()
        scalaMap = SparkContext._active_spark_context._jvm.PythonUtils.toScalaMap(paramMap)
        self._java_obj = self._new_java_obj(
            "ml.dmlc.xgboost4j.scala.spark.XGBoostEstimator", self.uid, scalaMap)
        self._defaultParamMap = paramMap
        self._paramMap = paramMap

    def setParams(self, paramMap = {}):
        return self._set(paramMap)

    def _create_model(self, javaTrainingData):
        return JavaModel(javaTrainingData)

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

Веслав благодарит вас за то, что поделились фрагментом кода в оболочке XGBoost PySpark. Можете ли вы поделиться кодом вызова класса XGBoost с соответствующими параметрами?

Спасибо

@wpopielarski, ты проделал

это что-то вроде:

        from app.xgboost import XGBoost
        xgboost_params = {
            "eta"  : 0.023,
            "max_depth" : 10,
            "min_child_weight" : 0.3,
            "subsample" : 0.7,
            "colsample_bytree" : 0.82,
            "colsample_bylevel" : 0.9,
            "base_score" : base_score,
            "eval_metric" : "auc",
            "seed" : 49,
            "silent" : 1,
            "objective" : "binary:logistic",
            "round" : 10,
            "nWorkers" : 2,
            "useExternalMemory" : True
        }
        xgboost_estimator = XGBoost.XGBoost(xgboost_params)
...
        model = xgboost_estimator.fit(data)

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

@thesuperzapper , это здорово!

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

Спасибо!

привет, я пишу простую версию с ParamGridBuilder на случай, если кому-то интересно, ее действительно легко настроить.

  • 1 создайте пакет dir mkdir -p ml/dmlc/xgboost4j/scala в любом допустимом каталоге PYTHONPATH.
  • 2 скопируйте приведенный ниже код в ml/dmlc/xgboost4j/scala/spark.py
from pyspark.ml.classification import JavaClassificationModel, JavaMLWritable, JavaMLReadable, TypeConverters, Param, \
    Params, HasFeaturesCol, HasLabelCol, HasPredictionCol, HasRawPredictionCol, SparkContext
from pyspark.ml.wrapper import JavaModel, JavaWrapper, JavaEstimator


class XGBParams(Params):
    '''

    '''
    eta = Param(Params._dummy(), "eta",
                "step size shrinkage used in update to prevents overfitting. After each boosting step, we can directly get the weights of new features. and eta actually shrinks the feature weights to make the boosting process more conservative",
                typeConverter=TypeConverters.toFloat)
    max_depth = Param(Params._dummy(), "max_depth",
                      "maximum depth of a tree, increase this value will make the model more complex / likely to be overfitting. 0 indicates no limit, limit is required for depth-wise grow policy.range: [0,∞]",
                      typeConverter=TypeConverters.toInt)
    min_child_weight = Param(Params._dummy(), "min_child_weight",
                             "minimum sum of instance weight (hessian) needed in a child. If the tree partition step results in a leaf node with the sum of instance weight less than min_child_weight, then the building process will give up further partitioning. In linear regression mode, this simply corresponds to minimum number of instances needed to be in each node. The larger, the more conservative the algorithm will berange: [0,∞]",
                             typeConverter=TypeConverters.toFloat)
    max_delta_step = Param(Params._dummy(), "max_delta_step",
                           "Maximum delta step we allow each tree’s weight estimation to be. If the value is set to 0, it means there is no constraint. If it is set to a positive value, it can help making the update step more conservative. Usually this parameter is not needed, but it might help in logistic regression when class is extremely imbalanced. Set it to value of 1-10 might help control the update.",
                           typeConverter=TypeConverters.toInt)
    subsample = Param(Params._dummy(), "subsample",
                      "subsample ratio of the training instance. Setting it to 0.5 means that XGBoost randomly collected half of the data instances to grow trees and this will prevent overfitting.",
                      typeConverter=TypeConverters.toFloat)
    colsample_bytree = Param(Params._dummy(), "colsample_bytree",
                             "subsample ratio of columns when constructing each tree",
                             typeConverter=TypeConverters.toFloat)
    colsample_bylevel = Param(Params._dummy(), "colsample_bylevel",
                              "subsample ratio of columns for each split, in each level.",
                              typeConverter=TypeConverters.toFloat)
    max_leaves = Param(Params._dummy(), "max_leaves",
                       "Maximum number of nodes to be added. Only relevant for the ‘lossguide’ grow policy.",
                       typeConverter=TypeConverters.toInt)

    def __init__(self):
        super(XGBParams, self).__init__()

class XGBoostClassifier(JavaEstimator, JavaMLWritable, JavaMLReadable, XGBParams,
                        HasFeaturesCol, HasLabelCol, HasPredictionCol, HasRawPredictionCol):
    def __init__(self, paramMap={}):
        super(XGBoostClassifier, self).__init__()
        scalaMap = SparkContext._active_spark_context._jvm.PythonUtils.toScalaMap(paramMap)
        self._java_obj = self._new_java_obj("ml.dmlc.xgboost4j.scala.spark.XGBoostEstimator", self.uid, scalaMap)
        self._defaultParamMap = paramMap
        self._paramMap = paramMap

    def setParams(self, paramMap={}):
        return self._set(paramMap)

    def _create_model(self, java_model):
        return XGBoostClassificationModel(java_model)


class XGBoostClassificationModel(JavaModel, JavaClassificationModel, JavaMLWritable, JavaMLReadable):

    def getBooster(self):
        return self._call_java("booster")

    def saveBooster(self, save_path):
        jxgb = JavaWrapper(self.getBooster())
        jxgb._call_java("saveModel", save_path)
  • 3 играй как нормальную pyspark модель!

@AakashBasuRZT @haiy , сейчас мы правильно работаем над этим в выпуске № 3370, при этом PR № 3376 обеспечивает начальную поддержку.

@haiy, не могли бы вы показать мне фрагмент кода, который соответствует классификатору на каком-то произвольном наборе данных? Я следовал пунктам 1 и 2, которые вы обрисовали в общих чертах, но я не могу понять ваш третий пункт.

@ sagnik-rzt проверьте этот образец

@haiy Я пытаюсь запустить это:

import pyspark
import pandas as pd
from dmlc.xgboost4j.scala.spark import XGBoostClassifier
from sklearn.utils import shuffle

sc = pyspark.SparkContext('local[2]')
spark = pyspark.sql.SparkSession(sc)
df = pd.DataFrame({'x1': range(10), 'x2': [10] * 10, 'y': shuffle([0 for i in range(5)] + [1 for i in range(5)])})
sdf = spark.createDataFrame(df)
X = sdf.select(['x1', 'x2'])
Y = sdf.select(['y'])
print(X.show(5))

params = {'objective' :'binary:logistic', 'n_estimators' : 10, 'max_depth' : 3, 'learning_rate' : 0.033}
xgb_model = XGBoostClassifier(params)

и это исключение:

Traceback (most recent call last):
  File "/home/sagnikb/PycharmProjects/auto_ML/pyspark_xgboost.py", line 20, in <module>
    xgb_model = XGBoostClassifier(params)
  File "/usr/lib/ml/dmlc/xgboost4j/scala/spark.py", line 47, in __init__
    self._java_obj = self._new_java_obj("ml.dmlc.xgboost4j.scala.spark.XGBoostEstimator", self.uid, scalaMap)
  File "/usr/local/lib/python3.6/dist-packages/pyspark/ml/wrapper.py", line 63, in _new_java_obj
    return java_obj(*java_args)
TypeError: 'JavaPackage' object is not callable

Error in sys.excepthook:
Traceback (most recent call last):
  File "/home/sagnikb/PycharmProjects/auto_ML/pyspark_xgboost.py", line 20, in <module>
    xgb_model = XGBoostClassifier(params)
  File "/usr/lib/ml/dmlc/xgboost4j/scala/spark.py", line 47, in __init__
    self._java_obj = self._new_java_obj("ml.dmlc.xgboost4j.scala.spark.XGBoostEstimator", self.uid, scalaMap)
  File "/usr/local/lib/python3.6/dist-packages/pyspark/ml/wrapper.py", line 63, in _new_java_obj
    return java_obj(*java_args)
TypeError: 'JavaPackage' object is not callable
Exception ignored in: <bound method JavaParams.__del__ of XGBoostClassifier_4f9eb5d1388e9e1424a4>
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/pyspark/ml/wrapper.py", line 105, in __del__
    SparkContext._active_spark_context._gateway.detach(self._java_obj)
  File "/usr/local/lib/python3.6/dist-packages/py4j/java_gateway.py", line 1897, in detach
    java_object._detach()
AttributeError: 'NoneType' object has no attribute '_detach'

Окружающая обстановка:
Python 3.6
Spark 2.3
Scala 2.11

@ sagnik-rzt
не уверен, но вы добавляете xgboost-spark.jar с deps в путь к классам spark?

@wpopielarski Эй, нет, я этого не делал. Есть идеи, где я могу найти этот файл jar?

@ sagnik-rzt привет, пожалуйста, скачайте банку здесь , это официальная толстая банка spark4j. . Извините, я только что обнаружил, что мой jar был построен на основе Mac, просто попробуйте собрать его, как предлагает @wpopielarski . И поместите его в каталог spark deps, например $SPARK_HOME/jars .

нужно создать его самостоятельно :), с maven и профилем assembly который создает толстую банку в jvm-packages/xgboost-spark/target или около того.

@ sagnik-rzt не уверен, что вы собираетесь делать, но для создания толстого jar-файла для вашей ОС просто клонируйте проект dmlc xgboost github, перейдите в jvm-packages и запустите mvn с профилем assemby . Я не имею ни малейшего представления, как написать файл сборки gradle.

Итак, я создал толстую банку с зависимостями, а затем скопировал ее в $ SPARK_HOME / jars.
Однако то же самое исключение сохраняется:

Traceback (most recent call last):
  File "/home/sagnikb/PycharmProjects/xgboost/test_import.py", line 21, in <module>
    clf = xgb(params)
  File "/usr/lib/ml/dmlc/xgboost4j/scala/spark.py", line 48, in __init__
    self._java_obj = self._new_java_obj("dmlc.xgboost4j.scala.spark.XGBoostEstimator", self.uid, scalaMap)
  File "/usr/local/lib/python3.6/dist-packages/pyspark/ml/wrapper.py", line 63, in _new_java_obj
    return java_obj(*java_args)
TypeError: 'JavaPackage' object is not callable

извините, но вы запускаете его в кластере, локально из какого-то проекта IDE? Если ты
используя spark-submit, лучше добавить deps в переключатель --jars

2018-06-29 14:30 GMT + 02: 00 sagnik-rzt [email protected] :

Итак, я создал толстую банку с зависимостями, а затем скопировал ее.
в $ SPARK_HOME / jars.
Однако то же самое исключение сохраняется:

Отслеживание (последний вызов последний):
Файл "/home/sagnikb/PycharmProjects/xgboost/test_import.py", строка 21, в
clf = xgb (параметры)
Файл "/usr/lib/ml/dmlc/xgboost4j/scala/spark.py", строка 48, в __init__
self._java_obj = self._new_java_obj ("dmlc.xgboost4j.scala.spark.XGBoostEstimator", self.uid, scalaMap)
Файл "/usr/local/lib/python3.6/dist-packages/pyspark/ml/wrapper.py", строка 63, в _new_java_obj
вернуть java_obj (* java_args)
TypeError: объект 'JavaPackage' не вызывается

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/dmlc/xgboost/issues/1698#issuecomment-401339910 или отключить звук
нить
https://github.com/notifications/unsubscribe-auth/ALEzS3JmKjO0AZ6JMzcixwCce0_3zRM0ks5uBh3ogaJpZM4KgAY_
.

В настоящее время я работаю над перебазированием # 3376 в новую ветку Spark. Между тем, несколько человек спросили, как использовать текущий код на XGBoost-0.72.

Вот zip-файл с кодом pyspark для XGBoost-0.72.
Скачать: sparkxgb.zip

Все, что вам нужно сделать, это:

  1. Добавьте в свою работу обычные файлы jar-файлов и зависимостей Scala XGBoost. (например, используя --jars или конфигурацию spark.jars ).
  2. После запуска задания запустите его в python: (или в любом локальном месте, которое может видеть каждый исполнитель)
sc.addPyFile("hdfs:///XXXX/XXXX/XXXX/sparkxgb.zip")
  1. Протестируйте с помощью следующего кода. (Предполагая, что вы переместили sample_binary_classification_data.txt в доступное место, обычно это $SPARK_HOME/data/mllib/sample_binary_classification_data.txt )
from sparkxgb import XGBoostEstimator

# Load Data
dataPath = "sample_binary_classification_data.txt"
dataDF = spark.read.format("libsvm").load(dataPath)

# Split into Train/Test
trainDF, testDF = dataDF.randomSplit([0.8, 0.2], seed=1000)

# Define and train model
xgboost = XGBoostEstimator(
    # General Params
    nworkers=1, nthread=1, checkpointInterval=-1, checkpoint_path="",
    use_external_memory=False, silent=0, missing=float("nan"),

    # Column Params
    featuresCol="features", labelCol="label", predictionCol="prediction", 
    weightCol="weight", baseMarginCol="baseMargin", 

    # Booster Params
    booster="gbtree", base_score=0.5, objective="binary:logistic", eval_metric="error", 
    num_class=2, num_round=2, seed=None,

    # Tree Booster Params
    eta=0.3, gamma=0.0, max_depth=6, min_child_weight=1.0, max_delta_step=0.0, subsample=1.0,
    colsample_bytree=1.0, colsample_bylevel=1.0, reg_lambda=0.0, alpha=0.0, tree_method="auto",
    sketch_eps=0.03, scale_pos_weight=1.0, grow_policy='depthwise', max_bin=256,

    # Dart Booster Params
    sample_type="uniform", normalize_type="tree", rate_drop=0.0, skip_drop=0.0,

    # Linear Booster Params
    lambda_bias=0.0
)
xgboost_model = xgboost.fit(trainDF)

# Transform test set
xgboost_model.transform(testDF).show()

# Write model/classifier
xgboost.write().overwrite().save("xgboost_class_test")
xgboost_model.write().overwrite().save("xgboost_class_test.model")

Примечание:

  • Это будет работать только для Spark 2.2+.
  • Конвейеры и ParamGridBuilder отчасти поддерживаются, используйте измененный объект конвейера с from sparkxgb.pipeline import XGBoostPipeline,XGBoostPipelineModel как обычные объекты.
  • Вы должны использовать float ("+ inf") для пропущенных значений, а не float ("nan") для правильной обработки нулевых значений из-за ошибки в XGboost-0.72.
  • Вы не можете загрузить обратно необученные объекты модели (см. №3035)
  • Этот API изменится с полной версией поддержки pyspark.

@thesuperzapper Я пытаюсь проверить это с помощью pyspark на ноутбуке jupyter.

Моя система:
Python 3.6.1
xgboost 0,72
искра 2.2.0
Java 1.8
scala 2.12

Когда я пытаюсь загрузить XGBoostEstimator, я получаю:

Exception in thread "Thread-19" java.lang.NoClassDefFoundError: ml/dmlc/xgboost4j/scala/EvalTrait
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
    at java.lang.Class.privateGetPublicMethods(Class.java:2902)
    at java.lang.Class.getMethods(Class.java:1615)
    at py4j.reflection.ReflectionEngine.getMethodsByNameAndLength(ReflectionEngine.java:345)
    at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:305)
    at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:326)
    at py4j.Gateway.invoke(Gateway.java:272)
    at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
    at py4j.commands.CallCommand.execute(CallCommand.java:79)
    at py4j.GatewayConnection.run(GatewayConnection.java:214)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassNotFoundException: ml.dmlc.xgboost4j.scala.EvalTrait
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 12 more

Это ошибка или мне не хватает каких-то требований?

@BogdanCojocar Похоже, вам не хватает библиотеки xgboost.

Для правильной работы xgboost вам понадобятся обе эти банки:

Вы можете скачать необходимые jar-файлы по этим ссылкам maven.

Спасибо @thesuperzapper. Работает отлично. Отличная работа с интеграцией с pyspark!

Любые предложения о том, как сохранить обученную модель в бустере для загрузки в модуль Python?

@ ericwang915 Обычно для получения модели, которая взаимодействует с другими библиотеками XGBoost, вы должны использовать метод .booster.saveModel("XXX/XXX") для объекта модели, где XXX - это локальный (не HDFS) путь к драйверу Spark. Если вы воспользуетесь другим способом сохранения, вы получите сообщение об ошибке (см .: # 2480).

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

Спасибо. Кстати, во время процесса обучения нет журнала, показывающего метрики оценки и раунда повышения, даже если для молчания установлено значение 1.

@thesuperzapper спасибо за инструкцию. Я смог следовать вашим инструкциям по обучению / сохранению модели xgboost в pyspark. Есть идеи, как получить доступ к другой функции модели xgboost, например (scala) getFeatureScore ()?

@ccdtzccdtz в настоящее время я перепрограммирую оболочку pyspark, так как в 0.8 были внесены серьезные изменения в Spark API, когда я закончу, я стремлюсь обеспечить паритет функций с Spark Scala API.

Я не раскрыл собственный метод бустера в моей начальной оболочке pyspark, но если вы используете Spark Scala API, вы можете вызвать xgboost_model_object.nativeBooster.getFeatureScore( и использовать его как обычно.

Я видел, как XGBoost на pyspark постоянно дает сбой, если он запускается 2 или более раз. Я запускаю его в том же наборе данных с тем же кодом. В первый раз это удается, но во второй раз, а затем и вовсе не получается. Я использую XGBoost 0.72 на Spark 2.3. Мне нужно перезапустить оболочку pyspark, чтобы снова успешно запустить задание.

Я использую xgboost.trainWithDataFrame в учебных целях.

Кто-нибудь видел эту проблему?

Привет @thesuperzapper
То, что вы прописали, у меня работает на одном рабочем узле.
Однако, когда я пытаюсь запустить pyspark xgboost на более чем одном воркере (в данном случае 3), исполнители бездействуют и через некоторое время закрываются.
Это код, который я пытаюсь запустить в наборе данных Titanic (который представляет собой небольшой набор данных):

from pyspark.sql.session import SparkSession
from pyspark.sql.types import *
from pyspark.ml.feature import StringIndexer, VectorAssembler
from pyspark.ml import Pipeline
from pyspark.sql.functions import col

spark = SparkSession\
        .builder\
        .appName("PySpark XGBOOST Titanic")\
        .getOrCreate()

#spark.sparkContext.addPyFile("../sparkxgb.zip")

from automl.sparkxgb import XGBoostEstimator

schema = StructType(
  [StructField("PassengerId", DoubleType()),
    StructField("Survival", DoubleType()),
    StructField("Pclass", DoubleType()),
    StructField("Name", StringType()),
    StructField("Sex", StringType()),
    StructField("Age", DoubleType()),
    StructField("SibSp", DoubleType()),
    StructField("Parch", DoubleType()),
    StructField("Ticket", StringType()),
    StructField("Fare", DoubleType()),
    StructField("Cabin", StringType()),
    StructField("Embarked", StringType())
  ])

df_raw = spark\
  .read\
  .option("header", "true")\
  .schema(schema)\
  .csv("titanic.csv")


df = df_raw.na.fill(0)

sexIndexer = StringIndexer() \
    .setInputCol("Sex") \
    .setOutputCol("SexIndex") \
    .setHandleInvalid("keep")

cabinIndexer = StringIndexer() \
    .setInputCol("Cabin") \
    .setOutputCol("CabinIndex") \
    .setHandleInvalid("keep")

embarkedIndexer = StringIndexer() \
    .setInputCol("Embarked") \
    .setOutputCol("EmbarkedIndex") \
    .setHandleInvalid("keep")

vectorAssembler  = VectorAssembler()\
  .setInputCols(["Pclass", "SexIndex", "Age", "SibSp", "Parch", "Fare", "CabinIndex", "EmbarkedIndex"])\
  .setOutputCol("features")

xgboost = XGBoostEstimator(nworkers=2,
    featuresCol="features",
    labelCol="Survival",
    predictionCol="prediction"
)

pipeline = Pipeline().setStages([sexIndexer, cabinIndexer, embarkedIndexer, vectorAssembler, xgboost])
trainDF, testDF = df.randomSplit([0.8, 0.2], seed=24)

model  =pipeline.fit(trainDF)
print(trainDF.schema)

Это трассировка стека:
Tracker started, with env={DMLC_NUM_SERVER=0, DMLC_TRACKER_URI=172.16.1.5, DMLC_TRACKER_PORT=9093, DMLC_NUM_WORKER=3}2018-09-04 08:52:55 ERROR TaskSchedulerImpl:70 - Lost executor 0 on 192.168.49.43: Remote RPC client disassociated. Likely due to containers exceeding thresholds, or network issues. Check driver logs for WARN messages.2018-09-04 08:52:55 ERROR AsyncEventQueue:91 - Interrupted while posting to TaskFailedListener. Removing that listener.java.lang.InterruptedException: ExecutorLost during XGBoost Training: ExecutorLostFailure (executor 0 exited caused by one of the running tasks) Reason: Remote RPC client disassociated. Likely due to containers exceeding thresholds, or network issues. Check driver logs for WARN messages. at org.apache.spark.TaskFailedListener.onTaskEnd(SparkParallelismTracker.scala:116) at org.apache.spark.scheduler.SparkListenerBus$class.doPostEvent(SparkListenerBus.scala:45) at org.apache.spark.scheduler.AsyncEventQueue.doPostEvent(AsyncEventQueue.scala:37) at org.apache.spark.scheduler.AsyncEventQueue.doPostEvent(AsyncEventQueue.scala:37) at org.apache.spark.util.ListenerBus$class.postToAll(ListenerBus.scala:91)

Исполнитель застрял на:
org.apache.spark.RDD.foreachPartition(RDD.scala:927) ml.dmlc.xgboost4j.scala.spark.XGBoost$$anonfun$trainDistributed$4$$anon$1.run(XGBoost.scala:348)

Среда: Python 3.5.4, Spark версии 2.3.1, Xgboost 0.72

Можете ли вы поделиться своими конфигурациями xgboost и spark? Как много
рабочие (xgboost worker), искровые исполнители, ядра и т. д.

-Нитин

Во вторник, 4 сентября 2018 г., в 5:03 sagnik-rzt [email protected] написал:

Привет, @thesuperzapper https://github.com/thesuperzapper
То, что вы прописали, у меня работает на одном рабочем узле.
Однако, когда я пытаюсь запустить pyspark xgboost на более чем одном
worker, исполнители бездействуют и через некоторое время отключаются.
Это трассировка стека:
'' '
Трекер запущен, env = {DMLC_NUM_SERVER = 0, DMLC_TRACKER_URI = 172.16.1.5,
DMLC_TRACKER_PORT = 9093, DMLC_NUM_WORKER = 3} 2018-09-04 08:52:55 ОШИБКА
TaskSche dulerImpl: 70 - Потерянный исполнитель 0 на 192.168.49.43: Удаленный RPC
клиент отключился. Вероятно, из-за превышения пороговых значений контейнеров, или
сетевые проблемы. Проверьте журналы драйверов на наличие сообщений WARN. 2018-09-04 08:52:55
ОШИБКА AsyncE ventQueue: 91 - Прервано при отправке в TaskFailedListener.
Удаление этого listener.java.lang.InterruptedException: ExecutorLost во время
Обучение XGBoost: ExecutorLostFailure (исполнитель 0 вышел из-за одного из
запущенные задачи) Причина: удаленный клиент RPC отключился. Скорее всего из-за
контейнеры, превышающие пороговые значения, или проблемы с сетью. Проверьте журналы драйверов для
Сообщения WARN. в
org.apache.spark.TaskFailedListener.onTaskEnd (SparkParallelismTracker.scala: 116)
в
org.apache.spark.scheduler.SparkListenerBus $ class.doPostEvent (SparkListenerBus.scala: 45)
в
org.apache.spark.scheduler.AsyncEventQueue.doPostEvent (AsyncEventQueue.scala: 37)
в
org.apache.spark.scheduler.AsyncEventQueue.doPostEvent (AsyncEventQueue.scala: 37)
в org.apache.spark.util.ListenerBus $ class.postToAll (ListenerBus.scala: 91)
'' '

-
Вы получили это, потому что прокомментировали.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/dmlc/xgboost/issues/1698#issuecomment-418341557 или отключить звук
нить
https://github.com/notifications/unsubscribe-auth/AJY-XklxsZB_FE7ZoAarV_fqw8D3JqxWks5uXmwqgaJpZM4KgAY_
.

@ sagnik-rzt Я удивлен, что это вообще работает, так как эта оболочка pyspark поддерживает только XGboost 0.72, мы все еще работаем над 0.8.

@thesuperzapper , основываясь на предоставленной вами версии, я переделал некоторые части для поддержки xgboost 0.80.
Однако я получаю ошибку py4j.protocol.Py4JError: ml.dmlc.xgboost4j.scala.spark.XGBoostClassifier does not exist in the JVM . Я дал полное описание здесь . Не могли бы вы взглянуть?

Все коды размещены здесь .

Для работы с 0.8 требуется гораздо больше изменений, чем вы внесли.

Основная причина, по которой я только что не выпустил версию 0.8, заключается в том, что я действительно не хочу создавать конкретный объект конвейера xgboost, как в 0.72, я работаю над тем, чтобы, надеюсь, заставить работать объект pyspark xgboost с постоянством конвейера по умолчанию.

@thesuperzapper , используя коды для 0.72, я использовал объект XGBoostEstimator напрямую, то есть без использования объекта XGBoostPipeline . И при этом я заметил, что обучение / настройка не распределяется между воркерами в кластере. Нужно ли использовать XGBoostPipeline для распределения по воркерам?

Если это не так, знаете ли вы, почему обучение не распределяется между рабочими?

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

Вы наблюдали такое поведение? Как мне с этим справиться?

Я в основном перекодировал оболочку для XGBoost 0.8, но, поскольку мой рабочий кластер все еще находится на 2.2, я не могу легко протестировать его в распределенном режиме, так как мой кластер Dockerized Spark 2.3 не может даже обучать распределенные модели Scala XGBoost без проблем с отсутствием местоположения в случайном порядке .

Я думаю, что проблемы, с которыми сталкиваются @ sagnik-rzt и другие, связаны с конфигурацией вашего кластера или более серьезной проблемой со Spark-Scala XGBoost.

Можете ли вы обучить модель в Spark-Scala XGBoost?

Спасибо @thesuperzapper , я думал, что расположение в случайном порядке обрабатывается внутренне, то есть об этом позаботятся независимо от конфигурации кластера. Но я нашел этот пост stackoverflow, поэтому буду реализовывать эти предложения.

Также не могли бы вы поделиться своей версией 0.8, если она будет готова? Я могу протестировать распространение в своем кластере. У него есть Spark 2.3.1 и Python 3.5.

после сохранения модели и загрузки появляется следующая ошибка

IllegalArgumentException: ошибка urequirement: ошибка загрузки метаданных: ожидаемое имя класса org.apache.spark.ml.Pipeline, но найдено имя класса org.apache.spark.ml.PipelineModel '

не могли бы вы помочь с этим. Благодарность

import pyspark
from pyspark.sql.session import SparkSession
from pyspark.sql.types import *
from pyspark.ml.feature import StringIndexer, VectorAssembler
from pyspark.ml import Pipeline
from pyspark.sql.functions import col

spark.sparkContext.addPyFile("sparkxgb.zip")
from sparkxgb import XGBoostEstimator
schema = StructType(
  [StructField("PassengerId", DoubleType()),
    StructField("Survival", DoubleType()),
    StructField("Pclass", DoubleType()),
    StructField("Name", StringType()),
    StructField("Sex", StringType()),
    StructField("Age", DoubleType()),
    StructField("SibSp", DoubleType()),
    StructField("Parch", DoubleType()),
    StructField("Ticket", StringType()),
    StructField("Fare", DoubleType()),
    StructField("Cabin", StringType()),
    StructField("Embarked", StringType())
  ])

df_raw = spark\
  .read\
  .option("header", "true")\
  .schema(schema)\
  .csv("train.csv")

 df = df_raw.na.fill(0)

 sexIndexer = StringIndexer()\
  .setInputCol("Sex")\
  .setOutputCol("SexIndex")\
  .setHandleInvalid("keep")

cabinIndexer = StringIndexer()\
  .setInputCol("Cabin")\
  .setOutputCol("CabinIndex")\
  .setHandleInvalid("keep")

embarkedIndexer = StringIndexer()\
  .setInputCol("Embarked")\
  .setOutputCol("EmbarkedIndex")\
  .setHandleInvalid("keep")

vectorAssembler = VectorAssembler()\
  .setInputCols(["Pclass", "SexIndex", "Age", "SibSp", "Parch", "Fare", "CabinIndex", "EmbarkedIndex"])\
  .setOutputCol("features")
xgboost = XGBoostEstimator(
    featuresCol="features", 
    labelCol="Survival", 
    predictionCol="prediction"
)

pipeline = Pipeline().setStages([sexIndexer, cabinIndexer, embarkedIndexer, vectorAssembler, xgboost])
model = pipeline.fit(df)
model.transform(df).select(col("PassengerId"), col("prediction")).show()

model.save("model_xgboost")
loadedModel = Pipeline.load("model_xgboost")


IllegalArgumentException: u'requirement failed: Error loading metadata: Expected class name org.apache.spark.ml.Pipeline but found class name org.apache.spark.ml.PipelineModel'


#predict2 = loadedModel.transform(df)

Пробовал следующий вариант

from pyspark.ml import PipelineModel
#model.save("model_xgboost")
loadedModel = PipelineModel.load("model_xgboost")

Получение следующей ошибки

Нет модуля с именем ml.dmlc.xgboost4j.scala.spark

ССЫЛКА ДЛЯ СКАЧИВАНИЯ DEV: sparkxgb.zip

Эта версия будет работать с XGBoost-0.8, но, пожалуйста, не используйте ее для чего-либо, кроме тестирования или участия в этом потоке, поскольку все будет меняться.
(Также обратите внимание: я удалил все бэкпорты для Spark 2.2, поэтому он поддерживает только Spark 2.3)

Основная проблема, о которой я знаю с этой версией, заключается в том, что модели классификации не загружаются обратно после сохранения, что дает ошибку: TypeError: 'JavaPackage' object is not callable . Однако, как ни странно, XGBoostPipelineModel отлично работает с этапом классификации XGBoost. Это заставляет меня думать, что это проблема с моей стороны, может ли кто-нибудь проверить, работают ли для них модели классификации чтения?

Тем не менее, я пытаюсь правильно реализовать DefaultParamsWritable , что устранило бы необходимость в выделенном XGBoostPipeline , который будет намного проще поддерживать в долгосрочной перспективе, поэтому проблема чтения / записи в любом случае должна стать неактуальной. (Это также может позволить постоянство работы CrossValidator)

Была ли эта страница полезной?
0 / 5 - 0 рейтинги