Xgboost: [DISKUSSION] Integration mit PySpark

Erstellt am 25. Okt. 2016  ·  53Kommentare  ·  Quelle: dmlc/xgboost

Mir ist gerade aufgefallen, dass es einige Anfragen zur Integration mit PySpark gibt http://dmlc.ml/2016/03/14/xgboost4j-portable-distributed-xgboost-in-spark-flink-and-dataflow.html

Ich habe auch einige E-Mails von Benutzern erhalten, die das gleiche Thema diskutieren

Ich möchte hier eine Diskussion anstoßen, ob/wann wir mit dieser Arbeit beginnen

@tqchen @terrytangyuan

python

Hilfreichster Kommentar

@CodingCat @tqchen Die Data Science-Community wird definitiv von der Implementierung von XGboost in PySpark profitieren, denn:

  • Im Allgemeinen ist Python die Sprache Nr. 3 im März 2017 mit 10,2 % der Popularität (gegenüber 1,8 % für Scala).
    http://redmonk.com/sogrady/2017/03/17/language-rankings-1-17/
    https://jobsquery.it/stats/language/group;
  • In Bezug auf die Leistung PySpark vs Scala würde ich annehmen, dass es nicht so wichtig ist, weil es fast alles Scala unter der Haube für Spark ist, oder?
  • Ich kenne mindestens 3 KI-Startups, die PySpark für die Produktion verwenden, und ganz allgemein ist Python bei Data Scientists viel beliebter und auf dem Arbeitsmarkt gefragt (
    http://r4stats.com/articles/popularity/)
    Mein Fazit: In PySpark implementiertes XGboost wird unter allen anderen Implementierungen den größten Einfluss auf DataScience haben.
    (PS sobald stabil, stellen Sie sicher, dass Cloudera es implementiert)

Alle 53 Kommentare

@CodingCat Wissen Sie, wie groß die PySpark-Community ist? Die meisten Leute verwenden nur die Scala-API. Es scheint, als müssten viele Dinge in Python neu implementiert werden - bitte korrigiere mich, wenn ich falsch liege.

Ich denke, PySpark ist in der Gemeinschaft der Data Scientists ziemlich weit verbreitet, das heißt im Szenario des schnellen Prototypings usw. Ich habe von vielen Fällen gehört, dass Data Scientists pySpark verwenden, um die großen Datenmengen zu analysieren.

Auf der anderen Seite basieren die meisten Szenarien auf Produktionsebene auf der Scala-API (ich kenne nur einen einzigen Fall, in dem Leute PySpark in der Großproduktion verwenden).

Ja, ich habe einfach das Gefühl, dass die aktuelle Python-API in der Lage sein sollte, die meisten Prototyping-Anforderungen zu erfüllen. Ich persönlich interessiere mich mehr für Spark, wenn wir mehr produktionsreife Sachen wollen. Vielleicht sollten wir die Diskussion hier belassen, damit die Leute ihre Bedürfnisse besprechen können. In der Zwischenzeit wäre es schön, wenn Sie einige Details zu Ansätzen/Abschätzungen/Schritten für die Integration angeben könnten.

habe gerade einige Diskussionen in der Community bemerkt

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

es scheint, dass die Entwicklung von PySpark hinterherhinkt...als nachgelagerte Bibliothek stimme ich für hold on , um mich der PySpark-Integration zu widmen.....

Ja, es ist auch schwierig, Probleme zu beheben, auf die Sie gestoßen sind (zumindest als ich es letztes Jahr ausprobiert habe) ...

In der Roadmap (#873) heißt es, verteiltes Python sei implementiert. Bedeutet dies, dass xgboost auf einem Hadoop-Cluster mit Python ausgeführt werden kann? (Ich meine nicht Pyspark)

ja, siehe das Beispiel im Link

Was ist der Unterschied zwischen dem Ausführen von xgboost auf einem Hadoop-Cluster mit Python und dem Ausführen von xgboost auf einem Hadoop-Cluster mit Scala-API? Gibt es große Leistungsunterschiede?
Ich denke, es gibt immer noch viele Leute, die pyspark auch für Produktionsmodelle verwenden.

@yiming-chen das Ziel von xgboost4j-spark ist es, ETL- und Modelltraining in derselben Pipeline zu vereinen

stellt sich die Frage, welche Sprache Benutzer beim ETL verwenden? Basierend auf meiner Beobachtung und Erfahrung bauen 95% der Benutzer ihr ETL-System mit scala

@CodingCat Ich weiß nicht, woher Sie Ihre 95%-Statistik haben, aber PySpark ist meiner Erfahrung nach definitiv weit verbreitet. Wir versuchen beispielsweise, Airflow zu integrieren, um den Job für unsere Pipeline zu planen, und Python wäre in dieser Situation geeignet.

@berch PySpark wird von Ihnen häufig verwendet und Sie werden sich in den Luftstrom integrieren ... ist es relevant für das, was ich gesagt habe?

@CodingCat @tqchen Die Data Science-Community wird definitiv von der Implementierung von XGboost in PySpark profitieren, denn:

  • Im Allgemeinen ist Python die Sprache Nr. 3 im März 2017 mit 10,2 % der Popularität (gegenüber 1,8 % für Scala).
    http://redmonk.com/sogrady/2017/03/17/language-rankings-1-17/
    https://jobsquery.it/stats/language/group;
  • In Bezug auf die Leistung PySpark vs Scala würde ich annehmen, dass es nicht so wichtig ist, weil es fast alles Scala unter der Haube für Spark ist, oder?
  • Ich kenne mindestens 3 KI-Startups, die PySpark für die Produktion verwenden, und ganz allgemein ist Python bei Data Scientists viel beliebter und auf dem Arbeitsmarkt gefragt (
    http://r4stats.com/articles/popularity/)
    Mein Fazit: In PySpark implementiertes XGboost wird unter allen anderen Implementierungen den größten Einfluss auf DataScience haben.
    (PS sobald stabil, stellen Sie sicher, dass Cloudera es implementiert)

Schicken Sie gerne eine PN, Sie werden die Kosten finden

Um nicht immer wieder auf den Thread zurückzukommen, schließe ich die Diskussion mit dem Schluss, dass

  • Ich persönlich werde nicht dafür stimmen, diese Bemühungen um die Integration von PySpark (vorerst) fortzusetzen.

  • Jeder andere ist mehr als willkommen, dazu beizutragen, aber wir müssen zumindest die folgenden Dinge berücksichtigen:

    • kein weiteres Python-Paket einführen

    • Abwärtskompatibilität zur aktuellen Python-API beim Implementieren der Integration

    • Behandeln Sie die zurückgebliebenen Funktionen von Pysparks ML

Wir können also pyspark nicht zum Laden des XGBoost-Spark-Modells verwenden? @CodingCat

Scala XGBoost kann also weniger schmerzhaft in die PySpark JavaEstimator API eingewickelt werden. Ich habe ein wenig gespielt und habe einen solchen Prototyp:

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)

Ich denke, es braucht noch etwas Arbeit, aber ich konnte damit Xgboost in PySpark ausführen.

Wieslaw vielen Dank für das Teilen des Code-Snippets auf dem XGBoost PySpark-Wrapper. Können Sie den Code beim Aufrufen der XGBoost-Klasse mit den entsprechenden Parametern teilen?

Danke

@wpopielarski es ist ein toller Job, den du gemacht hast. Können Sie bitte den Code zum Aufrufen von XGBoost mit den benötigten Parametern teilen? Das wäre eine große Hilfe!

das ist etwa so:

        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)

Ich bin kurz davor, eine PR mit der richtigen PySpark-Unterstützung zu machen.

@thesuperzapper , das ist großartig!

Was glaubst du, wie lange es dauern würde, es zu verpacken? Teilen Sie Erkenntnisse, während Sie Fortschritte machen.

Danke!

Hallo, ich schreibe eine einfache Version mit ParamGridBuilder falls es jemanden interessiert, es ist wirklich einfach es anzupassen.

  • 1 Erstellen Sie ein Paketverzeichnis mkdir -p ml/dmlc/xgboost4j/scala in einem beliebigen gültigen PYTHONPATH-Verzeichnis.
  • 2 kopiere den untenstehenden Code nach 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 spiele es als normales Pyspark-Modell!

@AakashBasuRZT @haiy , daran arbeiten wir jetzt richtig in Ausgabe #3370, wobei PR #3376 erste Unterstützung leistet.

@haiy könnten Sie mir einen

@sagnik-rzt prüfe diese Probe

@haiy Ich versuche das auszuführen:

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)

