├── .gitignore ├── 01_The_Dataset.ipynb ├── 02_Clustering_KMeans.ipynb ├── 03_Clustering_OtherAlgos.ipynb ├── 04_Classification_kNN.ipynb ├── 05_Classification_OtherAlgos.ipynb ├── 06_Classification_Decision_Trees.ipynb ├── 07_Classification_Random_Forest.ipynb ├── 08_Dimensionality_Reduction.ipynb ├── LICENSE ├── README.md └── fruit.csv /.gitignore: -------------------------------------------------------------------------------- 1 | .ipynb_checkpoints/*.* 2 | ignore/*.* 3 | ignore* 4 | simple.dotfile 5 | simpletree.png 6 | kNN_test_train.csv 7 | Thumbs.db -------------------------------------------------------------------------------- /06_Classification_Decision_Trees.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "", 4 | "signature": "sha256:84213b66dc238f70d6ee451ea986e0e6f1b761b35f059af8bb7d29774323efba" 5 | }, 6 | "nbformat": 3, 7 | "nbformat_minor": 0, 8 | "worksheets": [ 9 | { 10 | "cells": [ 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "# Introduction to data analysis using machine learning #\n", 16 | "\n", 17 | "## 06. Classification with Decision Trees ##\n", 18 | "\n", 19 | "by David Taylor, [www.prooffreader.com](http://www.prooffreader.com) (blog) [www.dtdata.io](http://dtdata.io) (hire me!)\n", 20 | "\n", 21 | "For links to more material including a slideshow explaining all this stuff in further detail, please see the front page of [this GitHub repo.](https://github.com/Prooffreader/intro_machine_learning)\n", 22 | "\n", 23 | "This is notebook 6 of 8. The next notebook is: [[07. Classification with Random Forest]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/07_Classification_Random_Forest.ipynb)\n", 24 | "\n", 25 | "[[01]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/01_The_Dataset.ipynb) [[02]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/02_Clustering_KMeans.ipynb) [[03]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/03_Clustering_OtherAlgos.ipynb) [[04]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/04_Classification_kNN.ipynb) [[05]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/05_Classification_OtherAlgos.ipynb) **[06]** [[07]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/07_Classification_Random_Forest.ipynb) [[08]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/08_Dimensionality_Reduction.ipynb)\n", 26 | "\n", 27 | "***\n", 28 | "\n", 29 | "We look further at one of the classification algorithms we saw in the [previous notebook](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/05_Classification_OtherAlgos.ipynb). Again, this is an algorithm that is not used a lot in practice, but is very intuitively useful for beginners. Don't worry, the [next algorithm](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/07_Classification_Random_Forest.ipynb) is one that's used a lot!\n", 30 | "\n", 31 | "For the first time, we encounter an algorithm that is convenient to visualize with all five of our features, not just two that we can see in a scatter plot." 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "#### 1. Import libraries and load data #" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "collapsed": false, 44 | "input": [ 45 | "import pandas as pd\n", 46 | "import numpy as np\n", 47 | "import matplotlib.pyplot as plt\n", 48 | "%matplotlib inline\n", 49 | "from sklearn import tree\n", 50 | "from sklearn.externals.six import StringIO\n", 51 | "import re\n", 52 | "\n", 53 | "df = pd.read_csv('fruit.csv')\n", 54 | "fruitnames = {1: 'Orange', 2: 'Pear', 3: 'Apple'}\n", 55 | "colors = {1: '#e09028', 2: '#55aa33', 3: '#cc3333'}\n", 56 | "fruitlist = ['Orange', 'Pear', 'Apple']\n", 57 | "\n", 58 | "df.sort('fruit_id', inplace=True) # This is important because the factorizer assigns numbers\n", 59 | " # based on the order the first label is encountered, e.g. if the first instance had\n", 60 | " # fruit = 3, the y value would be 0.\n" 61 | ], 62 | "language": "python", 63 | "metadata": {}, 64 | "outputs": [], 65 | "prompt_number": 4 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": {}, 70 | "source": [ 71 | "#### 2. Classify with a Decision Tree and view Confusion Matrix #\n", 72 | "\n", 73 | "With all five features used, the confusion matrix should be a perfect or near-perfect classifier on the testing set." 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "collapsed": false, 79 | "input": [ 80 | "df['is_train'] = np.random.uniform(0, 1, len(df)) <= .75 # randomly assign training and testing set\n", 81 | "train, test = df[df['is_train']==True], df[df['is_train']==False]\n", 82 | "features = ['color_id', 'elongatedness', 'weight', 'sweetness', 'acidity']\n", 83 | "y, _ = pd.factorize(train['fruit_id'])\n", 84 | "clf = tree.DecisionTreeClassifier()\n", 85 | "clf = clf.fit(train[features], y)\n", 86 | "preds = clf.predict(test[features])\n", 87 | "test_result = pd.crosstab(np.array([fruitnames[x] for x in test['fruit_id']]), \n", 88 | " np.array([fruitnames[x+1] for x in preds]), rownames=['actual'], colnames=['predicted'])\n", 89 | "test_result" 90 | ], 91 | "language": "python", 92 | "metadata": {}, 93 | "outputs": [ 94 | { 95 | "html": [ 96 | "
\n", 97 | "\n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | " \n", 123 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | "
predictedAppleOrangePear
actual
Apple 11 0 0
Orange 1 13 0
Pear 0 0 15
\n", 133 | "
" 134 | ], 135 | "metadata": {}, 136 | "output_type": "pyout", 137 | "prompt_number": 2, 138 | "text": [ 139 | "predicted Apple Orange Pear\n", 140 | "actual \n", 141 | "Apple 11 0 0\n", 142 | "Orange 1 13 0\n", 143 | "Pear 0 0 15" 144 | ] 145 | } 146 | ], 147 | "prompt_number": 2 148 | }, 149 | { 150 | "cell_type": "markdown", 151 | "metadata": {}, 152 | "source": [ 153 | "#### 3. View several different trees, each produced on a different randomly selected 70% training set. #\n", 154 | "\n", 155 | "Observe the differences between each.\n", 156 | "\n", 157 | "Note:\n", 158 | "\n", 159 | "1. You will need [Graphviz](http://www.graphviz.org/Download..php) installed and in the PATH environmental variable to visualize the graphs.\n", 160 | "\n", 161 | "2. I did not make this code block a function because of the IPython magic shell call and call to Image.\n", 162 | "\n", 163 | "3. I had some issues getting Pydot to work in Python 3, which is why I ran Graphviz in the shell and did a somewhat clunky regex sub to adjust the trees." 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "collapsed": false, 169 | "input": [ 170 | "# Repetition 1\n", 171 | "\n", 172 | "df['is_train'] = np.random.uniform(0, 1, len(df)) <= .75 # randomly assign training and testing set\n", 173 | "train, test = df[df['is_train']==True], df[df['is_train']==False]\n", 174 | "features = ['color_id', 'elongatedness', 'weight', 'sweetness', 'acidity']\n", 175 | "y, _ = pd.factorize(train['fruit_id'])\n", 176 | "clf = tree.DecisionTreeClassifier()\n", 177 | "clf = clf.fit(train[features], y)\n", 178 | "dot_data = StringIO() \n", 179 | "tree.export_graphviz(clf, out_file=dot_data) \n", 180 | "tree_string = dot_data.getvalue()\n", 181 | "# replace feature numbers with feature names\n", 182 | "tree_string = re.sub('gini = 0\\.[0-9]+\\\\\\\\n', '', tree_string)\n", 183 | "for i, feature in enumerate(features):\n", 184 | " tree_string = re.sub('X\\[{}\\]'.format(i), feature, tree_string)\n", 185 | "# repace lists of numeric label assignments with label name\n", 186 | "for result in re.finditer('\\[[ ]+([\\d]+)\\.[ ]+([\\d]+)\\.[ ]+([\\d]+)\\.\\]', tree_string):\n", 187 | " nums = []\n", 188 | " for i in range(0,3):\n", 189 | " nums.append(int(result.group(i+1)))\n", 190 | " if nums[0] > nums[1]:\n", 191 | " if nums[0] > nums[2]:\n", 192 | " tree_string = re.sub('\\[[ ]+{}\\.[ ]+{}\\.[ ]+{}\\.\\]'.format(nums[0], nums[1], nums[2]), fruitlist[0], tree_string)\n", 193 | " else:\n", 194 | " tree_string = re.sub('\\[[ ]+{}\\.[ ]+{}\\.[ ]+{}\\.\\]'.format(nums[0], nums[1], nums[2]), fruitlist[2], tree_string)\n", 195 | " elif nums[1] > nums[2]:\n", 196 | " tree_string = re.sub('\\[[ ]+{}\\.[ ]+{}\\.[ ]+{}\\.\\]'.format(nums[0], nums[1], nums[2]), fruitlist[1], tree_string)\n", 197 | " else:\n", 198 | " tree_string = re.sub('\\[[ ]+{}\\.[ ]+{}\\.[ ]+{}\\.\\]'.format(nums[0], nums[1], nums[2]), fruitlist[2], tree_string)\n", 199 | "with open('simple.dotfile', 'w+') as f:\n", 200 | " f.write(tree_string)\n", 201 | "# normally this would be done with libraries like pydot or networkx, but\n", 202 | "# I'm having trouble getting them to work in Python 3.4.2 under Windows,\n", 203 | "# so I'll just call the shell executable directly\n", 204 | "!dot.exe -Tpng simple.dotfile > simpletree.png\n", 205 | "from IPython.core.display import Image\n", 206 | "Image( filename ='simpletree.png')" 207 | ], 208 | "language": "python", 209 | "metadata": {}, 210 | "outputs": [ 211 | { 212 | "metadata": {}, 213 | "output_type": "pyout", 214 | "png": "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\nd955B5WVlZg0aRK2bNmC8vJys0MyxeWXXw63243nnnsOtbW1GBoaMjskIsoDTMqIKC3efvttVFZW\nory8HB6PB8cee6zZIZmquroamzdvxksvvYSamhomZkSUEJMyIhq1P/zhD5g3bx5OPfVUvPzyy5g8\nebLZIeWESy+9FC+99BK2bduGRYsW4YsvvjA7JCLKYUzKiGhUvF4v5s6di7/7u7/D5s2bMXHiRLND\nyikXXnghPB4Pdu7cCavViv3795sdEhHlKCZlRJSyXbt2obq6GmeffTY2b96Mo48+2uyQctKsWbPg\n8Xjw5ptvYuHChfjrX/9qdkhElIOYlBFRSnp6elBdXY0LLrgAbrcbRx55pNkh5bRzzjkHW7Zswdtv\nv43LL78coVDI7JCIKMcwKSOipP3P//wPFixYgMrKSjz//PM44ogjzA4pL5x55pnYunUr3n33Xcyf\nPx+ffvqp2SERUQ5hUkZESfF4PLj88suxYMECbNy4EWVlZWaHlFfOOOMMbNu2DX6/H9XV1fjzn/9s\ndkhElCOYlBGRYS+99BIsFguuuuoquFwuJmQpmj59OrZt24ZgMIh58+bB7/ebHRIR5QAmZURkyAsv\nvIBFixbhmmuuwfr16/n4oFE65ZRTsG3bNgwNDWHu3Ln48MMPzQ6JiEzGpIyIEvrlL3+Jb3/727ju\nuuuwdu1aJmRpctJJJ2Hr1q1QFAVz587F+++/b3ZIRGQiJmVEFJfL5cI111yDpUuX4sknn4SiKGaH\nVFCOP/54bNmyBWVlZaisrMR7771ndkhEZBImZUQU0/r163HttdfiBz/4AR555BEmZBlSXl6OLVu2\nYNKkSaisrMQ777xjdkhEZAImZUSkq729HTfccAPuvPNOOBwOJmQZduyxx8Lj8aC8vByVlZV4++23\nzQ6JiLKMSRkRRXnsscfwve99D6tXr8Z9991ndjhFY/LkyXj55Zdx6qmnYu7cufjd735ndkhElEVM\nyogozEMPPYTly5fjxz/+Me655x6zwyk6EydOxObNm3HGGWdg3rx5ePPNN80OiYiyhEkZEanuv/9+\n3HHHHWhpacFdd91ldjhF6+ijj8aLL76Ic889F5dddhl27dpldkhElAVMyogIAPCjH/0Id999Nx55\n5BHcdtttZodT9I488kh0dXXhm9/8Jqqrq9HT02N2SESUYYoQQpgdBBGZa+XKlbj//vvxxBNPYOnS\n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\n", 215 | "prompt_number": 3, 216 | "text": [ 217 | "" 218 | ] 219 | } 220 | ], 221 | "prompt_number": 3 222 | }, 223 | { 224 | "cell_type": "code", 225 | "collapsed": false, 226 | "input": [ 227 | "# Repetition 2\n", 228 | "\n", 229 | "df['is_train'] = np.random.uniform(0, 1, len(df)) <= .75 # randomly assign training and testing set\n", 230 | "train, test = df[df['is_train']==True], df[df['is_train']==False]\n", 231 | "features = ['color_id', 'elongatedness', 'weight', 'sweetness', 'acidity']\n", 232 | "y, _ = pd.factorize(train['fruit_id'])\n", 233 | "clf = tree.DecisionTreeClassifier()\n", 234 | "clf = clf.fit(train[features], y)\n", 235 | "dot_data = StringIO() \n", 236 | "tree.export_graphviz(clf, out_file=dot_data) \n", 237 | "tree_string = dot_data.getvalue()\n", 238 | "# replace feature numbers with feature names\n", 239 | "tree_string = re.sub('gini = 0\\.[0-9]+\\\\\\\\n', '', tree_string)\n", 240 | "for i, feature in enumerate(features):\n", 241 | " tree_string = re.sub('X\\[{}\\]'.format(i), feature, tree_string)\n", 242 | "# repace lists of numeric label assignments with label name\n", 243 | "for result in re.finditer('\\[[ ]+([\\d]+)\\.[ ]+([\\d]+)\\.[ ]+([\\d]+)\\.\\]', tree_string):\n", 244 | " nums = []\n", 245 | " for i in range(0,3):\n", 246 | " nums.append(int(result.group(i+1)))\n", 247 | " if nums[0] > nums[1]:\n", 248 | " if nums[0] > nums[2]:\n", 249 | " tree_string = re.sub('\\[[ ]+{}\\.[ ]+{}\\.[ ]+{}\\.\\]'.format(nums[0], nums[1], nums[2]), fruitlist[0], tree_string)\n", 250 | " else:\n", 251 | " tree_string = re.sub('\\[[ ]+{}\\.[ ]+{}\\.[ ]+{}\\.\\]'.format(nums[0], nums[1], nums[2]), fruitlist[2], tree_string)\n", 252 | " elif nums[1] > nums[2]:\n", 253 | " tree_string = re.sub('\\[[ ]+{}\\.[ ]+{}\\.[ ]+{}\\.\\]'.format(nums[0], nums[1], nums[2]), fruitlist[1], tree_string)\n", 254 | " else:\n", 255 | " tree_string = re.sub('\\[[ ]+{}\\.[ ]+{}\\.[ ]+{}\\.\\]'.format(nums[0], nums[1], nums[2]), fruitlist[2], tree_string)\n", 256 | "with open('simple.dotfile', 'w+') as f:\n", 257 | " f.write(tree_string)\n", 258 | "# normally this would be done with libraries like pydot or networkx, but\n", 259 | "# I'm having trouble getting them to work in Python 3.4.2 under Windows,\n", 260 | "# so I'll just call the shell executable directly\n", 261 | "!dot.exe -Tpng simple.dotfile > simpletree.png\n", 262 | "from IPython.core.display import Image\n", 263 | "Image( filename ='simpletree.png')" 264 | ], 265 | "language": "python", 266 | "metadata": {}, 267 | "outputs": [ 268 | { 269 | "metadata": {}, 270 | "output_type": "pyout", 271 | "png": "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\n", 272 | "prompt_number": 4, 273 | "text": [ 274 | "" 275 | ] 276 | } 277 | ], 278 | "prompt_number": 4 279 | }, 280 | { 281 | "cell_type": "code", 282 | "collapsed": false, 283 | "input": [ 284 | "# Repetition 3\n", 285 | "\n", 286 | "df['is_train'] = np.random.uniform(0, 1, len(df)) <= .75 # randomly assign training and testing set\n", 287 | "train, test = df[df['is_train']==True], df[df['is_train']==False]\n", 288 | "features = ['color_id', 'elongatedness', 'weight', 'sweetness', 'acidity']\n", 289 | "y, _ = pd.factorize(train['fruit_id'])\n", 290 | "clf = tree.DecisionTreeClassifier()\n", 291 | "clf = clf.fit(train[features], y)\n", 292 | "dot_data = StringIO() \n", 293 | "tree.export_graphviz(clf, out_file=dot_data) \n", 294 | "tree_string = dot_data.getvalue()\n", 295 | "# replace feature numbers with feature names\n", 296 | "tree_string = re.sub('gini = 0\\.[0-9]+\\\\\\\\n', '', tree_string)\n", 297 | "for i, feature in enumerate(features):\n", 298 | " tree_string = re.sub('X\\[{}\\]'.format(i), feature, tree_string)\n", 299 | "# repace lists of numeric label assignments with label name\n", 300 | "for result in re.finditer('\\[[ ]+([\\d]+)\\.[ ]+([\\d]+)\\.[ ]+([\\d]+)\\.\\]', tree_string):\n", 301 | " nums = []\n", 302 | " for i in range(0,3):\n", 303 | " nums.append(int(result.group(i+1)))\n", 304 | " if nums[0] > nums[1]:\n", 305 | " if nums[0] > nums[2]:\n", 306 | " tree_string = re.sub('\\[[ ]+{}\\.[ ]+{}\\.[ ]+{}\\.\\]'.format(nums[0], nums[1], nums[2]), fruitlist[0], tree_string)\n", 307 | " else:\n", 308 | " tree_string = re.sub('\\[[ ]+{}\\.[ ]+{}\\.[ ]+{}\\.\\]'.format(nums[0], nums[1], nums[2]), fruitlist[2], tree_string)\n", 309 | " elif nums[1] > nums[2]:\n", 310 | " tree_string = re.sub('\\[[ ]+{}\\.[ ]+{}\\.[ ]+{}\\.\\]'.format(nums[0], nums[1], nums[2]), fruitlist[1], tree_string)\n", 311 | " else:\n", 312 | " tree_string = re.sub('\\[[ ]+{}\\.[ ]+{}\\.[ ]+{}\\.\\]'.format(nums[0], nums[1], nums[2]), fruitlist[2], tree_string)\n", 313 | "with open('simple.dotfile', 'w+') as f:\n", 314 | " f.write(tree_string)\n", 315 | "# normally this would be done with libraries like pydot or networkx, but\n", 316 | "# I'm having trouble getting them to work in Python 3.4.2 under Windows,\n", 317 | "# so I'll just call the shell executable directly\n", 318 | "!dot.exe -Tpng simple.dotfile > simpletree.png\n", 319 | "from IPython.core.display import Image\n", 320 | "Image( filename ='simpletree.png')" 321 | ], 322 | "language": "python", 323 | "metadata": {}, 324 | "outputs": [ 325 | { 326 | "metadata": {}, 327 | "output_type": "pyout", 328 | "png": "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\nEREREWn/AwYTxXz+KUnfAAAAAElFTkSuQmCC\n", 329 | "prompt_number": 5, 330 | "text": [ 331 | "" 332 | ] 333 | } 334 | ], 335 | "prompt_number": 5 336 | }, 337 | { 338 | "cell_type": "code", 339 | "collapsed": false, 340 | "input": [], 341 | "language": "python", 342 | "metadata": {}, 343 | "outputs": [] 344 | } 345 | ], 346 | "metadata": {} 347 | } 348 | ] 349 | } -------------------------------------------------------------------------------- /07_Classification_Random_Forest.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "", 4 | "signature": "sha256:63fd463d06ca725cacea9d6caa81981f0c791d4b95f4fdb09d09484770b6d833" 5 | }, 6 | "nbformat": 3, 7 | "nbformat_minor": 0, 8 | "worksheets": [ 9 | { 10 | "cells": [ 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "# Introduction to data analysis using machine learning #\n", 16 | "\n", 17 | "## 07. Classification with Random Forest ##\n", 18 | "\n", 19 | "by David Taylor, [www.prooffreader.com](http://www.prooffreader.com) (blog) [www.dtdata.io](http://dtdata.io) (hire me!)\n", 20 | "\n", 21 | "For links to more material including a slideshow explaining all this stuff in further detail, please see the front page of [this GitHub repo.](https://github.com/Prooffreader/intro_machine_learning)\n", 22 | "\n", 23 | "This is notebook 7 of 8. The next notebook is: [[08. Dimensionality reduction with PCA]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/08_Dimensionality_Reduction.ipynb)\n", 24 | "\n", 25 | "[[01]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/01_The_Dataset.ipynb) [[02]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/02_Clustering_KMeans.ipynb) [[03]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/03_Clustering_OtherAlgos.ipynb) [[04]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/04_Classification_kNN.ipynb) [[05]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/05_Classification_OtherAlgos.ipynb) [[06]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/06_Classification_Decision_Trees.ipynb) **[07]** [[08]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/08_Dimensionality_Reduction.ipynb)\n", 26 | "\n", 27 | "***\n", 28 | "\n", 29 | "In the [previous notebook](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/06_Classification_Decision_Trees.ipynb), we saw Decision Trees; now we look at an ensemble method, Random Forest." 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "metadata": {}, 35 | "source": [ 36 | "#### 1. Import libraries and load data #" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "collapsed": false, 42 | "input": [ 43 | "import pandas as pd\n", 44 | "import numpy as np\n", 45 | "import matplotlib.pyplot as plt\n", 46 | "%matplotlib inline\n", 47 | "from matplotlib.colors import ListedColormap\n", 48 | "from sklearn import neighbors\n", 49 | "from sklearn.ensemble import RandomForestClassifier\n", 50 | "import time\n", 51 | "\n", 52 | "df = pd.read_csv('fruit.csv')\n", 53 | "fruitnames = {1: 'Orange', 2: 'Pear', 3: 'Apple'}\n", 54 | "colors = {1: '#e09028', 2: '#55aa33', 3: '#cc3333'}\n", 55 | "fruitlist = ['Orange', 'Pear', 'Apple']\n", 56 | "\n", 57 | "df.sort('fruit_id', inplace=True) # This is important because the factorizer assigns numbers\n", 58 | " # based on the order the first label is encountered, e.g. if the first instance had\n", 59 | " # fruit = 3, the y value would be 0.\n" 60 | ], 61 | "language": "python", 62 | "metadata": {}, 63 | "outputs": [], 64 | "prompt_number": 1 65 | }, 66 | { 67 | "cell_type": "markdown", 68 | "metadata": {}, 69 | "source": [ 70 | "#### 2. Train a Random Forest Classifier and show a confusion matrix of the test set #" 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "collapsed": false, 76 | "input": [ 77 | "df['is_train'] = np.random.uniform(0, 1, len(df)) <= .75 # randomly assign training and testing set\n", 78 | "train, test = df[df['is_train']==True], df[df['is_train']==False]\n", 79 | "features = ['color_id', 'elongatedness', 'weight', 'sweetness', 'acidity']\n", 80 | "y, _ = pd.factorize(train['fruit_id'])\n", 81 | "clf = RandomForestClassifier(n_jobs=2)\n", 82 | "clf = clf.fit(train[features], y)\n", 83 | "preds = clf.predict(test[features])\n", 84 | "test_result = pd.crosstab(np.array([fruitnames[x] for x in test['fruit_id']]), \n", 85 | " np.array([fruitnames[x+1] for x in preds]),\n", 86 | " rownames=['actual'], colnames=['predicted'])\n", 87 | "test_result" 88 | ], 89 | "language": "python", 90 | "metadata": {}, 91 | "outputs": [ 92 | { 93 | "html": [ 94 | "
\n", 95 | "\n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | " \n", 123 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | "
predictedAppleOrangePear
actual
Apple 15 0 0
Orange 0 11 0
Pear 1 0 18
\n", 131 | "
" 132 | ], 133 | "metadata": {}, 134 | "output_type": "pyout", 135 | "prompt_number": 7, 136 | "text": [ 137 | "predicted Apple Orange Pear\n", 138 | "actual \n", 139 | "Apple 15 0 0\n", 140 | "Orange 0 11 0\n", 141 | "Pear 1 0 18" 142 | ] 143 | } 144 | ], 145 | "prompt_number": 7 146 | }, 147 | { 148 | "cell_type": "markdown", 149 | "metadata": {}, 150 | "source": [ 151 | "Show feature importances" 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "collapsed": false, 157 | "input": [ 158 | "for i, score in enumerate(list(clf.feature_importances_)):\n", 159 | " print(round(100*score, 1), features[i])" 160 | ], 161 | "language": "python", 162 | "metadata": {}, 163 | "outputs": [ 164 | { 165 | "output_type": "stream", 166 | "stream": "stdout", 167 | "text": [ 168 | "2.2 color_id\n", 169 | "53.1 elongatedness\n", 170 | "7.0 weight\n", 171 | "24.8 sweetness\n", 172 | "12.9 acidity\n" 173 | ] 174 | } 175 | ], 176 | "prompt_number": 8 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "metadata": {}, 181 | "source": [ 182 | "Show confusion matrix of 100 runs of Random Forest Classifier using all features" 183 | ] 184 | }, 185 | { 186 | "cell_type": "code", 187 | "collapsed": false, 188 | "input": [ 189 | "reps=100\n", 190 | "features=['color_id', 'elongatedness', 'weight', 'sweetness', 'acidity']\n", 191 | "title_suffix='with all features'\n", 192 | "\n", 193 | "start = time.time()\n", 194 | "for i in range(reps):\n", 195 | " df['is_train'] = np.random.uniform(0, 1, len(df)) <= .75 # randomly assign training and testing set\n", 196 | " train, test = df[df['is_train']==True], df[df['is_train']==False]\n", 197 | " y, _ = pd.factorize(train['fruit_id'])\n", 198 | " clf = RandomForestClassifier(n_jobs=2)\n", 199 | " clf = clf.fit(train[features], y)\n", 200 | " preds = clf.predict(test[features])\n", 201 | " test_result = pd.crosstab(np.array([fruitnames[x] for x in test['fruit_id']]), \n", 202 | " np.array([fruitnames[x+1] for x in preds]), rownames=['actual'], colnames=['predicted'])\n", 203 | " if i == 0:\n", 204 | " final_result = test_result[:]\n", 205 | " else:\n", 206 | " final_result += test_result\n", 207 | "confmatrix = np.array(final_result)\n", 208 | "correct = 0\n", 209 | "for i in range(confmatrix.shape[0]):\n", 210 | " correct += confmatrix[i,i]\n", 211 | "accuracy = correct/confmatrix.sum()\n", 212 | "print('{} runs {}\\nFeatures: {}\\nAccuracy: {}\\ntime: {} sec'.format(reps, title_suffix, features, accuracy, int(time.time()-start)))\n", 213 | "final_result" 214 | ], 215 | "language": "python", 216 | "metadata": {}, 217 | "outputs": [ 218 | { 219 | "output_type": "stream", 220 | "stream": "stdout", 221 | "text": [ 222 | "100 runs with all features\n", 223 | "Features: ['color_id', 'elongatedness', 'weight', 'sweetness', 'acidity']\n", 224 | "Accuracy: 0.9856951274027715\n", 225 | "time: 23 sec\n" 226 | ] 227 | }, 228 | { 229 | "html": [ 230 | "
\n", 231 | "\n", 232 | " \n", 233 | " \n", 234 | " \n", 235 | " \n", 236 | " \n", 237 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 249 | " \n", 250 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 254 | " \n", 255 | " \n", 256 | " \n", 257 | " \n", 258 | " \n", 259 | " \n", 260 | " \n", 261 | " \n", 262 | " \n", 263 | " \n", 264 | " \n", 265 | " \n", 266 | "
predictedAppleOrangePear
actual
Apple 1184 31 21
Orange 4 1481 1
Pear 2 5 1745
\n", 267 | "
" 268 | ], 269 | "metadata": {}, 270 | "output_type": "pyout", 271 | "prompt_number": 9, 272 | "text": [ 273 | "predicted Apple Orange Pear\n", 274 | "actual \n", 275 | "Apple 1184 31 21\n", 276 | "Orange 4 1481 1\n", 277 | "Pear 2 5 1745" 278 | ] 279 | } 280 | ], 281 | "prompt_number": 9 282 | }, 283 | { 284 | "cell_type": "markdown", 285 | "metadata": {}, 286 | "source": [ 287 | "Show confusion matrix of 100 runs of Random Forest Classifier using only two most important features" 288 | ] 289 | }, 290 | { 291 | "cell_type": "code", 292 | "collapsed": false, 293 | "input": [ 294 | "reps=100\n", 295 | "features=['elongatedness','sweetness',]\n", 296 | "title_suffix='with only 2 most important features'\n", 297 | "\n", 298 | "import time\n", 299 | "start = time.time()\n", 300 | "for i in range(reps):\n", 301 | " df['is_train'] = np.random.uniform(0, 1, len(df)) <= .75 # randomly assign training and testing set\n", 302 | " train, test = df[df['is_train']==True], df[df['is_train']==False]\n", 303 | " y, _ = pd.factorize(train['fruit_id'])\n", 304 | " clf = RandomForestClassifier(n_jobs=2)\n", 305 | " clf = clf.fit(train[features], y)\n", 306 | " preds = clf.predict(test[features])\n", 307 | " test_result = pd.crosstab(np.array([fruitnames[x] for x in test['fruit_id']]), \n", 308 | " np.array([fruitnames[x+1] for x in preds]), rownames=['actual'], colnames=['predicted'])\n", 309 | " if i == 0:\n", 310 | " final_result = test_result[:]\n", 311 | " else:\n", 312 | " final_result += test_result\n", 313 | "confmatrix = np.array(final_result)\n", 314 | "correct = 0\n", 315 | "for i in range(confmatrix.shape[0]):\n", 316 | " correct += confmatrix[i,i]\n", 317 | "accuracy = correct/confmatrix.sum()\n", 318 | "print('{} runs {}\\nFeatures: {}\\nAccuracy: {}\\ntime: {} sec'.format(reps, title_suffix, features, accuracy, int(time.time()-start)))\n", 319 | "final_result" 320 | ], 321 | "language": "python", 322 | "metadata": {}, 323 | "outputs": [ 324 | { 325 | "output_type": "stream", 326 | "stream": "stdout", 327 | "text": [ 328 | "100 runs with only 2 most important features\n", 329 | "Features: ['elongatedness', 'sweetness']\n", 330 | "Accuracy: 0.9867831541218638\n", 331 | "time: 23 sec\n" 332 | ] 333 | }, 334 | { 335 | "html": [ 336 | "
\n", 337 | "\n", 338 | " \n", 339 | " \n", 340 | " \n", 341 | " \n", 342 | " \n", 343 | " \n", 344 | " \n", 345 | " \n", 346 | " \n", 347 | " \n", 348 | " \n", 349 | " \n", 350 | " \n", 351 | " \n", 352 | " \n", 353 | " \n", 354 | " \n", 355 | " \n", 356 | " \n", 357 | " \n", 358 | " \n", 359 | " \n", 360 | " \n", 361 | " \n", 362 | " \n", 363 | " \n", 364 | " \n", 365 | " \n", 366 | " \n", 367 | " \n", 368 | " \n", 369 | " \n", 370 | " \n", 371 | " \n", 372 | "
predictedAppleOrangePear
actual
Apple 1221 18 31
Orange 8 1481 0
Pear 1 1 1703
\n", 373 | "
" 374 | ], 375 | "metadata": {}, 376 | "output_type": "pyout", 377 | "prompt_number": 10, 378 | "text": [ 379 | "predicted Apple Orange Pear\n", 380 | "actual \n", 381 | "Apple 1221 18 31\n", 382 | "Orange 8 1481 0\n", 383 | "Pear 1 1 1703" 384 | ] 385 | } 386 | ], 387 | "prompt_number": 10 388 | }, 389 | { 390 | "cell_type": "markdown", 391 | "metadata": {}, 392 | "source": [ 393 | "Show confusion matrix of 100 runs of Random Forest Classifier using only two least important features" 394 | ] 395 | }, 396 | { 397 | "cell_type": "code", 398 | "collapsed": false, 399 | "input": [ 400 | "reps=100\n", 401 | "features=['color_id','acidity',]\n", 402 | "title_suffix='with only 2 least important features'\n", 403 | "\n", 404 | "import time\n", 405 | "start = time.time()\n", 406 | "for i in range(reps):\n", 407 | " df['is_train'] = np.random.uniform(0, 1, len(df)) <= .75 # randomly assign training and testing set\n", 408 | " train, test = df[df['is_train']==True], df[df['is_train']==False]\n", 409 | " y, _ = pd.factorize(train['fruit_id'])\n", 410 | " clf = RandomForestClassifier(n_jobs=2)\n", 411 | " clf = clf.fit(train[features], y)\n", 412 | " preds = clf.predict(test[features])\n", 413 | " test_result = pd.crosstab(np.array([fruitnames[x] for x in test['fruit_id']]), \n", 414 | " np.array([fruitnames[x+1] for x in preds]), rownames=['actual'], colnames=['predicted'])\n", 415 | " if i == 0:\n", 416 | " final_result = test_result[:]\n", 417 | " else:\n", 418 | " final_result += test_result\n", 419 | "confmatrix = np.array(final_result)\n", 420 | "correct = 0\n", 421 | "for i in range(confmatrix.shape[0]):\n", 422 | " correct += confmatrix[i,i]\n", 423 | "accuracy = correct/confmatrix.sum()\n", 424 | "print('{} runs {}\\nFeatures: {}\\nAccuracy: {}\\ntime: {} sec'.format(reps, title_suffix, features, accuracy, int(time.time()-start)))\n", 425 | "final_result" 426 | ], 427 | "language": "python", 428 | "metadata": {}, 429 | "outputs": [ 430 | { 431 | "output_type": "stream", 432 | "stream": "stdout", 433 | "text": [ 434 | "100 runs with only 2 least important features\n", 435 | "Features: ['color_id', 'acidity']\n", 436 | "Accuracy: 0.7456040191824618\n", 437 | "time: 23 sec\n" 438 | ] 439 | }, 440 | { 441 | "html": [ 442 | "
\n", 443 | "\n", 444 | " \n", 445 | " \n", 446 | " \n", 447 | " \n", 448 | " \n", 449 | " \n", 450 | " \n", 451 | " \n", 452 | " \n", 453 | " \n", 454 | " \n", 455 | " \n", 456 | " \n", 457 | " \n", 458 | " \n", 459 | " \n", 460 | " \n", 461 | " \n", 462 | " \n", 463 | " \n", 464 | " \n", 465 | " \n", 466 | " \n", 467 | " \n", 468 | " \n", 469 | " \n", 470 | " \n", 471 | " \n", 472 | " \n", 473 | " \n", 474 | " \n", 475 | " \n", 476 | " \n", 477 | " \n", 478 | "
predictedAppleOrangePear
actual
Apple 647 104 483
Orange 79 1359 25
Pear 353 70 1259
\n", 479 | "
" 480 | ], 481 | "metadata": {}, 482 | "output_type": "pyout", 483 | "prompt_number": 11, 484 | "text": [ 485 | "predicted Apple Orange Pear\n", 486 | "actual \n", 487 | "Apple 647 104 483\n", 488 | "Orange 79 1359 25\n", 489 | "Pear 353 70 1259" 490 | ] 491 | } 492 | ], 493 | "prompt_number": 11 494 | }, 495 | { 496 | "cell_type": "code", 497 | "collapsed": false, 498 | "input": [], 499 | "language": "python", 500 | "metadata": {}, 501 | "outputs": [] 502 | } 503 | ], 504 | "metadata": {} 505 | } 506 | ] 507 | } -------------------------------------------------------------------------------- /08_Dimensionality_Reduction.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "", 4 | "signature": "sha256:55da80124d4fb776789c8deec8f1a94af945058ee2ed7d6eb47aed6679e8e09f" 5 | }, 6 | "nbformat": 3, 7 | "nbformat_minor": 0, 8 | "worksheets": [ 9 | { 10 | "cells": [ 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "# Introduction to data analysis using machine learning #\n", 16 | "\n", 17 | "## 08. Dimensionality reduction with Principal Component Analysis (PCA) ##\n", 18 | "\n", 19 | "by David Taylor, [www.prooffreader.com](http://www.prooffreader.com) (blog) [www.dtdata.io](http://dtdata.io) (hire me!)\n", 20 | "\n", 21 | "For links to more material including a slideshow explaining all this stuff in further detail, please see the front page of [this GitHub repo.](https://github.com/Prooffreader/intro_machine_learning)\n", 22 | "\n", 23 | "This is notebook 8 of 8. \n", 24 | "\n", 25 | "[[01]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/01_The_Dataset.ipynb) [[02]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/02_Clustering_KMeans.ipynb) [[03]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/03_Clustering_OtherAlgos.ipynb) [[04]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/04_Classification_kNN.ipynb) [[05]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/05_Classification_OtherAlgos.ipynb) [[06]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/06_Classification_Decision_Trees.ipynb) [[07]](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/07_Classification_Random_Forest.ipynb) **[08]**\n", 26 | "***\n", 27 | "\n", 28 | "In the [previous notebook](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/07_Classification_Random_Forest.ipynb), we finished our look at Supervised Learning. Now we see a way to address the Curse of Dimensionality by reducing our features using PCA." 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "#### 1. Import libraries and load data #" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "collapsed": false, 41 | "input": [ 42 | "import pandas as pd\n", 43 | "import matplotlib.pyplot as plt\n", 44 | "%matplotlib inline\n", 45 | "import numpy as np\n", 46 | "from statsmodels.sandbox.tools.tools_pca import pcasvd\n", 47 | "from sklearn.ensemble import RandomForestClassifier\n", 48 | "\n", 49 | "df = pd.read_csv('fruit.csv')\n", 50 | "\n", 51 | "fruitnames = {1: 'Orange', 2: 'Pear', 3: 'Apple'}\n", 52 | "colors = {1: '#e09028', 2: '#55aa33', 3: '#cc3333'}\n", 53 | "fruitlist = ['Orange', 'Pear', 'Apple']\n", 54 | "\n", 55 | "numerical_columns = ['elongatedness', 'weight', 'sweetness', 'acidity', 'color_id']" 56 | ], 57 | "language": "python", 58 | "metadata": {}, 59 | "outputs": [], 60 | "prompt_number": 1 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "metadata": {}, 65 | "source": [ 66 | "#### 2. Run PCA #\n", 67 | "\n", 68 | "Scikit-learn has a PCA module, but instead I'm using statsmodels's ``pcasvd`` function in order to make a biplot." 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "collapsed": false, 74 | "input": [ 75 | "# code taken from http://okomestudio.net/biboroku/?p=2292\n", 76 | "\n", 77 | "import matplotlib.pyplot as plt\n", 78 | "import numpy as np\n", 79 | "import pandas as pd\n", 80 | "\n", 81 | "\n", 82 | "def biplot(plt, pca, labels=None, colors=None,\n", 83 | " xpc=1, ypc=2, scale=1):\n", 84 | " \"\"\"Generate biplot from the result of pcasvd of statsmodels.\n", 85 | "\n", 86 | " Parameters\n", 87 | " ----------\n", 88 | " plt : object\n", 89 | " An existing pyplot module reference.\n", 90 | "\n", 91 | " pca : tuple\n", 92 | " The result from statsmodels.sandbox.tools.tools_pca.pcasvd.\n", 93 | "\n", 94 | " labels : array_like, optional\n", 95 | " Labels for each observation.\n", 96 | "\n", 97 | " colors : array_like, optional\n", 98 | " Colors for each observation.\n", 99 | "\n", 100 | " xpc, ypc : int, optional\n", 101 | " The principal component number for x- and y-axis. Defaults to\n", 102 | " (xpc, ypc) = (1, 2).\n", 103 | "\n", 104 | " scale : float\n", 105 | " The variables are scaled by lambda ** scale, where lambda =\n", 106 | " singular value = sqrt(eigenvalue), and the observations are\n", 107 | " scaled by lambda ** (1 - scale). Must be in [0, 1].\n", 108 | "\n", 109 | " Returns\n", 110 | " -------\n", 111 | " None.\n", 112 | "\n", 113 | " \"\"\"\n", 114 | " xpc, ypc = (xpc - 1, ypc - 1)\n", 115 | " xreduced, factors, evals, evecs = pca\n", 116 | " singvals = np.sqrt(evals)\n", 117 | " \n", 118 | " # data\n", 119 | " xs = factors[:, xpc] * singvals[xpc]**(1. - scale)\n", 120 | " ys = factors[:, ypc] * singvals[ypc]**(1. - scale)\n", 121 | " \n", 122 | " colors = 'k' if colors is None else colors\n", 123 | " plt.scatter(xs, ys, c=colors, marker='o', alpha=0.4)\n", 124 | " \n", 125 | " # variables\n", 126 | " tvars = np.dot(np.eye(factors.shape[0], factors.shape[1]),\n", 127 | " evecs) * singvals**scale\n", 128 | " \n", 129 | " for i, col in enumerate(xreduced.columns.values):\n", 130 | " x, y = tvars[i][xpc], tvars[i][ypc]\n", 131 | " plt.arrow(0, 0, x, y, color='r',\n", 132 | " width=0.002, head_width=0.05)\n", 133 | " plt.text(x* 1.4, y * 1.4, col, color='r', ha='center', va='center')\n", 134 | " \n", 135 | " plt.title('Principal Component Analysis with biplot')\n", 136 | " plt.xlabel('PC{}'.format(xpc + 1))\n", 137 | " plt.ylabel('PC{}'.format(ypc + 1))\n", 138 | " \n", 139 | " return xs, ys " 140 | ], 141 | "language": "python", 142 | "metadata": {}, 143 | "outputs": [], 144 | "prompt_number": 2 145 | }, 146 | { 147 | "cell_type": "code", 148 | "collapsed": false, 149 | "input": [ 150 | "columns = ['elongatedness', 'weight', 'sweetness', 'acidity', 'color_id']\n", 151 | "\n", 152 | "data = df[columns]\n", 153 | "classes = df['fruit_id']\n", 154 | "data = (data - data.mean()) / data.std() # pca data must be normalized\n", 155 | "pca = pcasvd(data, keepdim=0, demean=False)\n", 156 | "\n", 157 | "colors = [['#e09028', '#55aa33', '#cc3333'][i-1] for i in classes]\n", 158 | "\n", 159 | "plt.figure(1)\n", 160 | "xs, ys = biplot(plt, pca, labels=classes, colors=colors,\n", 161 | " xpc=1, ypc=2)\n", 162 | "plt.show()" 163 | ], 164 | "language": "python", 165 | "metadata": {}, 166 | "outputs": [ 167 | { 168 | "metadata": {}, 169 | "output_type": "display_data", 170 | "png": "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\nxOvAyXsT0thUXFxMXV0dgYGBdw4jdFFaWsrmbW/hH2PC6XBx/NwRvrTxy/1+A5BS8tG2D7luLyQs\nJpgzpVcoryzlmSee6xxnramp4fM9GVTXVRETMZ6Vj6we0hrqw62+vh6Xy0VQUNDA5jxqayEkRPv+\niy+0wnhodeXXbNrE5x98QG5tLVFeXsxfuBCdXk+D3d5ZfKy8vJympiZCQ0MJuXEe0Nb0f/CBNgz0\nD/+g1TcKDNRKVZw5o5VpGMHsdjsGncRs0hKvXq/Dx2LAbr+79ow3pKenU5iXzedHLmM26cm+1kCQ\nr5WiU1VcK6+huLSSrz7zMNYKG0cOv8fVgny+8o3v3PIG4HK5qKmpQQhBaGjogOYKwsPDWbNmDenp\n6Vy8cAoQPLJh9pj5BN3bhO9ZKeWMnm7fC2NlzH/rRx+y7+wX+Ef44KsL4MEpS3ho0cPdHvvuh+/g\nDG0kKlZbbXL5fAHTIhawsMvqCCklbW1tmEymO0rT1tXV8bst/8WMR9JujAtydncOX37q64SEhNDe\n3s7v3vp/+CYaCQwN4GpuIb62UL7yZ18b0B9WYWEhew7upLW9lclJ6Sx+aMmwl8l1u918sX075Rcu\nYBACc1QU6557rn9NOQ4cuFmeubJSqzrajZycHA5v3UqU0Ui93U7g5MmsXr+eQ5mZXDl8mGCTiSqH\ng4VPPMHEtF5qz7/1ltZz4YajR7WSDSOQlJIt7/yeaFMNKfFRlFXWcKFc8tyXvjHoCXeXy0VpaSl2\nu53dn25m7YI4/H29uXLlChm79jMpOY4on3ZMRgMfHKlg3soXWbvhGYTQGq5s+/BdnI2luNwS38hk\nHlv39KCW+94vBjXmD0wVQjTd+ALSu9xuHNpQx66TJ0/yh23/g/9UgTu0mVafWg6e3UdjY/e/Yruj\nHYvXzT84k8WEw3HzCqyhoYE33vlffvn7f+Pnv/kZl3Iu3XGO299QJTcrGlqtVhwmG94BFo6dOUSl\nvZgdhz7lxMnj/X5NVVVVvP/5ZvxSDCQ8EM75suPsP7iv7wcOUnZ2Nk0XLvDYxImsTksjuKaGQ3v7\nMU31/e9riX/cOG2svofED5CWlsaGr32N+DVrWPD886xevx6r1Ur+oUOsSElhflISS+PiyPzkE1w3\neht056WXtCGmAwe02/PnaxPCN9pmjiBCCB7bsJF6UzwZpyq41hLM40+9NCQrrfR6PXFxccTExGAy\nCPx9td3ZXl4WdNJFc30VE2LDkUJPWlIsdWWXO/82jh05SLCo5LGFqaxdlIqx6Qpnz5wadExjRY9v\nkVLK+7+bwQiw9/AuwhKCiYzVEk7Z1QocrY09ViycOnE6u05tRzddh8PuoLawiZR1N8szfLJjK+7Q\nVmYvmExLUyvb9m0lPCyc0FBt52xgYCCJEalcPJFHWEwQ1rI6EsKSOsesTSYT7a0OTl04QUicL0aj\nieqoJvYc/YKJqWn92kFbWlqKT5SJkHDtnMnT4sk+lsXSYV7FUVtVxTh//86hnvFhYZy7fnNFcm1t\nLQ0NDQQFBRFYUKAN8TzwgDYxO4AuXyEhIbcM67S2tuJnNGLsuOL08/ZG73TS3t7ed6mJRYu0N4GC\nAq0HwsaN2tc//ZMW0whZIeTj48Pj6wddz7FHXl5e+ARHczG/hElJMaA3U27zpamkEX/fcsobJMsW\nL+LIperOx9TXVDApQtuLKoRgXJg/VdZ+1FFSANXA3eN0Bh3eBh8qCq04HS7qqxoxOi0EdteAA5g+\nbQbLZq6mPrcde7GBp1feLHDldrsprSohLlkbs/Tx88Y71ITVau18vBCC9Y9tYG7Cw3jVhzI77iE2\nPP5k55V/WFgYqdGTuXKmGGtJA/nHSpg5azrewRYaGhr69ZqMRiMO283yva0tbXib+1FvZ5CCw8Mp\na2zE3bHEsthqJaSjhvy506f58L//mzNbtvDhL3+J4/HHITFRS/yHDg2qvWNoaCj1QFV9PQD5ZWV4\nh4UNrAdsUpJWFK6mRisR8Q//oK0Qev55GOTY+kjicrl67O61et0zlLWH8s7uXI4VOnn1H/+D2OmP\nUeEIZsb06eQVVxM6Pq1z13BoeAxXy6xIKXG73RRdryc0YnSvz7+X+lzn70ljYcx/b+ZujuTso7bZ\nSlVlNTQb+fH3/5X4u5wE/PX//orwdB+Cw4JwOV2cz8xl0+qXBzSJ5XQ6ee1f/h7f8UZiE6PxC/Aj\n9/A1vrrpW/268rfb7bzz/h+pF5WYvI20XLfzzKrn7/o19Zfb7WZnRgZl58+jB7zGjWPtxo04nU7e\n/dWveDQxEW+zGeMbb+CfkYFOSm2yNTsbBlnmoqSkhF0ffoitoYGQ2FhWPvFEj2/g/WK3w5e/DG+/\nrd2ePl3bRBYcPKg4PSk7O4sjez5FJ10EhMWwat0z3S4k6NpRy+FwcPrkcWqtFYSGj2Pm7DmdY/oO\nh4OMTz+kvjwfKSWRidNYseqxMdGCsS9DssnLk8ZC8ne5XBw9doTcq5fw9vJhyYPLiIqKuuvzlZSU\nsGX7Oxj8BG0tdmanzL+rEg9lZWVs2fYuboMDd7tk9ZJ1TJ7U/x4+drudvLw87HY7sbGxhIWFDTiG\nAXntNa2uzquv3rHap6Kigr1vvMHy1FT0164R9Nd/TWNwMIa/+Rt8/vzPtVU3N/zP/2hNX1588dbz\nX7sGjz9+s7ZPD1wu19AmHym11UF///fabYtFi6G1VYvz9mY3I1RlZSWfbfkNj85NwNfbwoXLRVTL\ncax/enClxKWUNDU1IYRQRd+6UMl/jGpubsZqteLl5TWoPqd2u53GxkZ8fHwGNoThCT/6kdbK8dVX\n7/hRW1sbf/zVr5gfEsL47Gyu+/tzxM+PF//iL/q/MqSfyX9YvfeeNh9wg8Wi9QuYcU8X4d2VrKws\nKi9kMG9qIgAul5s/7cvna9/7ew9Hdn8a7GofZZTy9fUlPj5+0A2uTSYToaGhnk38b72lTYROn64t\njSwqgqVLtfseeUTrY3u7c+e0idxp0+CJJ7C0tbFq0yZC/vmfKTp+nOA33uDJlpbuE/9rr2mVOgFO\nn7753P/933cc2tTUxOnTp7X6Nh3j/cPq2We1TwJ/19Fmo61NWyU0wFK+nuDr64u10Y7Lpc3HXK+u\nxS8gpI9HKcNJJX9l5Lp4URvy2LdPS+i/+AV861vw8stat6znn4fvfOfm8TdWxrz0klZP5/x5SE+H\nH/2ImJgYIsePZ+LUqYQWFeH/j//Y/XN2bXX48svwX/+lPfdtGhoaeP93v6Nq925q9+7l/d/+lurq\n6juOGxZPPQW//S1873vaaqG/+ivYufPePPddio+PJyRxFtsPXWbfqSscy2tm6aoNng5rTFO7Ifrg\ncrnIysrCWmclPCSc9PT0Ya84OFo4HA4OHTlAYWkhQf7BLH1o2aCaqdxh71545hmaTSYOb9tGQ1UV\n6w8ehC1btI5aL7wAf/M3tz6msREaGrSkCNqnhaefBrSyLcbnn+/f8smGBu1rYcfmuRdf1EoydDh3\n8iTxQHpH/wGf0lJOHT7MqntRxXPmTO2rq96GR7/yFfjLv4TeNp196UvasNaTT956f1GRNrT03HN3\nHS5owxDLH13D9akzaWtrIzw83KO9JBR15d8rKSWf7viEPVkZFDkusfPsNj7f9VnfDxwBLl26xEfb\nP2Tnni8GPSRRUlLC8RPHyc7OvmXjUsYX2zlffoKAVAM1hhLe/uAt2traBhv6TULgcjr5+O23MeTl\nka7TIZ1OPtu6tf/nuD0p3m3Cue087W1t+JhMN09rsWDvYQnjPdHbG9rvftd74u/t8YWFsHnz3cd1\nm6ioKK2ujkr8HqeSfy9qa2vJK7/E1AUTiUuKIX1BCufzT9PU1OTp0Hp1+swpth/+gGa/Kq61XeKt\nLb+nubn5rs51/sI5Nme8yZmKg+w89wkffPweLpcLh8NBztVsJs1JJiDYn/jUWOymZq5fH3Sbh5uW\nLsW9ZQuWsjKmJiQQptNBWhp+H31ES0sLvPOO1j4RtOQspVZ7PyhIW7sP8Mc/wkBbf0qpFV0LDITD\nh7X73nnnlkMSJ07kUm0t1oYG6pqayKqoYMKUKd2cbAj97Gfwn/+pff+978Gyjm5Xe/dqn4J27dJa\nSc6aBc88o+0bAO31n+5oyfH665CaCvPmaZ8Ivv3tm+c/cAAefBAmTIAPP9Tu+/734eBBbVL5l78c\nlpfldrs5d/YMn2d8zJFDB3rc4KgMLZX8e+FyuTAYdJ3DPHq9Hp1edG4iGqmOnT1CypwEomIjSEyL\nQwQ5uHLlzlK5fZFSsvPAZ0x6MJHkKYlMXZBGSWMhJSUl6HQ6dELgdNz8JOB2uod2meOkSbR897ss\n++1vCXz1VXzeeov6V14h5cwZvObP1xLyjYTUdaz+D3/QyihPmwYXLmgbpgbixnneeEOr7HljNU2X\nq+OkpCTmPvkkZ9raON7czOTVq5mSnj7IF9yHhx7SEjFovQZaWrRG8gcPwtSp8OMfw+7dWqKfNQt+\n/vObcQsB5eXaMcePa29qly/ffE1SQkWFdv/27VrSB/jXf9WG0M6ehe8OT1HfzL27uHpqG9G6Elqu\nHeKT99/B6XT2/UBlUNSYfy9CQkIItkSQn1VIWHQwlSVWxgXH9dmX1NOkHJo3J7fbjdPtxHxLLSED\nDocDvV7Pg7MWc+TwPkJi/WmqbSXSZ/ygOyC5XC6Ki4txOp1ER0cT8O1v80lEBO6CAiL9/CiuqSH8\nN78hpqPiZqeuE7jTpmmF0m63rx/1hbqeZ+bMWyd7//Vfbzl08uTJTJ7c/70PgzZzppbYm5q0ZZ6z\nZ2tvAocOwdq1cOmSduUO2iaxBQtuPlZKOHFCq2F0Y/PZ009DXp72vRA3u46lpWnF7W48rhctLS3U\n1NTg4+NzayXTfrLb7RRkH+Pph1MwGPQkxETw+dE8rl+/TmxsbN8nUO6aSv690Ov1PLvhOTIP7qWq\noJLk8Kk89ODDI37Cd/7Mhew5uYPo1HBszW2464wkJiYO+Dx6vZ60xCnknskjfmIMDbUNuBp0nZvQ\nFi5YSFhIGGXXS/BPCWTa1GmDuvJ3OBx8/Kc/4SwuxmIwcMBoZN1LL/HYk09y4fx56mtqmBIdPaCE\n29bWhtlsHvH/Zv1iNEJCArz5ppbYp07VhnwKCrT7ly/vfXz+9t/B7Ym9yxxGX0kftDLkuz99hyBv\nSUOLi4kzl/DAAOv6SylBcsu/j04MTwMX5VYq+ffB29ub1Y8+5ukwBmTWzNmYzRbyruYSavFm3tPz\n73r346rlq9l3wMyVkwUE+AayacOTt2zJT01NJTU1tZcz9N/FixcxlJSwuGNy8sr16xzavZv1Gzcy\nc4AN0Wtra9mxZQst1dUIi4XlTz1FQkLCzQP++Z/h/fdvfdAzz9xcQz9SLVoE//Zv2pDUlCna2P+c\nOdq+hm9+E65c0cbsW1q0YZ6O1UgIoR33F38B9fXahrgPP9Q+JfXGz0/7pHEbKSW7M95n8ZRQwkIC\nsDucbD+8h4Sk5AHtLzGbzcSlzuTg6XMkjw+lsqaRdmPYoHa5K/2jkv99asrkKUyZPPgJSLPZzMrl\nq4cgor61NjURZLF03g7x8+PK7S0S+0FKScZ775HicpE4eTI1jY3s/tOf2Pitb918E/zBD7Sv0WbR\nIu2Na/588PLSvhYtgtBQ7RPBc8/BjQnTn/zkZvIHiI7WXvPcuVqNoIkTb+0m1vWTwY3vp00DvV7b\n6Pbyy53j/na7HVd7M2Eh2tCMyWggxM9IU1PTgDcXPvLoak6dCCGv/Bp+YRNYP3+h6ix3D6jkr4wY\nUTEx7N+3j4T2dixGI5fKyhjX0UD9dlVVVZ3lmW+Uq77BZrNhs1pJ7BgeCvH3J6iykpqamtFf/2Xp\n0pvJHbRJ2xuWLNHG9W/Xda5j0yZtlY/TCU88ARs6Nlq98catj7nRT8Jg0ArK3cZsNuPtH86V4gom\njI+koamV6iY3D97FuL9er2fe/AXAgj6PHQ5SSnJzc6mrsRISFk5KSsr9MUzYB5X8FaSUFBYWYrPZ\niIyMvKuJu6GQkJBA3erV7Ni5E+lyEZ+ezoM3umt1cfrECc598QUhJhNWu505jz3GtC71bcxmM5hM\n1Dc3E+jri93hoMFu9+jacpvNxr4vvqC8oADfoCAWr1lDZGTkvQ/ktde0FUFtbfDoo7Bu3V2fauW6\nZ9jx8bucvXoZFwYWLn+q+17GI9yuzzNoLDnNuBBvzme3UlY6n6XLVvT9wFFOFXYb47Sevlu5WpOD\nxc9Ea5WDp1Y+d1cTxEMZk9vd/bLRpqYm3v3FL1iVnIzFZKKlrY2dhYW8+Jd/eUsNovz8fPZ/8AHB\nOh31djsTFy9mwY1dvx7w0ebNeJWWMik2luqGBs41N7Px618f9ZudpJS0tLRgsVhGZfvEuro6Pnn7\nV6xflIper8PpdPHRgXyefuV7o/pTYn8Ku42+fy1lSBUWFnK1JpdpD2k9fetrGtix51O+lfgXHotJ\nCNHjqqHW1lZ8DAYsHStTfCwWzEJgs9luSf7JycmEf+Mb1NTU4OvrS3gvrRmHm8PhoOLKFZ6cNAkh\nBOPDwylqaKCiooIJEyZ4LK6hIITotib/aOFwODAb9ej12pYng0GP0SDGxD4DlfzHuLa2Nsy+xs4x\nTr9AXwpaS29pqDGSBAYG0mYyUV5TQ3RICMVVVbi9vbvdexEQEDC0tYbuksFgAIOBlrY2fL28tKtl\nhwNT16WVyrAoLy8nJ/scQqdjytSZd1wEBAcHIy2hXLhcRFx0GIWlVZgCokfE/5vhpnb4jnGRkZHY\nrE7qrA24XC7yswpJips4IhM/aOP5qzdt4ozNxgcXL5LtcrFm06YRPeQghODBVavYd/UqZwsK2Jeb\nS2Ba2oC6qykDV1JSwhcfvE6ALRefxmy2vfe/VFbe2uPXYDDw+JPPU29KJDOniRbvFB7bsLGzD/T9\nTI35KxQWFpKx+xOaW5tIjk9j9Yo1I795C9pH9sEuCZRSUlNTg9vtJiQkZMjKU+Tn53O9tBTfgADS\n09MxGo2UlZVRVVWFt7c3ycnJYyLBeFLGJ+8TY7xOYqw2sZ5TUEKz7ySWLl/l4ciGnxrzV/olISGB\nb33Fc2P8d2uwid/lcpGxdSu1ly+jEwJTVBTrnntu0G98J44eJXfXLhL8/SlqbeXKxYs8sWkT48aN\nG3T5C6X/pFui7/IGq9frRnxdrnvJI5ceQoinhRAXhRAuIcTMvh+h3O8cDgdFRUVcu3YNh8NxT57z\n3JkzOPPzWZ2Wxqq0NIJqajhy4MCgzul2uzm9Zw9LUlKYOH48CydOxFFcTGlp6RBFrfRX2tRZnM6v\noaisiqslFVy41kTalOmeDmvE8NSVfxawAfgfDz2/MoLYbDY+evtt9FYrAnAEB7PhxRfx9va+NQZF\nowAAGVlJREFUq/O1traye/t2SvPy8A4IYMnatcTFxd1xXF11NdH+/p3zG+OCg8mtqBjMS9GuLKXE\n1GUOwqzXj4nVIyPNhAkTYPULXDp/EqHTsWz9evXJqwuPXPlLKXOllHmeeG5l5Dl59CjB9fUsTU1l\nSWoqYY2NnDhy5K7Pt/OTT7AUFfFEaipzfHzYtXlztw1tQqOiKGnQJrqllBRZrYR1JAcp5V3VlTcY\nDMSlp3MsP5/apiYul5bSaLEQHR19169HuXsTJkzg8Sc28tj6Zxg/frynwxlR1Ji/4nHNdXVEdNlQ\nE+bvT2lt7V2dy+12U5afz9OTJyOEIDwwkAirlYqKCgwGA62trQQGBmIymZg6bRoVpaVsO38eHRCU\nmMgjixZRVFTErg8+wNnSgndoKGuefXZAu56Xr1nDEV9fzly9il90NOuXLRsVE+jK2DJsyV8IsQvo\nbv/6D6SU2/p7ntdee63z+8WLF7N4oF2ZlBEvMi6O/JwcojsSbIHVSsL0uxub1el0mH18qG9uJsjP\nDykljXY7V/LyOPDhh3jrdLSbzazZtInIyEhWPv44TYsX43a78ff3p7W1lZ3vvsuDERGEJSRQWFHB\n9nff5aVvfvPGCgqampoQQvS4A9RoNPLwI4/ccp/NZqOyshKz2UxkZOSIXUqrjE6ZmZlkZmYO6DEe\nXeophNgHvCqlPNPDz9VSzzHA7XaTuXs3l48fByBl7lyWLF9+10sh8/Pz2b9lCxEGAxcLCrjW2Iix\ntZUXly4lIS6OMquVs21tvPyd7wDaZPPxI0eoLCqize2GkhJWdBSFK6yo4IMTJ1jx3HPMnDOHAzt3\nYs3PRwpBzNSpPPrYY33GWV1dzad//CP+djs2p5PQ9HRWrV2r3gCUYTNalnqqv4AxTqfTsXTFCh5a\nuhQpJTabjV0ZGTTV1hKdmMi8BQsGtP4+OTmZoK9+lc937MC3qopnJ07k6pkzlGdlEeDnx7jQUI5e\nvIjdbsdkMrFz+3bsOTmkRkSQV1bGgbNnWThhAtcqKzlz7BgxgOPcOX6ekcGs8HDWTpqElJKDWVmc\ni45m5uzZvcazLyODdIuFhPh43G43ey9cID8tjZSUlEH+5hTl7nlqqecGIUQJ8ACQIYT4zBNxKCOL\nwWDA7Xbz0VtvYS4oIK6xkeytW9n85psD7uwUGhqKzmZj+dSpRIWE0CIEfno9tTU1lFZX49Ux7m+z\n2SjNzmZBSgoRQUEsmjKFkIgIPjp3jm0HDhBiMrF08WJmJyejq6rCB+2qSqfTERsYiLUfq4MarVYi\nO6pd6nQ6Qi0Wmpub7+ZXpChDxlOrfT6SUsZKKb2klJFSyvt/y53SL+Xl5Xg3NRHm5UXp+fMkNDdz\ndMsWtm/dOuA3AIuPD40tLYT4+5M+fTo7Sks5WFrKudZWVj3zDKAlYzfg7nLuhNhYlr7wAhGTJzP7\noYc6m5P4+vpyvWPVkJSS8sZGgm7rJdCdyIQELpeVAdDa3k6pzUZYWNiAXouiDLWRMOyjKJ10Oh0u\nIO/8eZKDgjAajSS2tlJ38SLFs2d3u16/JwseeYRtb75JdXMz7S4Xk1av5tENG4iIiOjcHWw2m5n4\nwAPsP36c+MBAqpqaMI8fz+TJk2lZtYpze/YwVaejsaUF38REZGAgn+Xk4JaSwKQkZvQx5AOwdNUq\nMj78kK3Z2bj1euatWqWakysep2r7KCOK0+nk/T/8gctbt7Jw/HgKm5qITk3FZTaTum7dgPsF19fX\nU1xcjF6vJykpSWv0chspJVkXLlBVVoZ/UBAzZs/GaDQipeTsqVMU5uZi8fFh7qJFBAcHY7VateGb\n0NABTdrabDaMRuOILkKn3B/6M+Grkr8y4rS3t/PLn/4UfWkpsydNIsTfn2NVVTz19a8TGBjo6fB6\n1dDQ0NkuUg3tKJ6ikr8yaFJKThw9yvlDhwCYtnAhc+fPH5ZlioWFhVRVVuIfEEBsbCx7tm+nLD8f\nL39/lq5fP6AhH0/Iz88n8/33te5hDgeTly3jgQWe6UurjG2jZamnMoJlZ2WRv3s3K5KSADi0ezde\n3t5MvctNWD05eewYl3btItbLi2ttbVyZNIm1zz4LMORvNA0NDezdsYOasjKCo6NZtmbNoJt3uFwu\n9m3dypKYmM6+wZ/v3UtyaqrHeiIrSm9UQXGlVyX5+aSFh+NjseBjsTApPJySgoIhfQ6Hw8Gp3btZ\nmpxMemIiS9LSqL14kevXrw848be2ttLQ0NDjyiCXy8W2d98ltKqKFePGEW618sk77wy68FpbWxvC\n4SCwo6WhyWjE32hUSzqVEUtd+Su98vL3p6GoqPN2fWsrliFubO10OtFJ2dmXVwiBxWgccGnng/v2\ncenQIYw6Hd5RUTz+7LN3NEivr6/HXVvLxIkTAUiNieFqbi51dXWDGqP39vbGFBREYUUFCZGR1DQ2\nUu92ExwcfNfnVJThpK78lV7NfuABio1GjuTlcSQvjyK9njnz5w/pc3h5eRE2YQKnr1yh2WajoLyc\nFrO5c319fxQUFFB06BCPp6byeFoaYXV17N+5847jTCYT7W43jo4rfYfTSbvbPeh+ukIIHtu4kVxg\n68WLHKiu5pGNG3us/6MonqYmfJU+2Ww2CgsLAYiPj7/rOvt9Pcf+XbuouHYN/5AQHl65ckBj5ceP\nHqXl8GHSExMBaLbZ2F9Tw5c66vd0dXDfPq4dOkSUlxfXbTbiFizgoWXLhuR13CgFbTabVe0exWPU\nhK8yJLy8vJg0adKwP8fKtWvv+vEBQUEUtrXhdrvR6XSUWq0ER3ZXVBYWLVnCuLg46urqSAwKIrHj\nDWMoCCGwWCxDdj5FGS7qyl+5L0gp+WL7dsrPn8ei1+MMCGDd888PehWPooxGap2/MuZYrVYcDgeh\noaGDbvA+HEpKSrh6+TImi4X06dPx7VgdpChDSSV/RRlBLl++zKEtW0jx88Nmt1Pu5cXTr7xyx4ok\nRRksNeavjEkul4sL585RU1lJcHg402bMGFA/gOFyOjOTB8aNI7yjRIUjP5+8vDymTJkCMCI/qSj3\nL5X8lfvOzowMWrKyiAkIoPDsWcqKinjsiSc8vvrG6XRi6tLL1yAERw8e5Nj27cDgO5gpykCo5K/c\nVxoaGig7f57H09LQ6XQkRkWxPSeHurq6XjdctbS0kJOTg9NuJ2HChAHtMeivtFmzOLlrF9PGjaOl\nrY1jxcXE+PuzZsYMJHDo1CnOBgUxa+7cIX9uRbmdSv7KfcXtdqPr6LQF2tinXghcLlePj2lpaeH9\n3/+e8NZWLHo92zIzWf7883ddSM5ut9PS0oKvr+8tQzmz581Dr9dzKTsbY3AwidOmMdnl6hySmhAS\nwvXiYlDJX7kHVPJX7gvl5eWcP34cl9NJm7c3JwsKGB8SQmlNDTVA9tmzBIWHk56efsf4/6WLF4lo\nbWV2cjIAQdXVnMjMJO7P/qzP53U6nRzOzKTo8mV8/P2JTkoia/9+TC4XTrOZlRs3EhMTA2hvRDPn\nzGHmnDkAHNi7l+rTp4kNDweguqkJP9XXV7lH1OCiMupVVlaS8eabBJWVEWm1oq+vpy48nFyDgUsu\nFyHt7RhzcijIyGDHxx/fUfTNabdj6XKF7mU242xr69dz79u1i9oTJ1jg709UTQ1/+PGPmR0YyJq0\nNB4ICuLz997rsWjcnPnzqQkMZM/ly+y5fJmawMAhL52hKD1RV/7KqJeTlUWqtzcToqMB0Ot0FJlM\nLF+3jnd+/nNWpKdj0OtJkZIdOTlYrdZbirjFT5jA9sxMgmtqsJhMnCkuJuXRR/v13AVnz7IuKQmj\nwQAOBwlGIy0dbxwRQUHoKytpbm7utgmNl5cXT3/pS5SXlwMQHR2tVvwo94y68ldGPQG3XM3f+N7l\ncqEXAkPHMI8QAqNOd8eVeFRUFMtfeIE8g4HTNhvJK1b0e9LVZDbT2t4OgNliodHhwN5x/tqmJhx6\nfa/r+I1GI3FxccTFxanEr9xTapOXMupVV1fz8euvM9FiwWgwkF1Xx7IXXiA+Pp6tmzfjVVZGYng4\nZTU1VPj68uyXvzxkfXSzs7I48dFHxPv40NjezlWXCy8g0GikGVj2zDNDWjtIUfpD7fBVxoyqqiou\nnD6N2+Vi4tSpjB8/HtCarBzev5/qkhICw8NZuHQpvr6+OBwOsrKyaG1uZlxsLAkJCXf93CUlJZQV\nF+Pl68ukSZNob2+nqamJgICAYamAqih9UclfUbrhdDr58O23MZeXE+TlRWFTE9PWrGHGrFmeDk1R\nhoQq76AoXbS3t2MymSgqKkKUl/NgRzevuLY2Pt+5UyV/ZUxRyV+571VXV7NjyxZstbWY/PxImjkT\nU5cSChajEelyIaX0eAkIRblXVPJX7mtOp5Ptmzcz1Wxm/OTJVNbVsf/gQfQGA1euXyfEz4/ssjIS\np09XiV8ZU9RST+W+1tTUhGhpYXzHLtqIoCCC9XoWrllDRUgIJ1paCJk7l2UrV3o4UkW5tzxy5S+E\n+BnwGGAHrgAvSykbPBGLcn/z9vamXUqabTZ8vbxos9tpdjoZP358ZyllT2tvb+fq1au43W7i4uJU\ngxflnvDIah8hxHJgj5TSLYT4KYCU8vvdHKdW+yiDln3hAkc//ZRQk4lau51py5cze948T4cFQGtr\nKx+8+Sb+jY3ohaDKYGDDyy/3WoFUUfoyKpZ6CiE2AE9KKV/o5mcq+StDoqamhrq6OgICAm4p7eBp\nhw8epOnoUWYlJQFwubSUxpgYVj/xhIcjU0az0bLU8xXgXU8HodzfQkJCCAkJ8XQYd2hrbiagS4OX\nQB8fKpubPRiRMlYM24SvEGKXECKrm6/HuxzzQ8Aupdw8XHEoykgWO2ECefX1NNts2Nrbyb5+nbjU\nVE+HpYwBw3blL6Vc3tvPhRBfAlYDy3o77rXXXuv8fvHixSxevHjwwSnKCJGSkkLzqlXs2b8ft9NJ\n2sKFnfX+FaW/MjMzyczMHNBjPDXhuxL4d+BhKaW1l+PUmL8y5rlcLs6eOkV1eTkBYWHMnjsXk8nk\n6bCUEWzETvgKIfIBE1DbcddRKeU3ujlOJX9lzPvs009pzcoiLjiY6w0NtMfE8MSmTT02eq+pqeFK\nQQE6vZ60tLReS0or96cRO+ErpUz2xPMqymjT0tJCyfnzrOtoSB8XEcFnOTlUV1d322T++vXrZPzh\nD8Tp9TjcbrIOHeKpL38ZPz8/D0SvjGRqh6+ijGA36g11LT1xe/Oark4cOMBUf3+mT5jAnORkYhwO\nss6du0fRKqPJSFjqqShKD3x9fYmaNInDly+TEBJCeX095piYHvcq2G02vM3mztteJhP2jk5jitKV\nSv7KmFBbW8vVq1cxGAykpKSMqiYrK9eu5eTx4xSXlhKYlMSyBx9E39Ga8nZJ6emcy8hgrsGA3enk\ncmMjy1NS7nHEymjg8R2+vVETvspQqKioYNubbxKn02GXEqu3N0+/8sqgJkKLi4spKy7G4uPD5MmT\n7/nqm4sXL3LhyBEAps6fz+SOOkVSSk6fOEHu6dPojUZmPfwwKSr5jzkjdrVPf6nkrwyFT957j6ia\nGhIiIwE4U1CA/4IFzF+4sPMYu91OfX09Xl5efU6OZmdlceLjj0nw8aGhrY22yEiefPHFe9aAPS8v\njyN/+hNzYmIAOFlayoKNG1WSVzqN2NU+inIv2Vta8LFYOm97m0zY29o6b1dUVJCxeTPm9nZaXS5m\nrVjBrLlzezzfsZ07WRIfj3/HJ4fM3FwKCwvvWfK9kp3N5NBQwgMDAZjS3s6V7GyV/JUBUat9lPte\n4pQpnC8tpbGlheqGBvKbmohPvrna+PP332eWry+PpqaycsIEzn3xBVVVVT2ez9HWhleXSVWLwYDD\n4RjW19CVwWymrcvz2ex2DF3iUZT+UMlfue/NnDOHpOXLOVRfz5m2NhY8/TRxcXEAOBwObPX1jAsN\nBcDLbCbUbKa+vr7H8yXNnMmx/HwaWloorKigAoiNjb0XLwWAGfPmkdvezvmrVzl/9Sq57e3MGCEl\nqpXRQ435K2PeH/7rv5ii1zM+PJzW9nZ2X7nC2q9+lbCwMJxOJ4cyM7ly4QImi4UHV65k/PjxHNm/\nn+LLl/Hy82PhihXdbrgaTnV1deTl5gKQMnEiQUFB9/T5lZFNTfgqSj9UVVWRsXkz+tZW2qRk7sqV\nTJ81C4D9u3djPX6cWQkJtLS1caS8nLVf+co9T/aKMhBqwldR+iE8PJwXvvlNGhsb8fLyumUPwNXs\nbBbHx+NjseBjsZBQW0tJSYlK/sqop8b8FQUwGo2EhITcsfnL4uNDU2tr5+0mux2zmlxV7gPqyl9R\nerFgxQp2vv024+vqaHE6aY+IIFU1W1HuA2rMX1H6YLVaKSkpwWQykZKScs82cynK3VITvoqiKGNQ\nf5K/GvNXFEUZg1TyVxRFGYNU8lcURRmDVPJXFEUZg9RST0UZIa5cucLpzEwcdjsTZ81i5pw5t7Rv\nVJShpK78FWUEKC0tZd/mzaRJyWxvb3I+/5xzZ854OizlPqaSv6KMAFfz8kjx8yMyOJhgPz9mxMRQ\ncP68p8NS7mMq+SvKCGA0mWiz2ztv29rbMXZpQKMoQ00lf0UZAaZMm0aZycSpvDwuXL3Kufp65jz8\nsKfDUu5jaoevoowQzc3N5Obm4nI4SExKIiwszNMhKaOUKu+gKIoyBqnyDoqiKEq3VPJXFEUZgzyS\n/IUQ/58Q4rwQ4pwQYo8Q4t51v1YURVE8duX/f6WU06SU04GPgX/0UBxDIjMz09Mh9IuKc+iMhhhB\nxTnURkuc/eGR5C+lbOpy0xeweiKOoTJa/kOoOIfOaIgRVJxDbbTE2R8eq+0jhPgJ8CLQCjzgqTgU\nRVHGomG78hdC7BJCZHXz9TiAlPKHUsrxwJvAfwxXHIqiKMqdPL7OXwgxHtghpZzSzc/UIn9FUZS7\n0Nc6f48M+wghkqWU+R031wFnuzuur+AVRVGUu+ORK38hxAdAKuACrgBfl1JW3fNAFEVRxiiPD/so\niqIo996o2OErhHhVCOEWQgR7OpbujJZNa0KInwkhcjpi3SqECPB0TN0RQjwthLgohHAJIWZ6Op7b\nCSFWCiFyhRD5Qoi/9XQ83RFC/F4IUSmEyPJ0LL0RQsQKIfZ1/HtnCyG+4+mYuiOEsAghjnf8jV8S\nQvyLp2PqiRBCL4Q4K4TY1ttxIz75dyTS5UCRp2PpxWjZtLYTmCylnAbkAX/n4Xh6kgVsAA54OpDb\nCSH0wK+BlcAk4DkhRJpno+rWG2gxjnQO4HtSysloS76/ORJ/n1LKNmBJx9/4VGCJEGKhh8PqyXeB\nS0CvwzojPvkDPwf+xtNB9Ga0bFqTUu6SUro7bh4HYjwZT0+klLlSyjxPx9GDuUCBlPKalNIB/Alt\n0cKIIqU8CNR5Oo6+SCkrpJTnOr5vBnKAaM9G1T0pZWvHtyZAD9R6MJxuCSFigNXA/wKjt6qnEGId\nUCqlvODpWPoihPiJEKIY+DPgp56Opx9eAXZ4OohRaBxQ0uV2acd9yiAJIeKBGWgXJiOOEEInhDgH\nVAL7pJSXPB1TN/4D+GvA3deBHtvhe4MQYhcQ2c2Pfog2LLGi6+H3JKhu9BLnD6SU26SUPwR+KIT4\nPto/wMv3NMAOfcXZccwPAbuUcvM9Da6L/sQ5QqkVEsNACOELfAB8t+MTwIjT8al5esdc2RdCiMVS\nykwPh9VJCPEYUCWlPCuEWNzX8R5P/lLK5d3dL4SYAiQA54UQoA1RnBZCzPXEstCe4uzGZjx4Rd1X\nnEKIL6F9LFx2TwLqwQB+nyNNGdB1Qj8W7epfuUtCCCPwIfC2lPJjT8fTFyllgxAiA5gNZHo4nK4W\nAGuFEKsBC+AvhHhLSvlSdweP2GEfKWW2lDJCSpkgpUxA+wObORL3Awghkrvc7HHTmqcJIVaifSRc\n1zGBNRqMtI1+p4BkIUS8EMIEPAt86uGYRi2hXdm9DlySUv7C0/H0RAgRKoQI7PjeC20Ryoj6O5dS\n/kBKGduRLzcCe3tK/DCCk383RvLH7X/pqFt0DlgMvOrheHryn2gT0rs6loL9t6cD6o4QYoMQogRt\n9UeGEOIzT8d0g5TSCXwL+AJtRcV7Usocz0Z1JyHEu8ARIEUIUSKE8MgwZD88CLyAtnrmbMfXSFyl\nFAXs7fgbPw5sk1Lu8XBMfek1Z6pNXoqiKGPQaLryVxRFUYaISv6KoihjkEr+iqIoY5BK/oqiKGOQ\nSv6KoihjkEr+iqIoY5BK/orSjY5y0mc79m9s6djYgxAiUgjxJyFEgRDilBAi48YmPyHE50KIur5K\n6SrKSKCSv6J0r1VKOUNKmQ7Yga913P8R2s7JJCnlbLT6UxEdP/u/wIv3PlRFGTiV/BWlbweBJCHE\nErSCeL+98QMp5QUp5aGO7/cCI7IomaLcTiV/RemFEMIArAIuAFOA056NSFGGhkr+itI9LyHEWeAk\nWhe533s4HkUZUh4v6awoI5RNSjmj6x1CiIvAU308ThXLUkYFdeWvKP3UMaZvFkJ85cZ9Qoipt/Vy\nHWklqBWlWyr5K0r3erqC3wA80rHUMxv4CXAdQAhxENgCLOsoozxaG9YoY4Aq6awoijIGqSt/RVGU\nMUglf0VRlDFIJX9FUZQxSCV/RVGUMUglf0VRlDFIJX9FUZQxSCV/RVGUMUglf0VRlDHo/we2zkjU\nHydRSQAAAABJRU5ErkJggg==\n", 171 | "text": [ 172 | "" 173 | ] 174 | } 175 | ], 176 | "prompt_number": 3 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "metadata": {}, 181 | "source": [ 182 | "#### 3. Do 100 runs of Random Forest Classifier using two principal components and show confusion matrix #" 183 | ] 184 | }, 185 | { 186 | "cell_type": "code", 187 | "collapsed": false, 188 | "input": [ 189 | "df_pca = pd.DataFrame({'PC1': xs,\n", 190 | " 'PC2': ys,\n", 191 | " 'fruit_id': classes})\n", 192 | "df_pca.sort('fruit_id', inplace=True)\n", 193 | "\n", 194 | "# parameters\n", 195 | "# I did not make a function because I wanted to preserve the \n", 196 | "# IPython output of the confusion matrix in the same cell.\n", 197 | "reps=100\n", 198 | "features = ['PC1', 'PC2']\n", 199 | "title_suffix='with two principal components'\n", 200 | "\n", 201 | "import time\n", 202 | "start = time.time()\n", 203 | "for i in range(reps):\n", 204 | " df_pca['is_train'] = np.random.uniform(0, 1, len(df_pca)) <= .75 # randomly assign training and testing set\n", 205 | " train, test = df_pca[df_pca['is_train']==True], df_pca[df_pca['is_train']==False]\n", 206 | " y, _ = pd.factorize(train['fruit_id'])\n", 207 | " clf = RandomForestClassifier(n_jobs=2)\n", 208 | " clf = clf.fit(train[features], y)\n", 209 | " preds = clf.predict(test[features])\n", 210 | " test_result = pd.crosstab(np.array([fruitnames[x] for x in test['fruit_id']]), \n", 211 | " np.array([fruitnames[x+1] for x in preds]), rownames=['actual'], colnames=['predicted'])\n", 212 | " if i == 0:\n", 213 | " final_result = test_result[:]\n", 214 | " else:\n", 215 | " final_result += test_result\n", 216 | "confmatrix = np.array(final_result)\n", 217 | "correct = 0\n", 218 | "for i in range(confmatrix.shape[0]):\n", 219 | " correct += confmatrix[i,i]\n", 220 | "accuracy = correct/confmatrix.sum()\n", 221 | "print('{} runs {}\\nFeatures: {}\\nAccuracy: {}\\ntime: {} sec'.format(reps, title_suffix, features, accuracy, int(time.time()-start)))\n", 222 | "final_result" 223 | ], 224 | "language": "python", 225 | "metadata": {}, 226 | "outputs": [ 227 | { 228 | "output_type": "stream", 229 | "stream": "stdout", 230 | "text": [ 231 | "100 runs with two principal components\n", 232 | "Features: ['PC1', 'PC2']\n", 233 | "Accuracy: 0.9665188470066519\n", 234 | "time: 23 sec\n" 235 | ] 236 | }, 237 | { 238 | "html": [ 239 | "
\n", 240 | "\n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 249 | " \n", 250 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 254 | " \n", 255 | " \n", 256 | " \n", 257 | " \n", 258 | " \n", 259 | " \n", 260 | " \n", 261 | " \n", 262 | " \n", 263 | " \n", 264 | " \n", 265 | " \n", 266 | " \n", 267 | " \n", 268 | " \n", 269 | " \n", 270 | " \n", 271 | " \n", 272 | " \n", 273 | " \n", 274 | " \n", 275 | "
predictedAppleOrangePear
actual
Apple 1146 8 92
Orange 8 1481 1
Pear 42 0 1732
\n", 276 | "
" 277 | ], 278 | "metadata": {}, 279 | "output_type": "pyout", 280 | "prompt_number": 4, 281 | "text": [ 282 | "predicted Apple Orange Pear\n", 283 | "actual \n", 284 | "Apple 1146 8 92\n", 285 | "Orange 8 1481 1\n", 286 | "Pear 42 0 1732" 287 | ] 288 | } 289 | ], 290 | "prompt_number": 4 291 | } 292 | ], 293 | "metadata": {} 294 | } 295 | ] 296 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 David Taylor 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction to Machine Learning 2 | From 2015, a series of Jupyter Notebooks and accompanying slideshow and video 3 | 4 | [Link to accompanying reveal.js slideshow](http://slides.com/prooffreader/intro-to-data-analysis-using-machine-learning#/) 5 | 6 | [Link to PDF version of slideshow](http://dtdata.io/introml/introml-complete.pdf) 7 | 8 | ~~[Link to video presentation](https://www.youtube.com/watch?v=U4IYsLgNgoY)~~ I'm so sorry, my google account was hacked and although I was able to get my gmail and OAuth back, all my youtube videos including this one with > 100,000 views, were permanently erased. 9 | 10 | Jupyter notebooks: 11 | 12 | 1. [The Dataset](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/01_The_Dataset.ipynb) 13 | 2. [Clustering with K-means](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/02_Clustering_KMeans.ipynb) 14 | 3. [Clustering with other algorithms](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/03_Clustering_OtherAlgos.ipynb) 15 | 4. [Classification with k-Nearest Neighbors](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/04_Classification_kNN.ipynb) 16 | 5. [Classification with other algorithms](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/05_Classification_OtherAlgos.ipynb) 17 | 6. [Classification with Decision Trees](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/06_Classification_Decision_Trees.ipynb) 18 | 7. [Classification with Random Forests](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/07_Classification_Random_Forest.ipynb) 19 | 8. [Dimensionality reduction](http://nbviewer.ipython.org/github/Prooffreader/intro_machine_learning/blob/master/08_Dimensionality_Reduction.ipynb) 20 | -------------------------------------------------------------------------------- /fruit.csv: -------------------------------------------------------------------------------- 1 | fruit_id,fruit_name,color_id,color_name,elongatedness,weight,sweetness,acidity 2 | 1,orange,2,brown,0.14,152,3.56,1095 3 | 1,orange,2,brown,0.09,167,3.33,1080 4 | 1,orange,2,brown,0.15,152,4,1035 5 | 1,orange,2,brown,0.03,155,3,680 6 | 1,orange,2,brown,0.08,147,2.69,1020 7 | 1,orange,2,brown,0.14,147,3.55,1045 8 | 1,orange,2,brown,0.14,152,3.33,985 9 | 1,orange,2,brown,0.18,159,2.88,1515 10 | 1,orange,3,green,0.08,152,3.17,1185 11 | 1,orange,4,orange,0.18,174,3.03,1120 12 | 1,orange,4,orange,0.12,162,3.1,1260 13 | 1,orange,4,orange,0.09,186,3.2,830 14 | 1,orange,4,orange,0.18,176,3.38,795 15 | 1,orange,4,orange,0.15,162,2.87,1285 16 | 1,orange,4,orange,0.14,173,2.57,1130 17 | 1,orange,4,orange,0.14,161,3.4,915 18 | 1,orange,4,orange,0.08,170,3.45,1480 19 | 1,orange,4,orange,0.09,177,3.31,970 20 | 1,orange,4,orange,0.09,168,2.85,1450 21 | 1,orange,4,orange,0.19,165,2.87,1095 22 | 1,orange,4,orange,0.02,165,2.78,880 23 | 1,orange,4,orange,0.09,161,3.35,885 24 | 1,orange,4,orange,0.08,153,3.44,1065 25 | 1,orange,4,orange,0.09,153,3.52,770 26 | 1,orange,4,orange,0.08,153,3,1547 27 | 1,orange,4,orange,0.02,146,2.85,1045 28 | 1,orange,4,orange,0.19,150,3.47,920 29 | 1,orange,4,orange,0.22,153,2.84,1270 30 | 1,orange,4,orange,0.1,158,3.17,1510 31 | 1,orange,4,orange,0.1,155,2.75,1060 32 | 1,orange,4,orange,0.09,147,2.51,1105 33 | 1,orange,4,orange,0.15,152,2.71,1285 34 | 1,orange,4,orange,0.16,156,2.87,990 35 | 1,orange,4,orange,0.08,150,3.4,1050 36 | 1,orange,4,orange,0.08,144,3.58,1290 37 | 1,orange,4,orange,0.19,144,3.82,845 38 | 1,orange,4,orange,0.1,143,2.82,1280 39 | 1,orange,4,orange,0.14,141,3.37,1265 40 | 1,orange,4,orange,0.2,135,3,1035 41 | 1,orange,4,orange,0.22,141,2.77,1285 42 | 1,orange,4,orange,0.11,144,3.59,1035 43 | 1,orange,4,orange,0.2,140,3.22,1195 44 | 1,orange,4,orange,0.08,138,2.91,1150 45 | 1,orange,4,orange,0.03,137,2.73,1150 46 | 1,orange,4,orange,0.09,143,3.63,1015 47 | 1,orange,4,orange,0.15,134,2.9,1320 48 | 1,orange,5,red,0.11,182,3.58,1295 49 | 1,orange,5,red,0.15,177,3.2,1060 50 | 1,orange,5,red,0.09,192,3.53,760 51 | 1,orange,5,red,0.15,173,2.93,1375 52 | 1,orange,5,red,0.11,189,3.71,780 53 | 1,orange,5,red,0.15,198,3,1235 54 | 1,orange,5,red,0.09,191,3.92,1065 55 | 1,orange,5,red,0.16,174,3.36,845 56 | 1,orange,5,red,0.14,167,3.26,1190 57 | 1,orange,5,red,0.16,168,2.88,1310 58 | 1,orange,5,red,0.08,180,2.65,1280 59 | 1,orange,5,red,0.08,177,2.93,735 60 | 1,orange,5,red,0.1,162,2.82,1680 61 | 2,pear,1,blue,0.37,132,1.82,520 62 | 2,pear,1,blue,0.39,128,2.31,750 63 | 2,pear,2,brown,0.39,147,3.38,438 64 | 2,pear,2,brown,0.37,147,2.3,678 65 | 2,pear,2,brown,0.37,132,2.78,342 66 | 2,pear,2,brown,0.35,132,2.78,325 67 | 2,pear,2,brown,0.37,129,2.84,352 68 | 2,pear,2,brown,0.35,128,3.57,672 69 | 2,pear,2,brown,0.35,120,2.63,937 70 | 2,pear,2,brown,0.37,123,2.96,345 71 | 2,pear,2,brown,0.43,128,3.28,378 72 | 2,pear,2,brown,0.37,120,3.12,365 73 | 2,pear,2,brown,0.37,117,3.48,510 74 | 2,pear,2,brown,0.39,117,1.67,680 75 | 2,pear,3,green,0.43,146,2.96,710 76 | 2,pear,3,green,0.37,131,2.87,420 77 | 2,pear,3,green,0.49,129,2.44,415 78 | 2,pear,3,green,0.45,129,2.65,450 79 | 2,pear,3,green,0.45,120,2.57,580 80 | 2,pear,3,green,0.49,117,3.18,502 81 | 2,pear,3,green,0.41,120,3.07,718 82 | 2,pear,3,green,0.39,120,1.82,870 83 | 2,pear,3,green,0.39,120,3.17,510 84 | 2,pear,4,orange,0.37,135,3.3,315 85 | 2,pear,4,orange,0.37,132,2.77,660 86 | 2,pear,4,orange,0.43,117,2.72,630 87 | 2,pear,5,red,0.39,132,2.83,406 88 | 2,pear,5,red,0.45,117,3.13,886 89 | 2,pear,6,yellow,0.54,147,2.96,345 90 | 2,pear,6,yellow,0.59,144,3.39,625 91 | 2,pear,6,yellow,0.59,149,3.16,450 92 | 2,pear,6,yellow,0.41,138,3.02,312 93 | 2,pear,6,yellow,0.49,141,2.46,630 94 | 2,pear,6,yellow,0.54,146,2.14,428 95 | 2,pear,6,yellow,0.54,141,3.26,680 96 | 2,pear,6,yellow,0.69,132,2.77,562 97 | 2,pear,6,yellow,0.54,132,3.21,562 98 | 2,pear,6,yellow,0.49,141,3.08,520 99 | 2,pear,6,yellow,0.41,135,2.26,495 100 | 2,pear,6,yellow,0.49,138,2.44,466 101 | 2,pear,6,yellow,0.59,132,2.31,434 102 | 2,pear,6,yellow,0.54,129,3.14,714 103 | 2,pear,6,yellow,0.45,129,3.12,278 104 | 2,pear,6,yellow,0.39,132,3.3,290 105 | 2,pear,6,yellow,0.49,131,2.78,472 106 | 2,pear,6,yellow,0.52,128,2.01,515 107 | 2,pear,6,yellow,0.49,128,2.26,625 108 | 2,pear,6,yellow,0.45,131,3.05,564 109 | 2,pear,6,yellow,0.49,129,3.33,495 110 | 2,pear,6,yellow,0.43,126,3.19,385 111 | 2,pear,6,yellow,0.49,126,2.52,500 112 | 2,pear,6,yellow,0.49,129,3.1,380 113 | 2,pear,6,yellow,0.69,128,2.87,407 114 | 2,pear,6,yellow,0.54,129,2.48,392 115 | 2,pear,6,yellow,0.39,128,2.74,428 116 | 2,pear,6,yellow,0.49,126,1.93,750 117 | 2,pear,6,yellow,0.49,129,3.16,410 118 | 2,pear,6,yellow,0.54,126,2.42,488 119 | 2,pear,6,yellow,0.52,120,2.5,607 120 | 2,pear,6,yellow,0.54,120,3.5,985 121 | 2,pear,6,yellow,0.56,126,3.69,465 122 | 2,pear,6,yellow,0.54,120,2.12,372 123 | 2,pear,6,yellow,0.54,126,2.75,680 124 | 2,pear,6,yellow,0.43,105,3.21,625 125 | 2,pear,6,yellow,0.59,120,2.06,495 126 | 2,pear,6,yellow,0.47,123,3.64,380 127 | 2,pear,6,yellow,0.56,117,3.13,463 128 | 2,pear,6,yellow,0.59,122,2.81,562 129 | 2,pear,6,yellow,0.43,122,2.27,480 130 | 2,pear,6,yellow,0.41,120,2.23,355 131 | 2,pear,6,yellow,0.59,105,1.59,450 132 | 3,apple,1,blue,0.35,146,2.06,520 133 | 3,apple,1,blue,0.32,143,1.74,740 134 | 3,apple,1,blue,0.28,132,1.58,520 135 | 3,apple,2,brown,0.3,147,1.36,560 136 | 3,apple,3,green,0.28,183,1.29,630 137 | 3,apple,3,green,0.25,155,1.55,640 138 | 3,apple,3,green,0.33,158,1.8,750 139 | 3,apple,3,green,0.27,159,1.75,675 140 | 3,apple,3,green,0.28,152,2.15,590 141 | 3,apple,3,green,0.27,146,1.73,880 142 | 3,apple,3,green,0.32,144,1.83,510 143 | 3,apple,3,green,0.23,144,1.6,560 144 | 3,apple,3,green,0.25,144,1.69,515 145 | 3,apple,3,green,0.27,144,2.31,600 146 | 3,apple,3,green,0.33,138,2.05,550 147 | 3,apple,3,green,0.28,134,1.64,480 148 | 3,apple,3,green,0.3,129,1.63,470 149 | 3,apple,3,green,0.3,134,1.27,720 150 | 3,apple,3,green,0.32,132,1.75,520 151 | 3,apple,5,red,0.22,180,1.56,835 152 | 3,apple,5,red,0.19,185,1.3,500 153 | 3,apple,5,red,0.25,170,1.33,550 154 | 3,apple,5,red,0.25,174,1.33,425 155 | 3,apple,5,red,0.28,156,1.42,530 156 | 3,apple,5,red,0.2,168,1.92,630 157 | 3,apple,5,red,0.19,167,1.56,695 158 | 3,apple,5,red,0.28,159,2.11,570 159 | 3,apple,5,red,0.2,147,1.96,660 160 | 3,apple,5,red,0.2,153,1.56,750 161 | 3,apple,5,red,0.2,138,1.62,650 162 | 3,apple,5,red,0.19,134,1.78,620 163 | 3,apple,5,red,0.2,134,2.47,780 164 | 3,apple,5,red,0.19,132,1.82,580 165 | 3,apple,5,red,0.27,128,1.51,650 166 | 3,apple,5,red,0.28,120,1.33,415 167 | 3,apple,6,yellow,0.23,180,1.62,840 168 | 3,apple,6,yellow,0.23,159,1.29,600 169 | 3,apple,6,yellow,0.32,161,1.82,680 170 | 3,apple,6,yellow,0.3,168,1.47,480 171 | 3,apple,6,yellow,0.3,168,2,855 172 | 3,apple,6,yellow,0.23,153,1.68,830 173 | 3,apple,6,yellow,0.22,147,1.51,675 174 | 3,apple,6,yellow,0.23,144,1.6,560 175 | 3,apple,6,yellow,0.23,140,1.48,725 176 | 3,apple,6,yellow,0.23,137,1.71,660 177 | 3,apple,6,yellow,0.25,141,1.58,695 178 | 3,apple,6,yellow,0.3,135,1.68,615 179 | 3,apple,6,yellow,0.3,132,1.75,685 180 | 3,apple,6,yellow,0.28,129,1.86,625 181 | --------------------------------------------------------------------------------