Xgboost: Komputasi terdistribusi dengan Dask

Dibuat pada 13 Feb 2017  ·  46Komentar  ·  Sumber: dmlc/xgboost

Halo, saya seorang penulis Dask , perpustakaan untuk komputasi paralel dan terdistribusi dengan Python. Saya ingin tahu apakah ada minat dalam komunitas ini untuk berkolaborasi dalam mendistribusikan XGBoost di Dask baik untuk pelatihan paralel atau untuk ETL.

Mungkin ada dua komponen Dask yang relevan untuk proyek ini:

  1. Sistem generik untuk komputasi paralel dan terdistribusi, dibangun di atas penjadwalan tugas dinamis yang berubah-ubah. API yang relevan di sini mungkin dask.delayed dan bersamaan.futures
  2. Sebuah subset paralel dan terdistribusi dari Pandas API, dask.dataframe berguna untuk rekayasa fitur dan pra-pemrosesan data. Ini tidak mengimplementasikan seluruh Pandas API, tetapi hampir mendekati.

Apakah ada minat untuk berkolaborasi di sini?

Komentar yang paling membantu

Buku Catatan: https://Gist.github.com/19c89d78e34437e061876a9872f4d2df
Screencast singkat (enam menit): https://youtu.be/Cc4E-PdDSro

Umpan balik kritis sangat diterima. Sekali lagi, mohon maafkan ketidaktahuan saya di bidang ini.

Semua 46 komentar

@mrocklin Saya pikir Dask memiliki integrasi dengan sklearn. Apakah Anda melihat pembungkus sklearn kami untuk melihat apakah itu akan bekerja dengan itu?

Integrasi yang berarti dengan sistem terdistribusi biasanya harus dilakukan di tingkat per-algoritma daripada di tingkat perpustakaan. Ada beberapa cara di mana SKLearn dan Dask dapat saling membantu, ya, tetapi tidak terlalu mendalam.

Kerangka data Dask akan menjadi awal yang baik. Di basis kode kami, kami memeriksa kerangka data pandas. Di situlah kerangka data dask akan cocok sebagai permulaan.

Jadi apa yang terjadi jika seseorang datang dengan dataframe dask multi-terabyte? Apakah Anda hanya mengubahnya menjadi Pandas dan melanjutkan? Atau adakah cara untuk memparalelkan XGBoost secara cerdas di seluruh cluster, menunjuk ke berbagai kerangka data panda yang membentuk kerangka data dask?

Pengguna dapat menentukan ukuran batch? Saya membayangkan pengguna dapat diuntungkan melalui partial_fit.

cc @tqchen siapa yang lebih akrab dengan bagian kode yang didistribusikan.

Versi xgboost terdistribusi dapat dihubungkan ke peluncur pekerjaan terdistribusi, idealnya dapatkan umpan partisi data ke xgboost lalu lanjutkan.

@mrocklin Saya pikir bagian yang paling relevan adalah modul xgboost-spark dan xgboost-flink, yang menyematkan xgboost ke fungsi mapPartition dari spark/flink. Saya kira akan ada sesuatu yang serupa di Dask

Persyaratan dari sisi xgboost adalah bahwa XGBoost menangani koneksi antar proses dengan rabit, dan perlu memulai pelacak (yang menghubungkan setiap pekerjaan) dari sisi klien.

lihat kode yang relevan di https://github.com/dmlc/xgboost/blob/master/jvm-packages/xgboost4j-spark/src/main/scala/ml/dmlc/xgboost4j/scala/spark/XGBoost.scala#L112

Rabit dirancang untuk disematkan ke sistem terdistribusi lain, jadi saya pikir mungkin tidak terlalu sulit untuk melakukan penyesuaian di sisi python.

Meluncurkan sistem terdistribusi lain dari Dask biasanya cukup bisa dilakukan. Bagaimana Anda memindahkan data dari sistem terdistribusi hosting (spark/flink/dask) ke xg-boost? Atau apakah ini untuk pelatihan terdistribusi tentang data kecil?

Lebih konkretnya, saya berharap untuk membangun sistem sebagai berikut:

  • Pada setiap pekerja dask saya memulai server Rabit. Dask memberi server Rabit ini informasi yang cukup untuk menemukan satu sama lain.
  • Saya membuat beberapa status XGBoost lokal pada setiap pekerja yang mewakili model pelatihan saat ini
  • Saya berulang kali memberi makan kerangka data panda objek per pekerja ini atau array numpy
  • Saya mendengarkan beberapa sinyal dari XGBoost yang menyuruh saya berhenti

