Время прочтения: 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.