Machine Learning

Введение

Вычисления на графических процессорах становятся всё более и более важными.

  1. Количество данных во всём мире удваивается каждый год.
  2. Приходит квантовая реальность. Закон Мура перестаёт работать.

Кроме того, растёт число онлайн-платформ анализа данных с поддержкой GPU. В их число входят:

  • Kaggle
  • Google Colaboratory
  • Microsoft Azure
  • AWS

В этой статье я познакомлю вас с RAPIDS  —  открытыми библиотеками NVIDIA для Python, а затем покажу, как она работает, ускоряя анализ данных в 50 раз. Код из статьи доступен на Github и Google Colaboratory.

RAPIDS

Для работы с большими данными в последние несколько дней было предложено множество решений: MapReduce, Hadoop, Spark. RAPIDS созданы как следующий шаг эволюции обработки данных. Благодаря формату Apache Arrow RAPIDS в оперативной памяти могут быть в 50 раз быстрее, чем Spark . Доступно масштабирование от однопроцессорной до мультипроцессорной архитектуры. RAPIDS имеет интерфейс, схожий с популярными Pandas и Sklearn.

Эволюция обработки больших данных

Все пакеты RAPIDS бесплатны и доступны в Anaconda, Docker, Google Colaboratory и других облачных платформах. Структура базируется на различных библиотеках для ускорения всех задач анализа данных от начала до конца:

  • cuDF для задач предварительной обработки данных, как Pandas.
  • cuML для создания моделей ML, как Sklearn.
  • cuGraph для выполнения задач с графами.

RAPIDS имеет дополнительную интеграцию с PyTorch и Chainer для глубокого обучения, Kepler GL для визуализации и Dask для распределённых вычислений.

Архитектура RAPIDS

Демонстрация

Я покажу, как RAPIDS ускоряет анализ данных более чем в 5 раз в сравнении со Sklearn. Напомню: весь код доступен в Google Colaboratory. Протестируйте его сами!

Чтобы использовать библиотеки, мы сначала должны подключить к нашему Google Colaboratory поддержку GPU. Это будет Tesla T4. Затем устанавливаем зависимости. На моём GC есть инструкция.

Предобработка

Как только всё установлено, импортируем необходимые библиотеки:

import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from xgboost import XGBClassifier
import cudf
import xgboost as xgb
from sklearn.metrics import accuracy_score

Сравниваем Sklearn и RAPIDS. В нашем случае я решил использовать Pandas для предварительной обработки данных и для Sklearn, и для RAPID. На GC доступна предобработка с cuDF вместо Pandas

Я решил сгенерировать простой набор данных, используя распределение Гаусса. Он содержит три признака и две метки, 0/1. Величины и стандартные отклонения подобраны так, чтобы упростить решение проблемы классификации. Данные разделимы линейно:

# Создаём линейно разделяемый набор с гауссовым распределением.
# Первая его половина с меткой 0, вторая с меткой 1.
# Принципы генерации данных схожи, а метки различны.
# Поэтому классифицировать их легко.
dataset_len = 8000000
dlen = int(dataset_len/2)
X_11 = pd.Series(np.random.normal(2,2,dlen))
X_12 = pd.Series(np.random.normal(9,2,dlen))
X_1 = pd.concat([X_11, X_12]).reset_index(drop=True)
X_21 = pd.Series(np.random.normal(1,3,dlen))
X_22 = pd.Series(np.random.normal(7,3,dlen))
X_2 = pd.concat([X_21, X_22]).reset_index(drop=True)
X_31 = pd.Series(np.random.normal(3,1,dlen))
X_32 = pd.Series(np.random.normal(3,4,dlen))
X_3 = pd.concat([X_31, X_32]).reset_index(drop=True)
Y = pd.Series(np.repeat([0,1],dlen))
df = pd.concat([X_1, X_2, X_3, Y], axis=1)
df.columns = ['X1', 'X2', 'X3', 'Y']
df.head()
Простой набор данных

Набор сгенерировался. Делим его признаки и метки по осям и определяем функцию предварительной обработки:

X = df.drop(['Y'], axis = 1).values
y = df['Y']

def preproces(df, X, y, train_size = 0.80):
  # label_encoder object knows how to understand word labels. 
  label_encoder = preprocessing.LabelEncoder() 

  # Преобразуем метки
  y = label_encoder.fit_transform(y) 

  # identify shape and indices
  num_rows, num_columns = df.shape
  delim_index = int(num_rows * train_size)

  # Делим данные на тестовые и тренировочные
  X_train, y_train = X[:delim_index, :], y[:delim_index]
  X_test, y_test = X[delim_index:, :], y[delim_index:]

  # Проверяем размерность.
  print('X_train dimensions: ', X_train.shape, 'y_train: ', y_train.shape)
  print('X_test dimensions:', X_test.shape, 'y_validation: ', y_test.shape)

  # Размерность в процентах.
  total = X_train.shape[0] + X_test.shape[0]
  print('X_train Percentage:', (X_train.shape[0]/total)*100, '%')
  print('X_test Percentage:', (X_test.shape[0]/total)*100, '%')
  
  return X_train, y_train, X_test, y_test

X_train, y_train, X_test, y_test = preproces(df, X, y)

У нас есть тестовые и тренировочные данные. Наконец, мы готовы обучить модель. Используем XGBoost как классификатор.

RAPIDS

Преобразуем наборы в матрицы для XGBoost:

dtrain = xgb.DMatrix(X_train, label=y_train)
dtest = xgb.DMatrix(X_test, label=y_test)

Начинаем обучение:

%%time

# Начальные параметры XGBoost.
params = {}

clf = xgb.train(params, dtrain)

Вывод ниже. С XGBoost из RAPIDS мы тренировали модель менее двух минут:

CPU times: user 1min 54s, sys: 307 ms, total: 1min 54s
Wall time: 1min 54s

Кроме того, RAPIDS предоставляет удобный метод importance для отрисовки важности данных на диаграмме:

xgb.plot_importance(clf)

Это может быть полезно для уменьшения размерности ваших данных. Мы можем уменьшить риск переобучения и ускорить работу, просто выбирая наиболее важные признаки и тренируя на них модель.

Важность признаков

Наконец, выясним точность классификатора:

XGB accuracy using RAPIDS: 98.0 %

Повторим это со Sklearn:

%%time

model = XGBClassifier()
model.fit(X_train, y_train)

11 минут. RAPIDS быстрее Sklearn в 5,8 раз: 662/114. Используя cuDF вместо Pandas, мы можем добиться результатов ещё быстрее.

CPU times: user 11min 2s, sys: 594 ms, total: 11min 3s
Wall time: 11min 2s

Считаем точность:

sk_pred = model.predict(X_test)
sk_pred = np.round(sk_pred)
sk_acc = round(accuracy_score(y_test, sk_pred), 2)
print("XGB accuracy using Sklearn:", sk_acc*100, '%')

Точность та же: 98,0%. Это значит, что RAPIDS работает быстрее и без потери точности.

XGB accuracy using Sklearn: 98.0 %

Заключение

Выше мы видим: используя RAPIDS, можно добиться стабильного уменьшения времени работы с данными (в случае очень больших данных с дней до часов и с часов до минут). Наконец, RAPIDS предоставляет ценную документацию и примеры. Посмотрите здесь и здесь, если хотите узнать больше. Также я создал два других примера: cuGraph и интеграция с Dask, здесь и здесь.

Читайте также:


Перевод статьи Pier Paolo Ippolito: GPU Accelerated Data Analytics & Machine Learning