{"cells":[{"metadata":{},"cell_type":"markdown","source":"We use [RAPIDS](https://rapids.ai/) for clustering faces in the train dataset. Rapids is a package developed and maintained by NVidia and uses the GPU for fast calculations\n\nThe faces were cropped using the facenet's pytorch version. They are 160x160 in dimension. Sample 2000(aprox) images can be found in the following [dataset](https://www.kaggle.com/skylord/sample-face-crop) \n\nInspiration is taken :) from the following awesome notebooks: \n\n- @Bojan's MNIST 2-D t-sne with rapids: [Link](https://www.kaggle.com/tunguz/mnist-2d-t-sne-with-rapids)\n- @Henrique's Proper clustering with facenet embeddings + PCA: [Link](https://www.kaggle.com/hmendonca/proper-clustering-with-facenet-embeddings-eda/)\n\n\n\nSo who is the fastest! \n![FastestSuperHero](https://www.kaggle.com/skylord/sample-face-crop#best-flash-super-hero-dc-laser-time.jpg)\n"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"%%time\n# We add the rapids kaggle dataset [Link](https://www.kaggle.com/cdeotte/rapids)\n# This installs the package offline. Installation takes place under a minute! \nimport sys\n!cp ../input/rapids/rapids.0.11.0 /opt/conda/envs/rapids.tar.gz\n!cd /opt/conda/envs/ && tar -xzvf rapids.tar.gz\nsys.path = [\"/opt/conda/envs/rapids/lib\"] + [\"/opt/conda/envs/rapids/lib/python3.6\"] + [\"/opt/conda/envs/rapids/lib/python3.6/site-packages\"] + sys.path\n!cp /opt/conda/envs/rapids/lib/libxgboost.so /opt/conda/lib/","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import cudf,cuml\nimport pandas as pd\nimport numpy as np\nfrom cuml.manifold import TSNE\nfrom cuml import PCA  \n#from cuml.decomposition import PCA << this is also supported\nfrom cuml.cluster import DBSCAN\n#from cuml import DBSCAN << this is also supported\nimport matplotlib.pyplot as plt\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The following scatter function is defined below, but not used in this notebook. You could call it your self for some interesting visualizations"},{"metadata":{"trusted":true},"cell_type":"code","source":"def scatter_thumbnails(data, images, zoom=0.12, colors=None):\n    assert len(data) == len(images)\n\n    # reduce embedding dimentions to 2\n    x = PCA(n_components=2).fit_transform(data) if len(data[0]) > 2 else data\n\n    # create a scatter plot.\n    f = plt.figure(figsize=(22, 15))\n    ax = plt.subplot(aspect='equal')\n    sc = ax.scatter(x[:,0], x[:,1], s=4)\n    _ = ax.axis('off')\n    _ = ax.axis('tight')\n\n    # add thumbnails :) Displaying thumbnails is something I have commented out. \n#     from matplotlib.offsetbox import OffsetImage, AnnotationBbox\n#     for i in range(len(images)):\n#         image = plt.imread(images[i])\n#         im = OffsetImage(image, zoom=zoom)\n#         bboxprops = dict(edgecolor=colors[i]) if colors is not None else None\n#         ab = AnnotationBbox(im, x[i], xycoords='data',\n#                             frameon=(bboxprops is not None),\n#                             pad=0.02,\n#                             bboxprops=bboxprops)\n#         ax.add_artist(ab)\n    return ax\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- Read pre-encoded embeddings. Created using the [original notebook](https://www.kaggle.com/skylord/face-clustering)> \n- This encodes the first-frame face crops, using the following codeblock\n\n```\nfrom torchvision.transforms import ToTensor\n\ntf_img = lambda i: ToTensor()(i).unsqueeze(0)\nembeddings = lambda input: resnet(input)\n\nlist_embs = []\nwith torch.no_grad():\n    for face in tqdm(face_files):\n        t = tf_img(Image.open(face)).to(device)\n        e = embeddings(t).squeeze().cpu().tolist()\n        list_embs.append(e)\n```\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nimport pickle\n\nembeddings = pd.read_pickle('/kaggle/input/sample-face-crop/embeddings_face_clusters.pkl')\nprint(embeddings.shape)\nembeddings.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Convert the embeddings to columns\ncolnames = list()\n\nfor idx in range(512):\n    colnames.append('colname_'+str(idx))\n    \ncolnames;\nembeddings[colnames] = pd.DataFrame(embeddings['embedding'].values.tolist(), index = embeddings.index)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Convert to numpy array\nembed_numpy = embeddings[colnames].to_numpy()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\n# PCA first to speed it up\nx = PCA(n_components=50).fit_transform(embed_numpy)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Default dimensions for t-sne is n_components=2. This uses the fast Barnes-Hut clustering technique. \nWith greater dimensions the exact method for calculating tsne is used"},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\ntsne = TSNE(random_state = 99) # \nx = tsne.fit_transform(embed_numpy)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Total time to fit the transform was ~ 7.35 secs !!! \n\nThis can be compared to the 3-5+ hours if you used sklearn's t-sne "},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\ntsne50 = TSNE(random_state=99, n_components=50)\nx50= tsne50.fit_transform(embed_numpy)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"DBSCAN’s main benefit is that the number of clusters is not a hyperparameter, and that it can find non-linearly shaped clusters. This also allows DBSCAN to be robust to noise. DBSCAN has been applied to analyzing particle collisions in the Large Hadron Collider, customer segmentation in marketing analyses, and much more.\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time \ndbscan = DBSCAN(eps=1.5, verbose=True ) #min_samples (default is 5)\nclusters =  dbscan.fit_predict(x)\nembeddings['RapidDBSCAN'] = clusters","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"embeddings.to_pickle('/kaggle/working/embeddings.pkl')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":1}