und es gibt diese Ausnahme:

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'

Umfeld:
Python 3.6
Funke 2.3
Skala 2.11

@sagnik-rzt
nicht sicher, aber fügen Sie xgboost-spark.jar mit deps on Spark Classpath hinzu?

@wpopielarski Hey nein, das habe ich nicht getan. Irgendeine Idee, wo ich diese JAR-Datei finden kann?

@sagnik-rzt hallo, bitte laden Sie das Glas hier herunter, es ist das offizielle spark4j-Fettglas. . Entschuldigung, ich habe gerade festgestellt, dass mein Glas auf Mac-Basis erstellt wurde. Versuchen Sie einfach, es so zu erstellen , wie $SPARK_HOME/jars .

muss es selbst bauen :), mit Maven und Profil assembly , das fette Gläser in jvm-packages/xgboost-spark/target oder so baut.

@sagnik-rzt nicht sicher, was Sie tun werden, aber um ein fettes Glas für Ihr Betriebssystem zu erstellen, klonen Sie einfach das dmlc xgboost-github-Projekt, cd zu jvm-packages und führen Sie mvn mit dem assemby Profil aus. Ich habe nicht die leiseste Ahnung, wie man eine Gradle-Build-Datei schreibt.

Okay, ich habe ein dickes Glas mit Abhängigkeiten erstellt und es dann in $SPARK_HOME/jars kopiert.
Die gleiche Ausnahme gilt jedoch immer noch:

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

