From 3064fffe13df2ee5d92202498e97f9dc6171d056 Mon Sep 17 00:00:00 2001 From: Nick Becker Date: Mon, 12 Sep 2022 17:30:48 -0400 Subject: [PATCH] updated kmeans notebook (cleanliness and performance) --- notebooks/kmeans_demo.ipynb | 138 +++++++++++++++++++++++------------- 1 file changed, 90 insertions(+), 48 deletions(-) diff --git a/notebooks/kmeans_demo.ipynb b/notebooks/kmeans_demo.ipynb index 6309596e99..d6b901adfe 100755 --- a/notebooks/kmeans_demo.ipynb +++ b/notebooks/kmeans_demo.ipynb @@ -26,7 +26,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -50,14 +50,14 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "n_samples = 100000\n", - "n_features = 2\n", + "n_features = 25\n", "\n", - "n_clusters = 5\n", + "n_clusters = 8\n", "random_state = 0" ] }, @@ -70,30 +70,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ - "device_data, device_labels = make_blobs(n_samples=n_samples,\n", - " n_features=n_features,\n", - " centers=n_clusters,\n", - " random_state=random_state,\n", - " cluster_std=0.1)\n", - "\n", - "device_data = cudf.DataFrame(device_data)\n", - "device_labels = cudf.Series(device_labels)" + "device_data, device_labels = make_blobs(\n", + " n_samples=n_samples,\n", + " n_features=n_features,\n", + " centers=n_clusters,\n", + " random_state=random_state,\n", + " cluster_std=0.1\n", + ")" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ - "# Copy dataset from GPU memory to host memory.\n", + "# Copy CuPy arrays from GPU memory to host memory (NumPy arrays).\n", "# This is done to later compare CPU and GPU results.\n", - "host_data = device_data.to_pandas()\n", - "host_labels = device_labels.to_pandas()" + "host_data = device_data.get()\n", + "host_labels = device_labels.get()" ] }, { @@ -107,17 +106,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1.44 s ± 74.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], "source": [ - "%%time\n", - "kmeans_sk = skKMeans(init=\"k-means++\",\n", - " n_clusters=n_clusters,\n", - " n_jobs=-1,\n", - " random_state=random_state)\n", - "\n", - "kmeans_sk.fit(host_data)" + "kmeans_sk = skKMeans(\n", + " init=\"k-means++\",\n", + " n_clusters=n_clusters,\n", + " random_state=random_state\n", + ")\n", + "%timeit kmeans_sk.fit(host_data)" ] }, { @@ -131,17 +137,25 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10.1 ms ± 98.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" + ] + } + ], "source": [ - "%%time\n", - "kmeans_cuml = cuKMeans(init=\"k-means||\",\n", - " n_clusters=n_clusters,\n", - " oversampling_factor=40,\n", - " random_state=random_state)\n", + "kmeans_cuml = cuKMeans(\n", + " init=\"k-means||\",\n", + " n_clusters=n_clusters,\n", + " random_state=random_state\n", + ")\n", "\n", - "kmeans_cuml.fit(device_data)" + "%timeit kmeans_cuml.fit(device_data)" ] }, { @@ -152,17 +166,28 @@ "\n", "Scikit-learn's k-means implementation uses the `k-means++` initialization strategy while cuML's k-means uses `k-means||`. As a result, the exact centroids found may not be exact as the std deviation of the points around the centroids in `make_blobs` is increased.\n", "\n", - "*Note*: Visualizing the centroids will only work when `n_features = 2` " + "*Note*: This is visualizing the centroids in only two dimensions. " ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABQoAAANCCAYAAAAuhvFjAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAACHE0lEQVR4nOzdZ5hdZdk24GtNT5tJIYGEJITeQu9IEaQXQQQRUEBs+GLBgogVeFUsfNheewFEARUUEWkiUlSQ3qW3QCCBkMykTqas7wcQiUlIJpk9OwnneRxz6Ky91nPfsyeTkCtPKcqyLAMAAAAAvKHVVLsBAAAAAKD6BIUAAAAAgKAQAAAAABAUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAAABEUAgBL6c1vfnOKoshaa62VsiwXeP2GG25IURQpiiLnnHPOvOvnnHNOiqLIbbfd1ofd9sx1112Xoihy3XXXLfNYb37zmzN+/PjF3jdu3Lgce+yxy1yvGlaE7+ny7Mknn1zg56Q3TZw4Maeeemruuuuuioz/6vf/ySefrMj4AEDfERQCAEtt0KBBeeKJJ3Lttdcu8NovfvGLNDc3V6Er4LUmTpyY0047rWJB4f7775+bbropI0eOrMj4AEDfERQCAEtt7Nix2X777fOLX/xivuvTp0/P7373uxx++OFV6owlNWvWrGq3wApq9uzZKcsyw4cPz/bbb5/GxsZqtwQALCNBIQC8gTz44IM54ogjsuqqq6axsTFjx47N0Ucfnfb29iTJqaeemqIoFnju9ZYWHnfccfn973+fadOmzbt24YUXJkne+c539mr/3//+97PLLrtkxIgRGTBgQDbZZJN84xvfSEdHx3z3vbrc99Zbb83OO++c/v37Z6211srXvva1dHd3z3fvgw8+mH322Sf9+/fPKquskuOPPz7Tp09fon5eeOGFfOADH8iYMWPS2NiY4cOH501velOuueaa133uD3/4Q/r375/3ve996ezsXOR9bW1t+dSnPpU111wzDQ0NWX311XPiiSdm5syZy/S+3HDDDdlxxx3Tv3//HHfccfOWvp555pk566yzsuaaa2bgwIHZYYcdcvPNNy/Re/HfnnvuuWy11VZZd91188gjjyRJjj322AwcODAPPvhg9t577wwYMCAjR47M1772tSTJzTffnJ122ikDBgzIeuutl3PPPXeBcZ9//vl88IMfzOjRo9PQ0JA111wzp5122gLv42mnnZbtttsuQ4cOTXNzc7bccsv8/Oc/X2CZ/Lhx43LAAQfkyiuvzJZbbpl+/fplgw02WCD8njVr1rzvRVNTU4YOHZqtt946F1xwwWLfi2effXber5OGhoaMGjUqhx56aCZNmrTIZ4499tiMGzdugesL+xn93e9+l+222y4tLS3zfq0fd9xxSV5eRr/NNtskSd7znvfM2w7g1FNPnff8bbfdlre+9a0ZOnRompqassUWW+S3v/3tfDVe/T3g6quvznHHHZfhw4enf//+aW9vX+jvDz35Gbz//vuz1157pX///hk+fHhOOOGE/PnPf+615f8AwJKrq3YDAEDfuPvuu7PTTjtllVVWyemnn5511103zz33XC699NLMnTt3qWcDvfOd78zHP/7xXHDBBfnQhz6UJPn5z3+eQw89tNeXHj/22GM58sgj5wVnd999d77yla/kwQcfXCDYef7553PUUUflk5/8ZL70pS/lD3/4Q0455ZSMGjUqRx99dJJk0qRJ2XXXXVNfX58f/OAHWXXVVfPrX/86H/7wh5eon3e/+92544478pWvfCXrrbdepk2bljvuuCNTpkxZ5DPf+ta3ctJJJ+XUU0/N5z//+UXeN2vWrOy666555pln8tnPfjabbrpp7r///nzxi1/Mvffem2uuuWZeYNST9+W5557Lu971rnz605/OV7/61dTU/Offjb///e9ngw02yLe//e0kyRe+8IXst99+eeKJJ9LS0rJE70mS3Hfffdlvv/0yevTo3HTTTVlllVXmvdbR0ZFDDjkkxx9/fE466aScf/75OeWUU9LW1paLL744J598ckaPHp3vfe97OfbYYzN+/PhstdVWSV7+nm677bapqanJF7/4xay99tq56aab8uUvfzlPPvlkzj777Hl1nnzyyXzwgx/M2LFjk7wcQn7kIx/Js88+my9+8Yvz9Xv33Xfnk5/8ZD7zmc9k1VVXzc9+9rO8973vzTrrrJNddtklSfKJT3wi5513Xr785S9niy22yMyZM3Pfffe97vc6eTkk3GabbdLR0THv+zhlypRcddVVmTp1alZdddUlfl8X5qabbsrhhx+eww8/PKeeemqampry1FNPzdsOYMstt8zZZ5+d97znPfn85z+f/fffP0kyevToJMnf/va37LPPPtluu+3yox/9KC0tLbnwwgtz+OGHZ9asWQvsm3ncccdl//33z3nnnZeZM2emvr5+kb0tyc/gc889l1133TUDBgzID3/4w4wYMSIXXHDBEv8MAgC9rAQA3hB23333cvDgweXkyZMXec+XvvSlcmH/eXD22WeXSconnnhi3rVdd9213HjjjcuyLMtjjjmm3HrrrcuyLMv777+/TFJed9115a233lomKc8+++wFxrr11luX6evp6uoqOzo6yl/+8pdlbW1t+dJLL83XW5LyX//613zPbLTRRuXee+897/OTTz65LIqivOuuu+a7b8899yyTlH/7299et4eBAweWJ5544uve8+r71NXVVX74wx8uGxoayl/96lcL3LfGGmuUxxxzzLzPzzjjjLKmpmaB9+miiy4qk5SXX375Qustyfvy17/+db5nnnjiiTJJuckmm5SdnZ3zrt9yyy1lkvKCCy543a/xtd/Tv/zlL2Vzc3N56KGHlrNnz57vvmOOOaZMUl588cXzrnV0dJTDhw8vk5R33HHHvOtTpkwpa2try0984hPzrn3wgx8sBw4cWD711FPzjXvmmWeWScr777//dd+T008/vRw2bFjZ3d0977U11lijbGpqmm/M2bNnl0OHDi0/+MEPzrs2fvz48uCDD37d92FhjjvuuLK+vr584IEHFnnPq+//a39OjjnmmHKNNdZY4N7//hl99WufNm3aIsdf2M/hqzbYYINyiy22KDs6Oua7fsABB5QjR44su7q6yrL8z/f46KOPXmCMRf3+sCQ/gyeddFJZFMUC37u99957iX4GAYDeZekxALwBzJo1K9dff33e8Y53ZPjw4b0+/nHHHZfbbrst9957b37+859n7bXXnjcTqzfdeeedeetb35phw4altrY29fX1Ofroo9PV1ZWHH354vntXW221bLvttvNd23TTTfPUU0/N+/xvf/tbNt5442y22Wbz3XfkkUcuUT/bbrttzjnnnHz5y1/OzTffvMBS31fNmTMnBx98cH7961/n6quvzlFHHbXYsS+77LKMHz8+m2++eTo7O+d97L333gssyezJ+zJkyJDsvvvuC625//77p7a2dt7nm266aZLM9569nnPPPTf77bdf3ve+9+W3v/1tmpqaFrinKIrst99+8z6vq6vLOuusk5EjR2aLLbaYd33o0KEZMWLEfLUvu+yy7Lbbbhk1atR878m+++6bJLn++uvn3Xvttddmjz32SEtLy7z35Itf/GKmTJmSyZMnz9fT5ptvPm/mYZI0NTVlvfXWm6/2tttumyuuuCKf+cxnct1112X27NlL9J5cccUV2W233bLhhhsu0f099eqy4ne84x357W9/m2effXaJn3300Ufz4IMPzvv1+Nr3dL/99stzzz2Xhx56aL5n3v72ty/x+EvyM3j99ddn/Pjx2Wijjea774gjjljiOgBA7xEUAsAbwNSpU9PV1TVvuWFv22WXXbLuuuvmxz/+cc4777wcd9xxC93rcFk8/fTT2XnnnfPss8/mO9/5Tm688cbceuut+f73v58kCwQ3w4YNW2CMxsbG+e6bMmVKVltttQXuW9i1hfnNb36TY445Jj/72c+yww47ZOjQoTn66KPz/PPPz3ff5MmTc9VVV2WHHXbIjjvuuERjT5o0Kffcc0/q6+vn+xg0aFDKssyLL76YpOfvy+udTPvf79mry9GXNBS78MIL069fv7zvfe9b5Pe/f//+CwSIDQ0NGTp06AL3NjQ0ZM6cOfM+nzRpUv70pz8t8J5svPHGSTLvPbnllluy1157JUl++tOf5h//+EduvfXWfO5zn1vo17Mkv1a++93v5uSTT84ll1yS3XbbLUOHDs3BBx88b//FRXnhhRcq9nOXvPyzd8kll6SzszNHH310Ro8enfHjxy/R3omv7pH4qU99aoH39H/+53+S/Oc9fVVPTjZe0p/BhS2/XtYl2QDA0rFHIQC8AQwdOjS1tbV55plnXve+VwOc9vb2+fYs/O+wYGFe3QOtKIocc8wxy9bwQlxyySWZOXNmfv/732eNNdaYd/2uu+5a6jGHDRu2QKiXZKHXFmaVVVbJt7/97Xz729/O008/nUsvvTSf+cxnMnny5Fx55ZXz7hs7dmzOOuusvO1tb8shhxyS3/3udwudbfffY/fr12+BPQZf+3rS8/eltwPc1/r1r3+dL3zhC9l1111z9dVXZ/PNN+/V8VdZZZVsuumm+cpXvrLQ10eNGpXk5cCyvr4+l1122Xzv8yWXXLLUtQcMGJDTTjstp512WiZNmjRvduGBBx6YBx98cJHPDR8+fLE/dwvT1NQ075Ch11rYz+JBBx2Ugw46KO3t7bn55ptzxhln5Mgjj8y4ceOyww47LLLGq7+GTjnllBxyyCELvWf99def7/Pe/vUzbNiwhR7qsqQ/gwBA7zKjEADeAPr165ddd901v/vd71439Hv1lNV77rlnvut/+tOfFlvjmGOOyYEHHpiTTjopq6+++jL1uzCvBhSvDTDLssxPf/rTpR5zt912y/3335+77757vuvnn39+j8caO3ZsPvzhD2fPPffMHXfcscDre+21V6666qrccMMNOeCAAxY4ufi/HXDAAXnssccybNiwbL311gt8vPq9qsT7srSGDh2aa665JhtuuGF22223pT4xeVEOOOCA3HfffVl77bUX+p68GhQWRZG6urr5llHPnj075513Xq/0seqqq+bYY4/NEUcckYceeiizZs1a5L377rtv/va3vy2whHdxxo0bl8mTJ88Xos2dOzdXXXXVIp9pbGzMrrvumq9//etJXl6S/ur1ZMGZlOuvv37WXXfd3H333Qt9P7feeusMGjSoR3331K677pr77rsvDzzwwHzXXz05HQDoW2YUAsAbxFlnnZWddtop2223XT7zmc9knXXWyaRJk3LppZfmxz/+cQYNGpT99tsvQ4cOzXvf+96cfvrpqauryznnnJMJEyYsdvxRo0b1aMbWtddemyeffHKB6/vtt1/69++/wPU999wzDQ0NOeKII/LpT386c+bMyQ9/+MNMnTp1iWv+txNPPDG/+MUvsv/+++fLX/7yvFOPX2+G2KtaW1uz22675cgjj8wGG2yQQYMG5dZbb82VV165yNlZO+20U/76179mn332yV577ZXLL798kacJn3jiibn44ouzyy675OMf/3g23XTTdHd35+mnn87VV1+dT37yk9luu+0q8r4si0GDBs17D/bcc89ceuml2W233Xpl7NNPPz1/+ctfsuOOO+ajH/1o1l9//cyZMydPPvlkLr/88vzoRz/K6NGjs//+++ess87KkUcemQ984AOZMmVKzjzzzKU+2TtJtttuuxxwwAHZdNNNM2TIkPz73//Oeeedlx122GGhv15f2/MVV1yRXXbZJZ/97GezySabZNq0abnyyivziU98IhtssMFCnzv88MPzxS9+Me985ztz0kknZc6cOfnud7+brq6u+e774he/mGeeeSZvectbMnr06EybNi3f+c53Ul9fn1133TVJsvbaa6dfv3759a9/nQ033DADBw7MqFGjMmrUqPz4xz/Ovvvum7333jvHHntsVl999bz00kv597//nTvuuCO/+93vlvo9WxKv/gzuu+++Of3007Pqqqvm/PPPn/cz+NpTuQGAyvMnLwC8QWy22Wa55ZZbstVWW+WUU07JPvvsk5NPPjmNjY1paGhIkjQ3N+fKK6/MoEGD8q53vSvHH398xo8fP29vt9508skn57DDDlvg478PmnjVBhtskIsvvjhTp07NIYccko985CPZfPPN893vfnepe1httdVy/fXXZ6ONNsqHPvShvOtd70pTU1P+7//+b7HPNjU1Zbvttst5552Xo446Kvvuu29+9rOf5eSTT37d2Xxbb711rr/++jz++OPZfffdFznDc8CAAbnxxhtz7LHH5ic/+Un233//vOMd78h3v/vdjB49et6Mwkq8L8uqX79++eMf/5i99947++23Xy6//PJeGXfkyJG57bbbstdee+Wb3/xm9tlnn7z73e/OL37xi2y++eYZMmRIkmT33XfPL37xi9x777058MAD87nPfS6HHnpoPvOZzyx17d133z2XXnpp3vOe92SvvfbKN77xjRx99NGLnW27+uqr55ZbbskBBxyQr33ta9lnn33ykY98JK2trQvdl/FVa665Zv74xz9m2rRpOfTQQ3PSSSflsMMOy9FHHz3ffdttt12ef/75nHzyydlrr73ygQ98IP369cu11147b+/G/v375xe/+EWmTJmSvfbaK9tss01+8pOfJHl5Vu0tt9ySwYMH58QTT8wee+yRD33oQ7nmmmuyxx57LPX7taRGjRqV66+/Puutt16OP/74HHXUUWloaMjpp5+eJBk8eHDFewAA/qMoy7KsdhMAAACv+sAHPpALLrggU6ZMmfcPGQBA5Vl6DAAAVM3pp5+eUaNGZa211sqMGTNy2WWX5Wc/+1k+//nPCwkBoI8JCgEAgKqpr6/PN7/5zTzzzDPp7OzMuuuum7POOisf+9jHqt0aALzhWHoMAAAAADjMBAAAAAAQFAIAAAAAERQCAAAAAFnODzPp7u7OxIkTM2jQoBRFUe12AAAAAGCFUpZlpk+fnlGjRqWm5vXnDC7XQeHEiRMzZsyYarcBAAAAACu0CRMmZPTo0a97z3IdFA4aNCjJy19Ic3NzlbsBAAAAgBVLW1tbxowZMy9nez3LdVD46nLj5uZmQSEAAAAALKUl2dbPYSYAAAAAgKAQAAAAABAUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAAAEnqqt0AAAAALMrM1pl54KaH09HemZFrr5o1x4+tdksAKy1BIQAAAFXTPrs9zz0+OUkycq0RaezXmLIsc8sVd+aHHz87Ex+dlLIs592/1qZr5IjPHpJdDt0+NTX/WSQ35bmpmfr8tAxo6Z/V1hyRoij6/GsBWNEV5Wt/x13OtLW1paWlJa2trWlubq52OwAAAPSSqZNb85uv/SGX/+yvmT1jTpKk38Cm7HTItrn7uvsz+ekpSzZQkdQ31KWjvXPepTU2Gp1DP3Fg9n7PbgJD4A2vJ/maoBAAAIA+NfGx5/M/W5+cma2zKlpnl8N2yOcv/LiwEHhDExQCAACwXHr0ridywjafSXdXd5/Ua15lYN79xXdkyKqDM3bD1e1xCLzhCAoBAABY7jz3+KS8b5NPZO7suVXrobF/Q9bcZI287SP7Zqe3b5+Gxvqq9QLQFwSFAAAAVE1Zlrn1yrtyyf9dkXuuuz9dnV0Zte7IdLZ3ZOJjk6rd3jyrjB6Wr135uayx0ZhqtwJQMYJCAAAAqqKrqyvf+sCPc9XZf0tNbU2fLTFeWoOGDsxP7z0rw0YOqXYrABXRk3yt5nVfBQAAgB74yUnn5aqz/5Yky31ImCTTX5qRT+95eqZOmlbtVgCqTlAIAABAr7j6l9fl99/+c7Xb6LGnH3gm/7PNyXlx4kvVbgWgqgSFAAAALLP7//lQvnns96vdxlJ78ZmX8v/e+4NqtwFQVYJCAAAAltnZn7+g2i0ss9uuujsTH3u+2m0AVI2gEAAAgGXy9IPP5O7r7q92G73i/z7y87z0/NRqtwFQFYJCAAAAltrj9z6V47f8dLXb6DW3XnlXjhj9wVx7/o3VbgWgzwkKAQAAWCozps3MiTt9IR1zOqrdSq/q7i5zxru+m9uuuqvarQD0qbpqNwAAAMCK6eKzLsvs6bMrWmNUOSP75/GsndY0pjszU5c7MzxXZ1ymFw0Vrf21o7+Xiyb9vKI1AJYnZhQCAADQI50dnfn2h36SX335oorVGF7OypfLf+TcXJk982yey3q5P1tkRsbkuNyf83N5PlzelYayq2I9tL7Qlj/96OqKjQ+wvDGjEAAAgCVWlmW+9u7v5Ybf3VSxGquX03NmbsycDMhH8rlcmt3Tlbkp0pUytWlJZ47Kn/LxnJNxmZnPl9tlTlGZv97+4GO/yO5H7pQBzf0rMj7A8sSMQgAAABZr7py5+dMPr85hq70v1//2nynLsiJ1msrOfDk3Z2qGZZ/8PH/KlqnNi2lIW+ozMw1py+zMyk+ydw7N97JOpubE3FeRXpKks6Mrf/nl9RUbH2B5IigEAADgdc1sm5VPvPmL+e4JP03rC20VrbV7nsnITM+7883MzOzUpHOh99WkMw9kcD6TT+YteTSjy1kV60lQCLxRCAoBAAB4Xd889vt56NbHKl+oLHNAnspV2SnPpz7FYm4vklyZTTI5Q7Nvnq9YWw/f9lj+3/t+kK7Oyu2HCLA8EBQCAACwSM8++lz+ccktSWVWGs9n9czIunkhv84Bi5xJ+N+6UuQ32Se759FUaDV0kuSqs/+WH3/ql5UrALAcEBQCAACwSNee//cUxeLm9vWOlrw8Y+/ZtPTouWcyLEMzPWXqK9FWkqQsk0v+74q8OPGlitUAqDZBIQAAAIs0bXJr+ignTMcrQV9dOnr0XH060pnadKUyJx+/qiiKXH3OdRWtAVBNgkIAAAAWadCQgX2x6jhJMilN6U6RLfNwj57bIg/n6ayWmlR2D8GiSJ57rHJ7IQJUm6AQAACARdr50O1TdvdNVNia2lyXzfLuXJEl3RRxaNpyQG7MRXlTajK3sg2mSH1j5ZY3A1SboBAAAIBFWnuzcdl0l42y2COIe0FRJH/Metkkj2TP3L5Ez/xPLkmZIn/NahVfIt3V2ZUt9ti0skUAqkhQCAAAwOv67AUnZuS4EX1S677U5Ipsl2/le9k5d73OnWU+lD/kuPw538hR6crkivc2eERLdnzr1hWvA1AtgkIAAABe17CRQ/J/t34th3/6oDT2b6xorZqiM9/IFvlnNskv8vX8X76VHXJfXl2K3JC5OSg35qJ8MSflwvy/HJWr0i+1Rc8OQFkah33ywNTW1Va8DkC1FGVZ9tW+tD3W1taWlpaWtLa2prm5udrtAAAAvOF1dnRm0lMvZOrzrRk0bGDet/HHK1KnvRyRXdORo/KXbJAnMzuNmZXGDMqsNKQz12frnJO98nBa07+YVJEe/tuXLzsl2+23ZZ/UAugtPcnXKnt2PAAAACuVuvq6rL7OyKy+zsiUZZma2pp0d3X3ep3GYnL+UdbnqhyedVKTdTM1/dKetgzIbRmdaZmWgXki/ftgJmGSpEjGbTymb2oBVImgEAAAgKVSFEXW33ad/Pvmh5f0kOIeqS060pLHMrlMnk9DulOXmryUmjyflj44XOVVNbU12WqvzbLqGsP7rihAFdijEAAAgKV28If3rUhI+FpFkdQWc1NfzEptMbfipxv/t7qGurz3q0f2bVGAKhAUAgAAsNR2PWyHbL3P5tVuo2IGDR2Yb17zxay92bhqtwJQcYJCAAAAllptXW1O+/1J2fd9b0mxEv0NsyiKrDpueH4z8SfZaIf1q90OQJ9YiX4bBwAAoBoamhryiZ8cn988+9Nqt9IramprMmzUkJx57ampb6ivdjsAfcZhJgAAAPSKIasOTn1jfTra++gk4groN6gpB3xgzxz2qbdmyKqDq90OQJ+q6IzCzs7OfP7zn8+aa66Zfv36Za211srpp5+e7u7uSpYFAACgSrZ4y/ikjw8b6S37v3+PXDT5F/nAN48WEgJvSBWdUfj1r389P/rRj3Luuedm4403zm233Zb3vOc9aWlpycc+9rFKlgYAAKAKDjph39xy+Z3VbmOJ1NS8kmgWRQ7/9EE59n/fmZoaO3QBb1wVDQpvuummHHTQQdl///2TJOPGjcsFF1yQ2267rZJlAQAAqJJt9tk8+77vLbniZ3+tdisLtcnOG2bHg7fNo3c8nq6u7ozbeEz2OW73DBs5pNqtAVRdRYPCnXbaKT/60Y/y8MMPZ7311svdd9+dv//97/n2t79dybIAAABUSVEUOfFHH8jINVfN+V+5OHNmtVe1n+ZVBmXIqi3Z7Z075R2ffmvq6x1OArAoFQ0KTz755LS2tmaDDTZIbW1turq68pWvfCVHHHHEQu9vb29Pe/t//hBpa2urZHsAAABUQE1NTY445W055MT9cuoh38xtV93d5z3UN9XnZ/d9K6PWWrXPawOsqCq6+cJvfvOb/OpXv8r555+fO+64I+eee27OPPPMnHvuuQu9/4wzzkhLS8u8jzFjxlSyPQAAACqosV9jvnr553Lk596eouiDE05eKbH6OqvlnAe/IyQE6KGiLMuyUoOPGTMmn/nMZ3LCCSfMu/blL385v/rVr/Lggw8ucP/CZhSOGTMmra2taW5urlSbAAAAVNgzj0zMr06/KDdcdHM62juSJON32iAHHL9XGvs1ZNKTL+SXp/02s6bPTpbwb6l1DbXZYrfxaRnenLntnWkeOjBvPvxN2XTXjfommARYAbS1taWlpWWJ8rWKLj2eNWvWAidG1dbWpru7e6H3NzY2prGxsZItAQAAUAWj1x2Vz5z30XzqF/+T6VNnpql/Q/oN7DffPeN32iAnveW0tM+em+6uhfy9sUjGbTwmG+2wfnY/YieBIEAvq2hQeOCBB+YrX/lKxo4dm4033jh33nlnzjrrrBx33HGVLAsAAMByqq6+LkNGtCz0tfW3WSf/d8vX8svTfpsbL7453Z0vh4WN/RvyliN3zjH/e3iGrup0YoBKqejS4+nTp+cLX/hC/vCHP2Ty5MkZNWpUjjjiiHzxi19MQ0PDYp/vydRIAAAAVh7TXmjNMw8/l5ramqw5fswCsw8BWDI9ydcqGhQuK0EhAAAAACy9nuRrFT31GAAAAABYMQgKAQAAAABBIQAAAAAgKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAANIHQeGzzz6bd73rXRk2bFj69++fzTffPLfffnulywIAAAAAPVBXycGnTp2aN73pTdltt91yxRVXZMSIEXnssccyePDgSpYFAAAAAHqookHh17/+9YwZMyZnn332vGvjxo2rZEkAAAAAYClUdOnxpZdemq233jqHHXZYRowYkS222CI//elPK1kSAAAAAFgKFQ0KH3/88fzwhz/Muuuum6uuuirHH398PvrRj+aXv/zlQu9vb29PW1vbfB8AAAAAQOUVZVmWlRq8oaEhW2+9df75z3/Ou/bRj340t956a2666aYF7j/11FNz2mmnLXC9tbU1zc3NlWoTAAAAAFZKbW1taWlpWaJ8raIzCkeOHJmNNtpovmsbbrhhnn766YXef8opp6S1tXXex4QJEyrZHgAAAADwiooeZvKmN70pDz300HzXHn744ayxxhoLvb+xsTGNjY2VbAkAAAAAWIiKzij8+Mc/nptvvjlf/epX8+ijj+b888/PT37yk5xwwgmVLAsAAAAA9FBFg8Jtttkmf/jDH3LBBRdk/Pjx+d///d98+9vfzlFHHVXJsgAAAABAD1X0MJNl1ZPNFgEAAACA+S03h5kAAAAAACsGQSEAAAAAICgEAAAAAASFAAAAAEAEhQAAAABABIUAAAAAQASFAAAAAEAEhQAAAABABIUAAAAAQASFAAAAAEAEhQAAAABABIUAAAAAQASFAAAAAEAEhQAAAABABIUAAAAAQASFAAAAAEAEhQAAAABABIUAAAAAQASFAAAAAEAEhQAAAABABIUAAAAAQASFAAAAAEAEhQAAAABABIUAAAAAQASFAAAAAEAEhQAAAABABIUAAAAAQASFAAAAAEAEhQAAAABABIUAAAAAQASFAAAAAEAEhQAAAABABIUAAAAAQASFAAAAAEAEhQAAAABABIUAAAAAQASFAAAAAEAEhQAAAABABIUAAAAAQASFAAAAAEAEhQAAAABABIUAAAAAQASFAAAAAEAEhQAAAABABIUAAAAAQASFAAAAAEAEhQAAAABABIUAAAAAQASFAAAAAEAEhQAAAABABIUA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AABgBeEwEwAAAABAUAgAAAAACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgPRRUPiDH/wga665ZpqamrLVVlvlxhtv7IuyAAAAAMASqnhQ+Jvf/CYnnnhiPve5z+XOO+/MzjvvnH333TdPP/10pUsDAAAAAEuoKMuyrGSB7bbbLltuuWV++MMfzru24YYb5uCDD84ZZ5zxus+2tbWlpaUlra2taW5urmSbAAAAALDS6Um+VtEZhXPnzs3tt9+evfbaa77re+21V/75z39WsjQAAAAA0AN1lRz8xRdfTFdXV1ZdddX5rq+66qp5/vnnF7i/vb097e3t8z5va2urZHsAAAAAwCv65DCToijm+7wsywWuJckZZ5yRlpaWeR9jxozpi/YAAAAA4A2vokHhKqusktra2gVmD06ePHmBWYZJcsopp6S1tXXex4QJEyrZHgAAAADwiooGhQ0NDdlqq63yl7/8Zb7rf/nLX7LjjjsucH9jY2Oam5vn+wAAAAAAKq+iexQmySc+8Ym8+93vztZbb50ddtghP/nJT/L000/n+OOPr3RpAAAAAGAJVTwoPPzwwzNlypScfvrpee655zJ+/PhcfvnlWWONNSpdGgAAAABYQkVZlmW1m1iUtra2tLS0pLW11TJkAAAAAOihnuRrfXLqMQAAAACwfBMUAgAAAACCQgAAAABAUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAAJKmrdgMA8N+6u8vc8uSEPNc2PS1NTdlm3OgMamqsdlsAAAArNUEhAMuNOR2dOfWya3LZvQ+ls7t73vXaosh+49fPlw54S+Z0dGTarDkZ3L8pNUWRi++8P3+464G8NHNWmpsac8CmG+TwrTbNqs0Dq/iVAAAArHiKsizLajexKG1tbWlpaUlra2uam5ur3Q4AFTRl5qy87Ue/yuTpM5f4mSLJov4QGzdscN6/07bZf/z6aar372IA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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "fig = plt.figure(figsize=(16, 10))\n", - "plt.scatter(host_data.iloc[:, 0], host_data.iloc[:, 1], c=host_labels, s=50, cmap='viridis')\n", + "plt.scatter(host_data[:, 0], host_data[:, 1], c=host_labels, s=50, cmap='viridis')\n", "\n", "#plot the sklearn kmeans centers with blue filled circles\n", "centers_sk = kmeans_sk.cluster_centers_\n", @@ -170,11 +195,11 @@ "\n", "#plot the cuml kmeans centers with red circle outlines\n", "centers_cuml = kmeans_cuml.cluster_centers_\n", - "plt.scatter(cupy.asnumpy(centers_cuml[0].values), \n", - " cupy.asnumpy(centers_cuml[1].values), \n", + "plt.scatter(cupy.asnumpy(centers_cuml[:, 0]), \n", + " cupy.asnumpy(centers_cuml[:, 1]), \n", " facecolors = 'none', edgecolors='red', s=100)\n", "\n", - "plt.title('cuml and sklearn kmeans clustering')\n", + "plt.title('cuML and sklearn kmeans clustering')\n", "\n", "plt.show()" ] @@ -188,20 +213,37 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 24.7 ms, sys: 4.36 ms, total: 29 ms\n", + "Wall time: 27.6 ms\n" + ] + } + ], "source": [ "%%time\n", - "cuml_score = adjusted_rand_score(host_labels, kmeans_cuml.labels_.to_numpy())\n", + "cuml_score = adjusted_rand_score(host_labels, kmeans_cuml.labels_.get())\n", "sk_score = adjusted_rand_score(host_labels, kmeans_sk.labels_)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "compare kmeans: cuml vs sklearn labels_ are equal\n" + ] + } + ], "source": [ "threshold = 1e-4\n", "\n", @@ -212,7 +254,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -226,7 +268,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.9.13" } }, "nbformat": 4,