Время прочтения: 4 мин.
Знакомство с реализацией алгоритмов машинного обучения для языка python многие начинают с библиотеки Scikit-learn. Эта многопрофильная библиотека содержит эффективные инструменты работы с данными и может использоваться в самых разнообразных сценариях. Однако Scikit-learn не поддерживает работу с графическими процессорами, поэтому при обработке больших массивов данных скорость не всегда удовлетворительна.
В статье мы расскажем об альтернативном решении – RAPIDS и приведем сравнительные данные.
RAPIDS – библиотека с открытым исходным кодом для анализа данных и машинного обучения с использованием графического процессора, разработанная и поддерживаемая компанией Nvidia. Она совместима со многими существующими инструментами, такими как Pandas, scikit-learn, numpy и т.д. При этом позволяет значительно ускорить многие задачи анализа данных и машинного обучения, часто в 100 раз или даже больше.
RAPIDS использует примитивы NVIDIA CUDA® для низкоуровневой оптимизации вычислений, что позволяет задействовать возможности параллельной обработки на графическом процессоре и увеличить пропускную способность памяти через удобные для пользователя интерфейсы Python.
RAPIDS также фокусируется на общих задачах подготовки данных для аналитики и обработки данных, в том числе с использованием знакомого API фреймов данных (DataFrame), который интегрируется с различными алгоритмами машинного обучения для ускорения обработки без типичных затрат на сериализацию. RAPIDS также включает поддержку многоузловых развертываний с несколькими графическими процессорами, что позволяет значительно ускорить обработку и обучение для наборов данных большого размера.
Для сравнения быстродействия библиотек мы сгенерируем датасеты со случайными данными, а затем отдельно обучим на них модели из cuml (Rapids.ai) и sklearn и оценим затраченное время.
Кластеризация
При помощи функции make_blobs сформируем датасет:
n_samples=1000000
n_features=100
n_classes=2
random_state=42
data ,labels = make_blobs(n_samples=n_samples, n_features=n_features, centers=n_classes, random_state=42)
cu_data = cudf.DataFrame(data)
pd_data = cu_data.to_pandas()
Затем обучим на этих данных две модели кластеризации методом K-средних и сравним время, за которое отработали функции.
Sklearn-вариант
%%time
kmeans_sk = skKMeans(init="k-means++",
n_clusters=n_classes,
n_jobs=-1,
random_state=random_state)
kmeans_sk.fit(pd_data)
CPU times: user 18.6 s, sys: 5.07 s, total: 23.6 s
Wall time: 13.6 s
Cuml-вариант
%%time
kmeans_cuml = cuKMeans(init="k-means||",
n_clusters=n_classes,
oversampling_factor=40,
random_state=random_state)
kmeans_cuml.fit(cu_data)
CPU times: user 492 ms, sys: 17.9 ms, total: 510 ms
Wall time: 508 ms
Rapids.ai модель обучилась почти в 30 раз быстрее чем sklearn.
Регрессия
Датасет сформируем, аналогично предыдущему, только теперь будем использовать функцию make_regression:
X, y = make_regression(n_samples=n_samples, n_features=n_features, random_state=random_state)
X = cudf.DataFrame(X)
y = cudf.DataFrame(y)[0]
cu_X_train, cu_X_test, cu_y_train, cu_y_test = train_test_split(X, y, test_size = 0.2, random_state=random_state)
pd_X_train = cu_X_train.to_pandas()
pd_X_test = cu_X_test.to_pandas()
pd_y_train = cu_y_train.to_pandas()
pd_y_test = cu_y_test.to_pandas()
Далее последовательно обучим две модели линейной регрессии и сравним время обучения и точность прогноза модели.
Sklearn-вариант
%%time
from sklearn.linear_model import LinearRegression as skLinearRegression
ols_sk = skLinearRegression(fit_intercept=True,
normalize=True,
n_jobs=-1)
ols_sk.fit(pd_X_train, pd_y_train)
CPU times: user 7.35 s, sys: 608 ms, total: 7.96 s
Wall time: 4.65 s
Cuml-вариант
%%time
from cuml.linear_model import LinearRegression as cuLinearRegression
ols_cuml = cuLinearRegression(fit_intercept=True,
normalize=True,
algorithm='eig')
ols_cuml.fit(cu_X_train, cu_y_train)
CPU times: user 32.2 ms, sys: 8.04 ms, total: 40.2 ms
Wall time: 39.4 ms
Почти в 150 раз быстрее!
Такого результата удалось добиться:
%%time
r2_score_sk = r2_score(pd_y_test, ols_sk.predict(pd_X_test))
r2_score_cuml = r2_score(cu_y_test, ols_cuml.predict(cu_X_test))
print("R^2 score (sklearn): %s" % r2_score_sk)
print("R^2 score (cuml): %s" % r2_score_cuml)
R^2 score (SKL): 1.0
R^2 score (cuML): 1.0
Классификация
Последней обучим модель RandomForest Classifier.
%%time
X, y = make_classification(n_samples=n_samples, n_features=n_features, n_classes=n_classes, random_state=random_state)
X = cudf.DataFrame(X)
y = cudf.DataFrame(y)[0]
cu_X_train, cu_X_test, cu_y_train, cu_y_test = train_test_split(X, y, test_size = 0.2, random_state=random_state)
pd_X_train = cu_X_train.to_pandas()
pd_X_test = cu_X_test.to_pandas()
pd_y_train = cu_y_train.to_pandas()
pd_y_test = cu_y_test.to_pandas()
Sklearn-вариант
%%time
from sklearn.ensemble import RandomForestClassifier as skrfc
sk_model = skrfc(n_estimators=10,
max_depth=8,
max_features=1.0,
random_state=random_state)
sk_model.fit(pd_X_train, pd_y_train)
CPU times: user 10min 42s, sys: 623 ms, total: 10min 43s
Wall time: 10min 44s
Cuml-вариант
%%time
cuml_model = curfc(n_estimators=10,
max_depth=8,
max_features=1.0,
random_state=random_state)
cuml_model.fit(cu_X_train, cu_y_train)
CPU times: user 8.44 s, sys: 50.5 ms, total: 8.49 s
Wall time: 5.31 s
В данном примере библиотека с поддержкой GPU имеет подавляющее преимущество перед CPU, обучение прошло более чем в 100 раз быстрее. Это объясняется тем, что для данной модели необходимо построить множество отдельных деревьев. Эта задача прекрасно распараллеливается и поэтому хорошо подходит для вычислений на множестве ядер. В данном случае строились модели с не очень большим количеством деревьев (n_estimators=10). С увеличением этого параметра разрыв в скорости обучения будет становиться еще больше.
Выводы
Несмотря на то, что библиотека Scikit-learn является неким «золотым стандартом» в отрасли машинного обучения, чтобы добиться приемлемой скорости при обработке больших наборов данных, имеет смысл присмотреться к библиотеке RAPIDS.