Apakah ini sesuai dengan harapan Anda? Apakah mudah bagi Anda untuk mengarahkan saya ke Python API yang relevan?

Ya, lihat informasi yang relevan di sini https://github.com/dmlc/xgboost/blob/master/tests/distributed/ untuk python API.

Apa yang perlu Anda lakukan sebagai tambahan adalah memulai pelacak kelinci di sisi pengemudi (kemungkinan menjadi tempat yang menggerakkan dask), ini dilakukan dalam skrip dmlc-submit di sini https://github.com/dmlc/dmlc-core /tree/master/tracker/dmlc_tracker

OK, mengisi outline saya dari sebelumnya:

Sebelum menjalankan kode XGBoost, kami menyiapkan jaringan Rabit

Pada node driver/scheduler kami memulai pelacak rabit

envs = {'DMLC_NUM_WORKER' : nworker,
        'DMLC_NUM_SERVER' : nserver}

rabit = RabitTracker(hostIP=ip_address, nslave=num_workers)
envs.update(rabit.slave_envs())
rabit.start(args.num_workers)  # manages connections in background thread

Saya juga dapat melalui proses serupa untuk memulai PSTracker . Haruskah ini berada di mesin terpusat yang sama atau haruskah di tempat lain dalam jaringan? Haruskah ada beberapa dari ini? Haruskah ini dapat dikonfigurasi pengguna?

Akhirnya saya memiliki pelacak (dan ptracker?) Saya bergabung dengan jaringan dan blok rabit.

rabit.join()  # join network

Pada node pekerja saya perlu membuang variabel lingkungan ini (yang akan saya pindahkan melalui saluran dask normal) ke lingkungan lokal. Maka cukup menelepon xgboost.rabit.init() saja sudah cukup

import os
os.environ.update(envs)
xgboost.rabit.init()

Melihat kode Rabit sepertinya variabel lingkungan adalah satu-satunya cara untuk memberikan informasi ini. Bisakah Anda memverifikasi ini? Apakah ada cara untuk menyediakan informasi host/port pelacak sebagai input langsung?

Pelatihan

Kemudian saya mengonversi numpy arrays / pandas dataframes / scipy sparse arrays ke objek DMatrix, ini tampaknya relatif mudah. Namun saya cenderung memiliki beberapa kumpulan data per pekerja. Apakah ada cara bersih untuk memanggil kereta beberapa kali dengan lebih banyak data saat tersedia? Saya prihatin dengan komentar di baris ini:

# Run training, all the features in training API is available.
# Currently, this script only support calling train once for fault recovery purpose.
bst = xgb.train(param, dtrain, num_round, watchlist, early_stopping_rounds=2)

Apakah kita perlu menunggu semua data tiba sebelum memulai pelatihan?

Contoh kumpulan data / masalah

Dengan asumsi bahwa saya memiliki semuanya di atas dengan benar, apakah ada contoh pelatihan terdistribusi standar yang digunakan orang untuk demonstrasi?

Tidak perlu memulai pstracker.

  • Tracker hanya perlu dijalankan di satu tempat, kemungkinan pada scheduler (driver), tidak memiliki pekerjaan berat data, dan hanya berfungsi untuk menghubungkan pekerjaan.
  • Argumen env dapat diteruskan sebagai kwargs di rabit.init
  • Karena peningkatan pohon adalah algoritme kumpulan, kita perlu menunggu semua data diserap sebelum memulai pelatihan.

    • Namun perhatikan, setiap pekerja hanya perlu mengambil pecahan (subset baris) data.

    • Idealnya, kita harus menggunakan antarmuka data iter untuk meneruskan data ke DMatrix sebagai mode mini-batch, sehingga seluruh dataset tidak harus berada di memori

    • Ini dilakukan melalui https://github.com/dmlc/xgboost/blob/master/include/xgboost/c_api.h#L117 , yang belum memiliki pembungkus python.

    • Untuk solusi pertama, saya akan merekomendasikan untuk langsung melewati array

Saya punya waktu untuk bermain dengan ini pagi ini. Hasil di sini: https://github.com/mrocklin/dask-xgboost