Entschuldigung, aber Sie führen es auf einem Cluster lokal aus einem IDE-Projekt aus? Wenn du bist
mit Spark-Submit ist es besser, deps zu --jars switch . hinzuzufügen

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

Okay, ich habe ein dickes Glas mit Abhängigkeiten gebaut und es dann kopiert und eingefügt
zu $SPARK_HOME/jars.
Die gleiche Ausnahme gilt jedoch immer noch:

Traceback (letzter Anruf zuletzt):
Datei "/home/sagnikb/PycharmProjects/xgboost/test_import.py", Zeile 21, in
clf = xgb(params)
Datei "/usr/lib/ml/dmlc/xgboost4j/scala/spark.py", Zeile 48, in __init__
self._java_obj = self._new_java_obj("dmlc.xgboost4j.scala.spark.XGBoostEstimator", self.uid, scalaMap)
Datei "/usr/local/lib/python3.6/dist-packages/pyspark/ml/wrapper.py", Zeile 63, in _new_java_obj
return java_obj(*java_args)
TypeError: 'JavaPackage'-Objekt ist nicht aufrufbar


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/dmlc/xgboost/issues/1698#issuecomment-401339910 oder stumm
der Faden
https://github.com/notifications/unsubscribe-auth/ALEzS3JmKjO0AZ6JMzcixwCce0_3zRM0ks5uBh3ogaJpZM4KgAY_
.

Ich arbeite derzeit daran, #3376 auf den neuen Spark-Zweig umzubasieren. In der Zwischenzeit haben einige Leute gefragt, wie man den aktuellen Code auf XGBoost-0.72 verwendet.

Hier ist eine ZIP-Datei mit dem Pyspark-Code für XGBoost-0.72.
Herunterladen: sparkxgb.zip

Alles was Sie tun müssen ist:

  1. Fügen Sie Ihrem Job die normalen Scala-XGBoost-Jars und -Abhängigkeiten hinzu. (zB mit --jars oder der spark.jars Konfiguration).
  2. Sobald der Job gestartet wurde, führen Sie dies in Python aus: (Oder einem beliebigen lokalen Speicherort, den jeder Executor sehen kann)
