{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np \nimport pandas as pd \nimport seaborn as sns\nfrom imageio import imwrite\nimport matplotlib\nimport matplotlib.pyplot as plt\nfrom matplotlib.offsetbox import OffsetImage, AnnotationBbox\nfrom matplotlib.cbook import get_sample_data\nimport random\n%matplotlib inline\nfrom sklearn.preprocessing import StandardScaler\nfrom PIL import Image, ImageChops\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## What are SOM?\nIn brief, Self-organizing maps are a type of artificial neural network based on competitive learning (at variance to error-correcting learning typical of other NNs). The idea is to iteratively adapt a connected two-dimensional matrix of vectors (or nodes) to the higher-dimensional topology of the input dataset. At each cycle, a node is selected and its elements (the weights) are updated, together with those of its neighbors, to approach a randomly chosen datapoint from the training set. The competitive element comes into play during the update stage, since the closest node (according to a chosen metric) to the extracted datapoint is selected for the weights update at each iteration.\n\nSOMs are particularly suited for cases where low-dimensional manifolds are hidden in higher dimensions and are often used together and/or competing with other dimensionality reduction methods and in particular Principal Component Analysis (PCA) for which it could be seen as a non-linear generalization: an exhaustive explanation of SOM's advantages and disadvantages, however, is beyond the scope of this notebook, but there are plenty of resources online for those who would like to know more."},{"metadata":{},"cell_type":"markdown","source":"I've used [this](http://https://github.com/fcomitani/SimpSOM) implementation of Kohonen Self-Organizing Maps"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"!pip install SimpSOM","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import SimpSOM as sps","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Data preparation"},{"metadata":{"trusted":true},"cell_type":"code","source":"np.random.seed(0)\n\n# get part of the dataset\ntrain = pd.read_csv('../input/Kannada-MNIST/train.csv')\ntrain = train.sample(n=600, random_state=0)\nlabels = train['label']\ntrain = train.drop(\"label\",axis=1)\n\n# check distribution\nsns.countplot(labels)\n\n# standardization of a dataset\ntrain_st = StandardScaler().fit_transform(train.values)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Training SOM"},{"metadata":{"trusted":true},"cell_type":"code","source":"# build a network 20x20 with a weights format taken from the train_st and activate Periodic Boundary Conditions. \nsom = sps.somNet(20, 20, train_st, PBC=True)\n\n# train it with 0.1 learning rate for 10000 epochs\nsom.train(0.05, 10000)\n\n# print unified distance matrix\nsom.diff_graph(show=True, printout=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Visualizing some nodes of the map"},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, axs = plt.subplots(10, 10, figsize=(20, 20))\naxs = axs.flatten()\n\nsome_nodes_indxs = random.sample(range(len(som.nodeList)), len(axs))\n\n\nfor i, ax in enumerate(axs):\n    ax.imshow(np.asarray(som.nodeList[some_nodes_indxs[i]].weights).reshape(28,28))\n    ax.axis('off')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# print picked coordinates\n', '.join([f'({i // 20}, {i % 20})' for i in some_nodes_indxs])\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"som.cluster(train_st, type='qthresh', show=True);","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"I hope you enjoyed the kernel. In case you are interested in understanding of this algorithm, I would recommend this <a href=\"https://www.youtube.com/watch?v=lFbxTlD5R98\">lecture</a>"},{"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}