Sejauh ini hanya menangani pembelajaran terdistribusi dari satu set data dalam memori. Beberapa pertanyaan muncul:

  1. Apa cara terbaik untuk membuat cerita bersambung dan menyebarkan objek DMatrix?
  2. Apa cara terbaik untuk membuat serial dan mengembalikan hasil Booster?
  3. Bagaimana variabel lingkungan yang tercantum di atas memetakan ke argumen di rabit.init ? Apa tepatnya bentuk input yang diharapkan dari rabit.init ? Melewati hasil slave_envs() ke rabit.init jelas tidak akan bekerja karena mengharapkan daftar. Haruskah kita mengonversi setiap nama kunci menjadi --key , mungkin menghapus awalan DMLC dan mengonversinya menjadi huruf kecil?
  4. Apakah ada cara yang baik untuk menguji kebenaran? Bagaimana kita membandingkan dua objek Booster? Haruskah kita mengharapkan pelatihan terdistribusi untuk menghasilkan hasil yang sama persis dan pelatihan berurutan?
  • Anda biasanya tidak membuat serialisasi DMatrix, ini lebih seperti pemegang data waktu pelatihan, saya menganggap data diedarkan dan dibagikan oleh dask (array/dataframe), kemudian diteruskan ke xgboost

    • Kita dapat mencari cara yang lebih baik untuk melewatkan data selain secara langsung melalui array dalam memori, mungkin dengan mengekspos iterator data ke xgboost

  • Anda dapat acar Booster, selama xgboost diinstal di kedua sisi.
  • Maaf karena tidak merinci bagaimana hal-hal berlalu, seharusnya
rabit.init(['DMLC_KEY1=VALUE1', 'DMLC_KEY2=VALUE2']
  • Biasanya booster yang dilatih dari mesin terdistribusi dan mesin tunggal tidak sama, tetapi berikut adalah beberapa hal yang perlu diperiksa:

    • Booster yang dikembalikan dari semua pekerja harus identik

    • Mencari kesalahan validasi prediktif, seharusnya hampir serendah kasing mesin tunggal

Dua pertanyaan lagi secara umum tentang bagaimana ini digunakan (saya tidak punya pengalaman dengan XGBoost dan hanya sedikit pengalaman dengan pembelajaran mesin, mohon maafkan ketidaktahuan saya).

  1. Apakah masuk akal untuk menggunakan banyak pekerja pada data input yang sama? (XGBoost terikat secara komputasi?)
  2. Jika kami beroperasi pada kumpulan data yang lebih besar, apakah saya harus melakukan sesuatu yang khusus untuk memberi tahu setiap pekerja XGBoost bahwa datanya berbeda dari rekan-rekannya?

Kasus penggunaan mana yang lebih umum?

Setiap pekerjaan harus bekerja pada partisi data yang berbeda (berdasarkan baris), mereka TIDAK boleh melihat data input yang sama.

  • Jika data tidak cukup besar, versi multi-utas harus dilakukan
  • Setiap karya akan mengumpulkan statistik secara terpisah di partisi mereka dan menyinkronkan satu sama lain

Ini biasanya sesuai dengan operasi mapPartition dalam kerangka kerja seperti spark/flink

Katakanlah kumpulan data saya memiliki 8 baris, 4 kolom, jika kita memulai dua pekerja

  • pekerja 0 membaca dari baris 0-3
  • pekerja 1 membaca dari baris 4 -7

OK, apa yang ada di sana sekarang sedikit lebih bersih. Akan lebih baik jika kami memiliki beberapa kemampuan untuk mengkonsumsi hasil seperti yang dihasilkan pada setiap pekerja, tetapi kami telah mengatasinya untuk saat ini. Inilah solusi saat ini:

  1. Pertahankan dask array atau dataframe di cluster, tunggu sampai selesai
  2. Temukan di mana setiap potongan/partisi berakhir
  3. Beri tahu setiap pekerja untuk menggabungkan potongan/partisi itu dengan tepat dan melatihnya

Solusi ini tampaknya dapat dikelola, tetapi tidak ideal. Akan lebih mudah jika xgboost-python dapat menerima hasil saat mereka tiba. Namun saya pikir hal selanjutnya yang harus dilakukan adalah mencobanya dalam praktik.

Aku akan melihat-lihat di internet untuk contoh. Jika ada yang kebetulan memiliki masalah buatan yang saya dapat dengan mudah menghasilkan dengan numpy atau pandas API yang akan diterima. Sampai saat itu, berikut adalah contoh sepele di laptop saya dengan data acak:

In [1]: import dask.dataframe as dd

In [2]: df = dd.demo.make_timeseries('2000', '2001', {'x': float, 'y': float, 'z': int}, freq='1s', partition_freq=
   ...: '1D')  # some random time series data

In [3]: df.head()
Out[3]: 
                            x         y     z
2000-01-01 00:00:00  0.778864  0.824796   977
2000-01-01 00:00:01 -0.019888 -0.173454  1023
2000-01-01 00:00:02  0.552826  0.051995  1083
2000-01-01 00:00:03 -0.761811  0.780124   959
2000-01-01 00:00:04 -0.643525  0.679375   980

In [4]: labels = df.z > 1000

In [5]: del df['z']

In [6]: df.head()
Out[6]: 
                            x         y
2000-01-01 00:00:00  0.778864  0.824796
2000-01-01 00:00:01 -0.019888 -0.173454
2000-01-01 00:00:02  0.552826  0.051995
2000-01-01 00:00:03 -0.761811  0.780124
2000-01-01 00:00:04 -0.643525  0.679375

In [7]: labels.head()
Out[7]: 
2000-01-01 00:00:00    False
2000-01-01 00:00:01     True
2000-01-01 00:00:02     True
2000-01-01 00:00:03    False
2000-01-01 00:00:04    False
Name: z, dtype: bool

In [8]: from dask.distributed import Client

In [9]: c = Client()  # creates a local "cluster" on my laptop

In [10]: from dask_xgboost import train
/home/mrocklin/Software/anaconda/lib/python3.5/site-packages/sklearn/cross_validation.py:44: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.
  "This module will be removed in 0.20.", DeprecationWarning)

In [11]: param = {'max_depth': 2, 'eta': 1, 'silent': 1, 'objective': 'binary:logistic'}  # taken from example

In [12]: bst = train(c, param, df, labels)
/home/mrocklin/Software/anaconda/lib/python3.5/site-packages/sklearn/cross_validation.py:44: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.
  "This module will be removed in 0.20.", DeprecationWarning)
/home/mrocklin/Software/anaconda/lib/python3.5/site-packages/sklearn/cross_validation.py:44: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.
  "This module will be removed in 0.20.", DeprecationWarning)
/home/mrocklin/Software/anaconda/lib/python3.5/site-packages/sklearn/cross_validation.py:44: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.
  "This module will be removed in 0.20.", DeprecationWarning)
/home/mrocklin/Software/anaconda/lib/python3.5/site-packages/sklearn/cross_validation.py:44: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.
  "This module will be removed in 0.20.", DeprecationWarning)
[14:46:20] Tree method is automatically selected to be 'approx' for faster speed. to use old behavior(exact greedy algorithm on single machine), set tree_method to 'exact'
[14:46:20] Tree method is automatically selected to be 'approx' for faster speed. to use old behavior(exact greedy algorithm on single machine), set tree_method to 'exact'
[14:46:20] Tree method is automatically selected to be 'approx' for faster speed. to use old behavior(exact greedy algorithm on single machine), set tree_method to 'exact'
[14:46:20] Tree method is automatically selected to be 'approx' for faster speed. to use old behavior(exact greedy algorithm on single machine), set tree_method to 'exact'

In [13]: bst
Out[13]: <xgboost.core.Booster at 0x7fbaacfd17b8>

Kode yang relevan ada di sini jika ada yang ingin melihatnya: https://github.com/mrocklin/dask-xgboost/blob/master/dask_xgboost/core.py

Seperti yang saya katakan, saya baru mengenal XGBoost, jadi saya mungkin melewatkan banyak hal.

contoh mainan khas untuk dicoba ada di https://github.com/dmlc/xgboost/tree/master/demo/data
Itu dalam format libsvm, dan perlu sedikit penguraian untuk membuatnya menjadi numpy

Ada yang lebih besar (yang sebenarnya Anda perlukan cluster)? Atau apakah ada cara standar untuk menghasilkan kumpulan data dengan ukuran sewenang-wenang?

Atau, mungkin pertanyaan yang lebih baik adalah: "Apa yang ingin Anda (atau siapa pun yang membaca edisi ini) ingin lihat di sini?"

Bangunan memprediksi sekarang. Jika saya memindahkan model kembali ke pekerja (melalui proses pickle/unpickle) dan kemudian memanggil bst.predict pada beberapa data, saya mendapatkan kesalahan berikut:

Doing rabit call after Finalize

Asumsi saya adalah, pada titik ini, modelnya mandiri dan tidak perlu lagi menggunakan rabit. Tampaknya berfungsi dengan baik di mesin klien. Adakah pemikiran mengapa saya mungkin menerima kesalahan ini saat menelepon predict ?

Beberapa bagian dari prediksi masih menggunakan rabit, terutama karena prediktor masih menggunakan pelajar dengan beberapa rutinitas inisialisasi yang dibagikan dengan pelatihan. Akhirnya ini harus diperbaiki, tetapi inilah masalahnya untuk saat ini.

