Press "Enter" to skip to content

代码详解:用RAPIDS库加速数据分析和机器学习

 

(来源:https://res.infoq.com/news/2018/10/Nvidia-keynote-gtc/en/resources/1BFA0900F-5083-497B-8275-B80D87C9CFF8-1539179054604.jpeg)

 

GPU加速如今变得越来越重要。这种转变的两个主要驱动因素是:

 

1. 世界每年的数据量都在翻倍。

 

2. 由于量子领域的限制,摩尔定律即将结束。

 

为了证实这一转变,越来越多的在线数据科学平台正在添加支持GPU的解决方案。例如:Kaggle、谷歌Colaboratory、Microsoft Azure和亚马逊网络服务(AWS)。

 

本文首先介绍NVIDIA开源Python RAPIDS库,接着实际说明RAPIDS如何将数据分析速度提高到原来的50倍。

 

本文使用的所有代码都可以在GitHub (https://github.com/pierpaolo28/Artificial-Intelligence-Projects/tree/master/NVIDIA-RAPIDS AI?source=post_page—————————)和谷歌Colaboratory (https://colab.research.google.com/drive/1oEoAxBbZONUqm4gt9w2PIzmLTa7IjjV9?source=post_page—————————)中找到并使用。

 

RAPIDS

 

为了处理大量的数据,在过去几年中提出了许多解决方案,比如MapReduce, Hadoop and Spark。

 

RAPIDS现在被设计为数据处理的下一个发展阶段。 由于其Apache Arrow的内存格式,与Spark内存处理相比,RAPIDS可以提高50倍左右的速度(图1),此外,还可以从一个扩展到多个GPU。

 

所有RAPIDS库都是基于Python的,并且都设计了类似于Pandas和Sklearn的接口,以便采用。

 

 

图1:数据处理发展

 

所有RAPIDS包现在都可以在  Anaconda, Docker and cloud-based solutions (如谷歌Colaboratory)上免费使用。

 

RAPIDS结构是基于不同的库来实现数据科学从一端到另一端的加速(图2),其主要组成部分为:

 

• cuDF =用于执行数据处理任务(如Pandas)。

 

• cuML =用于创建机器学习模型(如Sklearn)。

 

• cuGraph =用于执行绘图任务(图论Graph Theory)。

 

RAPIDS还结合了:用于深度学习的PyTorch & Chainer,用于可视化的Kepler GL,以及用于分布计算的Dask。

 

 

图2:RAPIDS架构

 

 

演示

 

现在,将演示如何使用RAPIDS比使用Pandas和Sklearn更快地进行数据分析。使用到的所有代码都可以在谷歌 Google Colaboratory上找到,所以可以随时亲自测试!

 

为了使用RAPIDS,首先让谷歌Colaboratory notebook与Tesla T4 GPU在GPU模式下使用,然后安装所需的依赖项(指南可在Google Colabortory notebook上找到)。

 

预处理

 

一旦一切都设置好了,就可以导入所有必要的库。

 

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对RAPIDS和Sklearn进行预处理分析。在 Google Colaboratory notebook上也有另一个例子,用cuDF进行预处理。使用cuDF而不是Pandas,可以进行更快的预处理,特别是在处理大量数据的情况下。

 

对于这个例子,会使用由三个特征和两个标签(0/1)组成的高斯分布构建一个简单的数据集。

 

# Creating a linearly separable dataset using Gaussian Distributions.

 

# The first half of the number in Y is 0 and the other half 1.

 

# Therefore I made the first half of the 3 features quite different from

 

# the second half of the features (setting the value of the means quite

 

# similar) so that make quite simple the classification between the

 

# classes (the data is linearly separable).

 

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()

 

为了使这个分类问题(线性可分数据)变得很容易,选择了分布的均值和标准差。

 

 

图3:示例数据集

 

创建数据集,将其分为特征和标签,然后定义一个函数对其进行预处理。

 

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()

 

# Encode labels

 

y = label_encoder.fit_transform(y)

 

# identify shape and indices

 

num_rows, num_columns = df.shape

 

delim_index = int(num_rows * train_size)

 

# Splitting the dataset in training and test sets

 

X_train, y_train = X[:delim_index, :], y[:delim_index]

 

X_test, y_test = X[delim_index:, :], y[delim_index:]

 

# Checking sets dimensions

 

print(‘X_train dimensions: ‘, X_train.shape, ‘y_train: ‘, y_train.shape)

 

print(‘X_test dimensions:’, X_test.shape, ‘y_validation: ‘, y_test.shape)

 

# Checking dimensions in percentages

 

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 (Extreme Gradient boost)作为分类器。

 

RAPIDS

 

为了在RAPIDS中使用XGBoost,首先需要将训练/测试输入转换为矩阵形式。

 

dtrain = xgb.DMatrix(X_train, label=y_train)

 

dtest = xgb.DMatrix(X_test, label=y_test)

 

接下来,可以开始训练模型。

 

%%time

 

# Initial xgb parameters

 

params = {}

 

clf = xgb.train(params, dtrain)

 

上面单元格的输出如下所示。使用RAPIDS提供的XGBoost库只花了不到两分钟的时间来训练模型。

 

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

 

此外,RAPIDS XGBoost库还提供了一个非常方便的函数来对数据集中每个特征的重要性进行排序和绘图(图4)。

 

# Feature Importance plot!

 

xgb.plot_importance(clf)

 

这对于降低数据的维数很有用。通过选择最重要的特征并在其上训练模型,实际上可以减少数据过拟合的风险,并且还可以加快训练时间。

 

 

图4:XGBoost的特征重要性

 

最后,计算分类器的精度。

 

rapids_pred = clf.predict(dtest)

 

rapids_pred = np.round(rapids_pred)

 

rapids_acc = round(accuracy_score(y_test, rapids_pred), 2)

 

print(“XGB accuracy using RAPIDS:”, rapids_acc*100, ‘%’)

 

使用RAPIDS模型的总体精度为98%。

 

XGB accuracy using RAPIDS: 98.0 %

 

Sklearn

 

现在使用plain Sklearn重复同样的分析。

 

%%time

 

model = XGBClassifier()

 

model.fit(X_train, y_train)

 

在这种情况下,训练模型只花了11分多一点的时间。这意味着使用Sklearn解决这个问题的速度比使用RAPIDS (662s/114s)慢5.8倍。通过在预处理阶段使用cuDF而不是Pandas,可以进一步减少这个例子的整体工作流的执行时间。

 

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

 

最后,使用Sklearn对模型的整体精度进行计算。

 

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%。这意味着使用RAPIDS可以在不影响模型精度的情况下获得更快的结果。

 

XGB accuracy using Sklearn: 98.0 %

 

结论

 

从这个例子中可以得出,使用RAPIDS会导致执行时间的持续减少。

 

当处理大量数据时,这一点非常重要,因为RAPIDS将执行时间从天减少到小时,从小时减少到分钟。

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注