Last active
May 18, 2020 09:17
-
-
Save gumdropsteve/ceab0ffdcfef63317747d33501137108 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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": "iVBORw0KGgoAAAANSUhEUgAAAyAAAABeCAYAAADbsHBEAAAABHNCSVQICAgIfAhkiAAAIABJREFUeF7tnX+wHcV15/ve9/T0E/SkJXgBg8TC2jjhhwgLm80uIDZsyFbFRiqva02IQbLLKUqhjID8EYOJhLEpqhIjoEBFmcKAKyl716Ekkt1K8HoXCXZTXohjYdgYHAiSHXAZbCPMb4l3785noJ/6ntcz0/Pr3pn7Tle9ku5MT5/T3z59+pzu090d05Z02brVZnJR9LdgddfMrH6X7YnlHdNbM1uFiUnTm5yc/dnn/5MdYxYubEstlU9FQBFQBBQBRUARUAQUAUUgHYGe2Wv6/X1xpn5/v+n195gFvf3m2u170j9sxtvIOm9g2rB22iw7am13cvJcHIxOt7u2NJfdrsEhmf1bsKB0kVqAIqAIKAKKgCKgCCgCioAi0CgE+pEzYswe0+ntNq8e3GVuunNvo/iLmGmOA7LpY2u6UwvWRSxd2O12D61q1IVYp2P6kRPSn5oyvejPRL81KQKKgCKgCCgCioAioAgoAuOFQD9aLTE7TefgfU1ZIRmt1c1Kx8pjNnR75tKhOB0p0tSPwrR60R9OiSZFQBFQBBQBRUARUAQUAUVg/BCInJFe/z7z+oF7R7kyMhoHJNrP0V2ydEvXdDc0rmGjUK3ekiWxM6JJEVAEFAFFQBFQBBQBRUARGE8E+jvNwZlbzdbbdw27fsN1QJrseEjk1RGRiOhvRUARUAQUAUVAEVAEFIFxQ6DT32UOzFw/TEdkOA5IFGrVnT52S2TTb25dm0VMzyxdGu8V0aQIKAKKgCKgCCgCioAioAiMJwLRisirb185jNCs+h2QzZ/Y0O2YbdHfdJsbi70hvWXLTD9ySDQpAoqAIqAIKAKKgCKgCCgCY4lAr3e9ue62rXXWrT4HJAq3mli09J5KjtCtE4E8ZUcnZcX7QxYtyvOV5lUEFAFFQBFQBBQBRUARUATagwBH+XYObqzr1KyJWpC4/KJ13YWL/6rb7ZxUS/kjLLRz8KDpvPPOuyFZenTvCFtCSSsCioAioAgoAoqAIqAI1IJAp/PPjZm4zKw98xXz0KPfrppG5Ssg3c2f2NbKvR55kY2cj5nDD48vNtSkCCgCioAioAgoAoqAIqAIjCcC0d6Ql17ZaG65d39V9avOAYk2mk9MH7NjrEKuAlBmX4ge2RsAlGZRBBQBRUARUAQUAUVAEWgnAoRkvfb2+qo2qFfjgMSnXB3z0KgvExxVi/aiU7J0X8io0Fe6ioAioAgoAoqAIqAIKAK1I9Dv74/2hZxXxb6Q8g7Ipo+t6U5N3TNfnQ/b2NykPhOthmhSBBQBRUARUAQUAUVAEVAExhKBipyQcg4IFwsuPuy7bT9ityoBUSekKiS1HEVAEVAEFAFFQBFQBBSBRiJQgRNS/FILwq4WLd2hzsch0ei8/bbpvvlmI2VFmVIEFAFFQBFQBBQBRUARUARKI9DpTJv+gofMFzetKVpWMQdknu/5SAO7+8Ybphs5IpoUAUVAEVAEFAFFQBFQBBSBsUTAOiF/eNnqIvUr5IB0Vr5/3u/5SAO7+9pr0R6dg2lZ9J0ioAgoAoqAIqAIKAKKgCLQXgRwQpYt3GE2b5jOW4ncDkh38+9snTCddXkJzbf8E6++ajq93nyrttZXEVAEFAFFQBFQBBQBRWC+INDprDG/tPyevNXNdxP65R9fOzE5mZtIXqbGJX98Y/qiReNSHa2HIqAIKAKKgCKgCCgCioAiIBDonJT3xvTwU7DY97Hi2Od003k+qestWWJ6ixfn+0hzKwKKgCKgCCgCioAioAgoAq1C4MDpoXeEBIdgxfs+OiZ3jFercKuBWTal636QGoDVIhUBRUARUAQUAUVAEVAEmoNAf0FwlFTYCkgUejU5FR23NU/SuSd8yCxfvMSsOea4gRrf9vCDZv+bb+RGoT85aWaWL8/9nX6gCCgCioAioAgoAoqAIqAItAaBXu96c91tW7P4nczKwPvugolgjyakvKbl+cjJZ5hzTzjJnHvih8xpRw86HZLXzz+4Qz7K/M1eEO4H0VCsTKg0gyKgCCgCioAioAgoAopAWxHodreYP7zsXnPTnXvTqpDpgHDqVbfTXZ1WSBvfscpxyZn/zuB8TEerHXWn2AFhQ3onbNGpbn60fEVAEVAEFAFFQBFQBBQBRaByBA5fyMLFeWnlplvDY7jx/JIzzzafOeeCzJUOH2i7n33KnL/9Rt+roGf9hQvNzLJlQXk1kyKgCCgCioAioAgoAoqAItBKBA6+c57ZevuuJN5TV0C600dvHpeN5zgef/Sb682qlUckYZH5/OFnv5+ZJy1DJ7ohvROditXvBu/9TytO3ykCioAioAgoAoqAIqAIKALNQ2BqYkvE1K4kxpIt4Wj1w3Qmrkj6sC3PCbX626u/YO7++KdLOR9V1ZdTsTQpAoqAIqAIKAKKgCKgCCgCY4tAv7PWbL18bVL9EldA2r76wb6O66IVD8KtmpQ6Bw4Y0+/rXpAmNYryoggoAoqAIqAIKAKKgCJQLQIL4oWMXb5Ck1dAOp1LfR+04RmrHv9w7c2VOx+7n3mqfPUj56MbhWJpUgQUAUVAEVAEFAFFQBFQBMYXgc666ESs1b76+VdALr9oXVtPvvrShRdX7nhY4Pa+/JIPw9zPZk/Eyv2lfqAIVINA/5ptswXt+uEz5rw/vaOagltUynzAYNt/WGc2n3lu3Cq08/o//4rZ/9abLWolZVURUASKILB21YnmoYt/f/bT8/7sDrNr3zNFitJvHAQkrtc/8qDZ+shfK0ZpCCxbyCrIlTKL1wHpTnUvlBmb/pvN5fdv3FzodKuQuu37+U8Nf5WkXs9wNwgXFI4ibT37t2bJ7n3l5+be7z06CjaUpiLgRWD18pVmw6lned/5HiLD8d/+d//15ZmPz9Z94JRZ54P6rz3uRLPl7AvMlf9j53yEY6DO04sWx3ised8x5txVJ8y+wzl7/CcvxM5aHcYaso0Bw7+rlq8wq6dXxrT3/OR588pbb8X/QruMkzgq/Q6W4EqCf+pSJoGTTVWUV4YX/VYRUARKINAx66KvAxwQjt413Q0lSA39U0Ku/nzjFbXe57G75AlYEhROxBqVA4IRYhODnTogsnX09ygRwChzZTQPLzgi933vMXPLY7tLGXF5aDY1LwahTL5nMs84/8ZARrY2nHLWrLEs64vjtsVcEMvPrY89XHp2E5rQu/TUM2OHx5dwhtyEXkaOi+jmUel3VtvcepSdcXdn75u0SisnSOpyVn1yos8UgXYi0Fkdb0YXR/LO3QOy7Ki1baogx+t+a9Nna3U+wIM7QKpMXTaja1IEFIFKEcA4wAB7btN18UzzfE47f/DEnOo/8PSTc57NlwcY/9/91B/Eq0J2pj6t7tZZ4ZuQ/L6yWMlDFjHOk5wP33cY8vf89kXmud9vrxzDf1HcfJg05ZmdIEHP8Cedx6bwqXwoAo1CYHJiTmTVHAekTeFX7PfgeN1hpL948jvVknkvDKvaQrU0RUARAAEMH2ZQ57MTQgjMxv/2tTgUhpUhVoX4m4/JygMOqptY5YhnsN/784UN4TggS3mMafLu+E+fjJ2ItO9s2yS1CfxCGwembclOBrSNb+VXEVAEakDg3TCsgYLnbkLom7Um/X70GjjLXySOB6sfw0hffewRs//N6u/vGOU+kGHgpjQUgSoQyNrkZ2PqL/zAyYbwGTft+OgnzfHbb5i34ViE8BQJ46mi3ZpUhnQEcDyQK59DhsPAKokbyoQTgkMRcliDdXZ8Kx6sShFa5dvnYfeHEKolZ9XjVZuFi2OHsk0Jvh/4wZO17KdpEw7KqyKgCHRWx6dh3XTnXovF4ArIZetWt+H0q2E6HwD11cf+dy2y0zl4sJZytVBFYD4hwGZhjGxOeCLu3N3Aa43J+YSH1nUQAQx76ZgiJz7ngy+RH061kcY+TkHW4QhJzgeOx/F33BDLKP/3bTK3B4Lg5MCfXI2BNo5U29K289u3etM2jJVfRaAVCBy2YK3L56ADsuiwgZdNrNCwnQ9Ovqp6A7rFVR2QJkqY8tRmBHBGpOHIjLKm+YuAdD5wPKRx70MHp5ZVEjddceY5vqyzzzC25coHp47heOBghCbk+PS7/2TO6hVOiD1WObSsUecDD/dkrlHzo/QVAUVgRAj0u++eCf8e+YEQrMgbOW1EbAWRDXE+nvrOj8x3dj9jfviDF82SZQvNSWcca87+7ZPNksMWBtGQmT7/zR3yUXW/o0sJO9FekH53zlac6miMqCQGfQYe96hJZv044pLB37dBlsHVjdGWZ2tXefpIyFGVWfzw/tzjToiP0iQ8gtlPjAzquXvfs3Ed8xgdSU1FueBJ/U9739GzMeUcO7vvlZcrObrTpW3pEdLE/6FLnfa//WZ81O3uH75bN98sblIdhvnc4m5lyZWpKvlAvmkXV8Ypn7an3X0z3YSLueE1GLlWRqR8F+FVnsiTJcPQSOPJvkcWrGG95shjzJ4X3z1i1cp5iEGfVR9kzR6N65NzWTdbXlZfdo/Z5RtCgkITOggH1soQGMCnT/bBUa6Q4AyXCYGzzrRbLqFhVemWUBzK5rM8VyEnobzQZjY805UBqzeT5MlXvitj9Hc3UfZWc+hoe/ddHhrIFvK/anrFgBNLH0Pe6mjzJIxop337X45DBatss6Q61kXPHTvLyoBPLkKewYNv0kDaN5RFe8RjiiMDWXZTCA8NyrPG5WXAAemYXvSymcbwZ865IHXPxxuvvm3uuv6vYufDTfzecdffmGvu/M/muA8cmasdWP1g/0etaWYmgryZmOett+1ozBLyf1+ys5F0Ko64dI9LlbHPsoPOOZ41apqiZ/WHHFWZxI+ND/fV0Roq1JONo9SPWVSfweLDx32GsoZPOYM7m+e4wRLsjG1Rp4f6QM+nLM3y92hFNDGGtr21rpIjSrMwKPoeuXCNNgyRorIiecAYcY1S+d46GPeYi2Ljk/a3bcI7KXuzDkiJ44dneRB9IkmGXZ6TeAIzQn58Dpyto/0WQ4WZ/iLGCuWDiTTeZ3l8T845Ghes2EPh6gaJpzT4ff1UtlnabylL9EufLMnwKPq+5CWNTtI7nBB0n8Xc9lO50pf0/aieI/du24APqzp1J+SWMShLb7pHLbvjkI8/tx7yPe1i20a+MwFjFHJP+b5+Rnm2bMYT+he4+ibw5tBOeQBG0Ezi230OTcbqMrIcWkdYpo9TxzL06pCBFDgTX9FXOUTCTt7YjLLv0vb3fPiixPaQdpO0jRIZaNqLTmfAARmwfPud7sDLpvD+kZPPMJx4lZZ8zofNj3Ny42X/JV4VyZNqXf14jxE2oo9DooNw3CRKLWTAt4Nom45LjZXJ7757Ik1IHWlXjHmO8ZQKKKvNGWz4LnEQ9RSAkufYTq8D4cnvPoI/e0RpRtb4tW0/8AjFIqTcqvKwWlN1AiPwTTMWJE3aBFwTjWv5QUN+I38MnElGkWQTg4X8eeuJrIJp6HfWWSnSpyTPob8xFjo3Xjn753M+6KcuVtaICqWRlW/jXw5uPgev0LbJKruu9xhJ7mQI/afOUCz0EAcFIIehetMdh0K/qQovq3OTnHwfHb6J61hC79q+neR8SLrQhMciNIvUMTbGI3pF+nhZGQjVQxKjpN/UQ479clXUYhTSHlZeyxwNnsTr0J5/cdOsnzHggHQ7ZnpoTAQSOu3o4zKP2rVhV2lF4oTs+PLfpGUZePf4Cz+sf/UDilEIVtsTnRalmGSIph1xyTdFDJdRYBYf6youDGN2yK5yMGtDXWVCoYYe4wkeaY4A9CyeSSsdDDByNlby5P4mfMxnbEKHOvGXFDdvDc+08kfxTip9n9GYhy+MEx9Gtgy3XWS5tCntUcQxlGVl/U6Siazv3PfsY5C8Uq5dzbEzsHJVz9Yz1JADk7TjZdP0Bu1Le8h29tVTrsoQQlZ1kvuMwEjiU4amxd8tIxTnMnTLfitnenHeQ9osL107jiRhAn5WnnxlW8O1TgfJpcsMfZL8uroEnn192urdpDHXV0eeJekhZDVrXIEmE4ah7ZfVR209Zf+0vGd9L+tYhQxk6SRJM+03ZUl5lM6H5Vm2o2tX+EJ5LTZp9Bv77mB31s84FIK16WONW/2YXrzE3H3R72VeMijDrpKAD83H91fv/LOkYip93iEEq8UJ58Nn7GKssGzrUy50yivOOmfAmMfoqWPWukpoXcWLUiDkZM7gEC25o0xsmJalbwe4rGM8fTMm0Egy+nBuLJ7ujCjtwv6QkKVaOaBYh8NnQEEDo9FVrHzPwB1Cq8r2SCoLrF1HcU4bJX2Y8Jz60S5ykGDAvvXRh73hEHxDGIg7o2ZDKBLIxGE9zLSHJspzHQX6WpmwBUvXlQfKvPJbO70hR+SnfvRdFxuw2rX9mVQDHHmRs43I271PPBqHWEm9QfnInBtSZgfvLLzYd+YmjGDo+OQ7q6yk925/oNyyITI+OvRLFzOwSDrJy/f9KJ4h0/DoyinyUWUolpUDqceQIcagJAMO/Lih3pVdZMPn7Ln90joPFk/aJY/ug0+OB3fpIjM2zMmnr3z6hGc4MfLkv6R2lgck5O1vlAvPTDbSfmn9x/ImdSb6iT1Yvv5BH2KvmSvjtm19p8K59UySgbSxEx59MoCssv+lTN9CxqV+k84H/EvdicwmHVhhbQqLKfw3adxNkrs5zye6a6Nnu3h+aAWkO9GI1Y9zT/iQ+aML1pu/vfoL5qUv3GlYAclKeUKrWC3JSlw6WNfJV1m02/Q+NkbFEYt0IJQTnU0aEbZuKB8McTqaVWJ0qqaHFFj+qVuSkiAPdWJAkrN/GMUMXkkJBSNnTBjcOL4Txe1T+ChYFKXvxJw4xjeFnuSD8ikH3n20yA896i4N3bR9P5JO3b+lTGLQlknS+QAbBkRk2DeQQgvZp/3B0+0H0kgqyhflyFUKKW9Fy7bf0cbwn7Z6RB5pANGXJW8uL/CObLrJ6o2kfSSxsQStCHPy2CQNHF+dpQFqjZWq9I3sYzimSf3Hx1/oM/qea5xWJUuh9IvmQ4dJvqtcafCtqiAjVif62gJ5s3nkOOWbBCpad993MloA+txVJEPW3G+tPpF9zdeXfDR55spL0f5GOTZEKokO/UvW0epMdFSSzuQ572UdKc83yenST5KBtLHTygDY02fdxORO0f7lcz6QNTlmQk9OXFB3nwNKXsZ53rupSePuAGOBP0a++3nVyiPizeX3b7widji+temz5rrfXB/keNg6ctpVaDriaLub1v8FFw5+6ut3+V/W8LTNKyB0etcAoONkzVS4EMaOiLi3oQaIKy2SwdSnSHxEyEd+N116iv9IWHCURhlKK3RmDQXvm2GRZfr4tM/SnEb5HXldpQ3/zCaOMjEwMvC5M0/gUmYmi7LcgcgOpGlGuYsBg1yePhGKnxyQkTNpSIWW5ctnDR7fO/mMvOvv/8rA47TjamXYlcUoaeCV9GjPPM4WbSb7IW1KqCO8lHVEZFgmpxbVlaTcSeenLrplyrW6yS0D+SiLO+VRf+nsIhuhfT5pzJIyWqb+7rc4Xm69rez7nCQfTdpfGqHUPw+WVfQ3DOck2ZP85NWZto4uJvTXJKe1rAzE/EUTGz4nxNcGac98K7vYAUny6NpPcqLER4e2c3UZ38tJS993TX12yAGZXLB6mEyysvHMtTfHfxyvy0ZzQq6KJI7aDUlHHLXcHHHU4alZcT7quPU8kWhL94DEBmdknLnJXdFIrK94kcfQCS2zrnxFjFmpeJKUhQwFQBnKb0PqRbiMq7gxjkIGJ+glzUwl0ZVG3YUfPDkpa6nn8TGXhHgl/GEssEGSzcwSX4yR0MHdx6R04IoY+j4DzEcr9Bk4yNnMUEc1lAZylCdhNEiH1DeDyDPXYAebInrD59yn8UtfkhMH6DCMJeTG7rsK6StpdHhnjyjOylfkPWGVbmL/VhuSDcWyvMaz2tGpP2WTdHR97ZxFwxrIUm/65DerrKz3cq9QEf0kjVBoEtIcknx1DfnOZ0QnTabJNmFyAp7zJJ9dILGz5Uk+isgAZUk9lBWxIOuDPSTHC3BLmiyRDpzs27J8+1vqMY4sb1Wa6MzeBTLrgHTNzOphVQJH4/6Nmw2rH1Wk0Hs+zv7wr6SS48hdwq80ZSMgDT06RV4lY6lg+MrZh2wOhp+jSNw4Cl8aZj4jRypXadyH1hZ6xBK7SbaVr6wiYUoYFe6gXcfmXnhlIECxJ/1hRMpZaGY2CcHI61S52GCAuG1FmUWcQsqkb8iBw9cOWc/gSQ5ySQNcVllJ76mnnGlPyus+f+Dpwfs1ZJuQV8o5shq68iF5SAtZkXn5DU5J/QpccWRxRvjLszIi7xnx0a7qmdSTdRjJVfEqywF7t62RD7l6Ib9J+y1nf9FFSe2bVg7vfHpTympWGVnv0cOuPikzZko9FKLj4U9OUGXx7L4HW1ffywlI8vLMndVHXovoEsqSdgHYyXrKidCyMiAnXqRzk4QX9Zar0mnOB+VIXOT9Mkm06EMD426ku9qaRhKC9a1N11TmfAA8lwxu/uN1qZcN4qSs//SvJ7YTp15d/cBwNp4nMtGiF2wWc1Oey7181SxiAPvKqfNZ0dAK+R1n+rsJJSpntKVyylMvaaSEzJAUpefO9roDTx5+68grlXQRGnKwY8N5mVTUOHJpytCQIisyWXUo6rTJmX+fPEinpKxTlldv4LQQF44B5w7iLiYYOnZlhJU1OVOZhV/RvpRVbtvfg7d0lnGmfRMyIXWdI0slDxaQRr0sP4SntDzSWbzvieJ708DS7achGPJNmf4maVJX2Te4mNdNZXWm7N/S2ZdtFBLGlNZGUvfJ+vm+xRbK63zYclyHHCfG59T5aOIoofv5kxj58jf12dAdEMKtQjaW5wWMMCwuG/yQCMci7Gr97/26+fQW/02l0In3fXzty8MNvcpbwYbllwpPdty87Jb9Pi+9IvmLrvBk0ZIDk3Qgsr6X7zGArHLiX24uz0pFZ6G5VbjuFM/IM5Pm+UuizcBU5Bx5tzzpuJVtF+pRFGf4kis9lCWNpiQ88jznBJgiKUQWpKNdBg94LKI3oMn+qhU3XzN7oEKSM4IccdKQ3FSbho/UjWl559s7dJNrBJcJxZJ6U0705MUWGXB1vCw/b3kyvzSeyzqq8nS3LGO5rP6iPnKiUToAcnKtSP90cZPfyzaRvyV/sg2yfiMDLk4hfVnykLXy4fIgnQccGf7k5JfkGxpMpvBXxqmU5Q779+wxvD0zsbdubyTrNvOyleem889GTgiJ067YcJ6154O8rHywAqIpHAG301Wh2Oj4GAYhHT6cy2pzljWWkriRoUtyYEn6Lu15nj0BZdovNG41jdesdyjprPogjyht91QQjBt7TGUR51HO4BcpQ9aNMorION/4Qq+SDGdJN89vuZIR+m1W/5B4VnHsdtk2wcDhb6P5Wiw/zGbyr+Q1Dp+5eKX30IzY8XIOa8QIy8IiFFOZT8pOHe0vaVb9m9lbF2MbipXXmZYTBGVlgXpShju28f8qyqVsd78O8pHlMGThHhqyY8upYlzJ6rOuQ1IFbsg3f7Y/SvmXGFTR7+DbrQftFOos5nE+aBfGNXSOK3N2JcQ6QzjWjNFV4JklU8N+f+gekHcO7jVTC2qjH3KbeZXEQzem3/DNHcO5cDCpcp1O0pt597zpDkhdDSKNnSqUaF28NrVclDN/GDHuBV9gS9hS1v0rw6oXRkDW7JaPFzbsunJCPUMHRV95o3gmZwrLzlhXXQfXGbEbSl2DB/5xAt1jgOFBOuF1bgyXBlhRZ7Fq7PKUh2FFKBarSjaBK/jn0X116M05bRnpj6qSK/+0I3pqmCkPtkl8SZ0jnUD3uyxnJYmGfI6MW4dAyr9ccanCSH/lrbckC0G/oS33kIR8yKlmvlUP5Juxwo4X9Bv6SNI9KiG0GpFnpr/b8lH3okdMJ+Q281EAw6bzzz+4YxSkZ2n2Jw/5gCNlRIkrAmOAAEpaHnvL4FV2tnGU0PhCr6rYTzLKOjWdNjOZvrt15BGj1EMadjLUpsq6yrJDwt6qpF9VWdbZs+VhbFVxKlZV/LWxHOkcyDpIOZXvi/yWTmCRMsblGxyQIiuSfMMJXIxb6J2kMsCaiREcdw7KaPOYZtu8dus39DbzYQshIVfDvO9j2PVTeu1FoM4Z1PaiEs45ChwD3Z1hZZk7a4AOp1A8pwwZyCqJQWdYoVdZvJR9LwfWvFiUpZ/3eztTzyyrG5KBEeCGBEq5knHxeekm5UcW3LLhrw6jMol+1c9ZBVm76cTZlT3qxmyvjPsPpQs+UsZCvx1GPneFHz6rXL0KqTf4SlnNW2+5AjGMVcw84+EoZcBuIJcHLYRiTNvwRzgozgXtxYSDT5/YFTRojcUeEHP713eZqz4RilVwvlUrjqhl03kwA56MOB/nb7/R82YEj7pDWYSqvGIoPDv7IfcwFCXm62hFy2rTd8R3bjGHboZmqb7oINymetfJq8RPhv8UoV3F4CZDBrL4YGnenWWkXmWNiCyadb2X4RF5sfDxJQ0iX56yz3Bm11584mwx8SrEI4dKxbB0jUtkrcq9A5aSDN2TMl62nsP+3jp47kQB8r5re9hN8jJWH8zL9g25wiRltgxGroxQzrDDQpcvWlSG/fjbrD7r1rGq8dzV3XK/Ig6QS6cOGcizyogTwqEvZZ0C64xYPUPf9+1P23b+uljmWzURMdPbZQVxwPrt9c3+0hIqCsDYX3D1Jeaj99xqbnv4QbPv5z+tmkSu8qzzMdTLBlM47E9MpLxt7it5/GpZQ6AKAzEUraYtXcrZq7S42pA60hb9a7bN/nGUqKb8CMjZvbIDqpzBzuLIjf8lrzXYsr5r8nt3oCyLJ/UM6cvxioVziaXr0IVgFWLUytNs5GVsIXSy8siVsLIn/mTRG8Z7byhW5ISEJHlaWxUTYW4Z9Depm0P4SsrjGrLIYNkxE2fN1fNZfaGS/hbNyrtJGr7SYStZnPfNAAAVVElEQVQ7rss6yfaQ9Kuoo5QjSUO2r+SJdgk9TleWlfSbfsJqx/HbbxjYjI4chV5CmVT20J8v6M36GQMOSKff21MXM1zwx2lTJ37xKvOvvvS5+P+7n32qLnLecpvmfMBkWx0QaZzJ2TlvA6Q8DBmw5UxE0RAOqWBS2BrKKxk7CpZ5jSSXUam0ZVsNpVJjQEQOpvLum7xVzNNHaH95tjwDkBzs8vIw6vwS0zyY+HgPuSwOQ8+9xLKsUeTjQ854YoDIfuj7LvSZ3HuCUdT2FRBbdynX0vFOwkjOhofIQlJZPJd6V5af9m3IO3kcelnZl3Kc5SiTX34TwrebR+pASVOONWXrKOnJ8iV9mT9v/eizcsU5qwwuU5X9P8QJYVIkjwMJH+h/9oq440AVTldWHSt9f+32WT9jwAHpm25tDohbARwBVkMIg/qlz102lAsAm+h8xJi0dBO6HPzwwosazRgIIYpKzkQUHeAv/ODgJYqVdq6ChUk8y9wQLAdiafQVZLFVn5UdaKmsNEAwKsvMWsoZ7DRAWVqXA6GUkbTvm/pOztqXmb2j/4cMvtJpC73dOA+G6CZ5jKwMn8tTnpsXWZayM06HENA+8vQg6Xz7sEOvuWMCOBUdEyhfyqKUVR8PeZ5JY1nSy1OWdCZCdby8yDQPTbB19arEn7KkjnKPRc9Di7zo2g2nnDXwmSyf9pcyEGJLJPEi+1moDPj2YmQ5IbLNQidG6S9uBEoVY10SHpU/7/cHfIzBECxjHq+cYEaBhEI9/ny9d3Cw+oKz05Swq1lIoiN4+y3dA0LncTuQnWXMaG7va3nEqDfTew9dBRQrqMgozJNCjZY8ZVaRV96KiyIsolhQvq5RhrKSSrsKfptehlxRkzNnIfyD3ZyZreg43CKJgT/UeUFGXbmGj6IbG4vwWuc38pQXZLWIs41zhpMWkqT853UkpUEjHRrLA06B+4725qjVohMzlIsOkGXgGEu5DMGhyXmoj+vwh2ImHbGiTp88aa4OvYmh7LYb8sEseJEkHQkZAphUJv0t75hJWb4VWWb+ZaKOsh1DnElZDr+lXQB2chKSfE2RgbxOiHRAmjgx6muXks+SHRBz4K2hrIDICux+9vvyUaW/b3v4m81zPqIa9hfUd+9KpQAmFCY7Pko8rzGBcgqZxbQsyBkJDPXQwcqnRBOqNvTHzI5JQ8m9zyKEIQxXqex9g0RIWW3OwwArB9miBpuUcWRVYpyFVZ5+4ZNRadhm0Wv6eymTGFOyvdLqAEZ5+oY0iig7z83mobOiGK3r7//KAOs4EN/91B8UmpkHE+l8xM7oX34tDZ7WvqNeSc5dUqWkUVrE6QNnadCn9TkZCpxnz57UJ8hWHtkHBzlmxhMlTzyaBNGc51kz8/ID29/cCRTpTLnfyHtycODz6kxZR8qX2FmaUgYsv6F2AeX4ZAA9lVcecULkynkS3lIvhTqH1MtdLZGOjGy/Rv3u9QYWOQaPYNr+jT11bEQPAaDOm8gff2FfCAtDz9N2BwSDWRrNKHIG96zZXoxlBua8ylcqGzvgZK0WWEMgi6+hC4FDEMXtKjyrSLOcOvIxkyaNFRRT1g3io6xv1bRpY2RPDnZSZvLQZZCQAx8yG2JUxrIZHQAgjZs0+hgkrowymMnQnrTv2/AOmZSDJm3GX1b/tNhn9XeJgzSK7MpCGj3rDLq0smbGmUiQq1VWR1G/EL4x2JAb8rtGFLSJ//bNAsv6tvG3r6+F1EPiDcbPbbouc2yhXXz6IqvPwaerp+NV52g8C0m+OtLO6Igsg9nqEzlmEr4WYii7ecr2N4m5W3f6tk9nItNZOCXZBZSXJvfco+GmPDJgsZB1KDp2wotPv8l2g57ECV58+VzeZHiudHhC5HBked44uNOlPfcekE4vytDdMGwG2RNy98c/XTlZTt1qXOjVe7VswiWEKLU8y8CyU6KIVl+8cmBgRSHzRydkxQLFwR9e+6rpFfE7OfBjJMrz9pOEAWPCPbrROheUAT1uYIU2z6Fjj69LKq8pz8EIA8N1JBiUGJwwTHH2uKkXhcPZ6NSP2TcZIkJ9GGykUm5KPfPywZ4WeTymLAPZ8g3gYCrjy+W3Wb+ReQ48cAcGa8AiZ7QHJ/IQl4u8WZmTxqbNm+RQMvjKd8y25umf1EX20az6jeI9sokT57YZ+PKHnHNjfKjeyBqwqR/Yo6sY4G2KjZToQi/0BhuEXQPH6gypp9Jmxm25drXNpcU7Wz/o4KjQl+mnFgP6MrOgPjm2zoc0bLLarqx+zyq/6vc424Si5FkVt06fi7d1HjHWXL1p+2fS/QrgG6I3KdOVO3Q238rbvwmNsvJgsfLpE7tKSrmEi7ox/mCBPEp9QnmULctPahNk140YkP3N8g89juz1jdOUzfgr97NImr46Ui7HWUudmWYX2Dpm6TRf/y4jA4zDRZPtq3KVFlmET7cPgyPt58oScsyY98DTT8ZywBhAXZBd9g3JvnHro3ND4YryXu93/b3mpjv3ujTmOCC9Xnd3tC1hQ72MDK/0vS+P9tjfxJpGIDfFAZEhBok8Ry+kIkjqbJSBwvQpTVk+HRDjIPS4WJS0NCYo0ypUWb787ftW5hnVb5STdELgBQVklZR7Z4iPT6uM02aMfN819Zk1GvLyZ3EImR3MKtvO+EljN1TGbbtKB8OlKwcW3kl6WXzyXvbRkG+Gncc62wy2UkfYCYwsnjBWMYZCMcpyDLLo8X3oahR5aXPfajDyHMozPOHgEp5UpD9Dq4x+z8KkjvfUVTqnWXRs28rZ4bx6U54wlEQXYx45dZ1FKcd8m7T3LEmfhMo+ZVv5T+JRPseY9Y0teWjCd6jDQ14cMqnzQnVm3joOWwYkvu5vn12ErOCU0AauEwJOvHMnEmNnLfrLSnxbRC9klVvL+74ZWP2AxmAIFk/2/2hOplqYcQo97ejjzJcuvLgWMg/XvL+kKNO9qaminzbuOzrb6Xf/SbycmMfYIy8GhFXGeSqGsmGmKg89a/SEKtA8/FSZF+XEed9F+GRQkgquSt7aUBYygSxWjQNyiszlVfi2TfLIahtwLsujdcpCjXpLD/xpBxlWFcIPfQpd5RoAWd8V1VNxP77jhtx6UfKDEZtX5mQZbfpNXWVoSgj/tm3zhqTY9kUuQvuoHUvKtEtRfWJpF5H/omMLmKJP845J8Mh3eXEqWkcrAzI0PEt+7JiRRwZCypR1t06IdFbRZ3nsJ/jN4wxm8TqU9/2Z3ZLOnBUQc++u/TNX/e7OCdMJO2JElpjz9/TiJeb+jZsN/9aR9o744sOkOvUXLkx6VfvzvAo6lCFmXjEmODovbRkd+iwvsnHOVfh5jAJ4Qslway4zLCxZynAJyzflyrO6XQyS6CY9D8XD5kOZuvRCBjmrYFBKdtlVKi1bvsUTPEIVfUj9Q+op6xbyTVYe6l5ERmkvjDW+DcG4CAZgbMMvCItglsqdBXVljvAL2SYSL5dP+S4Lp5D3ITIs6YZgl0TbxTREFqGFkUIYATOASXrDygQhlnmNIMkrmGBoEPLGkbz869Md5IMeOq0MJuhF/lj1OPe4ExLpwSc0mTV2Zz9ZwSAEMDTWv0jfkRgV+R0ia6Hlgjkhafbm7dCyY8P1T+8YCFfx6U1XnuijRdoXnnAwbbv6bgnP6gNWn8Syjz5JkMW4j0bhOshjqHFt62gxt3XkX4zXrLHF0uSExqyQq7R25VtwqqOOPrrwjUHvhixVKQMS17Q2Ji+8yH2A9Ol4hSh6b1OI/QQt2h99mUbXh8ton0XhV9fdPmdxo+Nl6vKL1k1OTe7wvqv44f0brzAfOfmMOaWyb4PVi9OOXmVWrTwifs+zV6I/+3vOR54HXHpY5wZ3D8nsR1H41TsrVmTnG5McduNZGSUWAkUcqjO9ciBrPKA7nTyknCbnwdi1yrRuPJuMQ9N4o01om3GTt1HhnEfOuczLJoxvDNAiybYhMdfDGNwtPXiVNH2bUZGt0BChIvUf52+sPDEWhDozo8Rj2LJIXe34OSyMLD0p+3Xh3jYZAIc28uxtv37/FvO5W6+U7/wOSJSre+XFz3U73dXyg6p/X3Lm2XM2n+NocG+Hz3HAWcFpCU0Lrr4kNOvQ8vWWLjW9aJOXJkVAEVAE5hsC7kk4ZY0dBuiXr7pxFsIyDkjT2oGZdbmRHbyqDi1sWr2VH0VAERgzBF5963i5AZ0azt0DYuvd799XFIL3/+xw88HnjzBT70xkFvHVxx4xn/r6XbP50pwPMnGpICdbhSSfAxPyXd15eiMMv6q7blq+IqAIKAJpCBB+wGZM/vJuNpblyo2aSZt+5Xdt+O3b54bDBW7uhtU21EV5VAQUgXmKQKe/y+d8gEaiA9Lb/8ItRe4EOf4nK8zZ/2+1+dVnjzb//nv/IpcTgvOBM5LlODwQOSFZiTJYRWlaivd+RDega1IEFAFFYD4iwP4vN7FnrGgibt5NbQivyVNX4r1l2BVOCKdrydOF8pSreRUBRUARGAoCB2auT6KTagl3N//O1m53YkvSx/I5zsevPX3swOO/O+EF8/Qxh1YsVry22Jz996vMgckZ879O/cf437yJPSDPXHtz4mfW+Wji/R8z0d6PfrQHRJMioAgoAvMRAWK/uX/DJsKKOPUt714tQrlYDXDLWXHzNWMJqV35kJtpWSUpcorgWIKklVIEFIFmIcDqxzW3npfEVKolnGcV5MhXls1xPiD68rK3ZmnjfLAqsvStKcP/P/zoSUErJJJ5QrCSVkma7Hyw+qHOh2xN/a0IKALzCQE2eLsnWVnjmn9DE4b4jo9+ciA7J92Na7J7P+QJSOwTKRvGNq6Yab0UAUVgxAikrH7AWeoKCBlCVkGsYyH3fHz7gz8yz73v5RgBnI7f+rt/Ocfh+Otf/YfISTl0FFkoXJ8554I5d4c02fkg7GpmelodkNAG1nyKgCIwtgiwCiINZxwTZvOzTndj/wObs12HhW+rPMO/ycC7m/gtn3r6WpNbTHlTBOYhAhmrHyCS6YCYDWunuyuO+W7SiVghzgeOCSsf5HUTzglOSpHEvSEvfeHO2U8b7XxEXPaWLDG9xeEzfEUw0W8UAUVAEWgLAjgS7GWQCWOaO1S4uZnE7H98HOWRx8T3/cgwJD0ZSiKovxUBRUARGDECCSdfuVxlOyDkTrgXZFTOh62AvUNEnqQ1Ytjnkp9n937MBUCfKAKKgCIwFwFCiLadv857mePc3HOfqPMxFxN9oggoAorASBHo9a431922NYuH7HNyKeHRJ5/q/5tT13RN5yRbIKsavxGtaiw+sGCABqsaT676SfysjpUPl9jTL/7YPP3Sj821//2/DvDQtB8zhx1mzEQY1E3jXflRBBQBRaAuBFjtePAfnzInHXGk9zbyNLrc+fEfv/5l89TPXkzLpu8UAUVAEVAEhoZAdOv5T3+x0Xx7z6EN4Am0w1ZA+DgOxTo2upzQTIc6Fr/xvRPMkfuXDpBmvwf7PmxiFYWTsF5fdCCBxXY/5sJBLh7UpAgoAoqAIpCMAHsbLj3lzPiOi7QN6WzEZsN51l6RZEr6RhFQBBQBRaAeBA6cbq7dviek7HAHhNKiUKwl3YU7QvZzcBwvx/K6CefDPXrXPbbX3bAewngb8vQnJ83M8uVtYFV5VAQUAUWgMQiwz8PnhKjT0ZgmUkYUAUVAERhEIDD0yn6UzwGJvlr3b2/cdtjbCza7VF+cft38z1OfnX2U1/mwH/7FWU+Nz0oIp14dfrjBCdGkCCgCioAioAgoAoqAIqAIjCUCAadeyXqn3gMiM/N75/+55srohvRd9h2rGo/88t7ZrD7ng/Aqd+WDsCt5YaGPVpufzSxbps5HmxtQeVcEFAFFQBFQBBQBRUARSEeg399jXnxlfXqmuW9zOyAU8fzPnl/fiwj6Qqpk2BX7Ox755X2zN57bk7MkK4Rgjcs+kB7Ox9SUrKL+VgQUAUVAEVAEFAFFQBFQBMYDgX5/v+kc3GhuuXd/3grlDsGyBNau3jz9fz/y8nMHJ3vTPHP3c9g8OB+sfNiLBkOO7c1bgabl57ZzVj80KQKKgCKgCCgCioAioAgoAmOJwLvOx3mhm84lBoVWQChk195b9r/5zhvnReFY+0OcD25CZ/O6vC2dI3vtbemSubb9VuejbS2m/CoCioAioAgoAoqAIqAI5EKgpPMBrcIOSMzo9m/sOeqfFp33a98/ds7SyyO/sm925QOn4+y/XzXH+cDxeOK9O0NyVbyBmdX5aGCjKEuKgCKgCCgCioAioAgoAtUhUIHzATPlHJCogOe/cdeeV994/XT2hNjasZ/jxeWvxT9D7wypDpnhl8RdHxp2NXzclaIioAgoAoqAIqAIKAKKwJAQqMj5gNvCe0BkVdkTcsw/O/qhR0/6pzU2pGpeOB/Rfo9etO9DkyKgCCgCioAioAgoAoqAIjCWCLDQwIbzwIsGszCozAGxhLpXXXxP13Q38DvkJvQsBhv7nns+DjvM9BcsaCyLypgioAgoAoqAIqAIKAKKgCJQCgHu+eCo3QKnXSXRrdwBiQlt/sSGf/3s+7d94Mcr4xOybJLH9rrv2vR/nI74qN1u6Qi2NlVbeVUEFAFFQBFQBBQBRUARmE8I5LzhPBSaehyQiPq6k7auXrp06T3djlkLM+PifPSWLDG9xYtD8dV8ioAioAgoAoqAIqAIKAKKQMsQ6O815uD6qkKuZOVrc0AsoYvX/PHm15e+veWbZzwzzb0gbU3xqkfkfPQnJ9taBeVbEVAEFAFFQBFQBBQBRUARSEeAVY+f/eKWKkOuJMHaHZCY4GXrVneXLN1i94ZIJhr9O9rr0Vu6VDeaN7qRlDlFQBFQBBQBRUARUAQUgVIIsNfjF29vNDfdubdUOQEfD8cBsYxs+tiaiampbZ1ud20Ab6PNguMRhVpxxK6J/q9JEVAEFAFFQBFQBBQBRUARGDsEcDwOzFxvtt6+a1h1G41lHTki3UVTVzRyRSTaWI7ToY7HsERQ6SgCioAioAgoAoqAIqAIDB2BETgeto6jcUAsdUKzFi3ZEK0wXNrtdFcPHXiHYH9qKg6z4l9NioAioAgoAoqAIqAIKAKKwNghwGWCxtxrXnv71mGEWiXhN1oHxOWKVZGpRZeaTm/dsJwRnI3Y8cDp0DCrJBnR54qAIqAIKAKKgCKgCCgCrUUgOtGqb3aZ/swD5rrbdzahGs1xQFw0opURs+iwtd1u71zTM2u63e6a0mBFDgYnWHGalf23dJlagCKgCCgCioAioAgoAoqAItAoBN5zOHq9x83EzK66jtItU+X/D2w/ylzlTn46AAAAAElFTkSuQmCC" | |
} | |
}, | |
"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", | |
"[](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