Saya pikir selama itu berfungsi dengan baik untuk kumpulan data umum, ini adalah titik awal yang menarik.

Ada alasan untuk menggunakan cluster untuk data menengah (kemudahan penjadwalan di cluster env), beberapa pengguna pyspark mungkin tertarik untuk mencobanya jika kami mengiklankannya sedikit

Menguji dataset yang benar-benar penting itu sulit, misalnya (coba 1 dataset dengan 1 miliar baris). Kaggle mungkin beberapa dataset besar yang bisa relevan yaitu sekitar 10 juta.

Repositori ini menunjukkan eksperimen terhadap dataset maskapai penerbangan, yang menurut saya ada dalam puluhan juta baris dan puluhan kolom (ribuan setelah satu-hot-encoding?) Untuk tolok ukur mereka, sepertinya mereka mengambil sampel 100 ribu baris dan dibuat secara artifisial kumpulan data yang lebih besar dari sampel ini. Agaknya kita bisa meningkatkan ini jika perlu.

Berikut adalah contoh menggunakan data ini dengan pandas dan xgboost pada satu inti. Rekomendasi apa pun tentang persiapan data, parameter, atau cara melakukannya dengan benar akan diterima dengan senang hati.

In [1]: import pandas as pd

In [2]: df = pd.read_csv('train-0.1m.csv')

In [3]: df.head()
Out[3]: 
  Month DayofMonth DayOfWeek  DepTime UniqueCarrier Origin Dest  Distance  \
0   c-8       c-21       c-7     1934            AA    ATL  DFW       732   
1   c-4       c-20       c-3     1548            US    PIT  MCO       834   
2   c-9        c-2       c-5     1422            XE    RDU  CLE       416   
3  c-11       c-25       c-6     1015            OO    DEN  MEM       872   
4  c-10        c-7       c-6     1828            WN    MDW  OMA       423   

  dep_delayed_15min  
0                 N  
1                 N  
2                 N  
3                 N  
4                 Y  

In [4]: labels = df.dep_delayed_15min == 'Y'

In [5]: del df['dep_delayed_15min']

In [6]: df = pd.get_dummies(df)

In [7]: len(df.columns)
Out[7]: 652

In [8]: import xgboost as xgb
/home/mrocklin/Software/anaconda/lib/python3.5/site-packages/sklearn/cross_validation.py:44: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.
  "This module will be removed in 0.20.", DeprecationWarning)

In [9]: dtrain = xgb.DMatrix(df, label=labels)

In [10]: param = {}  # Are there better choices for parameters?  I could use help here

In [11]: bst = xgb.train(param, dtrain)  # or other parameters here?
[17:50:28] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 124 extra nodes, 0 pruned nodes, max_depth=6
[17:50:30] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 120 extra nodes, 0 pruned nodes, max_depth=6
[17:50:32] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 120 extra nodes, 0 pruned nodes, max_depth=6
[17:50:33] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 116 extra nodes, 0 pruned nodes, max_depth=6
[17:50:35] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 112 extra nodes, 0 pruned nodes, max_depth=6
[17:50:36] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 114 extra nodes, 0 pruned nodes, max_depth=6
[17:50:38] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 106 extra nodes, 0 pruned nodes, max_depth=6
[17:50:39] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 116 extra nodes, 0 pruned nodes, max_depth=6
[17:50:41] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 104 extra nodes, 0 pruned nodes, max_depth=6
[17:50:43] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 100 extra nodes, 0 pruned nodes, max_depth=6

In [12]: test = pd.read_csv('test.csv')

In [13]: test.head()
Out[13]: 
  Month DayofMonth DayOfWeek  DepTime UniqueCarrier Origin Dest  Distance  \
0   c-7       c-25       c-3      615            YV    MRY  PHX       598   
1   c-4       c-17       c-2      739            WN    LAS  HOU      1235   
2  c-12        c-2       c-7      651            MQ    GSP  ORD       577   
3   c-3       c-25       c-7     1614            WN    BWI  MHT       377   
4   c-6        c-6       c-3     1505            UA    ORD  STL       258   

  dep_delayed_15min  
0                 N  
1                 N  
2                 N  
3                 N  
4                 Y  

In [14]: test_labels = test.dep_delayed_15min == 'Y'

In [16]: del test['dep_delayed_15min']

In [17]: test = pd.get_dummies(test)

