Я хотел бы использовать несколько графических процессоров, распределенных по множеству узлов, для обучения модели XGBoost на очень большом наборе данных в рамках машинного обучения Azure с использованием 3 вычислительные узлы NC12s_v3. Размер набора данных превышает размер как VRAM, так и RAM при сохранении в Dask, но удобно помещается на диске. Однако модуль dask сохраняет все данные при обучении. (по крайней мере, по умолчанию).
Вся предварительная обработка данных была обработана (одна горячая кодировка с типом данных np.bool), и можно предположить, что у меня есть наиболее эффективные типы данных в другом месте (например, изменение np.float64 на np.float32 для десятичных функций, изменение на int8 для порядковые данные и т. д.).
В настоящее время я пытаюсь получить простую игрушечную модель, работающую только с обучающим набором. Мой код выглядит следующим образом:
from dask_cuda import LocalCUDACluster
import dask
import xgboost as xgb
import pandas as pd
import numpy as np
import distributed
from dask.distributed import Client, wait, LocalCluster
# Start cluster and client. This is currently local, although I would like to make this distributed across many nodes.
cluster = LocalCUDACluster(n_workers=2, device_memory_limit='16 GiB')
client = distributed.Client(cluster)
# Read in training data.
train_dd = dask.dataframe.read_parquet("folder_of_training_data/*.parquet", chunksize="128 MiB")
# Split into features and target, all other preprocessing including one hot encoding has been completed.
X = train_dd[train_dd.columns.difference(['label'])]
y = train_dd['label']
# Delete dask dataframe to free up memory.
del train_dd
# Create DaskDMatrix from X, y inputs.
dtrain = xgb.dask.DaskDMatrix(client, X, y)
# Delete X and y to free up memory.
del X
del y
# Create watchlist for input into xgb train method.
watchlist = [(dtrain, 'train')]
# Train toy booster on 10 rounds with subsampling and gradient based sampling to reduce memory requirements.
bst = xgb.dask.train(
client,
{
'predictor': 'gpu_predictor',
'tree_method': 'gpu_hist',
'verbosity': 2,
'objective': 'binary:logistic',
'sampling_method': 'gradient_based',
'subsample': 0.1
},
dtrain,
num_boost_round=10,
evals=watchlist
)
del dtrain
print("History:", str(bst['history']))
С указанным выше на одном узле, содержащем 2 графических процессора, я могу загружать только до 32 ГБ за раз (ограничения VRAM).
Из моего текущего кода у меня есть несколько вопросов:
Есть ли способ остановить XGBoost от сохранения всех данных в памяти, вместо этого, возможно, работая через разделы в пакетах?
Есть ли способ заставить Dask обрабатывать пакетный процесс изначально, а не вручную выполнять, например, инкрементное обучение?
В документации они упоминают, что вы можете использовать режим внешней памяти вместе с их распределенным режимом. Предполагая, что у меня есть файлы libsvm, как мне это сделать с несколькими узлами и несколькими графическими процессорами?
Как я могу изменить приведенный выше код, чтобы я мог работать более чем с одним узлом?
Дополнительный вопрос: предполагая, что существует способ пакетной обработки с помощью xgboost.dask, как я могу интегрировать это с RAPIDS для обработки исключительно на графических процессорах?