{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "**CSC 466: Knowledge Discovery in Data **\n", "** Individual Test**\n", "\n", "**Task 1 **" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Your Name **: \n", "\n", "**Cal Poly Email**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The program below performs hierarchical clustering using Complete Link distance.\n", "\n", "**Your Task**: Perform the following:\n", "\n", " 1. Add to the notebook the computation of the Centroid Distance method for computing the distance between two data points.\n", " The function getCentroid() is defined and stubbed below for your convenience\n", " \n", " 2. Change the code of the hierarchical clustering function to use the Centroid distance. \n", " \n", " 3. Display the vector of cluster assignments constructed by function flatten()\n", " \n", " 4. Plot the dataset colored by cluster (marking outliers with a separate color)\n", " \n", " 5. Write a function computeClusterRadius(), which, given a cluster returns its radius.\n", " \n", " 6. Report the radii for each cluster" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Notes:**\n", "\n", "Please read carefully the comments to the existing code - they may explain things you need to know in order to complete some of the tasks.\n", "\n", "I have created placeholders for the main functions you need to create and Jupyter cells at the bottom of the notebook for you to produce the desired output. You may need/want/find it convenient to define additional functions, or to change the parameters in the function definitions provided to you. Feel free to do both/either as you see fit." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "## Imports\n", "\n", "import numpy as np\n", "from matplotlib import pyplot as plt\n", "import seaborn\n", "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Distance Metrics**\n", "\n", "We use Eucledian distance between two points for this assignment. For simplicity, we declare our own function." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def eucledian(x,y):\n", " return np.sqrt(np.sum((x - y)*(x-y)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "** Complete Link Distance Computation **\n", "\n", "The code below is simply to make the original Hierarchical code run." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "## Parameters\n", "## m: matrix of cluster distances\n", "## i, j: clusters that are being merged (new cluster is {i,j})\n", "## k: cluster to which the new distance needs to be computed\n", "\n", "## complete link is the largest distance between two points belonging to two different clusters\n", "## if a cluster i = {x1,...,xn} and cluster j = {y1,...,ym} are merged, then \n", "## the complete link distance from the new cluster ij = {x1,..,xn,y1,..,ym} to a cluster \n", "## k = {z1,...,zp} is the larger of the complete link distances between clusters k and i and clusters k and j\n", "\n", "def completeLink(m, i,j,k):\n", " # assume i maxHeight:\n", " maxHeight = clusters[i][0]\n", " idx = i\n", " s = clusters[idx]\n", " left = s[1]\n", " right = s[2]\n", " l = []\n", " if len(left)==3: ## check if leaf\n", " l.append(left)\n", " if len(right)==3:\n", " l.append(right)\n", " del clusters[idx]\n", " clusters.extend(l)\n", " \n", " return clusters\n", " \n", " \n", "def getClusters(clusters, k):\n", "\n", " s = clusters\n", " while len(clusters) < k:\n", " s = split(s)\n", " \n", " return s\n", " \n", "def flatten(cluster, assignment, label):\n", " left = cluster[1]\n", " right = cluster[2]\n", " if len(left)== 3:\n", " flatten(left, assignment,label)\n", " else:\n", " assignment[left[0]] = label\n", " if len(right) == 3:\n", " flatten(right,assignment, label)\n", " else:\n", " assignment[right[0]]= label\n", " \n", " return\n", " \n", " \n", "\n", "## takes the output of getClusters() function and assigns a cluster label to each data label\n", "## n: number of data points in the dataset\n", "def flattenClusters(clusters,n): \n", "\n", " k = len(clusters) ## number of clusters.\n", " \n", " assignment = np.full((n), -1)\n", " \n", " for i in range(k):\n", " flatten(clusters[i], assignment,i)\n", " \n", " return assignment\n", " \n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "** Reading in the Dataset **\n" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [], "source": [ "filename = \"data1.csv\"\n", "\n", "rawData = np.loadtxt(filename, delimiter = \",\")\n", "\n", "## let's keep only the two columns with the data attributes\n", "\n", "data = rawData[:,0:2]\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Let's visualize the dataset**" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAWkAAAD4CAYAAAAuNhccAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAIABJREFUeJzt3X9wG+d5J/AvCBAAIYIiSELRD0qWLUqvE8tSZOlsKYojW2bOcRpddCfHahw353Hi+Dq1L527m7vexI3j1mmnzeTaTnsz52rsepIb99SxW9e55s6uLNtRreicyLZkJe0ribLqWJZDiIRI0PhFgrw/KJAAubtYALvYd3e/nxnPWCAEvHqxfPDu8z7v+wZmZmZARERqanO6AUREpI9BmohIYQzSREQKY5AmIlIYgzQRkcJCVr9gKpWxpFwkkYghnc5a8VKux76oxv6Yx76o5ub+SCbjAa3HlR1Jh0JBp5ugDPZFNfbHPPZFNS/2h7JBmoiIGKSJiJTGIE1EpDAGaSIihTFIExEpjEGaiJRQmCxhOJ1FYbLkdFOUYnmdNBFRPUrT0zh4+CzePJ3C6HgBPV0RbNmQxP7dAwi2cRzJIE1Ejjp4+CwO/fS9uT+PjBfm/nz34AanmqUMfk0RkWMKkyW8eTql+bM3T19i6gMM0kTkoLGJAkbHC5o/S2fyGJvQ/pmfMEgTkWOWdkbQ0xXR/FkiHsXSTu2f+QmDNBGZZnUFRqQ9iC0bkpo/27KhD5F27+3FUS9OHBJRTXZWYOzfPQBgNgedzuSRiEexZUPf3ON+xyBNRDXZWYERbGvD3YMbsG/XOoxNFLC0M6I5gi5Mlgx/7lU1g7QQ4isAfq3ioW1Syk77mkREKqlVgbFv1zpLgmakPYhlidiix/1eR10zSEspnwDwBAAIIXYBuMvuRhGROsxUYGgFV6v4vY663q+hbwL4XTsaQkRqcrICg3XUdeSkhRD/AsAvpJQfGD0vkYhZdjpCMhm35HW8oFZf5ItTSI8XkOiKIBr2/lQDr415reiLnZtX4fkj5zQeX4n+ld22ve/FSx9iNKM/ig+G25HsW1L1uNeujXp+m78K4KlaT7LqfLFkMo5UKmPJa7mdUV/4MV/Ha2Neq/piz441yOaKiyow9uxYY+v7lyZL6IlHMKKRbknEoygVJ6ve383Xht6XSz1B+hYAD1nRGLKO3/N11BpmKzCsVq6jrrzGy/xSR21qqCWEWAlgQkpZtLk9VAfm66jVyhUYrQyO+3cPYHBbP3q7omgLAL1dUQxu6/dNHbXZkfQKAMN2NoTq5/SsO1ErODWKV4WpIC2lPA7gDpvbQnUqz7rr5eu47wF5iV4dtdd5c2bJJ7jvAZH3eb9Wy+Oc3PfAr8t0SW3NXpeqXdcM0i7nRL7Oj2V/pL7S9DQOPPc2XjtxoaHrUtXrmkHaI1qZr2PZH6mo2etS1euawx6qC8v+SEXNXpcqX9cM0gTA/GbuPO6IVNTsdanydc10h8/Vm4dj2R+pqNnrUuXrmiNpnyvn4UbGC5jBfB7u4OGzms9n2R+pqNnrUuXrmiNpH2t0M3ced0Qq2r97ALGO8Gx1R6aAnvj8XaHZvw+od10zSPtYo8vK/b5Ml9SUyU5iOJ3D9PQ0ZmaAmZmZuv6+qtc1g7SPNZuH8+syXVJLcWoK3/7eG/jF8ETV46OZYkMldKpd18xJ+5jKeTgis7QCdCWzJXhmqpucwJG0z6mahyMyI5Mt4kJKP0ADxqk7veqmvTdfjYnspBIpDwZpn1M1D0dkxnvDE5iukXpemLqr3Jvj2VeHNFcZ/sPJiygUS0osDWeQJgDq5eGIzOhf1om2AAwDdTl1pzVq/jA/qfl38sXZtIcKS8OZk7aQynktIi+Kx8JYlezU/FmwDVUnuGitCcgXp029j5NLwzmStoCqu2cR+cE3vnwDvv29N3AhNZv6aAsAH0nE8Fu/dgPiHWEAxmsCzHDypCMGaQuounsWkR+EQyE8et+NyGSLyBSnEQ+3IR4LVz3HaE2AGU4uDTd7EO2XhBAnhBDHhRCftbtRbqLy7llEfhKPhSGuSmBsooD3UhNVv3vlNQFaouEgeuLGAdjJktSaI2khRC+ARwBsBdAJ4FEAP7S5Xa7Bw2CJnFeansZfvnQGPz71AXKF2eAcDQex8/rl+NXb1s+tCai84y375KYV2POJtXjkyddxeaK46OfRcBB7b77G9n+DHjPpjkEAh6SUGQAZAF+zt0nuovLuWUR+cfDwWRw+fqHqsXyxhJeOX0AgEMDdgxsM1wSMjOUxphGgAaA4WcJEtohYxJnssJl3XQsgIIQ4CGAlgG9JKV/Se3IiEUMoZM1tQTIZt+R17LZz8yo8f+ScxuMr0b+y25L3cEtftAr7Y57f+yJfnMKJs5d0f35yaAT37gkjm5/CA/s2AwDS4wUkuiKIhmdDYHdiCZKJDgync4v+fl93B9at7Z17bquZedcAgH4A/xrAVQBeFkJcJaXUrExMp7OWNCyZjCOVyljyWnbbs2MNsrniom/oPTvWWPJvcFNftAL7Y14jfaHaQavNGk5nkbqcN/h5Dg9952VcnqiuvMqMTaOy5zat69VMh2xa14vMWA5GvWxFn+p92ZoJ0r8EcFRKOQVgSAiRAZAEMNxQSzyIq/bIDbxaKrq0M4KeeBijGe10BQCkr5ysYlR51cgWCa3oUzNB+kUATwkh/gBAD2YnD/XvLXyMq/ZIZV4tFY20B3GDWKY5CtajtV96I4OtVvRpzVAvpbwA4BkAhzFb1fGQlNLcMh0iUoKbS0XNrOTdv3sAu7euQkdkPqiG2/XDm9G5heXBVq0A3ao+NZUJl1I+DuBxS96RiFrOjaWi9aQSgm1tuOfTAr9+58fxj2eGgUAAS5eE8TtP/cS2yqtW9al7E1FEZJrRYg5VS0XrPX8TAKLhEPqXxdGf7EQ8Fsbm9X2az9u8vrfpeaNW9SmDNJEPuO2AB6tSCYE6H69Hq/qUQdqDuBsfadm/ewCD2/rR2xVFWwDo7YpW7RKnEjOphFoKkyW8dUa7xuGtMyOW/H60ok+5wZKHaOXwNq3rxeC21ejpiio3WqLWclOpqPFK3oipVEIrcsat6FOOpD1EK4f38pvv4xsH/h8ePnAMTx86jdI0C3P8zmz1gpOMUgkf5ifx7KtDNa/lVubh7exTBmmPqLVfrplJFyKVlFMJ0XB14MsXp01dy27Lw+thkPaI0fG85q3hQqrXxBKVBdvasG/XOsQi2sHUzLXspjy8HuakPeLQT39h6nmq1sQSaRmbKCCts9zbzLXspjy8Ho6kPaAwWcLJoRFTz1W1JpZIi1V5ZTfk4fUwSHtAPUcDbVrX48oLlfzJK3nlZjBIe4DRaKNctN925X9ODo2wyoNcxQt55WYwJ+0BRkcDrUouwXupDzF9Zfdvr+x8Rv7hVF5ZlX23GaQ9Qmsv3E3renRz1VpbNRKpzIqtgM0EXtX23WaQ9git0cbYRAGvvPm+5vNZ5UF+Uk/gVW3fbeakPaZyFtuNO58R2cHsjnoq7rvNIO2QVmyCxJlxovoCrxUbO1mN6Y4Wa3W+q5Fz24i8pJ6Nlow3dnLm7pNBusVane/ywoorombUE3iNKqWcuvusGaSFEFsB/C2AcvLmbSnlQ7a2yqNq3XbZWW3BQ3LJr+oNvKrdfZoZSXcCeEZK+Zt2N8br3HjOHJEX1BN4Vbv7NBOk47a3widUzHcR+YFqgbceZkfSnxRC/B8ASwA8IqV82d5meZOK+S4iPzGT9lNtMUtgZmbG8AlCiI8CWC+lfF4IsQHAIQADUkrN/QOnpkozoRCDjZ5SaRpP/uBnOHbqIi5dzqGvuwPbN67AfXuuQzDIikgipx147m08f+Tcosf/1c3X4P6919v51prn49YM0gsJIV4HsF9K+Y7Wz1OpTH0vqCOZjCOVyljxUkqqZ18Ar/dFvdgf89gX1Zrtj8JkCQ8fOKaZkuztiuKx+2+y7Y43mYxrBumaQzchxH1CiH9/5f+XA/gIgAvWNs9/3Ly/LZFXqbiYxcz99d8A+IwQ4keYLcX7db1UBxGRm6m4lULNiUMpZRrAZ1vQFiIiR6k4uc8Vh0REFdy4mIWIyDdUq6lmkCYi0qDKVgoszCUiUhiDNBGRwhikiYgUxiBNRKQwBmkiIoUxSBMRKYxBmohIYQzSHteKU8mJyD5czOJRqm1cTkSNYZD2qFafSk5E9uCQyoNqnUrO1AeRezBIe5CKG5cTUWMYpD1IxY3LiagxDNIeVN64XAtPJfeWfHGK1Tsex4lDj1Jt43KyVrl65+TQCFLpHKt3PIxB2qNU27icrMXqHf8w9ZUrhOgQQpwTQtxrc3vIYjyV3HtYveMvZu+LHgYwYmdDiMgcVu/4S80gLYS4FsDHAPyd/c0holpYveMvZnLS3wXwIIB/a+YFE4kYQiFrbq2Tybglr+MF7Itqfu+PnZtX4fkj5zQeX4n+ld0OtKhavjiF9HgBia4IouHWTn157dow7D0hxJcB/FhK+Y4QwtQLptNZK9qFZDKOVCpjyWu5HfuiGvsD2LNjDbK5Ik4OjeDS5dxc9c6eHWsc7Run94xx87Wh9+VS6yvuVwBcI4T4HIB+AAUhxHtSykMWt4+I6lCu3nlgXweGzo8oU73DqhPrGQZpKeX+8v8LIb4F4DwDNJE6ouEQliViTjcDQO2qk3271inxReI2rHoncqnCZAkXL32oTMkdq07sYTqjL6X8lo3tICKTqvK+mQJ64mqsNixXnYxoBGpWnTSOI2kilynnfUfGC5iZmc/7Hjx81tF2cc8YezBIE7mI6qsN9+8ewOC2fvR2RdEWAHq7ohjc1s89Y5rAvTuIXMRM3tfJiUTuGWM9jqSJXMQtqw25Z4x1GKTJEjyVvDXM5n35eXgH0x3UFKdXmPmR0V7h/Dy8h0GamsIVZq1XmfcNhttRKk7OjaCfPnSan4fH8KuVGqZ6pUGZV2/9I+1BrOhbUpXisOPz0Os/r/arajiSpoa1utKgMFnC2EQB8aUdmo8vrCTw262/1Z+HXv/decs1eOaVc77pV6cxSFPDWrXCbGGwSCY6sGldb81g0UgqRi/gu4HVn4de/8l3L+MXwxOLHgfMp1S0+tnNfW8nBmlqWLnSoPIXuczKFWYLg8VwOlczWOzbta6uzX7MjrpVDiRWfh5GqZMLqQnNx81soqTVz5vX9yEA4K0zlzgy18AgTU2x+1TyRoPFpzavrOvWv9ao2y2pE6s+D6PUyfSM9t8xk1LR6ufDxy9UPYeTndUYpKkpja4wMzsibTRYYGbG9K2/mS02n311yBVVE1at+DNKnbQFtPu+VkrFqJ+1cHvTWeoMAcjVzK4wK01P4+lDp/HwgWP4r48fw8MHjuHpQ6dRmp7WfL7RCruAznssXRIGAgFsGujT/PnCW/9aE26pyzlXVLFUanbFn9GimVXJTs3Ha6VUjPpZS+X2pn6uJOFImmxXOWqud0RqlGdd0hHCRG5q0ePj2Uk88sTrSMTDWL2sE9n8JNKZgu6tf60JN8zMKL1fhln15tP1UifzE7bmUirl9+2IhJCIhzGaKZpqb3dnBLliCd9/UeLkWf/mqxmkyTYL87iJeBjZgvZIyOjWdmGw6OvuwHVrEzg5NKIZpEtX7sVHM0WMZoq4dctK3H7jGt3gVGvCLZmIuXqf5Ebz6UapEzMplcr3HRkvINwewNSUTo5KQ7YwhUf/4idVj6maZrITgzTZZuEkkdEIymhEujBYrFvbi6HzI3jlzfdNtePk0Cju2r3ecPRoNOEWbGtrSRWLXZ4+dAYvvzE/OVdvoCunTsw+DsyOnr//gsTRUx/MPVacXBygo+EgPnH98ivVHSNIZ/IItweRL5aQL+qnNvyUr2aQJlvUO0mUiEdqjkjLQSEaDhmmKBYyk5KoNeFmdxWLHUrT03j670/j1be0v8ysCnSVaZRQMFA1eq5lSTSEL9wygEh7EHfeUkIqncWfPHPSMEAD7kozNatmkBZCxAA8BeAjAKIAfldK+b9tbhe5XL2TRB/mJ/Hsq0Omc41GKYqF6klJ6I0O3bhP8tN/fxovG9xtNBvotNIosWh7Ve16LelMYa4NkfYgwu1BU9eNG9JMVjGTed8D4KdSyl0A7gLw3+xtEnlBRySEbp1fomg4iEi4+tLLF6frPgJq783XYOfG5ejtiqAtMPu6WqxMSbhhn+TS9DS+/6LUHUGXNRvoqo7xwmwapZ4ArdUGo2qeStev61H6M7BSzZG0lPJgxR9XA6g9dCHfqhxdpXVOh77xo0mcOjeKQnFxjtrUqrXSbBlf5YTk9uuWY/9tA/jBa+ddlZKww8HDZ6ty0Ho2XQl0jayirDedZdSGyvc2e4dUqJEO8RLTOWkhxFEA/QA+Z/S8RCKGUMiab7hkMm7J63iBW/riwHNv6/6CtbUB09PAqXfSupOI6UwewXA7kn1LTL/HaKaIo6c+QF8ihq9/cSvyxSmkxwtIdEUQDXt/2qXy2sgXp3ByaMTU37vztg147rXzOHbqIlKXc0h2d2D7xhW4b891CAaNb7IvXvoQoxnz6ayFouEgVvYtwc/Op/HKW+9XvfeDd21BOBzC/z12Hjrl8zh7YQzxpR2an69bflfMMn0FSyk/IYT4OID/KYTYLKXUrKVJp7OWNCyZjCOVyljyWm7nlr4oTJbw2gn9EVz5F84o55iIR1EqTur+ewuTJRw7dVHzZ6+deB933LgakfYgQgAyYzmo32vNWXhtDKezSKVzNf9eb1cUz7xUnbMeTufw/JFzyOaKtcvrJkvoiZubuK3U0xXBR9ckEGpvw6s673334Abc+alrMHo5h2M//6Xm64yM5TF0fmRRPt0tvyta9L5cauakhRBbhRCrAUBK+RZmA7v2UiTytXonC7WYWbWWuqwdhCpXqPmV2ZzupoFe3RH3P5y8WHNFqNGKRD0BAL955ybcc7vAKZ33fvN0Cu8NZ1CYLOGe2wWiYe0QxYnDap8C8B8BQAjxEQCdAC7Z2ShyJ7MBolKic3bSr7crisFt/TXzx0s7I0h2d2j+zE+/uHpqBc9EZwS33rAKg1v7db9Q88VS1WSg3oTu3puvxg3rtZfea+npiiKZiBl+mY+MF/DNJ3+Chw8cw3NHzuET16/QfJ4b6tOtYibd8T8APCGEOAKgA8BvSCl1MkXkZ/WUxQGzgfmb925DrjBletIq0h7E9o0r8PyRc4t+5qdfXCOLa7oj6IiEkMkWkZ4o4OTZ2TFWPUu0Kyd0F64k1NtwaaHy52Omxr385XDb1lUY3Nbv68lgM9UdOQB3t6At5AFaiz5i0ZBmadaWDX2Ix8KIx8J1vcd9e65DNlf05C+uFftVL6zpfuH1d6tyzyPjBbz8xgWsXtZpOkhX1lQvXEmqF6Cj4SCKk6VFn089X+ZvnRnBY/ff5Kr6dKt5f+qbWirY1oZ9u9bhU5tXAjMzSCZiFavQrAmqwWDthSWVwQ6A8r/gduxXXR616uWes/lJ3LplJU4OjSKdyaO7M4JsYUpztV85lWRUetcWAGZmMNf2vTdfjYnspGa/V36Zj2bymDGxR7UfVhdqYZAmyxgFGjtW62mtDlx4Kz478RRAoVhSegc1u05dN96GtYDbb1yDu3av192lsKycqhhOZ2vu7z1zJeJG2oOIJdo1nzv3Zb5pBSanpvHf/+ZtzVE95xkYpMlCtQKN0YY8drUhX5yfPlF1BzUzhw40+qVm5tzDys+l1h4lZvLJo5miYT9rfZkv6dDOj3OegZv+k0VqBRorNmsvb/yeLy7enrRWG+xoj1XMnPLdKKNqD60AWM5nP3b/Tfi9r23HY/ffhLsHN8zdedRTeqfXz3rLyVcv60RvV7Suah8/4EiaLGEm0Fi1kU/5tPCFaQuzddqq7aBm96nrjezgZ3TXU/57b8iU4arD0fHF/Wz0RZq6nMPvfW07ipMlpecPWo1BmixhZ6DROy0cqL6dNrt9qWp5TrtPXbd6B7/y631q80o88sTr0Ku+W9oZXtTPRl+k+WIJz74yhK987mMNt82LmO4gS4SCAcSi2pNEzQSaetIoZm/FNw30KjdK2797AIPb+m293bd6B79kd4fh4qUt6xd/7ks7I0jE9Usu/+ndtFKpKBVwJE2WOHj4rGYt9OplnU0FmnrTKPt3DyCXn8JrFSeCLDS4tb/h9tjFLftVL6zj/vj6Prx0fPF+Lf3LluDuT2ufWXntVT1VJ7ZUqtxfmmYxSNvEikUJbmE02s3mpzBVmkGNTdV01ZtGCba14Z7bBf7xn0c1qwV6u6Lo6Yo21pgWaEUFTCP0yitLOgXOG1Z365Y53v3p9XjjdMqwHpvmMUhbzI5FCaqzc9KwkXxtpD2IG8Qy155JqCK98kq9DZBOnBnBF24pafZ1LNKOT25awc/HJF8GaTtHuXYtSlBZq6sT+rrnqzvM/h0vLR1vNaM7pco69Eq1vpz5+ZjnqyBt9yjXzkUJKmt1dcK6tb3IjBnvmeyWHK8bNLIFba0vZ34+5vkqSNs9yrXztl91rRgZVZ4WbnZbd1VzvG5idKcUDQc1c8ubBnpNBV9+PrX5Jki3YpRr922/yjgy8i6jO6Wd1y9HIBCo2hY1Fm3HiTMpvPLGBV/MydjNN0G6FaNcu2/73YAjI28yulMqb5akty2q1+dk7OabIN2qUS4nRMiLat0p1doW1ctzMnbzTZBu1SiXt/32yxenMJzOsm8dYHSn5Oc5GTv5JkgDrR3l8rbfeuXqnJNDI0ilc8x3KqYzFkYk3KZZluf1ORk7mQrSQog/BHDzlef/vpTyr21tlU04ynU3P9agu8lzR87p1k37ZU7GDjWHH0KIWwFslFLuAPAZAH9se6tsZvVGM2SN8n7RWhvstGK/amqc0ecTDQex9+arLXkPvevDy8yMpH8E4PUr/58GsEQIEZRS+qunyDZmFhkx36k2o8+nOFnCRHYSsYj2Lom1+HGrhUpmTgsvAfjwyh+/CuCHDNBkJTNpDD/XoLtBK/cT91uay/TEoRDi8wC+AuBfGj0vkYghFLJov9pk3JLXcYt8cQrp8QISXRFEw9UfjVf7Il+c0i3bOjk0ggf2dcz1xc7Nq/D8kXOLnrdz80r0r+w2fI8PRrIAZrC8d8mivnU7Va6NRj8fI/VcH2Wq9IdVzE4c3g7gGwA+I6UcM3puOp21ol1IJuNIpcwu/nW3WrdzXu6L4XQWqbT2PhyXLucwdH5kLo2xZ8caZHNFnBwawaXLubnqnD071mj2T2l6Gn/50hkcffvi3IRWNBzEzuuX41dvW++JW+Vmrw0rNxsrfz4Lq6f0Ph8z6rk+AHfHDb0vl5pBWgixFMB3AAxKKUctbhfB37dz9dwml6tzHtjXgaHzIzUDy8HDZ3F4wYb0+WIJLx2/gEAg4Pm+NWJHnteO6immucwdn7UfQB+AvxJCvHLlvzU2t8s3/F61UO9p1gAQDYdqVucUJkt4Qw7r/vzN0ynP960RrRO7D/30PRw8fLbp17ayeqqR68NrzEwc/jmAP29BW3zJTNWCeoc9WcuORUZjEwXNk1nKRn18TJPbttT1+1YL3ppBcSHeztl4mxwP6wbqnnjEF32rxW3ljH5fhOb+mROX4+3cPKtvk28Qy3R/vmVD0ld9W6k8MNBiZmDg1KISvy5C40haAX6/nbPL/t0DmJ6ZwdG3P5jbmL5c3eHnvm10szG/LypxSmBG57TfRqVSGUte0M2lNI3SK4fyY18Yqbc/CpMlpNJZIBBAsrvDUyOxRq+N+YCrvT+0lqcPndYM7IPb+pWplHHz70oyGQ9oPc6RtEWsqDflznn2iLQH0b/MWwscmlVvntdtk41ewiDdJN4CkpuZHRi4bbLRSxhF6qA1YWJnvSmRKpqdbKTGcSRtgt5oee/NV/MWkHyB53c6h0HaBL1l29n8FG8ByTdYheQMBukajCZM/umf075fiEL+4fdFJU5hTroGowmTyxMFXLsmofmzTQO9GJso+Hp/CPImvy4qcYovRtLNlMfVWrb9xU9vQEc0VHELGEEs2o4TZ1J45Y0LrPYgoqa4Ikg3GmStKI+rNWESi4SqbgFfeP1dvPzm+3PP8dO2o0RkPaWDdLNB1qp9ms1MmETag1jaGdE9RYLVHkTUCKWDdDNB1soVUmYnTOop+LfyRAwi8i5lg3S+ONVUkLVjhVSt1Vlmth3lCkUiqoeyUSE9XjvIGnFihZSZbUe5QpGI6qFskE50NRdkndqnef/uAQxu60dvVxRtAaC3K4rBbf3Yv3vA90dlEVH9lE13RMOhppehOrFCyih/PTKW5QpFIqqLqSAthNgI4G8B/JGU8s/sbdK8ZoOskyuktPLXzRyVxYlGIn+qGaSFEEsA/CmAl+xvTjWrgqwq+zQ3sklNaXoaB557G6+duMCJRiIfMjOSLgD4LID/YnNbdDkRZO0audZ7d2BVrTcRuVPNIC2lnAIwJYQw9YKJRAyhkDVBLZls/WkapdI0nvzBz3Ds1EWkLueQ7O7A9o0rcN+e6xAMWjNy/foXtyJfnEJ6vIBEVwTRsPbHkC9O6S6OOTk0ggf2dej+Xa9z4tpQFfuimtf6w/Lf8HQ6a8nrtPKssspR87OvDlWNXIfTOTx/5ByyuaLlI9cQgMxYDnr/yuF0Fql0TvNnly7nMHR+RIk0Tqu5+Rw7q7Evqrm5P/S+XPw5DLti4cKSRDyMbEG7DM6JZd3NTDQSkTf4euZp4cKS0UwR+aJ2kDazgMZqTtV6E5E6zFR3bAXwXQBrAUwKIe4E8G+klKM2t81WRgtLtITbg+iMtdvYIm37dw8g1hHGayfe52kYRD5kZuLwOIBb7G9Kaxnt7aElXyzhuSPvtLyiItjWhvv3Xo87blzNOmkiH/JduqN84ndHJKS77FyPk0u3eRoGkT/5ZuJQa/e5WLRdc1JOjypLt7n6kMg/fBOktRaFjIwXsHpZJ7L5qbl876aBXpw4k8JoprjoNZyuqOA2p0T+44sgbTRJmM1P4Zv3bkOuMDU3Mg22BZra2MkuXH1I5D++GH7VOgAgV5iqyvcabTfqFG5zSuRPvhhJ17soxMnd8/TYcdIMEalPmZF0uerCjhFho4tCVKqocOKkGSIpjwIXAAAFfElEQVRynuMjab3JsAfv2mLp+zhxAICVGtnmlIjcz/EgrTcZFusIY+/OtZa9j4opjHq5/YuGiOrnaJA2mgw7duoi7rhxdVOBVKueWJUDABrhhS8aIqqPo0HaaDLs0uVcw5NhKtcTW7EQxc1fNERUH0eDtFHVRV93R8OTYSrWE6v8xUFE6nI0OhhVXWzfuML0SLOyMkTVeuKF26KWvzgOHj7rSHuIyB0cnzjUmwy7b891GB390PDvao1O1/cvVa6euNYXR6sPEyAi93A8SC+cDOuIhJArTGGyNF3z72rux/HzYd3nl+uJW71BEReiEFGjHA/SZaFgAIeOvzc3Kk4mOrBpXa9uzrbeTfsB4OPre/Hsq0MtzwvzGCwiapQyM1YLc7bD6ZxhzraeTft7uyIY3NaPGcCRvDCPwSKiRikRpBuZ7DNaJl0pAODrd27Cvl3rcOLMpbrew0oqbtpEROozle4QQvwRgO0AZgB8XUr5Eysb0UjO1miZdKWeriiSiZjjeWEuRCGiRtQcSQshdgFYL6XcAeCrAP7M6kY0unlQ5ehUTzmdoMoGRSpt2kRE6jOT7rgNwHMAIKX8OYCEEKLLykY0mrMtj04fu/8mfPv+m3DrDat00wnMCxORG5lJdywHcLziz7+88ti41pMTiRhCofoD3oN3bUGsI4xjpy7i0uUc+ro7sH3jCty35zoEg7W/S/pXApuuXY58cQrp8QISXRFEw9X/vGbfw0nJZNzpJiiF/TGPfVHNa/1hJkgHNP48o/fkdDrbcGP27lyLO25cjbGJAtat7UVmLFdzQYuWEIDMWA6ZGu9Rzgs38h6tlEzGkUpp/Wv8if0xj31Rzc39offlYiZIX8DsyLlsJYAPLGiTpnLONhoOaQZZK9+DiEh1Zu7xXwRwJwAIIbYAeF9K6c6vKiIil6kZpKWURwEcF0IcBfCnAH7D9lYREREAk3XSUsrfsrshRES0mNolDUREPscgTUSksMDMjG41HREROYwjaSIihTFIExEpjEGaiEhhDNJERApjkCYiUhiDNBGRwhikiYgUpsxp4WV2H9XlNkKIPwRwM2Y/q9+XUv61w01ylBCiA8DPAPyOlPIph5vjKCHElwD8ZwBTAH5bSvlDh5vkGCFEJ4DvAegBEAbwqJTyBWdbZQ2lRtKtOKrLTYQQtwLYeKU/PgPgjx1ukgoeBjDidCOcJoToBfAIgE8C+ByAvc62yHH3ApBSylswu2vnnzjaGgspFaTRgqO6XOZHAL5w5f/TAJYIIXx7zpcQ4loAHwPwd063RQGDAA5JKTNSyotSyq853SCHXQLQe+X/E1f+7AmqBenlAFIVfy4f1eVLUsqSlLJ8bMxXAfxQSllysk0O+y6A/+B0IxSxFkBACHFQCHFECHGb0w1ykpTyfwFYI4Q4i9nBzX9yuEmWUS1I13VUl18IIT4P4CsAHnS6LU4RQnwZwI+llO843RZFBAD0A/gSZm/1/0IIsfD3xzeEEPcAeFdKOQBgN2b3vvcE1YJ0S4/qcgMhxO0AvgHgDinlmNPtcdCvAPi8EOIYZu8qflsIMehwm5z0SwBHpZRTUsohABkASYfb5KSdAF4AACnlCQCrhBDKFUY0QrV/xIsAHgXwOI/qAoQQSwF8B8CglHLU6fY4SUq5v/z/QohvATgvpTzkXIsc9yKAp4QQf4DZioZOeCgP24CzAG4C8KwQ4ioAE1LKKYfbZAmlgrSU8qgQonxU1zR4VNd+AH0A/koIUX7sy1LKd51rEqlASnlBCPEMgMMAYgAeklJOO9wsJz0O4EkhxKuYjWv/zuH2WIb7SRMRKUy1nDQREVVgkCYiUhiDNBGRwhikiYgUxiBNRKQwBmkiIoUxSBMRKez/A43bgPkJOrfpAAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.scatter(data[:,0],data[:,1])" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [], "source": [ "## Perform Clustering\n", "\n", "distanceMatrix = computeDistanceMatrix(data, eucledian)\n", "clusters = hierarchical(data,distanceMatrix)\n", "\n", "# Get five clusters \n", "five = getClusters(clusters, 5)\n", "\n", "# Flatten those clusters into usable values\n", "flattened = flattenClusters(five, len(data))\n", "\n", "# Create a dictionary of all the individual clusters\n", "clusters = {}\n", "for i, point in enumerate(flattened):\n", " if point not in clusters:\n", " clusters[point] = [data[i]]\n", " else:\n", " clusters[point].append(data[i])\n", "\n", "# This is just some light data formatting\n", "for c in clusters:\n", " clusters[c] = np.stack(clusters[c], axis=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Your Task**: output the cluster assignment. \n", "\n", "We are looking for **five (5)** clusters" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "** Your Task**: visualize the scatterplot of your cluster assignments" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Cluster 1 with radius 1.5050503818586876: \n", "[[ 1.13914451 1.42127638]\n", " [ 2.05490501 0.94506381]\n", " [ 1.68718074 1.1498139 ]\n", " [ 1.84522469 1.83389662]\n", " [ 0.34916704 0.20757109]\n", " [ 0.71312273 2.29592454]\n", " [ 1.45120283 1.30024144]\n", " [ 1.34923173 1.50134826]\n", " [ 0.68673661 0.62518478]\n", " [ 1.00956961 0.73643864]\n", " [ 0.81778376 0.80011884]\n", " [ 0.59629252 1.25168355]\n", " [ 0.45972192 0.15943312]\n", " [ 0.70812176 0.12705347]\n", " [ 0.9877163 0.88087237]\n", " [ 2.13006473 0.58668393]\n", " [ 1.63906411 0.27282683]\n", " [-0.07439339 0.39514351]\n", " [ 0.53158587 0.30863246]\n", " [ 0.1284272 1.21343064]\n", " [-0.01671219 0.10049069]\n", " [ 1.44887643 2.36205833]]\n", "Cluster 4 with radius 1.0605860542418464: \n", "[[ 3.35485443 2.93165325]\n", " [ 4.14035686 3.33299415]\n", " [ 4.09297082 2.91941295]\n", " [ 4.0255524 2.0603712 ]\n", " [ 4.34792055 2.52103225]\n", " [ 3.97263885 3.35778194]\n", " [ 3.4400606 3.10399365]\n", " [ 4.39475248 1.84578503]\n", " [ 3.30182989 2.46335266]\n", " [ 3.24289466 3.4846477 ]\n", " [ 4.94876467 3.25362572]\n", " [ 4.28558271 2.65092888]\n", " [ 3.73850811 1.93814949]\n", " [ 3.96621709 2.54236809]\n", " [ 3.4944046 2.88808942]\n", " [ 3.65815333 3.01243996]\n", " [ 4.38450682 2.64807034]\n", " [ 4.16127113 3.18042862]\n", " [ 3.57659967 3.1872377 ]\n", " [ 4.42818966 1.85642644]\n", " [ 4.27975805 3.15859511]\n", " [ 4.72411876 3.31727824]\n", " [ 4.39687162 3.38838496]\n", " [ 3.32977397 2.65770565]]\n", "Cluster 5 with radius 1.5105212286442755: \n", "[[ 7.74178165 2.98820786]\n", " [ 7.23877304 3.11233171]\n", " [ 7.13997585 2.19156537]\n", " [ 7.0069634 3.02368756]\n", " [ 7.05139949 2.63671635]\n", " [ 7.41742855 2.61724531]\n", " [ 6.48432308 1.81779005]\n", " [ 6.86508344 1.6115423 ]\n", " [ 6.2032856 3.50225275]\n", " [ 6.94687453 2.76920293]\n", " [ 7.04917701 2.89365498]\n", " [ 6.02489295 4.07673433]\n", " [ 7.44888086 2.53461879]\n", " [ 5.65779909 2.69738454]\n", " [ 6.28670454 3.03973959]\n", " [ 6.33782706 3.11854403]\n", " [ 6.93046716 3.36804613]\n", " [ 6.53349031 2.91376934]\n", " [ 7.10903004 2.07571773]\n", " [ 6.33939021 2.74087906]\n", " [ 7.03391515 2.41297226]\n", " [ 7.36649548 3.31924822]\n", " [ 6.30653573 3.01781923]\n", " [ 7.719528 3.05130484]\n", " [ 6.76350196 3.36047975]\n", " [ 7.15592462 3.05347983]\n", " [ 6.66273713 2.84304108]\n", " [ 7.33364818 3.12884973]\n", " [ 6.21583128 2.96251341]\n", " [ 7.5728735 2.78429215]\n", " [ 5.99485326 3.69010212]\n", " [ 7.42802257 2.88418269]\n", " [ 7.13471635 3.84256047]\n", " [ 7.53605744 3.32103687]\n", " [ 7.1819572 2.95003399]\n", " [ 6.86121822 2.37042466]\n", " [ 7.63642691 3.10655575]\n", " [ 7.2747744 3.09505402]\n", " [ 7.02453215 2.60155743]\n", " [ 7.76509682 1.94725476]\n", " [ 7.74914167 3.17197454]]\n", "Cluster 2 with radius 1.430299037770285: \n", "[[ 2.45473115 4.30576896]\n", " [ 1.36845274 6.10263427]\n", " [ 2.35347325 5.44650425]\n", " [ 2.35967528 5.57684932]\n", " [ 2.4758371 5.52198907]\n", " [ 1.68981927 5.08565087]\n", " [ 2.51901262 5.3235015 ]\n", " [ 3.13287714 6.61450036]\n", " [ 2.75038807 6.46789207]\n", " [ 2.29412747 6.86917004]]\n", "Cluster 3 with radius 1.6847625897254654: \n", "[[ 8.54991328 6.58307743]\n", " [ 7.78045274 5.54953381]\n", " [ 8.52654346 6.05561829]\n", " [ 8.43657199 6.21754073]\n", " [ 7.52139659 7.30566686]\n", " [ 8.92301108 5.84377781]\n", " [ 8.60768773 5.2297361 ]\n", " [ 8.00818768 6.31721167]\n", " [ 8.57580943 6.21368595]\n", " [ 8.25585671 5.20895508]\n", " [ 8.02082345 5.95926999]\n", " [ 7.71764847 5.72116412]\n", " [ 8.05906408 5.97456223]\n", " [ 8.21513793 5.87175774]\n", " [ 7.76486087 7.01476363]\n", " [ 8.29286791 6.14634376]\n", " [ 8.59056135 4.89706758]\n", " [ 8.06248476 6.34177293]\n", " [ 6.84885249 7.05820496]\n", " [ 6.39545529 5.82832459]\n", " [ 8.19700245 5.666758 ]\n", " [ 8.05345784 6.58039393]\n", " [ 7.99653757 6.32082644]]\n" ] } ], "source": [ "def computeClusterRadius(cluster):\n", " centroid = sum(cluster) / len(cluster)\n", " \n", " radius = 0\n", " for point in cluster:\n", " dist = eucledian(centroid, point)\n", " if dist > radius:\n", " radius = dist\n", " return radius\n", "\n", "# This outputs all the data points and which clusters they belong to\n", "for c in clusters:\n", " if c == -1:\n", " continue\n", " else:\n", " radius = computeClusterRadius(clusters[c])\n", " print(\"Cluster {} with radius {}: \\n{}\".format(c+1, radius, clusters[c]))\n", "if -1 in clusters:\n", " print(\"Outliers:\\n{}\".format(clusters[-1])) " ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "## Use the array of colors below. Use black for outliers, other colors for the five clusters you constructed.\n", "\n", "colors=['black', 'blue', 'green', 'red', 'purple', 'brown']\n", "\n", "# Print out all the clusters, normal colors for good values,\n", "# black for outliers\n", "color_index = 1\n", "for c in clusters:\n", " if c == -1:\n", " plt.scatter(clusters[c][:, 0], clusters[c][:, 1], color='black')\n", " else:\n", " plt.scatter(clusters[c][:, 0], clusters[c][:, 1], color=colors[color_index])\n", " color_index += 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "**When you are done**: download the notebook, submit using the following command:\n", "\n", " handin dekhtyar 466-test " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "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.6.5" } }, "nbformat": 4, "nbformat_minor": 2 }