Здравствуйте, я автор Dask , библиотеки для параллельных и распределенных вычислений на Python. Мне любопытно, есть ли в этом сообществе интерес к сотрудничеству в распространении XGBoost на Dask либо для параллельного обучения, либо для ETL.
Вероятно, есть два компонента Dask, которые имеют отношение к этому проекту:
Есть ли здесь интерес к сотрудничеству?
@mrocklin Я думал, что у Dask есть интеграция со sklearn. Вы взглянули на нашу оболочку sklearn, чтобы увидеть, будет ли она работать с этим?
Значимая интеграция с распределенной системой обычно должна выполняться на уровне каждого алгоритма, а не на уровне библиотеки. Есть несколько способов, которыми SKLearn и Dask могут помочь друг другу, да, но они не особенно глубоки.
Dask dataframe был бы хорошим началом. В нашей базе кода у нас есть проверка на кадр данных pandas. Возможно, для начала подойдет dask dataframe.
Итак, что произойдет, если кто-то прибудет с многотерабайтным кадром данных dask? Вы просто конвертируете его в Pandas и продолжаете? Или есть способ разумно распараллелить XGBoost в кластере, указав на различные кадры данных pandas, которые составляют кадр данных dask?
Пользователи могут указать размер партии? Я полагаю, что пользователи могут получить пользу от partial_fit.
cc @tqchen , который лучше знаком с распределенной частью кода.
Распределенную версию xgboost можно подключить к распределенному средству запуска заданий, в идеале получить поток данных раздела в xgboost, а затем продолжить.
@mrocklin Я думаю, что наиболее важной частью является модуль xgboost-spark и xgboost-flink, который встраивает xgboost в функцию mapPartition spark/flink. Я думаю, в Даске было бы что-то подобное
Требование со стороны xgboost заключается в том, что XGBoost обрабатывает межпроцессное соединение по обыкновению, и ему нужно будет запустить трекер (который соединяет каждое задание) со стороны клиента.
см. соответствующий код в https://github.com/dmlc/xgboost/blob/master/jvm-packages/xgboost4j-spark/src/main/scala/ml/dmlc/xgboost4j/scala/spark/XGBoost.scala#L112 .
Rabit предназначен для встраивания в другую распределенную систему, поэтому я думаю, что не составит труда выполнить настройку на стороне Python.
Запуск других распределенных систем из Dask обычно вполне выполним. Как вы перемещаете данные из распределенной системы хостинга (spark/flink/dask) в xg-boost? Или это для распределенного обучения на малых данных?
Более конкретно, я ожидаю построить систему следующим образом:
Соответствует ли это вашим ожиданиям? Легко ли вам указать мне на соответствующий Python API?
Да, см. соответствующую информацию здесь https://github.com/dmlc/xgboost/blob/master/tests/distributed/ для API Python.
Что вам нужно будет сделать дополнительно, так это запустить средство отслеживания кроликов на стороне водителя (вероятно, это место, которое управляет dask), это делается в сценарии dmlc-submit здесь https://github.com/dmlc/dmlc-core /дерево/мастер/трекер/dmlc_tracker
ОК, заполнение моей схемы из ранее:
На узле драйвер/планировщик запускаем трекер кроликов
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
Я также могу пройти через аналогичный процесс, чтобы начать PSTracker
. Это должно быть на той же централизованной машине или где-то еще в сети? Их должно быть несколько? Должно ли это быть настраиваемым пользователем?
В конце концов, мой трекер (и пстрекеры?) присоединяются к сети кроликов и блокируются.
rabit.join() # join network
На рабочих узлах мне нужно сбросить эти переменные среды (которые я буду перемещать по обычным каналам dask) в локальную среду. Тогда достаточно просто позвонить xgboost.rabit.init()
import os
os.environ.update(envs)
xgboost.rabit.init()
Глядя на код Rabit, кажется, что переменные среды — единственный способ предоставить эту информацию. Вы можете это проверить? Есть ли способ предоставить информацию о хосте / порте трекера в качестве прямых входов?
Затем я конвертирую свои массивы numpy / кадры данных pandas / разреженные массивы scipy в объекты DMatrix, это кажется относительно простым. Однако у меня, вероятно, будет несколько пакетов данных на одного работника. Есть ли чистый способ вызвать поезд несколько раз с дополнительными данными по мере их поступления? Меня беспокоят комментарии к этим строкам:
# 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)
Нужно ли ждать поступления всех данных перед началом обучения?
Если предположить, что у меня все правильно, то есть ли стандартный пример распределенного обучения, который люди используют для демонстрации?
Нет необходимости запускать pstracker.
У меня было немного времени, чтобы поиграть с этим сегодня утром. Результаты здесь: https://github.com/mrocklin/dask-xgboost
Пока он обрабатывает только распределенное обучение одного набора данных в памяти. Возникли некоторые вопросы:
rabit.init
? Какова именно ожидаемая форма входных данных для rabit.init
? Очевидно, что передача результата slave_envs()
в rabit.init не сработает, потому что он ожидает список. Должны ли мы преобразовать каждое имя ключа в --key
, возможно, убрав префикс DMLC
и преобразовав его в нижний регистр?rabit.init(['DMLC_KEY1=VALUE1', 'DMLC_KEY2=VALUE2']
Еще два вопроса о том, как это используется (у меня нет опыта работы с XGBoost и только небольшой опыт машинного обучения, простите мое невежество).
Какой вариант использования более распространен?
Каждая работа должна работать с разными разделами данных (по строкам), они НЕ должны смотреть на одни и те же входные данные.
Обычно это соответствует операции mapPartition в таких фреймворках, как spark/flink.
Скажем, мой набор данных имеет 8 строк, 4 столбца, если мы запустим двух рабочих
Хорошо, то, что там сейчас, немного чище. Было бы неплохо, если бы у нас была возможность использовать результаты по мере того, как они генерируются на каждом воркере, но пока мы поработали над этим. Вот текущее решение:
Это решение кажется управляемым, но не идеальным. Было бы удобно, если бы xgboost-python мог принимать результаты по мере их поступления. Однако я думаю, что следующее, что нужно сделать, это попробовать это на практике.
Поищу примеры в интернете. Если у кого-то возникнет искусственная проблема, которую я могу легко создать с помощью API numpy или pandas, это будет приветствоваться. А пока вот тривиальный пример на моем ноутбуке со случайными данными:
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>
Соответствующий код находится здесь, если кто-то хочет взглянуть: https://github.com/mrocklin/dask-xgboost/blob/master/dask_xgboost/core.py
Как я уже сказал, я новичок в XGBoost, поэтому, вероятно, что-то упускаю.
типичный пример игрушки, который можно попробовать, находится в https://github.com/dmlc/xgboost/tree/master/demo/data .
Однако он находится в формате libsvm, и его нужно немного разобрать, чтобы получить его в numpy.
Что-то большее (для чего вам действительно понадобится кластер)? Или есть стандартный способ создать набор данных произвольного размера?
Или, может быть, лучше задать вопрос: «Что бы вы (или кто-либо еще, читающий этот выпуск) хотели бы здесь увидеть?»
Строительство прогнозируют сейчас. Если я верну модель обратно рабочему процессу (проходя процесс рассола/разбора), а затем вызову bst.predict
для некоторых данных, я получу следующую ошибку:
Doing rabit call after Finalize
Мое предположение заключалось в том, что на данный момент модель автономна и больше не нуждается в использовании кролика. Кажется, он отлично работает на клиентской машине. Любые мысли, почему я могу получить эту ошибку при вызове predict
?
Некоторая часть прогнозирования по-прежнему использует rabbit, в основном из-за того, что предиктор по-прежнему использует учащегося с некоторыми процедурами инициализации, которые используются совместно с обучением. Со временем это должно быть исправлено, но пока это так.
Я думаю, что пока это работает нормально для общего набора данных, это интересная отправная точка.
В любом случае есть причины использовать кластер для средних данных (простота планирования в окружении кластера), некоторым пользователям pyspark может быть интересно попробовать его, если мы немного рекламируем его.
Тестирование набора данных, который действительно имеет значение, было сложным, например (попробуйте 1 набор данных с 1 миллиардом строк). Kaggle может иметь какой-то большой набор данных, который может иметь отношение, около 10 миллионов.
В этом репозитории показаны эксперименты с набором данных авиакомпаний, который, как мне кажется, состоит из десятков миллионов строк и десятков столбцов (тысячи после однократного горячего кодирования?). большие наборы данных из этой выборки. Предположительно, мы могли бы масштабировать это, если это необходимо.
Вот пример использования этих данных с пандами и xgboost на одном ядре. Приветствуются любые рекомендации по подготовке данных, параметрам или тому, как это сделать правильно.
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
В любом случае, вот вариант. Набор данных авиакомпаний кажется хорошо известным и на практике может быть неудобно большим. Опять же, машинное обучение не является моей специальностью, поэтому я не знаю, уместно это или нет.
cc @TomAugspurger , похоже, у него есть мысли по этому поводу.
Что касается Dask и Predict, я всегда могу снова настроить Rabit. Это кажется немного нечистым, потому что заставляет оценивать, а не делает вещи ленивыми. Но это не серьезный блокировщик для использования.
Возникли некоторые проблемы с прогнозированием. Два вопроса:
Booster.predict
несколько раз в течение одного и того же сеанса Rabit?rabit.init
, Booster.predict
и rabit.finalize
в отдельных потоках?В настоящее время я создаю новый трекер и вызываю rabit.init
в основном потоке рабочего. Это прекрасно работает. Однако, когда я вызываю Booster.predict
в рабочих потоках (каждый рабочий dask поддерживает пул потоков для вычислений), я получаю такие ошибки, как Doing rabit call after Finalize
. Есть рекомендации?
Некоторая часть прогнозирования по-прежнему использует rabbit, в основном из-за того, что предиктор по-прежнему использует учащегося с некоторыми процедурами инициализации, которые используются совместно с обучением. Со временем это должно быть исправлено, но пока это так.
Мне любопытно об этом. После того, как мы сериализуем-переносим-десериализуем обученную модель с рабочего на мою клиентскую машину, кажется, что она отлично работает с обычными данными, даже если нет сети rabit. Похоже, что модель, обученную с помощью Rabit, можно использовать для прогнозирования данных без Rabit. Это также кажется необходимым в производстве. Можете ли вы рассказать больше об ограничениях использования модели, обученной кроликам, здесь?
Пример набора данных/проблемы
Если предположить, что у меня все правильно, то есть ли стандартный пример распределенного обучения, который люди используют для демонстрации?
Было бы неплохо воспроизвести результаты этого эксперимента:
https://github.com/Microsoft/LightGBM/wiki/Experiments#parallel — эксперимент
с новой опцией binning + fast hist от XGBoost (# 1950) можно будет получить аналогичные результаты.
типичный пример игрушки, который можно попробовать, находится в https://github.com/dmlc/xgboost/tree/master/demo/data .
Однако он находится в формате libsvm, и его нужно немного разобрать, чтобы получить его в numpy.
Вас может заинтересовать этот PR в sklearn: https://github.com/scikit-learn/scikit-learn/pull/935
@mrocklin Нет ограничений на повторное использование модели. Таким образом, модель, обученная в распределенной версии, может быть использована в последовательной версии. Просто текущее ограничение предиктора (при компиляции с rabit) имеет смешанную функцию с функцией обучения (поэтому произошел вызов rabit).
Теперь, когда вы это сказали, я думаю, у нас может быть решение проблемы. Просто сделайте rabit.init
(ничего не передавая и заставьте предсказатель думать, что это единственный рабочий), прежде чем предсказать, что проблема должна решиться.
да. Действительно, это решает проблему. dask-xgboost теперь поддерживает прогнозирование: https://github.com/mrocklin/dask-xgboost/commit/827a03d96977cda8d104899c9f42f52dac446165
Спасибо за обходной путь @tqchen !
Вот рабочий процесс с dask.dataframe и xgboost для небольшого образца набора данных авиакомпаний на моем локальном ноутбуке. Всем ли это кажется нормальным? Есть ли элементы API XGBoost, которые мне здесь не хватает?
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
Моя краткосрочная цель — написать короткий пост об этом в блоге, чтобы, надеюсь, кто-то еще с большим опытом работы с XGBoost и с большим количеством времени принял этот проект и продвигал его вперед. (Я, как и все здесь, одновременно работаю над несколькими другими подобными проектами.)
Я неравнодушен к набору данных об авиакомпаниях только потому, что он у меня уже есть в корзине S3. Однако я согласен с тем, что набор данных Criteo поможет лучше продемонстрировать масштабирование.
Я до сих пор не уверен, какие параметры использовать или как судить о результате. Для параметров могу использовать эксперимент от @szilard здесь . Есть ли хороший способ судить о предсказаниях? Например, мы ищем predictions > 0.5
, чтобы соответствовать labels_test
?
Возможно, наиболее распространенным способом оценки прогностической эффективности бинарной классификации (особенно в исследованиях или условиях конкуренции) является использование площади под кривой ROC (AUC), хотя в реальных приложениях следует использовать показатели, которые соответствуют «бизнес» значениям. производится с использованием моделей.
Например, мы ищем прогнозы> 0,5, чтобы соответствовать labels_test?
да. Если вы возьмете среднее значение этого на тестовом наборе, это точность теста. Но вполне вероятно, что набор данных несбалансирован (гораздо больше отсутствие кликов, чем кликов). В этом случае показатель ROC AUC является лучшим показателем.
from sklearn.metrics import roc_auc_score
print(roc_auc_score(labels_test, predictions))
предполагая, что predictions
представляет собой одномерный массив положительных вероятностей, оцененных моделью для каждой строки в тестовом наборе.
@mrocklin Один дополнительный вопрос: разрешает ли dask многопоточные рабочие задания? Я знаю, что это не очень актуально для python из-за GIL. Но xgboost может обеспечить многопоточное обучение для каждого работника, при этом все еще распределяя координацию друг с другом. Мы всегда должны устанавливать аргументы nthread xgboost равным количеству работающих ядер этого работника.
Короткий ответ: «да». Чаще всего Dask используется с такими проектами, как NumPy, Pandas, SKLearn и другими, которые в основном представляют собой просто код C и Fortran, завернутый в Python. GIL не влияет на эти библиотеки. Некоторые люди используют Dask для приложений, аналогичных PySpark RDD (см. dask.bag ), и это будет затронуто. Хотя эта группа в меньшинстве.
Так что да, Dask позволяет выполнять многопоточные задачи. Как мы говорим XGBoost использовать несколько потоков? Пока что в своих экспериментах я вижу высокую загрузку ЦП без изменения каких-либо параметров, так что, может быть, по умолчанию все работает хорошо?
XGBoost по умолчанию использует многопоточность и будет использовать все доступные потоки процессора на машине (а не на этом рабочем), если nthread не установлен. Это может создать состояние гонки, когда несколько рабочих назначены на одну и ту же машину.
Поэтому всегда полезно установить параметр nthread на максимальное количество ядер, разрешенных для использования работником. Обычно хорошей практикой является использование, скажем, 4 потоков на одного рабочего.
Конечно, должно быть выполнено в
https://github.com/mrocklin/dask-xgboost/commit/c22d066b67c78710d5ad99b8620edc55182adc8f
В понедельник, 20 февраля 2017 г., в 18:31, Тяньци Чен, [email protected]
написал:
XGBoost по умолчанию использует многопоточность и будет использовать весь доступный процессор.
потоки на машине (а не на этом рабочем), если nthread не установлен.
Это может создать состояние гонки, когда несколько рабочих назначены на один и тот же
машина.Поэтому всегда полезно установить для параметра nthread максимальное количество
ядер, которые разрешено использовать работнику. Обычно хорошей практикой является использование, скажем,
4 потока на одного рабочего—
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/dmlc/xgboost/issues/2032#issuecomment-281205747 или отключить звук
нить
https://github.com/notifications/unsubscribe-auth/AASszPELRoeIvqEzyJhkKumIs-vd0PHiks5reiJngaJpZM4L_PXa
.
Блокнот: https://gist.github.com/19c89d78e34437e061876a9872f4d2df
Короткий скринкаст (шесть минут): https://youtu.be/Cc4E-PdDSro
Критическая обратная связь очень приветствуется. Еще раз прошу простить мое невежество в этой области.
@mrocklin отличная демонстрация! Я думаю, что производительность во время выполнения (и, возможно, использование памяти) можно значительно улучшить, используя 'tree_method': 'hist', 'grow_policy': 'lossguide'
в параметре dict.
Спасибо @ogrisel. При этих параметрах время тренировки увеличивается с шести минут до одной минуты. Однако использование памяти, похоже, остается примерно таким же.
Хорошо, возвращаясь к этому. Существуют ли какие-либо операции XGBoost, кроме обучения и прогнозирования, которые мы должны реализовать?
@tqchen или @ogrisel , если у кого-то из вас есть время просмотреть реализацию на https://github.com/mrocklin/dask-xgboost/blob/master/dask_xgboost/core.py , я был бы признателен. Я понимаю, однако, что просмотр чужой кодовой базы не всегда занимает первое место в списках приоритетов.
Если все в порядке, я добавлю еще немного в README, опубликую в PyPI, и тогда, вероятно, мы сможем закрыть эту проблему.
Я думаю, что только обучение и прогнозирование должны быть распределены. Другие вещи не нужно распространять, так как они не отвечают на набор данных.
Я отправил dask-xgboost в PyPI и переместил его на https://github.com/dask/dask-xgboost .
Спасибо @tqchen и @ogrisel за вашу помощь. Сотрудничество сделало это относительно легко.
Я был бы рад помочь людям, если они хотят запустить тесты. А пока закрываю.
Самый полезный комментарий
Блокнот: https://gist.github.com/19c89d78e34437e061876a9872f4d2df
Короткий скринкаст (шесть минут): https://youtu.be/Cc4E-PdDSro
Критическая обратная связь очень приветствуется. Еще раз прошу простить мое невежество в этой области.