Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save gumdropsteve/ceab0ffdcfef63317747d33501137108 to your computer and use it in GitHub Desktop.
Save gumdropsteve/ceab0ffdcfef63317747d33501137108 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# [Distributed Linear Regression with cuML](https://medium.com/dropout-analytics/distributed-linear-regression-with-cuml-b4f32d727e22?source=friends_link&sk=458531bdbb4cf88060d06736f2d4c646)\n",
"\n",
"In this Notebook we're going to build a distributed cuML `LinearRegression` model. \n",
"\n",
"Start by identifying your `client`, which is how BlazingSQL and cuML connect to all available GPUs and distribute."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from dask_cuda import LocalCUDACluster\n",
"from dask.distributed import Client\n",
"\n",
"cluster = LocalCUDACluster()\n",
"client = Client(cluster)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ETL - Data Prep"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"With `client` out of the way, let's grab our data. \n",
"\n",
"Initialize a distributed BlazingContext instance, and create a table from a sample of the NYC Taxi dataset stored in a public AWS S3 bucket."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from blazingsql import BlazingContext\n",
"\n",
"# initilize BlazingContext distributed \n",
"bc = BlazingContext(dask_client=client, network_interface='lo')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# register AWS S3 bucket \n",
"bc.s3('blazingsql-colab', bucket_name='blazingsql-colab')\n",
"\n",
"# create table from parquet file in that S3 bucket\n",
"bc.create_table('taxi', 's3://blazingsql-colab/yellow_taxi/1_0_0.parquet')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Our model will take three X variables (`passenger_count`, `trip_distance`, `tolls`) and, based on those values, try to predict the `fare_amount` (y) of any given ride. \n",
"\n",
"Let's query (`.sql()`) for all of these, and keep the dask_cudf.DataFrame of the results as a variable df to see what it's about."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"query = '''\n",
" select\n",
" passenger_count,\n",
" trip_distance,\n",
" Tolls_amount as tolls,\n",
" Fare_amount as fare_amount\n",
" from \n",
" taxi\n",
" '''\n",
"\n",
"df = bc.sql(query)\n",
"\n",
"# queries return as dask_cudf.DataFrame\n",
"type(df)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"cuML expects y values to be float64 dtype, we can easily convert `fare_amount` (currently float32 dtype) to match that with `.astype()`, and then call `.tail()`  -- _which, like .compute() and .head(), converts the dask_cudf.DataFrame to a cudf.DataFrame_ --  to display some data."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# adjust fare_amount to be expected dtype\n",
"df.fare_amount = df.fare_amount.astype('float64')\n",
"\n",
"# calling .compute(), .head() or .tail() converts to cudf.DataFrame\n",
"df.tail()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To conclude the ETL process, noting that we have 18.8M rows to work with, let's split the data into training and testing datasets by taking the first 15,000,000 rows as `train_data` and the last 3,000,000 rows as `test_data`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# crude train / test split\n",
"bc.create_table('train_data', df.head(15000000))\n",
"\n",
"bc.create_table('test_data', df.tail(3000000))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Distributed Linear Regression"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It's time to build our model! Start by importing `LinearRegression` from cuml.dask's `linear_model`, and pass in client upon initialization to link the model with our GPU cluster."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from cuml.dask.linear_model import LinearRegression\n",
"\n",
"lr = LinearRegression(client=client)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`.fit()` the model with training data so it can learn how our X and y values interact."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# training X & y values\n",
"X_train = bc.sql('SELECT passenger_count, trip_distance, tolls FROM train_data')\n",
"y_train = bc.sql('SELECT fare_amount FROM train_data').fare_amount"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"lr.fit(X_train, y_train)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then `.predict()` the `fare_amount` of the taxi rides in our test dataset. Predictions are returned as a dask_cudf.Series."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# testing X & y values\n",
"X_test = bc.sql('SELECT passenger_count, trip_distance, tolls FROM test_data')\n",
"y_test = bc.sql('SELECT fare_amount FROM test_data').fare_amount\n",
"\n",
"preds = lr.predict(X_test)\n",
"\n",
"# predictions return as dask_cudf.Series\n",
"type(preds)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Results\n",
"\n",
"Let's make a quick dataframe to compare the first 10 actual fares with the first 10 predicted fares side by side."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"r_df = bc.sql('SELECT fare_amount AS actual FROM test_data LIMIT 10')\n",
"\n",
"r_df = r_df.compute()\n",
"\n",
"r_df['predicted'] = preds.head(10)\n",
"\n",
"r_df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Those are pretty close! Let's scatter the first 100 actual and predicted values to get a better picture."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"r_df = bc.sql('SELECT fare_amount AS actual FROM test_data LIMIT 100')\n",
"\n",
"r_df = r_df.compute()\n",
"\n",
"r_df['predicted'] = preds.head(100)\n",
"\n",
"r_df.to_pandas().plot(kind='scatter', x='actual', y='predicted')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Looks like we're almost on the money, with some outliers throwing us off past $40.\n",
"\n",
"We can `.compute().to_pandas()` and score the model with sklearn's r2_score() to find out."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.metrics import r2_score\n",
"\n",
"# convert to pandas.DataFrame for sklearn r2 score\n",
"actual = y_test.compute().to_pandas()\n",
"predicted = preds.compute().to_pandas()\n",
"\n",
"r2_score(y_true=actual, y_pred=predicted)"
]
},
{
"attachments": {
"image.png": {
"image/png": "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"
}
},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Try for yourself\n",
"\n",
"You can run this demo (no set up required) by cloning the [Notebook's gist](https://gist.github.com/gumdropsteve/ceab0ffdcfef63317747d33501137108) into a BlazingSQL Notebooks environment with this command in Terminal:\n",
"\n",
"```bash\n",
"git clone https://gist.github.com/gumdropsteve/ceab0ffdcfef63317747d33501137108 distributed_lr_story\n",
"```\n",
"\n",
"[![image.png](https://miro.medium.com/max/1400/0*KYxjArF5xE2957G-)](https://bit.ly/bsql-notebooks)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "RAPIDS Stable",
"language": "python",
"name": "rapids-stable"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment