Xgboost: [DISCUSSION] Integrasi dengan PySpark

Dibuat pada 25 Okt 2016  ·  53Komentar  ·  Sumber: dmlc/xgboost

Saya baru menyadari bahwa ada beberapa permintaan untuk integrasi dengan PySpark http://dmlc.ml/2016/03/14/xgboost4j-portable-distributed-xgboost-in-spark-flink-and-dataflow.html

Saya juga menerima beberapa email dari pengguna yang membahas topik yang sama

Saya ingin memulai diskusi di sini tentang apakah/kapan kita akan memulai pekerjaan ini

@tqchen @terrytangyuan

python

Komentar yang paling membantu

Komunitas @CodingCat @tqchen Data Science pasti akan mendapat manfaat dari XGboost yang telah diimplementasikan di PySpark, karena:

  • Secara umum, Python adalah bahasa #3 pada Maret 2017 dengan popularitas 10,2% (vs 1,8% untuk Scala)
    http://redmonk.com/sogrady/2017/03/17/language-rankings-1-17/
    https://jobsquery.it/stats/language/group;
  • Dalam hal kinerja PySpark vs Scala, saya berasumsi, itu tidak masalah karena hampir semua Scala di bawah kap untuk Spark, bukan?
  • Saya tahu, setidaknya, 3 startup AI yang menggunakan PySpark untuk produksi dan, lebih umum, Python jauh lebih populer untuk Ilmuwan Data dan diminati di pasar kerja (
    http://r4stats.com/articles/popularity/)
    Kesimpulan saya: XGboost yang diimplementasikan di PySpark akan memiliki dampak terbesar untuk DataScience di antara semua implementasi lainnya.
    (PS setelah stabil, pastikan, Cloudera mengimplementasikannya)

Semua 53 komentar

@CodingCat Tahukah Anda seberapa besar komunitas PySpark? Kebanyakan orang hanya menggunakan Scala API. Sepertinya banyak hal yang perlu diimplementasikan kembali dengan Python - tolong perbaiki saya jika saya salah.

Saya pikir PySpark cukup umum di komunitas Ilmuwan Data, itu berarti dalam skenario pembuatan prototipe cepat, dll. Saya mendengar tentang banyak kasus bahwa ilmuwan data menggunakan pySpark untuk menganalisis volume data yang besar.

Di sisi lain, sebagian besar skenario tingkat produksi didasarkan pada Scala API (Saya hanya tahu satu kasus bahwa orang menggunakan PySpark dalam produksi skala besar)

Ya, saya hanya merasa bahwa python API saat ini harus dapat menangani sebagian besar kebutuhan pembuatan prototipe. Saya pribadi lebih peduli tentang Spark ketika kami menginginkan lebih banyak barang siap produksi. Mungkin kita harus meninggalkan diskusi di sini sehingga orang dapat mendiskusikan kebutuhan mereka. Sementara itu, alangkah baiknya jika Anda dapat memberikan beberapa detail tentang pendekatan/perkiraan/langkah untuk integrasi.

baru saja memperhatikan beberapa diskusi di komunitas

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

tampaknya pengembangan PySpark tertinggal...sebagai perpustakaan hilir, saya memilih hold on untuk mendedikasikan ke integrasi PySpark.....

Ya, itu juga sulit untuk men-debug masalah apa pun yang Anda temui (setidaknya ketika saya mencobanya tahun lalu) ...

Di peta jalan (#873), dikatakan python terdistribusi telah diimplementasikan. Apakah ini berarti xgboost dapat berjalan di cluster hadoop dengan python? (Saya tidak bermaksud pyspark)

ya, lihat contoh yang diposting di tautan

apa perbedaan menjalankan xgboost di cluster hadoop dengan python vs. menjalankan xgboost di cluster hadoop dengan scala api? Apakah ada perbedaan kinerja utama?
Saya pikir masih banyak orang yang menggunakan pyspark untuk model produksi juga.

@yiming-chen tujuan xgboost4j-spark adalah untuk menyatukan pelatihan ETL dan model dalam saluran yang sama

pertanyaannya turun ke bahasa apa yang digunakan pengguna saat melakukan ETL? berdasarkan pengamatan dan pengalaman saya, 95% pengguna sedang membangun sistem ETL mereka dengan skala

@CodingCat Saya tidak tahu dari mana Anda mendapatkan 95% stat Anda, tetapi PySpark pasti banyak digunakan dalam pengalaman saya. Misalnya, kami mencoba mengintegrasikan Airflow untuk menjadwalkan pekerjaan untuk saluran pipa kami dan Python akan cocok dalam situasi itu.

@berch PySpark banyak digunakan oleh Anda dan Anda akan berintegrasi dengan aliran udara...apakah relevan dengan apa yang saya katakan?

Komunitas @CodingCat @tqchen Data Science pasti akan mendapat manfaat dari XGboost yang telah diimplementasikan di PySpark, karena:

  • Secara umum, Python adalah bahasa #3 pada Maret 2017 dengan popularitas 10,2% (vs 1,8% untuk Scala)
    http://redmonk.com/sogrady/2017/03/17/language-rankings-1-17/
    https://jobsquery.it/stats/language/group;
  • Dalam hal kinerja PySpark vs Scala, saya berasumsi, itu tidak masalah karena hampir semua Scala di bawah kap untuk Spark, bukan?
  • Saya tahu, setidaknya, 3 startup AI yang menggunakan PySpark untuk produksi dan, lebih umum, Python jauh lebih populer untuk Ilmuwan Data dan diminati di pasar kerja (
    http://r4stats.com/articles/popularity/)
    Kesimpulan saya: XGboost yang diimplementasikan di PySpark akan memiliki dampak terbesar untuk DataScience di antara semua implementasi lainnya.
    (PS setelah stabil, pastikan, Cloudera mengimplementasikannya)

jangan ragu untuk mengirim PR, Anda akan menemukan biayanya

untuk menghindari kembali ke utas berulang kali, saya akan menutup diskusi dengan kesimpulan bahwa

  • Saya pribadi tidak akan memilih untuk melanjutkan upaya ini untuk mengintegrasikan PySpark (untuk saat ini)

  • siapa pun lebih dari menyambut untuk berkontribusi dalam hal ini, namun, kita perlu setidaknya mempertimbangkan hal-hal berikut:

    • jangan perkenalkan paket python lain

    • kompatibilitas mundur ke API python saat ini saat mengimplementasikan integrasi

    • menangani ketertinggalan fitur ML pyspark

Jadi kami tidak dapat menggunakan pyspark untuk memuat model XGBoost-spark? @CodingCat

jadi, sebenarnya scala XGBoost bisa lebih tidak menyakitkan dibungkus dengan PySpark JavaEstimator API. Saya bermain sedikit dan memiliki prototipe seperti itu:

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)

Saya pikir itu masih perlu beberapa pekerjaan tetapi saya dapat menjalankan Xgboost di PySpark dengannya.

Wieslaw terima kasih telah membagikan cuplikan kode pada pembungkus XGBoost PySpark. Bisakah Anda membagikan kode tentang menjalankan kelas XGBoost dengan parameter yang sesuai?

Terima kasih

@wpopielarski ini adalah pekerjaan luar biasa yang Anda lakukan. Bisakah Anda membagikan kode tentang menjalankan XGBoost dengan parameter yang diperlukan? Itu akan sangat membantu!

ini adalah sesuatu seperti:

        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)

Saya semakin dekat untuk melakukan PR dengan dukungan PySpark yang tepat.

@thesuperzapper , itu bagus!

Menurut Anda berapa lama waktu yang dibutuhkan untuk membungkusnya? Bagikan wawasan sambil maju.

Terima kasih!

hai, saya menulis versi sederhana dengan ParamGridBuilder jika ada yang tertarik, sangat mudah untuk menyesuaikannya.

  • 1 buat direktori paket mkdir -p ml/dmlc/xgboost4j/scala di direktori PYTHONPATH apa pun yang valid.
  • 2 salin kode di bawah ini ke 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 mainkan sebagai model pyspark normal!

@AakashBasuRZT @haiy , kami sekarang mengerjakan ini dengan benar di Edisi #3370, dengan PR #3376 memberikan dukungan awal.

@haiy bisakah Anda menunjukkan kepada saya potongan kode yang sesuai dengan pengklasifikasi pada beberapa dataset arbitrer? Saya telah mengikuti poin 1 dan 2 yang telah Anda uraikan, tetapi saya tidak dapat memahami poin ke-3 Anda.

@sagnik-rzt periksa sampel ini

@haiy saya mencoba menjalankan ini:

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)

dan itu memberikan pengecualian ini:

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'

Lingkungan:
Python 3.6
percikan 2.3
Skala 2.11

@sagnik-rzt
tidak yakin tetapi apakah Anda menambahkan xgboost-spark.jar dengan deps di spark classpath?

@wpopielarski Hei tidak, saya belum melakukan itu. Adakah yang tahu di mana saya dapat menemukan file jar itu?

@sagnik-rzt hai, silakan unduh toplesnya @wpopielarski . Dan taruh di dir spark deps, seperti $SPARK_HOME/jars .

perlu membuatnya sendiri :), dengan pakar dan profil assembly yang membuat toples gemuk di jvm-packages/xgboost-spark/target atau lebih.

@sagnik-rzt tidak yakin apa yang akan Anda lakukan tetapi untuk membangun jar gemuk untuk OS Anda, cukup klon proyek dmlc xgboost github, cd ke paket jvm dan jalankan mvn dengan profil assemby . Saya tidak tahu sama sekali bagaimana menulis file build gradle.

Oke jadi saya telah membuat toples gemuk dengan dependensi dan kemudian menyalinnya ke $SPARK_HOME/jars.
Namun, pengecualian yang sama masih berlaku:

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

maaf, tetapi Anda menjalankannya di cluster, secara lokal dari beberapa proyek IDE? Jika Anda
menggunakan spark-submit lebih baik menambahkan deps ke --jars switch

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

Oke jadi saya telah membuat toples gemuk dengan dependensi dan kemudian menyalin-menempelnya
ke $SPARK_HOME/jars.
Namun, pengecualian yang sama masih berlaku:

Traceback (panggilan terakhir terakhir):
File "/home/sagnikb/PycharmProjects/xgboost/test_import.py", baris 21, di
clf = xgb(param)
File "/usr/lib/ml/dmlc/xgboost4j/scala/spark.py", baris 48, di __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", baris 63, di _new_java_obj
kembalikan java_obj(*java_args)
TypeError: objek 'JavaPackage' tidak dapat dipanggil


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/dmlc/xgboost/issues/1698#issuecomment-401339910 , atau bisukan
benang
https://github.com/notifications/unsubscribe-auth/ALEzS3JmKjO0AZ6JMzcixwCce0_3zRM0ks5uBh3ogaJpZM4KgAY_
.

Saat ini saya sedang mengerjakan rebasing #3376 ke cabang percikan baru, Sementara itu, beberapa orang telah menanyakan cara menggunakan kode saat ini di XGBoost-0.72.

Ini adalah file zip dengan kode pyspark untuk XGBoost-0.72.
Unduh: sparkxgb.zip

Yang perlu Anda lakukan adalah:

  1. Tambahkan stoples dan dependensi Scala XGBoost normal ke pekerjaan Anda. (misalnya menggunakan --jars atau spark.jars config).
  2. Setelah pekerjaan dimulai, jalankan ini dengan python: (Atau lokasi lokal mana pun yang dapat dilihat oleh setiap pelaksana)