In [18]: len(test.columns)  # oops, looks like the columns don't match up
Out[18]: 670

In [19]: dtest = xgb.DMatrix(test)

In [20]: predictions = bst.predict(dtest)  # this fails because of mismatched columns

Bagaimanapun, ini adalah pilihan. Dataset maskapai penerbangan tampaknya terkenal dan dalam praktiknya bisa sangat besar. Sekali lagi, pembelajaran mesin bukanlah keahlian saya, jadi saya tidak tahu apakah ini pantas atau tidak.

cc @TomAugspurger , yang sepertinya tipe pria yang mungkin memikirkan hal ini.

Mengenai Dask dan prediksi, saya selalu bisa mengatur rabit lagi. Ini terasa sedikit tidak bersih karena memaksa evaluasi daripada membuat hal-hal malas. Tapi ini bukan pemblokir yang serius untuk digunakan.

Mengalami beberapa masalah dengan prediksi. Dua pertanyaan:

  1. Bisakah saya menelepon Booster.predict beberapa kali dalam sesi rabit yang sama?
  2. Bisakah saya menelepon rabit.init , Booster.predict dan rabit.finalize pada utas terpisah?

Saat ini saya membuat pelacak baru, dan memanggil rabit.init di utas utama pekerja. Ini bekerja dengan baik. Namun ketika saya memanggil Booster.predict di utas pekerja (setiap pekerja dask memelihara kumpulan utas untuk perhitungan) saya mendapatkan kesalahan seperti Doing rabit call after Finalize . Ada rekomendasi?

Beberapa bagian dari prediksi masih menggunakan rabit, terutama karena prediktor masih menggunakan pelajar dengan beberapa rutinitas inisialisasi yang dibagikan dengan pelatihan. Akhirnya ini harus diperbaiki, tetapi inilah masalahnya untuk saat ini.

Saya ingin tahu tentang ini. Setelah kami membuat serial-transfer-deserialisasi model terlatih dari pekerja ke mesin klien saya, tampaknya berfungsi dengan baik pada data normal meskipun tidak ada jaringan rabit. Sepertinya model yang dilatih dengan Rabit dapat digunakan untuk memprediksi data tanpa rabit. Ini juga sepertinya akan diperlukan dalam produksi. Bisakah Anda mengatakan lebih banyak tentang kendala menggunakan model terlatih kelinci di sini?

Contoh kumpulan data / masalah
Dengan asumsi bahwa saya memiliki semuanya di atas dengan benar, apakah ada contoh pelatihan terdistribusi standar yang digunakan orang untuk demonstrasi?

Saya akan senang untuk mereproduksi hasil percobaan ini:

https://github.com/Microsoft/LightGBM/wiki/Experiments#parallel -experiment