sc.addPyFile("hdfs:///XXXX/XXXX/XXXX/sparkxgb.zip")
  1. Testen Sie mit dem folgenden Code. (Angenommen, Sie haben sample_binary_classification_data.txt an einen erreichbaren Ort verlegt, normalerweise in $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")

Notiz:

  • Dies funktioniert nur für Spark 2.2+
  • Pipelines und ParamGridBuilder werden irgendwie unterstützt, verwenden Sie das modifizierte Pipeline-Objekt mit from sparkxgb.pipeline import XGBoostPipeline,XGBoostPipelineModel wie die normalen Objekte.
  • Sie müssen float("+inf") für fehlende Werte anstelle von float("nan") verwenden, damit Nullwerte aufgrund eines Fehlers in XGboost-0.72 korrekt behandelt werden.
  • Sie können nicht trainierte Modellobjekte nicht zurückladen (Siehe #3035)
  • Diese API wird sich mit einer vollständigen Version der pyspark-Unterstützung ändern.

@thesuperzapper Ich versuche dies mit pyspark auf dem Jupyter-Notebook zu testen.

Mein System:
Python 3.6.1
xgboost 0,72
Funke 2.2.0
java 1.8
Skala 2.12

Wenn ich versuche, den XGBoostEstimator zu laden, erhalte ich:

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

Ist das ein Bug oder übersehe ich einige Anforderungen?

@BogdanCojocar Es scheint, als ob Sie die xgboost-Bibliothek vermissen.

Sie benötigen diese beiden Gläser, damit xgboost richtig funktioniert:

Sie können die erforderlichen Jars von diesen Maven-Links herunterladen.

Danke @thesuperzapper. Funktioniert gut. Tolle Arbeit mit dieser Integration in pyspark!

Haben Sie einen Vorschlag, wie Sie das trainierte Modell zum Laden im Python-Modul im Booster speichern können?

@ericwang915 Um ein Modell zu erhalten, das mit anderen XGBoost-Bibliotheken zusammenarbeitet, verwenden Sie normalerweise die Methode .booster.saveModel("XXX/XXX") für das Modellobjekt, wobei XXX ein lokaler (nicht HDFS) Pfad im Spark-Treiber ist. Wenn Sie eine andere Speichermethode verwenden, erhalten Sie eine Fehlermeldung (Siehe: #2480)

Ich habe jedoch vergessen, in dieser Version des Wrappers eine Methode zum Aufrufen der Speicherfunktion hinzuzufügen. Ich werde dies morgen tun, wenn ich Zeit habe. (Ich lebe in Neuseeland... also Zeitzonen)

Danke schön. Übrigens gibt es während des Trainingsprozesses kein Protokoll, das die Bewertungsmetriken und die Boosting-Runde anzeigt, obwohl die Stummschaltung auf 1 eingestellt ist.

@thesuperzapper danke für die Anleitung. Ich konnte Ihrer Anweisung folgen, das xgboost-Modell in pyspark zu trainieren / zu speichern. Haben Sie eine Idee, wie Sie auf andere xgboost-Modellfunktionen wie (Scala)getFeatureScore() zugreifen können?

@ccdtzccdtz derzeit

Ich habe die native Booster-Methode in meinem anfänglichen Pyspark-Wrapper nicht verfügbar gemacht, aber wenn Sie die Spark Scala-API verwenden, können Sie xgboost_model_object.nativeBooster.getFeatureScore( aufrufen und wie gewohnt verwenden.

Ich habe gesehen, dass XGBoost auf pyspark ständig fehlschlägt, wenn es zweimal oder öfter ausgeführt wird. Ich führe es auf demselben Datensatz mit demselben Code aus. Das erste Mal ist es erfolgreich, aber das zweite Mal und anschließend scheitert es. Ich verwende XGBoost 0.72 auf Spark 2.3. Ich muss die pyspark-Shell neu starten, um den Job erneut erfolgreich auszuführen.

Ich verwende xgboost.trainWithDataFrame zu Trainingszwecken.

Hat jemand dieses Problem gesehen?

Hallo @thesuperzapper
Was Sie verschrieben haben, funktioniert für mich auf einem einzelnen Worker-Knoten.
Wenn ich jedoch versuche, pyspark xgboost auf einem mit mehr als einem Worker (in diesem Fall 3) auszuführen, werden die Executoren inaktiv und werden nach einer Weile heruntergefahren.
Dies ist der Code, den ich versuche, auf dem Titanic-Dataset (das ein kleines Dataset ist) auszuführen:

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)

Dies ist der Stacktrace:
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)

Der Executor hängt an:
org.apache.spark.RDD.foreachPartition(RDD.scala:927) ml.dmlc.xgboost4j.scala.spark.XGBoost$$anonfun$trainDistributed$4$$anon$1.run(XGBoost.scala:348)

Umgebung: Python 3.5.4, Spark-Version 2.3.1, Xgboost 0.72

Können Sie Ihre xgboost- und Spark-Konfigurationen teilen? Wie viele
Arbeiter (xgboost Arbeiter), Spark Executors, Cores etc.

-Nitin

Am Di, 4. September 2018 um 05:03 schrieb sagnik-rzt [email protected] :

Hallo @thesuperzapper https://github.com/thesuperzapper
Was Sie verschrieben haben, funktioniert für mich auf einem einzelnen Worker-Knoten.
Wenn ich jedoch versuche, pyspark xgboost auf einem mit mehr als einem auszuführen
Worker werden die Executoren inaktiv und werden nach einer Weile abgeschaltet.
Dies ist der Stacktrace:
'''
Tracker gestartet, mit 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 FEHLER
TaskSche dulerImpl:70 - Verlorener Executor 0 auf 192.168.49.43: Remote-RPC
Kunde getrennt. Wahrscheinlich aufgrund von Containern, die die Schwellenwerte überschreiten, oder
Netzwerkprobleme. Überprüfen Sie die Treiberprotokolle auf WARN-Meldungen.2018-09-04 08:52:55
FEHLER AsyncE ventQueue:91 - Beim Posten an TaskFailedListener unterbrochen.
Entfernen dieser listener.java.lang.InterruptedException: ExecutorLost during
XGBoost Training: ExecutorLostFailure (Executor 0 wurde beendet, verursacht durch einen von
die laufenden Aufgaben) Grund: Remote-RPC-Client getrennt. Wahrscheinlich wegen
Container, die Schwellenwerte überschreiten, oder Netzwerkprobleme. Überprüfen Sie die Fahrerprotokolle auf
WARN-Meldungen. beim
org.apache.spark.TaskFailedListener.onTaskEnd(SparkParallelismTracker.scala:116)
beim
org.apache.spark.scheduler.SparkListenerBus$class.doPostEvent(SparkListenerBus.scala:45)
beim
org.apache.spark.scheduler.AsyncEventQueue.doPostEvent(AsyncEventQueue.scala:37)
beim
org.apache.spark.scheduler.AsyncEventQueue.doPostEvent(AsyncEventQueue.scala:37)
at org.apache.spark.util.ListenerBus$class.postToAll(ListenerBus.scala:91)
'''


Sie erhalten dies, weil Sie einen Kommentar abgegeben haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/dmlc/xgboost/issues/1698#issuecomment-418341557 oder stumm
der Faden
https://github.com/notifications/unsubscribe-auth/AJY-XklxsZB_FE7ZoAarV_fqw8D3JqxWks5uXmwqgaJpZM4KgAY_
.

@sagnik-rzt Ich bin überrascht, dass das überhaupt funktioniert, da dieser pyspark-Wrapper nur XGboost 0.72 unterstützt, wir arbeiten noch an der 0.8.

@thesuperzapper , basierend auf der von Ihnen bereitgestellten Version, habe ich einige Teile überarbeitet, um xgboost 0.80 zu unterstützen.
Am Ende erhalte ich jedoch einen py4j.protocol.Py4JError: ml.dmlc.xgboost4j.scala.spark.XGBoostClassifier does not exist in the JVM Fehler. Ich habe eine vollständige Beschreibung versehen hier . Könntest du mal nachschauen?

Alle Codes werden hier platziert.

Es sind viel mehr Änderungen erforderlich, als Sie vorgenommen haben, damit es mit 0.8 funktioniert.

Der Hauptgrund, warum ich nicht nur eine 0.8-Version herausgebracht habe, ist, dass ich wirklich kein xgboost-spezifisches Pipeline-Objekt wie in der 0.72 erstellen möchte. Ich arbeite daran, dass das pyspark xgboost-Objekt hoffentlich funktioniert mit der Standard-Pipeline-Persistenz.

@thesuperzapper , während ich die Codes für 0.72 verwendet habe, habe ich das Objekt XGBoostEstimator direkt verwendet, dh ohne das Objekt XGBoostPipeline . Dabei ist mir aufgefallen, dass die Schulung/Anpassung nicht auf die Arbeiter im Cluster verteilt wird. Ist es notwendig, die XGBoostPipeline für die Verteilung auf die Arbeiter zu verwenden?

Wenn dies nicht der Fall ist, wissen Sie, warum die Schulungen nicht auf die Mitarbeiter verteilt werden?

Aktualisieren
Ich habe das Training ausprobiert, indem ich XGBoostEstimator als Stufe in XGBoostPipeline aber das Problem besteht weiterhin. Das Training wird nicht auf die Worker verteilt, wenn ich es auf dem Cluster ausführe, während dies bei anderen von Pyspark unterstützten Modellen der Fall ist.

Haben Sie dieses Verhalten beobachtet? Wie gehe ich damit um?

Ich habe den Wrapper größtenteils für XGBoost 0.8 neu codiert, aber da mein Arbeitscluster immer noch auf 2.2 ist, kann ich ihn im verteilten Modus nicht einfach testen, da mein Dockerized Spark 2.3-Cluster nicht einmal verteilte Scala XGBoost-Modelle trainieren kann, ohne dass Probleme mit dem Shuffle-Standort auftreten .

Ich denke, die Probleme, die @sagnik-rzt und andere haben, hängen mit Ihrer Clusterkonfiguration oder einem tieferen Problem mit Spark-Scala XGBoost zusammen.

Können Sie ein Modell in Spark-Scala XGBoost trainieren?

Danke @thesuperzapper , ich dachte, Shuffle-Standorte würden intern gehandhabt, das heißt, es würde unabhängig von der Cluster-Konfiguration behandelt. Aber ich habe diesen Stackoverflow-Beitrag gefunden und werde diese Vorschläge implementieren.

Könnten Sie auch Ihre 0.8-Version teilen, wenn sie fertig ist? Ich kann die Verteilung auf meinem Cluster testen. Es hat Spark 2.3.1 und Python 3.5.

Nach dem Speichern des Modells und Laden wird die folgende Fehlermeldung angezeigt

IllegalArgumentException: u'Anforderung fehlgeschlagen: Fehler beim Laden von Metadaten: Klassenname org.apache.spark.ml.Pipeline erwartet, aber Klassenname org.apache.spark.ml.PipelineModel gefunden'

kannst du bitte dabei helfen. Danke

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)

Habe folgende Option probiert

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

Bekomme den folgenden Fehler

Kein Modul namens ml.dmlc.xgboost4j.scala.spark

DEV DOWNLOAD-LINK: sparkxgb.zip

Diese Version wird mit XGBoost-0.8 funktionieren, aber bitte verwenden Sie sie nur zum Testen oder für Beiträge zu diesem Thread, da sich die Dinge ändern werden.
(Außerdem: Ich habe alle Backports für Spark 2.2 entfernt, daher unterstützt dies nur Spark 2.3)

Das Hauptproblem, das mir bei dieser Version bekannt ist, besteht darin, dass Klassifizierungsmodelle nach dem Speichern nicht zurückgeladen werden, was zu folgendem Fehler führt: TypeError: 'JavaPackage' object is not callable . Seltsamerweise funktioniert XGBoostPipelineModel jedoch gut mit einer XGBoost-Klassifizierungsstufe. Dies führt mich zu der Annahme, dass es sich bei mir um ein Problem handelt. Kann jemand überprüfen, ob das Lesen von Klassifizierungsmodellen für sie funktioniert?

Unabhängig davon versuche ich , XGBoostPipeline überflüssig würde, das auf lange Sicht viel einfacher zu warten ist, sodass das Lese-/Schreibproblem sowieso irrelevant werden sollte. (Dies kann auch dazu führen, dass die Persistenz auf CrossValidator funktioniert)

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

choushishi picture choushishi  ·  3Kommentare

pplonski picture pplonski  ·  3Kommentare

hx364 picture hx364  ·  3Kommentare

vkuznet picture vkuznet  ·  3Kommentare

RanaivosonHerimanitra picture RanaivosonHerimanitra  ·  3Kommentare