sc.addPyFile("hdfs:///XXXX/XXXX/XXXX/sparkxgb.zip")
  1. Uji dengan kode berikut. (Dengan asumsi Anda telah memindahkan sample_binary_classification_data.txt ke lokasi yang dapat dijangkau, biasanya di $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")

Catatan:

  • Ini hanya akan berfungsi untuk Spark 2.2+
  • Pipelines dan ParamGridBuilder adalah jenis yang didukung, gunakan objek pipeline yang dimodifikasi dengan from sparkxgb.pipeline import XGBoostPipeline,XGBoostPipelineModel seperti yang Anda lakukan pada objek normal.
  • Anda harus menggunakan float("+inf") untuk nilai yang hilang daripada float("nan") agar nilai null diperlakukan dengan benar karena kesalahan dalam XGboost-0.72.
  • Anda tidak dapat memuat kembali objek model yang tidak terlatih, (Lihat #3035)
  • API ini akan berubah dengan rilis penuh dukungan pyspark.

@thesuperzapper Saya mencoba menguji ini dengan pyspark di notebook jupyter.

Sistem saya:
python 3.6.1
xgboost 0.72
percikan 2.2.0
jawa 1.8
skala 2.12

Ketika saya mencoba memuat XGBoostEstimator saya mendapatkan:

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

Apakah ini bug atau saya melewatkan beberapa persyaratan?

@BogdanCojocar Sepertinya Anda melewatkan perpustakaan xgboost.

Anda memerlukan kedua stoples ini agar xgboost berfungsi dengan baik:

Anda dapat mengunduh toples yang diperlukan dari tautan pakar tersebut.

Terima kasih @thesuperzapper. Berfungsi dengan baik. Kerja bagus dengan integrasi ini ke pyspark!

Adakah saran tentang cara menyimpan model terlatih ke booster untuk memuat dalam modul python?

@ericwang915 Biasanya untuk mendapatkan model yang saling beroperasi dengan pustaka XGBoost lainnya, Anda akan menggunakan metode .booster.saveModel("XXX/XXX") pada objek model, di mana XXX adalah jalur lokal (non HDFS) pada driver Spark. Jika Anda menggunakan metode penyimpanan lain, Anda mendapatkan kesalahan (Lihat: #2480)

Namun, saya lupa menambahkan metode untuk memanggil fungsi simpan di versi pembungkus itu, saya akan melakukan ini besok jika saya punya waktu. (Saya tinggal di NZ... jadi zona waktu)

Terima kasih. Omong-omong, selama proses pelatihan, tidak ada log yang menunjukkan metrik evaluasi dan putaran booster meskipun silent disetel ke 1.

@thesuperzapper terima kasih atas instruksinya. Saya dapat mengikuti instruksi Anda untuk melatih/menyimpan model xgboost di pyspark. Adakah ide tentang cara mengakses fungsi model xgboost lainnya seperti (scala)getFeatureScore()?

@ccdtzccdtz saat ini saya sedang memasang ulang pembungkus pyspark sejak 0.8 memiliki perubahan besar pada Spark API, ketika selesai, saya bertujuan untuk memiliki paritas fitur dengan Spark Scala API.

Saya tidak mengekspos metode booster asli di pembungkus pyspark awal saya, tetapi jika Anda menggunakan API Spark Scala, Anda dapat memanggil xgboost_model_object.nativeBooster.getFeatureScore( dan menggunakannya seperti biasa.

Saya telah melihat XGBoost di pyspark gagal secara konsisten jika dijalankan 2 kali atau lebih. Saya menjalankannya pada dataset yang sama dengan kode yang sama. Pertama kali berhasil tetapi kedua kalinya dan kemudian gagal. Saya menggunakan XGBoost 0.72 di Spark 2.3. Saya harus me-restart pyspark Shell untuk menjalankan pekerjaan dengan sukses lagi.

Saya menggunakan xgboost.trainWithDataFrame untuk tujuan pelatihan.

Apakah ada yang melihat masalah ini?

Hai @thesuperzapper
Apa yang Anda resepkan berfungsi untuk saya pada satu simpul pekerja.
Namun, ketika saya mencoba menjalankan pyspark xgboost dengan menggunakan lebih dari satu pekerja (3 dalam kasus ini), pelaksana menjadi tidak aktif dan mati setelah beberapa saat.
Ini adalah kode yang saya coba jalankan pada kumpulan data Titanic (yang merupakan kumpulan data kecil):

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)

Ini adalah jejak tumpukan:
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)

Pelaksana terjebak di:
org.apache.spark.RDD.foreachPartition(RDD.scala:927) ml.dmlc.xgboost4j.scala.spark.XGBoost$$anonfun$trainDistributed$4$$anon$1.run(XGBoost.scala:348)

Lingkungan: Python 3.5.4, Spark Versi 2.3.1, Xgboost 0.72

Bisakah Anda membagikan konfigurasi xgboost dan spark Anda? Berapa banyak
pekerja (pekerja xgboost), pelaksana percikan, inti, dll.

-Nitin

Pada Selasa, 4 Sep 2018 pukul 5:03 sagnik-rzt [email protected] menulis:

Hai @thesuperzapper https://github.com/thesuperzapper
Apa yang Anda resepkan berfungsi untuk saya pada satu simpul pekerja.
Namun, ketika saya mencoba menjalankan pyspark xgboost menggunakan lebih dari satu
pekerja, pelaksana menjadi menganggur dan ditutup setelah beberapa saat.
Ini adalah jejak tumpukan:
'''
Pelacak dimulai, dengan env={DMLC_NUM_SERVER=0, DMLC_TRACKER_URI=172.16.1.5,
DMLC_TRACKER_PORT=9093, DMLC_NUM_WORKER=3}04-09-2018 08:52:55 KESALAHAN
TaskSche dulerImpl:70 - Eksekutor 0 hilang pada 192.168.49.43: RPC jarak jauh
klien terputus. Kemungkinan karena kontainer melebihi ambang batas, atau
masalah jaringan. Periksa log driver untuk pesan WARN.2018-09-04 08:52:55
KESALAHAN AsyncE ventQueue:91 - Terganggu saat mengeposkan ke TaskFailedListener.
Menghapus listener.java.lang.InterruptedException: ExecutorLost selama
Pelatihan XGBoost: ExecutorLostFailure (pelaksana 0 keluar karena salah satu dari
tugas yang sedang berjalan) Alasan: Klien RPC jarak jauh tidak terkait. Kemungkinan karena
kontainer melebihi ambang batas, atau masalah jaringan. Periksa log driver untuk
PERINGATAN pesan. pada
org.apache.spark.TaskFailedListener.onTaskEnd(SparkParallelismTracker.scala:116)
pada
org.apache.spark.scheduler.SparkListenerBus$class.doPostEvent(SparkListenerBus.scala:45)
pada
org.apache.spark.scheduler.AsyncEventQueue.doPostEvent(AsyncEventQueue.scala:37)
pada
org.apache.spark.scheduler.AsyncEventQueue.doPostEvent(AsyncEventQueue.scala:37)
di org.apache.spark.util.ListenerBus$class.postToAll(ListenerBus.scala:91)
'''


Anda menerima ini karena Anda berkomentar.
Balas email ini secara langsung, lihat di GitHub
https://github.com/dmlc/xgboost/issues/1698#issuecomment-418341557 , atau bisukan
benang
https://github.com/notifications/unsubscribe-auth/AJY-XklxsZB_FE7ZoAarV_fqw8D3JqxWks5uXmwqgaJpZM4KgAY_
.

@sagnik-rzt Saya terkejut itu berfungsi sama sekali, karena pembungkus pyspark itu hanya mendukung XGboost 0,72, kami masih mengerjakan yang 0,8.

@thesuperzapper , berdasarkan versi yang Anda berikan, saya membuat ulang beberapa bagian untuk mendukung xgboost 0.80.
Namun, saya berakhir dengan kesalahan py4j.protocol.Py4JError: ml.dmlc.xgboost4j.scala.spark.XGBoostClassifier does not exist in the JVM . Penjelasan lengkapnya sudah saya berikan di sini . Bisakah Anda melihat-lihat?

Semua kode ditempatkan di sini .

Ada lebih banyak perubahan yang diperlukan daripada yang Anda buat untuk membuatnya bekerja dengan 0.8.

Alasan utama saya belum mengeluarkan versi 0.8, adalah karena saya benar-benar tidak ingin membuat objek pipa khusus xgboost seperti yang saya miliki di 0.72, saya sedang mengerjakan cara semoga objek pyspark xgboost berfungsi dengan persistensi pipa default.

@thesuperzapper , saat menggunakan kode untuk 0,72, saya menggunakan objek XGBoostEstimator secara langsung yaitu tanpa menggunakan objek XGBoostPipeline . Dan saat melakukannya, saya perhatikan bahwa pelatihan/pemasangan tidak didistribusikan ke seluruh pekerja di cluster. Apakah perlu menggunakan XGBoostPipeline untuk didistribusikan ke seluruh pekerja?

Jika bukan itu masalahnya, tahukah Anda mengapa pelatihan tidak didistribusikan ke seluruh pekerja?

Memperbarui
Saya mencoba pelatihan dengan menetapkan XGBoostEstimator sebagai tahap di XGBoostPipeline tetapi masalah tetap ada. Pelatihan tidak didistribusikan ke seluruh pekerja ketika saya menjalankannya di kluster sementara itu terjadi untuk model lain yang didukung pyspark.

Sudahkah Anda mengamati perilaku ini? Bagaimana cara mengatasinya?

Saya sebagian besar telah mengkode ulang pembungkus untuk XGBoost 0.8, tetapi karena cluster kerja saya masih di 2.2, saya tidak dapat mengujinya dengan mudah dalam mode terdistribusi, karena cluster Dockerized Spark 2.3 saya bahkan tidak dapat melatih model terdistribusi Scala XGBoost tanpa mendapatkan lokasi acak yang hilang masalah .

Saya pikir masalah yang dialami @sagnik-rzt dan yang lainnya, terkait dengan konfigurasi cluster Anda atau masalah yang lebih dalam dengan Spark-Scala XGBoost.

Apakah Anda dapat melatih model di Spark-Scala XGBoost?

Terima kasih @thesuperzapper , saya pikir lokasi shuffle ditangani secara internal, yaitu, itu akan diurus secara independen dari konfigurasi cluster. Tapi saya menemukan posting stackoverflow ini jadi akan menerapkan saran itu.

Juga, bisakah Anda membagikan versi 0.8 Anda, jika sudah siap? Saya dapat menguji distribusi di cluster saya. Ini memiliki percikan 2.3.1 dan python 3.5.

setelah menyimpan model dan memuat mendapatkan kesalahan berikut:

IllegalArgumentException: persyaratan Anda gagal: Kesalahan memuat metadata: Nama kelas yang diharapkan org.Apache.spark.ml.Pipeline tetapi menemukan nama kelas org.Apache.spark.ml.PipelineModel'

dapatkah Anda membantu dengan ini. Terima kasih

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)

Mencoba opsi berikut

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

Mendapatkan kesalahan berikut

Tidak ada modul bernama ml.dmlc.xgboost4j.scala.spark

LINK UNDUH DEV: sparkxgb.zip

Versi ini akan bekerja dengan XGBoost-0.8, tetapi tolong jangan menggunakannya untuk apa pun selain pengujian, atau berkontribusi pada utas ini, karena hal-hal akan berubah.
(Juga perhatikan: Saya telah menghapus semua backport untuk Spark 2.2, jadi ini hanya mendukung Spark 2.3)

Masalah utama yang saya ketahui dengan versi itu, adalah bahwa model klasifikasi tidak akan dimuat kembali setelah disimpan, memberikan kesalahan: TypeError: 'JavaPackage' object is not callable . Namun, anehnya XGBoostPipelineModel bekerja dengan baik dengan tahap klasifikasi XGBoost. Ini membuat saya berpikir adalah masalah di pihak saya, dapatkah seseorang memverifikasi apakah membaca model klasifikasi berfungsi untuk mereka?

Terlepas dari itu, saya mencoba untuk mengimplementasikan DefaultParamsWritable dengan benar, yang akan menghilangkan kebutuhan akan XGBoostPipeline , yang akan jauh lebih mudah untuk dipertahankan dalam jangka panjang, jadi masalah baca/tulis seharusnya menjadi tidak relevan. (Ini juga memungkinkan kegigihan di CrossValidator berfungsi)

Apakah halaman ini membantu?
0 / 5 - 0 peringkat