dengan opsi binning + hist cepat baru dari XGBoost (#1950), seharusnya mungkin untuk mendapatkan hasil yang serupa.

contoh mainan khas untuk dicoba ada di https://github.com/dmlc/xgboost/tree/master/demo/data
Itu dalam format libsvm, dan perlu sedikit penguraian untuk membuatnya menjadi numpy

Anda mungkin tertarik dengan PR ini di sklearn: https://github.com/scikit-learn/scikit-learn/pull/935

@mrocklin Tidak ada batasan untuk menggunakan kembali model. Jadi model yang dilatih dalam versi terdistribusi dapat digunakan dalam versi serial. Hanya saja batasan prediktor saat ini (ketika dikompilasi dengan rabit) memiliki fungsi campuran dengan fungsi pelatihan (jadi panggilan rabit terjadi).

Sekarang setelah Anda mengatakannya, saya pikir kita mungkin memiliki solusi untuk masalah tersebut. Cukup lakukan rabit.init (tanpa memasukkan apa pun, dan buat prediktor berpikir itu adalah satu-satunya pekerja) sebelum prediksi harus menyelesaikan masalah

Ya. Memang itu menyelesaikan masalah. dask-xgboost sekarang mendukung prediksi: https://github.com/mrocklin/dask-xgboost/commit/827a03d96977cda8d104899c9f42f52dac446165

Terima kasih atas solusinya @tqchen !

Berikut adalah alur kerja dengan dask.dataframe dan xgboost pada sampel kecil kumpulan data maskapai di laptop lokal saya. Apakah ini terlihat baik untuk semua orang? Apakah ada elemen API XGBoost yang saya lewatkan di sini?

In [1]: import dask.dataframe as dd

In [2]: import dask_xgboost as dxgb

In [3]: df = dd.read_csv('train-0.1m.csv')

In [4]: df.head()
Out[4]: 
  Month DayofMonth DayOfWeek  DepTime UniqueCarrier Origin Dest  Distance  \
0   c-8       c-21       c-7     1934            AA    ATL  DFW       732   
1   c-4       c-20       c-3     1548            US    PIT  MCO       834   
2   c-9        c-2       c-5     1422            XE    RDU  CLE       416   
3  c-11       c-25       c-6     1015            OO    DEN  MEM       872   
4  c-10        c-7       c-6     1828            WN    MDW  OMA       423   

  dep_delayed_15min  
0                 N  
1                 N  
2                 N  
3                 N  
4                 Y  

In [5]: labels = df.dep_delayed_15min == 'Y'

In [6]: del df['dep_delayed_15min']

In [7]: df = df.categorize()

In [8]: df = dd.get_dummies(df)

In [9]: data_train, data_test = df.random_split([0.9, 0.1], random_state=123)

In [10]: labels_train, labels_test = labels.random_split([0.9, 0.1], random_state=123)

In [11]: from dask.distributed import Client

In [12]: client = Client()  # in a large-data situation I probably should have done this before calling categorize above (which requires computation)

In [13]: param = {}  # Are there better choices for parameters?

In [14]: bst = dxgb.train(client, {}, data_train, labels_train)
[14:00:46] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 120 extra nodes, 0 pruned nodes, max_depth=6
[14:00:48] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 120 extra nodes, 0 pruned nodes, max_depth=6
[14:00:50] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 122 extra nodes, 0 pruned nodes, max_depth=6
[14:00:53] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 118 extra nodes, 0 pruned nodes, max_depth=6
[14:00:55] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 120 extra nodes, 0 pruned nodes, max_depth=6
[14:00:57] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 114 extra nodes, 0 pruned nodes, max_depth=6
[14:00:59] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 118 extra nodes, 0 pruned nodes, max_depth=6
[14:01:01] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 118 extra nodes, 0 pruned nodes, max_depth=6
[14:01:04] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 94 extra nodes, 0 pruned nodes, max_depth=6
[14:01:06] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 102 extra nodes, 0 pruned nodes, max_depth=6

In [15]: bst
Out[15]: <xgboost.core.Booster at 0x7f689803af60>

In [16]: predictions = dxgb.predict(client, bst, data_test)

In [17]: predictions
Out[17]: 
Dask Series Structure:
npartitions=1
None    float32
None        ...
Name: predictions, dtype: float32
Dask Name: _predict_part, 9 tasks

Tujuan jangka pendek saya adalah menulis posting blog singkat tentang ini sehingga mudah-mudahan ada orang lain yang lebih berpengalaman dengan XGBoost dan dengan lebih banyak waktu datang untuk mengadopsi proyek ini dan mendorongnya ke depan. (Saya, seperti semua orang di sini, sedang mengerjakan beberapa proyek lain seperti ini pada saat yang bersamaan.)

Saya tidak setuju dengan kumpulan data maskapai penerbangan hanya karena saya sudah memilikinya di ember S3. Saya setuju meskipun dataset Criteo akan membuat demonstrasi skala yang lebih baik.

Saya masih tidak yakin parameter apa yang digunakan atau bagaimana menilai hasilnya. Untuk parameter saya bisa menggunakan eksperimen dari @szilard di sini . Apakah ada cara yang baik untuk menilai prediksi? Misalnya kita mencari predictions > 0.5 untuk mencocokkan labels_test ?

Mungkin cara paling umum untuk mengevaluasi kinerja prediktif untuk klasifikasi biner (terutama dalam penelitian atau pengaturan kompetisi) adalah dengan menggunakan area di bawah kurva ROC (AUC), meskipun dalam aplikasi dunia nyata seseorang harus menggunakan metrik yang selaras dengan nilai "bisnis". dihasilkan dengan menggunakan model.

Misalnya, apakah kita mencari prediksi > 0,5 untuk mencocokkan labels_test?

Ya. Jika Anda mengambil rata-rata itu pada set tes, ini adalah akurasi tes. Tapi kemungkinan dataset tidak seimbang (lebih banyak tidak adanya klik daripada klik). Dalam hal ini, skor ROC AUC adalah metrik yang lebih baik.

from sklearn.metrics import roc_auc_score
print(roc_auc_score(labels_test, predictions))

dengan asumsi predictions adalah larik 1D dari probabilitas positif yang diperkirakan oleh model untuk setiap baris dalam set pengujian.

@mrocklin Satu pertanyaan lanjutan, apakah dask mengizinkan pekerjaan pekerja multi-utas? Saya tahu ini tidak terlalu relevan dengan python karena GIL. Tetapi xgboost dapat mengizinkan pelatihan multi-utas per pekerja sambil tetap berkoordinasi satu sama lain secara terdistribusi. Kita harus selalu menetapkan argumen nthread dari xgboost menjadi jumlah inti kerja dari pekerja itu

Jawaban singkatnya adalah "ya". Sebagian besar penggunaan Dask adalah dengan proyek-proyek seperti NumPy, Pandas, SKLearn dan lainnya yang kebanyakan hanya kode C dan Fortran, dibungkus dengan Python. GIL tidak memengaruhi perpustakaan ini. Beberapa orang memang menggunakan Dask untuk aplikasi serupa dengan RDD PySpark (lihat dask.bag ) dan akan terpengaruh. Meskipun kelompok ini minoritas.

Jadi ya, Dask memungkinkan tugas multi-utas. Bagaimana cara kami memberi tahu XGBoost untuk menggunakan banyak utas? Dalam percobaan saya sejauh ini, saya melihat penggunaan CPU yang tinggi tanpa mengubah parameter apa pun, jadi mungkin semuanya berfungsi dengan baik secara default?

XGBoost menggunakan multi-threaded secara default, dan akan menggunakan semua thread cpu yang tersedia pada mesin (bukan pada pekerja itu) jika nthread tidak disetel. Ini dapat menciptakan kondisi balapan ketika beberapa pekerja ditugaskan ke mesin yang sama.

Jadi selalu baik untuk mengatur parameter nthread ke jumlah inti maksimum yang diizinkan untuk digunakan pekerja. Biasanya praktik yang baik digunakan sekitar katakanlah 4 utas per pekerja

Tentu, harus dicapai dalam
https://github.com/mrocklin/dask-xgboost/commit/c22d066b67c78710d5ad99b8620edc55182adc8f

Pada Senin, 20 Februari 2017 pukul 18:31, Tianqi [email protected]
menulis:

XGBoost menggunakan multi-threaded secara default, dan akan menggunakan semua cpu yang tersedia
utas pada mesin (bukan pada pekerja itu) jika nthread tidak disetel.
Ini dapat menciptakan kondisi balapan ketika beberapa pekerja ditugaskan ke yang sama
mesin.

Jadi selalu baik untuk mengatur parameter nthread ke jumlah maksimum
core yang diizinkan untuk digunakan oleh pekerja. Biasanya praktik yang baik digunakan di sekitar say
4 utas per pekerja


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

Buku Catatan: https://Gist.github.com/19c89d78e34437e061876a9872f4d2df
Screencast singkat (enam menit): https://youtu.be/Cc4E-PdDSro

Umpan balik kritis sangat diterima. Sekali lagi, mohon maafkan ketidaktahuan saya di bidang ini.

@mrocklin demo hebat! Saya pikir kinerja runtime (dan mungkin penggunaan memori) dapat sangat ditingkatkan dengan menggunakan 'tree_method': 'hist', 'grow_policy': 'lossguide' di param dict.

Terima kasih @ogrissel. Dengan parameter tersebut, waktu pelatihan berubah dari enam menit menjadi satu menit. Penggunaan memori tampaknya tetap sama.

Oke, kembali ke ini. Apakah ada operasi XGBoost selain melatih dan memprediksi yang harus kita terapkan?

@tqchen atau @ogrisel jika salah satu dari Anda punya waktu untuk melihat implementasi di https://github.com/mrocklin/dask-xgboost/blob/master/dask_xgboost/core.py Saya akan berterima kasih. Saya mengerti bahwa melihat melalui basis kode asing tidak selalu tinggi dalam daftar prioritas.

Jika semuanya baik-baik saja maka saya akan menambahkan sedikit lebih banyak ke README, mempublikasikan ke PyPI, dan kemudian kami mungkin dapat menutup masalah ini.

Saya pikir hanya melatih dan memprediksi perlu didistribusikan. Hal-hal lain tidak harus didistribusikan karena mereka tidak membalas pada dataset

Saya telah mendorong dask-xgboost ke PyPI dan memindahkannya ke https://github.com/dask/dask-xgboost

Terima kasih @tqchen dan @ogrisel atas bantuan Anda di sini. Kolaborasi membuat ini relatif mudah.

Saya akan dengan senang hati membantu orang-orang jika mereka ingin menjalankan benchmark. Sampai saat itu, tutup.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat