{ "cells": [ { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", " \n", " Loading BokehJS ...\n", "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "(function(global) {\n", " function now() {\n", " return new Date();\n", " }\n", "\n", " var force = \"1\";\n", "\n", " if (typeof (window._bokeh_onload_callbacks) === \"undefined\" || force !== \"\") {\n", " window._bokeh_onload_callbacks = [];\n", " window._bokeh_is_loading = undefined;\n", " }\n", "\n", "\n", " \n", " if (typeof (window._bokeh_timeout) === \"undefined\" || force !== \"\") {\n", " window._bokeh_timeout = Date.now() + 5000;\n", " window._bokeh_failed_load = false;\n", " }\n", "\n", " var NB_LOAD_WARNING = {'data': {'text/html':\n", " \"
\\n\"+\n", " \"

\\n\"+\n", " \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n", " \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n", " \"

\\n\"+\n", " \"\\n\"+\n", " \"\\n\"+\n", " \"from bokeh.resources import INLINE\\n\"+\n", " \"output_notebook(resources=INLINE)\\n\"+\n", " \"\\n\"+\n", " \"
\"}};\n", "\n", " function display_loaded() {\n", " if (window.Bokeh !== undefined) {\n", " Bokeh.$(\"#8a778317-7654-476a-96af-afb6f61a0309\").text(\"BokehJS successfully loaded.\");\n", " } else if (Date.now() < window._bokeh_timeout) {\n", " setTimeout(display_loaded, 100)\n", " }\n", " }\n", "\n", " function run_callbacks() {\n", " window._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n", " delete window._bokeh_onload_callbacks\n", " console.info(\"Bokeh: all callbacks have finished\");\n", " }\n", "\n", " function load_libs(js_urls, callback) {\n", " window._bokeh_onload_callbacks.push(callback);\n", " if (window._bokeh_is_loading > 0) {\n", " console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", " return null;\n", " }\n", " if (js_urls == null || js_urls.length === 0) {\n", " run_callbacks();\n", " return null;\n", " }\n", " console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", " window._bokeh_is_loading = js_urls.length;\n", " for (var i = 0; i < js_urls.length; i++) {\n", " var url = js_urls[i];\n", " var s = document.createElement('script');\n", " s.src = url;\n", " s.async = false;\n", " s.onreadystatechange = s.onload = function() {\n", " window._bokeh_is_loading--;\n", " if (window._bokeh_is_loading === 0) {\n", " console.log(\"Bokeh: all BokehJS libraries loaded\");\n", " run_callbacks()\n", " }\n", " };\n", " s.onerror = function() {\n", " console.warn(\"failed to load library \" + url);\n", " };\n", " console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.getElementsByTagName(\"head\")[0].appendChild(s);\n", " }\n", " };var element = document.getElementById(\"8a778317-7654-476a-96af-afb6f61a0309\");\n", " if (element == null) {\n", " console.log(\"Bokeh: ERROR: autoload.js configured with elementid '8a778317-7654-476a-96af-afb6f61a0309' but no matching script tag was found. \")\n", " return false;\n", " }\n", "\n", " var js_urls = ['https://cdn.pydata.org/bokeh/release/bokeh-0.12.2.min.js', 'https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.2.min.js', 'https://cdn.pydata.org/bokeh/release/bokeh-compiler-0.12.2.min.js'];\n", "\n", " var inline_js = [\n", " function(Bokeh) {\n", " Bokeh.set_log_level(\"info\");\n", " },\n", " \n", " function(Bokeh) {\n", " \n", " Bokeh.$(\"#8a778317-7654-476a-96af-afb6f61a0309\").text(\"BokehJS is loading...\");\n", " },\n", " function(Bokeh) {\n", " console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-0.12.2.min.css\");\n", " Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-0.12.2.min.css\");\n", " console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.2.min.css\");\n", " Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.2.min.css\");\n", " }\n", " ];\n", "\n", " function run_inline_js() {\n", " \n", " if ((window.Bokeh !== undefined) || (force === \"1\")) {\n", " for (var i = 0; i < inline_js.length; i++) {\n", " inline_js[i](window.Bokeh);\n", " }if (force === \"1\") {\n", " display_loaded();\n", " }} else if (Date.now() < window._bokeh_timeout) {\n", " setTimeout(run_inline_js, 100);\n", " } else if (!window._bokeh_failed_load) {\n", " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", " window._bokeh_failed_load = true;\n", " } else if (!force) {\n", " var cell = $(\"#8a778317-7654-476a-96af-afb6f61a0309\").parents('.cell').data().cell;\n", " cell.output_area.append_execute_result(NB_LOAD_WARNING)\n", " }\n", "\n", " }\n", "\n", " if (window._bokeh_is_loading === 0) {\n", " console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n", " run_inline_js();\n", " } else {\n", " load_libs(js_urls, function() {\n", " console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n", " run_inline_js();\n", " });\n", " }\n", "}(this));" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from sklearn import random_projection\n", "from sklearn.mixture import GaussianMixture\n", "from sklearn import cluster, datasets\n", "import pandas as pd\n", "import numpy as np\n", "from sklearn.metrics import accuracy_score\n", "import seaborn as sns\n", "import matplotlib.pyplot as plt\n", "from sklearn.neighbors import kneighbors_graph\n", "from sklearn.neighbors import KNeighborsClassifier\n", "from sklearn.decomposition import PCA as pca\n", "import time\n", "%matplotlib inline\n", "import bokeh.plotting as bp\n", "from sklearn.manifold import TSNE\n", "from bokeh.models import HoverTool\n", "from bokeh.io import output_notebook\n", "from collections import Counter\n", "from sklearn.cluster import KMeans\n", "output_notebook()" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true }, "outputs": [], "source": [ "plt.rc(\"figure\", figsize=(9, 4))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Motivation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Random projection (RP) is a commonly used dimensionality reduction technique. As a relatively young technique that was invented around 1980, RP gains a lot of tractions becuase it doesn't require a lot of computational power and it has beend shown to have some promises for various applications such as high dimensional clustering, image and text data dimension reductions(Fern & Brodley, 2003; Bingham & Mannila, 2001). In this post, we are going explore RP's mathematical meaning, as well as some implementations of RP using python.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Where & How\n", "\n", "RP comes from a famous lemma called the Johnson-Lindenstrauss lemma. Based on the Johnson-Lindenstrauss lemma, one can project a high-dimensional data onto a lower dimensional subspace using a random matrix because the distances between points are approximately preserved. When putting into mathematical prospective, the original matrix D is projected onto P using a random matrix R. \n", "\n", "$$P = R \\times D$$\n", "\n", "The basic dimension is shown as below, \n", " \n", "$$ \\left[\\begin{array}\n", "{rrr}\n", " & & \\\\\n", " & Projected & \\\\\n", " & & \n", "\\end{array}\\right]_{k \\times n} = \\left[\\begin{array}\n", "{rrr}\n", " & & \\\\\n", " & Random & \\\\\n", " & & \n", "\\end{array}\\right]_{k \\times d}\\left[\\begin{array}\n", "{rrr}\n", " & & \\\\\n", " & Original & \\\\\n", " & & \n", "\\end{array}\\right]_{d \\times n}\n", "$$ \n", "\n", "where k << d. Each entry of the random matrix R is sampled from an standard normal distribution and is normalized by the columns to a unit length. A way to think about each column of R is as random \"weights\" to decompose D. \n", "\n", "Achlioptas (Achlioptas, 2001) provides another method to fill in values for R that theoratically meets the requirment for the Johnson-Lindenstrauss lemma: \n", "\n", "$$r_ij = \\sqrt3 \\Bigg\\{\\begin{array}\n", "{rrr}\n", " +1& & probability = \\frac{1}{6} \\\\\n", " 0& & probability = \\frac{2}{3} \\\\\n", " -1 & & probability = \\frac{1}{6}\n", "\\end{array}\n", "$$\n", "\n", ", where we called R a **sparse** matrix. Achlioptas's finding help further computational saving with easier-to-simulate matrix. Below, we will compare the two methods of populating R and see if Achlioptas's finding can be used in practice. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Why\n", "\n", "Why do we want to use RP and what is its limitations compared to the widely known dimension reduction method, PCA? \n", "\n", "The dataset we are going to explore is [CHART](https://archive.ics.uci.edu/ml/datasets/Synthetic+Control+Chart+Time+Series). CHART contains 600 examples of control charts synthetically generated by the process in Alcock and Manolopoulos (1999). There are six different classes of control charts: \n", "\n", " A. Normal \n", " B. Cyclic \n", " C. Increasing trend \n", " D. Decreasing trend \n", " E. Upward shift \n", " F. Downward shift \n", "\n", "Here is a image provided by UCI showing the different classes in picture.\n", "\"term-document" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(600, 60)\n" ] } ], "source": [ "df = pd.read_table('synthetic_control_data.txt',sep='\\s+',header=None)\n", "print df.shape" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def RP(component):\n", " RP = random_projection.SparseRandomProjection(n_components=component)\n", " return RP\n", "\n", "def PCA(component):\n", " p = pca(n_components=component)\n", " return p\n", "\n", "\n", "## define KNN to have 6 neighbors\n", "neigh = KNeighborsClassifier(n_neighbors=6)" ] }, { "cell_type": "code", "execution_count": 77, "metadata": { "collapsed": false }, "outputs": [], "source": [ "components = range(1,15,1) \n", "names = ['rp','pca']\n", "name2func = {'rp':'RP','pca':'PCA'}\n", "summary = pd.DataFrame(index=pd.MultiIndex.from_product([['RP','PCA'],components ],\n", " names=['method','n_component']),\n", " columns=['Time','Accuracy'])\n", "\n", "for name in names: # use both random projection and PCA\n", " for component in components:# reduce dimension to number within 1 to 15\n", "\n", " fcn = name2func[name]\n", " ## measure run time\n", " start_time = time.time()\n", " df_ = pd.DataFrame(locals()[fcn](component).fit_transform(df))\n", " summary.loc[(fcn,component),'Time'] =time.time() - start_time \n", " \n", " ## measure accuracy \n", " df_['y_true'] = np.array(sum([[i]*100 for i in range(6)],[]))\n", " neigh = KNeighborsClassifier(n_neighbors=6)\n", " neigh.fit(df_.iloc[:,:-1],df_.iloc[:,-1]) \n", " df_['y_pred'] = neigh.predict(df_.iloc[:,:-1])\n", " summary.loc[(fcn,component),'Accuracy'] = accuracy_score(df_.y_true,df_.y_pred)\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Time" ] }, { "cell_type": "code", "execution_count": 76, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "method\n", "PCA Axes(0.125,0.125;0.775x0.755)\n", "RP Axes(0.125,0.125;0.775x0.755)\n", "Name: Time, dtype: object" ] }, "execution_count": 76, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\nIgXr/wOqQXTXoPVt7QAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "summary.groupby(level='method').Time.plot(legend=True)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When we reduce dimension from 60 to a smaller number, random projection is always faster. Especially when we reduce dimension to 1, random projection is about four times faster than PCA.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Accuracy" ] }, { "cell_type": "code", "execution_count": 66, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "method\n", "PCA Axes(0.125,0.125;0.775x0.755)\n", "RP Axes(0.125,0.125;0.775x0.755)\n", "Name: Accuracy, dtype: object" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "summary.groupby(level='method').Accuracy.plot(legend=True)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "However, PCA are almost always more accurate than RP. PCA is going after the best/perfect seperation to retain the distance from high dimension whereas RP gives a stochastic answer to dimension reduction. \n", "\n", "So we conclude:\n", "\n", "| | Advantage | Disadvantage |\n", "| ------------- | ------------- |------------- |\n", "| RP | Fast | Stochastic solution |\n", "| PCA | Slow |Perfect solution |" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## RP and its applications\n", "### High dimensional unsupervised clustering\n", "\n", "As google dictionary suggests, clustering means grouping similar things together. This is hard for dataset with high dimensionality. Give you a concrete example. In situation A, there are two points in a 200 dimensional world: two points are very close in the x,y,z dimension and yet not similar at all in the other 197 dimensions. How should the machine cluster those two points? Are they extremely similar or not? However, in situation B, you are given two points in a 1 dimensional world: one point is at 1.0 and another is at 1.01. To cluster those two points, you just have to look at the euclidean disctance (1.01-1.0) between the two and the euclidean disctance of those two points with the rest of the dataset. Hence, for a high dimensional dataset, we want to reduce the dimensionality before clustering. As Fern (Fern & Brodley, 2003) suggests, an cluster ensemble framework based on RP and expectation-maximization (EM) proved its effectiveness for high dimensional data clustering. \n", "\n", "Without reshown their work, we are going to do something a little bit different -- **visualize the clustering**\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " #### step 1 - reduce dimension using RP " ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(600, 6)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "transformer = RP(6) ## reduce dimension\n", "df_sparse = transformer.fit_transform(df) \n", "df_sparse.shape" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " #### step 2 - use T-SNE to visualize high dimensional data\n", " On [scikit-learn](http://scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.html) website, it wrote\n", " \n", " \n", " t-SNE is a tool to visualize high-dimensional data. It converts similarities between data points\n", " to joint probabilities and tries to minimize the Kullback-Leibler divergence between the joint\n", " probabilities of the low-dimensional embedding and the high-dimensional data." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(600, 2)" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "## visualize 6-dimension data into x and y coordinate\n", "xycoords = TSNE().fit_transform(df_sparse) \n", "xycoords.shape" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### step 3 - use unsupervised clustering method to identify cluster" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": true }, "outputs": [], "source": [ "n_clusters = 6 ## is a given (we are cheating a little bit here)\n", "km = KMeans(n_clusters)\n", "clusters = km.fit_predict(df_sparse)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### step 4 - identify cluster using given label\n", "\n", "We are given labels for CHART data. The first 100 rows are normal, the second 100 rows are cyclic and so on... \n", "We look at what K-mean result looks like and find the most common label for the first 100 rows, second 100 rows, and so on. If two clusters share the same label, then we will look over the two clusters and decide by eye-picking. \n" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[4, 4, 2, 0, 3, 5]" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def most_common(lst):\n", " data = Counter(lst)\n", " return data.most_common(1)[0][0]\n", "\n", "chunks = [clusters[x:x+100] for x in xrange(0, len(clusters), 100)]\n", "\n", "class_name = [most_common(i) for i in chunks]\n", "class_name" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[array([4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n", " 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n", " 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n", " 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n", " 4, 4, 4, 4, 4, 4, 4, 4], dtype=int32),\n", " array([1, 4, 1, 1, 4, 4, 4, 1, 4, 1, 1, 1, 4, 1, 1, 4, 1, 4, 1, 1, 1, 1, 1,\n", " 4, 1, 4, 1, 4, 4, 4, 4, 4, 1, 1, 4, 4, 4, 3, 1, 4, 4, 1, 1, 1, 4, 4,\n", " 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, 1, 1, 4, 4, 1, 4, 4, 4, 4,\n", " 4, 4, 4, 4, 1, 4, 1, 4, 1, 1, 1, 4, 4, 4, 4, 1, 4, 4, 4, 1, 4, 4, 1,\n", " 4, 4, 1, 4, 4, 1, 1, 4], dtype=int32)]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "chunks[0:2]" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class_name[1]=1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since cluster[0] and cluster[1] shares the same label, we have to make changes\n", "#### step 5 - use bokeh to visualize the data\n", "\n", "The points are situated based on the x and y coordinates derided from step 1 and colored by K-mean cluster. \n", "The pop-up is color-coded and denoted by the class labels we assign (given the fact that we know there are 6 classes and each 100 rows represent a different class.) " ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [], "source": [ "colormap = np.array([\n", " \"#dbdb8d\", \"#9edae5\", \"#ff7f0e\", \"#c5b0d5\", \"#2ca02c\", \n", " \"#c49c94\"\n", "])\n", "names = sum([[i]*100 for i in class_name],[])\n", "color = sum([[colormap[i]]*100 for i in class_name],[])" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "source=bp.ColumnDataSource({\"classtype\": names,'color':color})\n", "\n", "hover = HoverTool(tooltips=''' \n", "
\n", "

class: @classtype

\n", " \n", "
''')\n", "\n", "p = bp.figure(plot_width=900, plot_height=400, title=\"CHART Map by t-SNE\",\n", " tools=[hover],\n", " x_axis_type=None, y_axis_type=None, min_border=1)\n", "p.scatter(\n", " x = xycoords[:,0],\n", " y = xycoords[:,1],\n", " size=8,\n", " color= colormap[clusters],\n", " source=source)\n" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "
\n", "
\n", "
\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "bp.show(p)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "If a point has the same color as the pop-up notation, then we correctly cluster that point. On the other hand, if a point has a different color than that of the pop-up notation, then we do not correctly identify the right cluster for that point. Because github doesn't support dynamic javascript, I will show you screenshots of graphs for both situations I described here.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**correctly identified**\n", "\"term-document\n", "\n", "\n", "**incorrectly identified**\n", "\"term-document" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python [default]", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.12" } }, "nbformat": 4, "nbformat_minor": 1 }