From bc73108d745e4005512153e13f0c3f55cb1207d8 Mon Sep 17 00:00:00 2001 From: Tuan-Dat Tran Date: Mon, 17 May 2021 16:31:29 +0000 Subject: [PATCH] Fixed crossvalidatoin/classification in pipeline and prepared for others to work on --- 0-pilot-project/MNIST-kNN-base.ipynb | 759 ++++++++++++++++ 0-pilot-project/MNIST-kNN-best-pipeline.ipynb | 522 ----------- 0-pilot-project/MNIST-kNN-pipeline.ipynb | 837 ++++++++++++++++++ 0-pilot-project/MNIST-kNN-prepoc-vis.ipynb | 410 +++++++++ 0-pilot-project/MNIST-kNN.ipynb | 725 --------------- 5 files changed, 2006 insertions(+), 1247 deletions(-) create mode 100644 0-pilot-project/MNIST-kNN-base.ipynb delete mode 100644 0-pilot-project/MNIST-kNN-best-pipeline.ipynb create mode 100644 0-pilot-project/MNIST-kNN-pipeline.ipynb create mode 100644 0-pilot-project/MNIST-kNN-prepoc-vis.ipynb delete mode 100644 0-pilot-project/MNIST-kNN.ipynb diff --git a/0-pilot-project/MNIST-kNN-base.ipynb b/0-pilot-project/MNIST-kNN-base.ipynb new file mode 100644 index 0000000..ccf45d2 --- /dev/null +++ b/0-pilot-project/MNIST-kNN-base.ipynb @@ -0,0 +1,759 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2507dc1b", + "metadata": {}, + "source": [ + "### Load MNIST dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "d214bb2f", + "metadata": {}, + "outputs": [], + "source": [ + "# Python ≥3.5 is required\n", + "import sys\n", + "assert sys.version_info >= (3, 5)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "056cad96", + "metadata": {}, + "outputs": [], + "source": [ + "# scikit-learn ≥0.20 is required\n", + "import sklearn\n", + "assert sklearn.__version__ >= \"0.20\"" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "80c92d8a", + "metadata": {}, + "outputs": [], + "source": [ + "# common imports\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "e07cdb1a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "sklearn.utils.Bunch" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# import function to scikit-learn datasets\n", + "from sklearn.datasets import fetch_openml\n", + "\n", + "# load specified dataset (MNIST)\n", + "mnist = fetch_openml('mnist_784', version=1, as_frame=False)\n", + "\n", + "# print type of dataset\n", + "type(mnist)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "8ccbd6b7", + "metadata": {}, + "outputs": [], + "source": [ + "X, y = mnist[\"data\"], mnist[\"target\"]" + ] + }, + { + "cell_type": "markdown", + "id": "78c78c04", + "metadata": {}, + "source": [ + "### Plot data" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "2963a0bf", + "metadata": {}, + "outputs": [], + "source": [ + "# import plotting libraries\n", + "import matplotlib as mpl\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "a7f1c08b", + "metadata": {}, + "outputs": [], + "source": [ + "# convert string labels to int\n", + "y = y.astype(np.uint8)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "b33ff35b", + "metadata": {}, + "outputs": [], + "source": [ + "# function to quickly plot an image\n", + "def plot_digit(data):\n", + " image = data.reshape(28, 28)\n", + " plt.imshow(image, cmap = mpl.cm.binary, interpolation=\"nearest\")\n", + " plt.axis(\"off\")" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "89a76fba", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_digit(X[10000])" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "0f59fcd5", + "metadata": {}, + "outputs": [], + "source": [ + "# function to quickly plot several digits\n", + "def plot_digits(instances, **options):\n", + " size = 28\n", + " images = [instance.reshape(size,size) for instance in instances]\n", + " image = np.concatenate(images, axis=1)\n", + " plt.imshow(image, cmap = mpl.cm.binary, **options)\n", + " plt.axis(\"off\")" + ] + }, + { + "cell_type": "markdown", + "id": "ff272b79", + "metadata": {}, + "source": [ + "### Prepare data for machine learning" + ] + }, + { + "cell_type": "markdown", + "id": "a330fd86", + "metadata": {}, + "source": [ + "### Identify Train Set and Test Set" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "36f7f273", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "X_train: 56000, (56000, 784)\n", + "X_test: 14000, (14000, 784)\n", + "y_train: 56000, (56000,)\n", + "y_test: 14000, (14000,)\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "from sklearn.model_selection import train_test_split\n", + "\n", + "k = 3\n", + "\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1337)\n", + "\n", + "print(f\"X_train: {len(X_train)}, {X_train.shape}\")\n", + "print(f\"X_test: {len(X_test)}, {X_test.shape}\")\n", + "print(f\"y_train: {len(y_train)}, {y_train.shape}\")\n", + "print(f\"y_test: {len(y_test)}, {y_test.shape}\")\n", + "\n", + "plot_digit(X_test[10000])" + ] + }, + { + "cell_type": "markdown", + "id": "b3267043", + "metadata": {}, + "source": [ + "## Train kNN classifier" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "afb277c8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 107 ms, sys: 3.58 ms, total: 111 ms\n", + "Wall time: 110 ms\n" + ] + }, + { + "data": { + "text/plain": [ + "KNeighborsClassifier(n_neighbors=3)" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%time\n", + "from sklearn.neighbors import KNeighborsClassifier\n", + "\n", + "classifier = KNeighborsClassifier(n_neighbors=k)\n", + "classifier.fit(X_train, y_train)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "e30c9192", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n" + ] + } + ], + "source": [ + "# take a test digit\n", + "td = 4000\n", + "test_digit = X_test[td]\n", + "print(y_test[td])" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "2e4676ab", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_digit(test_digit)" + ] + }, + { + "cell_type": "markdown", + "id": "2d53bd60", + "metadata": {}, + "source": [ + "### Evaluation" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "cae65dc4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accuracy Train 98.57321428571429\n", + "CPU times: user 7min 43s, sys: 14min 20s, total: 22min 4s\n", + "Wall time: 51.7 s\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "# trainings accuracy\n", + "wrong_images = X_train[(classifier.predict(X_train)-y_train) != 0]\n", + "percentage = ((1-len(wrong_images)/len(X_train)) * 100)\n", + "print(\"Accuracy Train \" + str(percentage))" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "b551da35", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accuracy Test 97.14285714285714\n", + "CPU times: user 1min 54s, sys: 3min 39s, total: 5min 34s\n", + "Wall time: 13.2 s\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "# test accuracy\n", + "wrong_images = X_test[(classifier.predict(X_test)-y_test) != 0]\n", + "percentage = ((1-len(wrong_images)/len(X_test)) * 100)\n", + "print(\"Accuracy Test \" + str(percentage))" + ] + }, + { + "cell_type": "markdown", + "id": "22c0058c", + "metadata": {}, + "source": [ + "Accuracy is strongly influenced by the distribution of the classes in the test data." + ] + }, + { + "cell_type": "markdown", + "id": "351768b0", + "metadata": {}, + "source": [ + "#### Cross Validation\n", + "[Find more information on cross validation here.](https://scikit-learn.org/stable/modules/cross_validation.html#cross-validation)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "7d943683", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.96866127 0.9686077 0.9694632 ]\n", + "CPU times: user 4min 38s, sys: 10min, total: 14min 38s\n", + "Wall time: 33.7 s\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "# cross validation score\n", + "from sklearn.model_selection import cross_val_score\n", + "\n", + "print(cross_val_score(classifier, X_train, y_train, cv=3, scoring=\"accuracy\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "d49c670c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[5 8 0 ... 9 3 7]\n", + "CPU times: user 5min 52s, sys: 11min 7s, total: 17min\n", + "Wall time: 41.3 s\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "# prediction of classifier\n", + "from sklearn.model_selection import cross_val_predict\n", + "\n", + "y_train_pred = cross_val_predict(classifier, X_train, y_train, cv=5)\n", + "print(y_train_pred)" + ] + }, + { + "cell_type": "markdown", + "id": "182a1c52", + "metadata": {}, + "source": [ + "#### Accuracy" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "1d66c93e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.970375" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from sklearn.metrics import accuracy_score\n", + "\n", + "accuracy_score(y_train, y_train_pred)" + ] + }, + { + "cell_type": "markdown", + "id": "2c1c857b", + "metadata": {}, + "source": [ + "#### Precision" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "327ca201", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.9705500243024229" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from sklearn.metrics import precision_score\n", + "\n", + "precision_score(y_train, y_train_pred, average='weighted')" + ] + }, + { + "cell_type": "markdown", + "id": "1a051995", + "metadata": {}, + "source": [ + "#### Recall" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "0852a4e4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.970375" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from sklearn.metrics import recall_score\n", + "\n", + "recall_score(y_train, y_train_pred, average='weighted')" + ] + }, + { + "cell_type": "markdown", + "id": "4848e2f8", + "metadata": {}, + "source": [ + "#### F1 Score" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "d5d2fe0e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.9703221334372104" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from sklearn.metrics import f1_score\n", + "\n", + "f1_score(y_train, y_train_pred, average='weighted')" + ] + }, + { + "cell_type": "markdown", + "id": "3acab292", + "metadata": {}, + "source": [ + "#### Confusion Matrix" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "f8f613b8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[5464 4 3 0 0 7 16 2 0 3]\n", + " [ 1 6252 9 2 3 1 4 10 2 3]\n", + " [ 35 49 5396 14 5 4 11 67 11 3]\n", + " [ 5 15 36 5475 2 67 3 30 30 16]\n", + " [ 4 45 4 1 5260 0 13 9 2 112]\n", + " [ 17 9 4 60 10 4887 46 5 9 21]\n", + " [ 23 17 1 0 5 14 5480 0 2 0]\n", + " [ 3 67 16 0 12 1 0 5691 1 55]\n", + " [ 20 69 28 85 27 69 19 15 5134 38]\n", + " [ 10 16 10 44 61 15 3 63 6 5302]]\n" + ] + } + ], + "source": [ + "# confusing matrix\n", + "from sklearn.metrics import confusion_matrix\n", + "\n", + "print(confusion_matrix(y_train, y_train_pred))" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "57dc8b25", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[9.93635206e-01 7.27404983e-04 5.45553737e-04 0.00000000e+00\n", + " 0.00000000e+00 1.27295872e-03 2.90961993e-03 3.63702491e-04\n", + " 0.00000000e+00 5.45553737e-04]\n", + " [1.59058374e-04 9.94432957e-01 1.43152537e-03 3.18116749e-04\n", + " 4.77175123e-04 1.59058374e-04 6.36233498e-04 1.59058374e-03\n", + " 3.18116749e-04 4.77175123e-04]\n", + " [6.25558534e-03 8.75781948e-03 9.64432529e-01 2.50223414e-03\n", + " 8.93655049e-04 7.14924039e-04 1.96604111e-03 1.19749777e-02\n", + " 1.96604111e-03 5.36193029e-04]\n", + " [8.80436697e-04 2.64131009e-03 6.33914422e-03 9.64078183e-01\n", + " 3.52174679e-04 1.17978517e-02 5.28262018e-04 5.28262018e-03\n", + " 5.28262018e-03 2.81739743e-03]\n", + " [7.33944954e-04 8.25688073e-03 7.33944954e-04 1.83486239e-04\n", + " 9.65137615e-01 0.00000000e+00 2.38532110e-03 1.65137615e-03\n", + " 3.66972477e-04 2.05504587e-02]\n", + " [3.35438043e-03 1.77584846e-03 7.89265983e-04 1.18389897e-02\n", + " 1.97316496e-03 9.64285714e-01 9.07655880e-03 9.86582478e-04\n", + " 1.77584846e-03 4.14364641e-03]\n", + " [4.15012631e-03 3.06748466e-03 1.80440274e-04 0.00000000e+00\n", + " 9.02201371e-04 2.52616384e-03 9.88812703e-01 0.00000000e+00\n", + " 3.60880549e-04 0.00000000e+00]\n", + " [5.13171399e-04 1.14608279e-02 2.73691413e-03 0.00000000e+00\n", + " 2.05268560e-03 1.71057133e-04 0.00000000e+00 9.73486144e-01\n", + " 1.71057133e-04 9.40814232e-03]\n", + " [3.63372093e-03 1.25363372e-02 5.08720930e-03 1.54433140e-02\n", + " 4.90552326e-03 1.25363372e-02 3.45203488e-03 2.72529070e-03\n", + " 9.32776163e-01 6.90406977e-03]\n", + " [1.80831826e-03 2.89330922e-03 1.80831826e-03 7.95660036e-03\n", + " 1.10307414e-02 2.71247740e-03 5.42495479e-04 1.13924051e-02\n", + " 1.08499096e-03 9.58770344e-01]]\n" + ] + } + ], + "source": [ + "cm = confusion_matrix(y_train, y_train_pred, normalize='true')\n", + "print(cm)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "a0891a45", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import seaborn as sn" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "c584cc3d", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "set_digits = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }\n", + "\n", + "df_cm = pd.DataFrame(cm, index=set_digits, columns=set_digits)\n", + "plt.figure(figsize = (10,7))\n", + "sn_plot = sn.heatmap(df_cm, annot=True, cmap=\"Greys\")\n", + "plt.ylabel(\"True Label\")\n", + "plt.xlabel(\"Predicted Label\")\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "dc855642", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pipeline: knn (97.0375%)\n", + " precision recall f1-score support\n", + "\n", + " 0 0.98 0.99 0.99 5499\n", + " 1 0.96 0.99 0.97 6287\n", + " 2 0.98 0.96 0.97 5595\n", + " 3 0.96 0.96 0.96 5679\n", + " 4 0.98 0.97 0.97 5450\n", + " 5 0.96 0.96 0.96 5068\n", + " 6 0.98 0.99 0.98 5542\n", + " 7 0.97 0.97 0.97 5846\n", + " 8 0.99 0.93 0.96 5504\n", + " 9 0.95 0.96 0.96 5530\n", + "\n", + " accuracy 0.97 56000\n", + " macro avg 0.97 0.97 0.97 56000\n", + "weighted avg 0.97 0.97 0.97 56000\n", + "\n" + ] + } + ], + "source": [ + "from sklearn.metrics import classification_report\n", + "\n", + "accuracy = accuracy_score(y_train, y_train_pred, normalize=True)*100\n", + "print(f\"Pipeline: knn ({accuracy:.4f}%)\")\n", + "print(classification_report(y_train, y_train_pred))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b27fdf05", + "metadata": {}, + "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.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/0-pilot-project/MNIST-kNN-best-pipeline.ipynb b/0-pilot-project/MNIST-kNN-best-pipeline.ipynb deleted file mode 100644 index a22c0ea..0000000 --- a/0-pilot-project/MNIST-kNN-best-pipeline.ipynb +++ /dev/null @@ -1,522 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "e4d89124", - "metadata": {}, - "source": [ - "### Load MNIST dataset" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "5789ec72", - "metadata": {}, - "outputs": [], - "source": [ - "# Python ≥3.5 is required\n", - "import sys\n", - "assert sys.version_info >= (3, 5)" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "f491d383", - "metadata": {}, - "outputs": [], - "source": [ - "# scikit-learn ≥0.20 is required\n", - "import sklearn\n", - "assert sklearn.__version__ >= \"0.20\"" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "575a6a42", - "metadata": {}, - "outputs": [], - "source": [ - "# common imports\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "921dc114", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "sklearn.utils.Bunch" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# import function to scikit-learn datasets\n", - "from sklearn.datasets import fetch_openml\n", - "\n", - "# load specified dataset (MNIST)\n", - "mnist = fetch_openml('mnist_784', version=1, as_frame=False)\n", - "\n", - "# print type of dataset\n", - "type(mnist)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "6271045c", - "metadata": {}, - "outputs": [], - "source": [ - "X, y = mnist[\"data\"], mnist[\"target\"]" - ] - }, - { - "cell_type": "markdown", - "id": "37777133", - "metadata": {}, - "source": [ - "### Fix labels" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "30a441d3", - "metadata": {}, - "outputs": [], - "source": [ - "# import plotting libraries\n", - "import matplotlib as mpl\n", - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "2d9693b1", - "metadata": {}, - "outputs": [], - "source": [ - "# convert string labels to int\n", - "y = y.astype(np.uint8)" - ] - }, - { - "cell_type": "markdown", - "id": "182f4b1b", - "metadata": {}, - "source": [ - "### Prepare data for machine learning" - ] - }, - { - "cell_type": "markdown", - "id": "77ff6bd1", - "metadata": {}, - "source": [ - "### Identify Train Set and Test Set" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "f8247d13", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "X_train: 56000, (56000, 784)\n", - "X_test: 14000, (14000, 784)\n", - "y_train: 56000, (56000,)\n", - "y_test: 14000, (14000,)\n" - ] - } - ], - "source": [ - "from sklearn.model_selection import train_test_split\n", - "\n", - "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1337)\n", - "\n", - "print(f\"X_train: {len(X_train)}, {X_train.shape}\")\n", - "print(f\"X_test: {len(X_test)}, {X_test.shape}\")\n", - "print(f\"y_train: {len(y_train)}, {y_train.shape}\")\n", - "print(f\"y_test: {len(y_test)}, {y_test.shape}\")" - ] - }, - { - "cell_type": "markdown", - "id": "c4062436", - "metadata": {}, - "source": [ - "## Pipeline Declaration" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "67645a47", - "metadata": {}, - "outputs": [], - "source": [ - "from sklearn.pipeline import Pipeline\n", - "from sklearn.decomposition import PCA\n", - "from sklearn.preprocessing import StandardScaler, MinMaxScaler\n", - "from sklearn.neighbors import KNeighborsClassifier\n", - "from sklearn.model_selection import cross_val_predict\n", - "from sklearn.metrics import classification_report, precision_score\n", - "\n", - "n_neighbors = 3\n", - "n95_components = 0.95\n", - "n99_components = 0.99" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "82b1e834", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "6" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "names = ['knn', \n", - " 'scalar+knn', \n", - " 'standard+pca95+knn', \n", - " 'minmax+pca95+knn', \n", - " 'standard+pca99+knn', \n", - " 'minmax+pca99+knn'\n", - " ]\n", - "\n", - "classifiers = [\n", - " Pipeline([('knn', KNeighborsClassifier(n_neighbors=n_neighbors))]),\n", - " Pipeline([\n", - " ('scaler', StandardScaler()),\n", - " ('knn', KNeighborsClassifier(n_neighbors=n_neighbors))\n", - " ]),\n", - " Pipeline([\n", - " ('standard', StandardScaler()),\n", - " ('pca', PCA(n_components=n95_components)),\n", - " ('knn', KNeighborsClassifier(n_neighbors=n_neighbors))\n", - " ]),\n", - " Pipeline([\n", - " ('minmax', MinMaxScaler()),\n", - " ('pca', PCA(n_components=n95_components)),\n", - " ('knn', KNeighborsClassifier(n_neighbors=n_neighbors))\n", - " ]),\n", - " Pipeline([\n", - " ('standard', StandardScaler()),\n", - " ('pca', PCA(n_components=n99_components)),\n", - " ('knn', KNeighborsClassifier(n_neighbors=n_neighbors))\n", - " ]),\n", - " Pipeline([\n", - " ('minmax', MinMaxScaler()),\n", - " ('pca', PCA(n_components=n99_components)),\n", - " ('knn', KNeighborsClassifier(n_neighbors=n_neighbors))\n", - " ])\n", - "]\n", - "\n", - "len(names)" - ] - }, - { - "cell_type": "markdown", - "id": "156dbf2c", - "metadata": {}, - "source": [ - "# Crossvalidation" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "8e5168e4", - "metadata": {}, - "outputs": [], - "source": [ - "# for name, clf in zip(names, classifiers):\n", - "# y_train_pred = cross_val_predict(clf, X_train, y_train, cv=3)\n", - "# print(f\"Pipeline: {name} ({precision_score(y_train, y_train_pred, average='weighted'):.4f})\")\n", - "# print(classification_report(y_train, y_train_pred))\n", - "precs = []" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "id": "db14a027", - "metadata": {}, - "outputs": [], - "source": [ - "def cv(num):\n", - " name = names[num]\n", - " clf = classifiers[num]\n", - " y_train_pred = cross_val_predict(clf, X_train, y_train, cv=3)\n", - " precision = precision_score(y_train, y_train_pred, average='weighted')\n", - " print(f\"Pipeline: {name} ({precision:.4f})\")\n", - " print(classification_report(y_train, y_train_pred))\n", - " return precision" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "b8983bf8", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Pipeline: knn (0.9691)\n", - " precision recall f1-score support\n", - "\n", - " 0 0.98 0.99 0.99 5499\n", - " 1 0.95 0.99 0.97 6287\n", - " 2 0.98 0.96 0.97 5595\n", - " 3 0.96 0.97 0.96 5679\n", - " 4 0.98 0.96 0.97 5450\n", - " 5 0.96 0.96 0.96 5068\n", - " 6 0.98 0.99 0.98 5542\n", - " 7 0.96 0.97 0.97 5846\n", - " 8 0.99 0.93 0.96 5504\n", - " 9 0.95 0.96 0.96 5530\n", - "\n", - " accuracy 0.97 56000\n", - " macro avg 0.97 0.97 0.97 56000\n", - "weighted avg 0.97 0.97 0.97 56000\n", - "\n" - ] - } - ], - "source": [ - "cv(0)" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "62ff42f4", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Pipeline: scalar+knn (0.9420)\n", - " precision recall f1-score support\n", - "\n", - " 0 0.95 0.99 0.97 5499\n", - " 1 0.95 0.99 0.97 6287\n", - " 2 0.95 0.93 0.94 5595\n", - " 3 0.92 0.94 0.93 5679\n", - " 4 0.94 0.93 0.94 5450\n", - " 5 0.93 0.92 0.93 5068\n", - " 6 0.96 0.97 0.97 5542\n", - " 7 0.94 0.93 0.94 5846\n", - " 8 0.97 0.89 0.93 5504\n", - " 9 0.91 0.92 0.91 5530\n", - "\n", - " accuracy 0.94 56000\n", - " macro avg 0.94 0.94 0.94 56000\n", - "weighted avg 0.94 0.94 0.94 56000\n", - "\n" - ] - } - ], - "source": [ - "cv(1)" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "9b553141", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Pipeline: standard+pca95+knn (0.9457)\n", - " precision recall f1-score support\n", - "\n", - " 0 0.96 0.99 0.97 5499\n", - " 1 0.95 0.99 0.97 6287\n", - " 2 0.95 0.94 0.95 5595\n", - " 3 0.93 0.94 0.94 5679\n", - " 4 0.95 0.93 0.94 5450\n", - " 5 0.93 0.92 0.93 5068\n", - " 6 0.96 0.97 0.97 5542\n", - " 7 0.95 0.94 0.94 5846\n", - " 8 0.97 0.89 0.93 5504\n", - " 9 0.92 0.92 0.92 5530\n", - "\n", - " accuracy 0.95 56000\n", - " macro avg 0.95 0.94 0.94 56000\n", - "weighted avg 0.95 0.95 0.95 56000\n", - "\n" - ] - } - ], - "source": [ - "cv(2)" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "id": "2a1d6c65", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Pipeline: minmax+pca95+knn (0.9706)\n", - " precision recall f1-score support\n", - "\n", - " 0 0.98 0.99 0.99 5499\n", - " 1 0.96 0.99 0.98 6287\n", - " 2 0.98 0.97 0.97 5595\n", - " 3 0.96 0.96 0.96 5679\n", - " 4 0.98 0.97 0.97 5450\n", - " 5 0.96 0.96 0.96 5068\n", - " 6 0.98 0.99 0.98 5542\n", - " 7 0.97 0.98 0.97 5846\n", - " 8 0.99 0.93 0.96 5504\n", - " 9 0.95 0.96 0.96 5530\n", - "\n", - " accuracy 0.97 56000\n", - " macro avg 0.97 0.97 0.97 56000\n", - "weighted avg 0.97 0.97 0.97 56000\n", - "\n" - ] - } - ], - "source": [ - "cv(3)" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "de40f817", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Pipeline: standard+pca99+knn (0.9424)\n", - " precision recall f1-score support\n", - "\n", - " 0 0.95 0.99 0.97 5499\n", - " 1 0.95 0.99 0.97 6287\n", - " 2 0.95 0.93 0.94 5595\n", - " 3 0.92 0.94 0.93 5679\n", - " 4 0.94 0.93 0.94 5450\n", - " 5 0.93 0.92 0.93 5068\n", - " 6 0.96 0.97 0.97 5542\n", - " 7 0.94 0.93 0.94 5846\n", - " 8 0.97 0.89 0.93 5504\n", - " 9 0.91 0.92 0.92 5530\n", - "\n", - " accuracy 0.94 56000\n", - " macro avg 0.94 0.94 0.94 56000\n", - "weighted avg 0.94 0.94 0.94 56000\n", - "\n" - ] - } - ], - "source": [ - "cv(4)" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "id": "2c1c26b0", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Pipeline: minmax+pca99+knn (0.9695)\n", - " precision recall f1-score support\n", - "\n", - " 0 0.98 0.99 0.99 5499\n", - " 1 0.95 0.99 0.97 6287\n", - " 2 0.98 0.96 0.97 5595\n", - " 3 0.96 0.97 0.96 5679\n", - " 4 0.98 0.96 0.97 5450\n", - " 5 0.96 0.96 0.96 5068\n", - " 6 0.98 0.99 0.98 5542\n", - " 7 0.96 0.97 0.97 5846\n", - " 8 0.99 0.93 0.96 5504\n", - " 9 0.95 0.96 0.96 5530\n", - "\n", - " accuracy 0.97 56000\n", - " macro avg 0.97 0.97 0.97 56000\n", - "weighted avg 0.97 0.97 0.97 56000\n", - "\n" - ] - } - ], - "source": [ - "cv(5)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cb6b6d69", - "metadata": {}, - "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.8.5" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/0-pilot-project/MNIST-kNN-pipeline.ipynb b/0-pilot-project/MNIST-kNN-pipeline.ipynb new file mode 100644 index 0000000..ddb78d6 --- /dev/null +++ b/0-pilot-project/MNIST-kNN-pipeline.ipynb @@ -0,0 +1,837 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "03d83636", + "metadata": {}, + "source": [ + "### Load MNIST dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "242d14f0", + "metadata": {}, + "outputs": [], + "source": [ + "# Python ≥3.5 is required\n", + "import sys\n", + "assert sys.version_info >= (3, 5)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "cfd3a54a", + "metadata": {}, + "outputs": [], + "source": [ + "# scikit-learn ≥0.20 is required\n", + "import sklearn\n", + "assert sklearn.__version__ >= \"0.20\"" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "7e1587b3", + "metadata": {}, + "outputs": [], + "source": [ + "# common imports\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "bbccfc32", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "sklearn.utils.Bunch" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# import function to scikit-learn datasets\n", + "from sklearn.datasets import fetch_openml\n", + "\n", + "# load specified dataset (MNIST)\n", + "mnist = fetch_openml('mnist_784', version=1, as_frame=False)\n", + "\n", + "# print type of dataset\n", + "type(mnist)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6db7c96a", + "metadata": {}, + "outputs": [], + "source": [ + "X, y = mnist[\"data\"], mnist[\"target\"]" + ] + }, + { + "cell_type": "markdown", + "id": "459780d0", + "metadata": {}, + "source": [ + "### Fix labels" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "48c4e861", + "metadata": {}, + "outputs": [], + "source": [ + "# import plotting libraries\n", + "import matplotlib as mpl\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "72876ab1", + "metadata": {}, + "outputs": [], + "source": [ + "# convert string labels to int\n", + "y = y.astype(np.uint8)" + ] + }, + { + "cell_type": "markdown", + "id": "c9dacae4", + "metadata": {}, + "source": [ + "### Prepare data for machine learning" + ] + }, + { + "cell_type": "markdown", + "id": "b44b3f87", + "metadata": {}, + "source": [ + "### Identify Train Set and Test Set" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "51c5da44", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "X_train: 56000, (56000, 784)\n", + "X_test: 14000, (14000, 784)\n", + "y_train: 56000, (56000,)\n", + "y_test: 14000, (14000,)\n" + ] + } + ], + "source": [ + "from sklearn.model_selection import train_test_split\n", + "\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1337)\n", + "\n", + "print(f\"X_train: {len(X_train)}, {X_train.shape}\")\n", + "print(f\"X_test: {len(X_test)}, {X_test.shape}\")\n", + "print(f\"y_train: {len(y_train)}, {y_train.shape}\")\n", + "print(f\"y_test: {len(y_test)}, {y_test.shape}\")" + ] + }, + { + "cell_type": "markdown", + "id": "673e237d", + "metadata": {}, + "source": [ + "## Pipeline Declaration" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "8ca34ce2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(11, 11)" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from sklearn.pipeline import Pipeline\n", + "from sklearn.decomposition import PCA\n", + "from sklearn.preprocessing import (StandardScaler, \n", + " MinMaxScaler, \n", + " MaxAbsScaler, \n", + " PowerTransformer)\n", + "from sklearn.neighbors import KNeighborsClassifier\n", + "from sklearn.model_selection import cross_validate\n", + "from sklearn.metrics import classification_report, accuracy_score\n", + "\n", + "n_neighbors = 3\n", + "n95_components = 0.95\n", + "n99_components = 0.99\n", + "\n", + "names = ['knn (baseline)', \n", + " 'scalar+knn', \n", + " 'minmax+knn', \n", + " 'standard+pca95+knn', \n", + " 'minmax+pca95+knn', # Best so far w/ 97.0429%\n", + " 'standard+pca99+knn', \n", + " 'minmax+pca99+knn',\n", + " 'maxabs+pca95+knn', \n", + " 'maxabs+pca99+knn', # Best so far w/ 97.0429%\n", + " 'power+pca95+knn',\n", + " 'power+pca99+knn',\n", + " ]\n", + "\n", + "classifiers = [\n", + " Pipeline([('knn', KNeighborsClassifier(n_neighbors=n_neighbors, n_jobs=-1))]),\n", + " Pipeline([\n", + " ('standard', StandardScaler()),\n", + " ('knn', KNeighborsClassifier(n_neighbors=n_neighbors, n_jobs=-1))\n", + " ]),\n", + " Pipeline([\n", + " ('minmax', MinMaxScaler()),\n", + " ('knn', KNeighborsClassifier(n_neighbors=n_neighbors, n_jobs=-1))\n", + " ]),\n", + " Pipeline([\n", + " ('standard', StandardScaler()),\n", + " ('pca', PCA(n_components=n95_components)),\n", + " ('knn', KNeighborsClassifier(n_neighbors=n_neighbors, n_jobs=-1))\n", + " ]),\n", + " Pipeline([\n", + " ('minmax', MinMaxScaler()),\n", + " ('pca', PCA(n_components=n95_components)),\n", + " ('knn', KNeighborsClassifier(n_neighbors=n_neighbors, n_jobs=-1))\n", + " ]),\n", + " Pipeline([\n", + " ('standard', StandardScaler()),\n", + " ('pca', PCA(n_components=n99_components)),\n", + " ('knn', KNeighborsClassifier(n_neighbors=n_neighbors, n_jobs=-1))\n", + " ]),\n", + " Pipeline([\n", + " ('minmax', MinMaxScaler()),\n", + " ('pca', PCA(n_components=n99_components)),\n", + " ('knn', KNeighborsClassifier(n_neighbors=n_neighbors, n_jobs=-1))\n", + " ]),\n", + " Pipeline([\n", + " ('maxabs', MaxAbsScaler()),\n", + " ('pca', PCA(n_components=n99_components)),\n", + " ('knn', KNeighborsClassifier(n_neighbors=n_neighbors, n_jobs=-1))\n", + " ]),\n", + " Pipeline([\n", + " ('maxabs', MaxAbsScaler()),\n", + " ('pca', PCA(n_components=n95_components)),\n", + " ('knn', KNeighborsClassifier(n_neighbors=n_neighbors, n_jobs=-1))\n", + " ]),\n", + " Pipeline([\n", + " ('power', PowerTransformer()),\n", + " ('pca', PCA(n_components=n99_components)),\n", + " ('knn', KNeighborsClassifier(n_neighbors=n_neighbors, n_jobs=-1))\n", + " ]),\n", + " Pipeline([\n", + " ('power', PowerTransformer()),\n", + " ('pca', PCA(n_components=n95_components)),\n", + " ('knn', KNeighborsClassifier(n_neighbors=n_neighbors, n_jobs=-1))\n", + " ]),\n", + "]\n", + "\n", + "len(names), len(classifiers)" + ] + }, + { + "cell_type": "markdown", + "id": "f38b2bb2", + "metadata": {}, + "source": [ + "# Crossvalidation" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "3465f546", + "metadata": {}, + "outputs": [], + "source": [ + "accuracies = []" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "1f087f92", + "metadata": {}, + "outputs": [], + "source": [ + "def cv_train(num,cv):\n", + " name = names[num]\n", + " clf = classifiers[num]\n", + " y_train_pred = cross_val_predict(clf, X_train, y_train, cv=cv, n_jobs=-1)\n", + " accuracy = accuracy_score(y_train, y_train_pred, normalize=True)*100\n", + " print(f\"Pipeline: {name} ({accuracy:.4f}%)\")\n", + " print(classification_report(y_train, y_train_pred))\n", + " return accuracy" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "9cb9b3e7", + "metadata": {}, + "outputs": [], + "source": [ + "def cv_test(num):\n", + " name = names[num]\n", + " clf = classifiers[num]\n", + " y_test_pred = cross_val_predict(clf, X_test, y_test, cv=5, n_jobs=-1)\n", + " accuracy = accuracy_score(y_test, y_test_pred, normalize=True)*100\n", + " print(f\"Pipeline: {name} ({accuracy:.4f}%)\")\n", + " print(classification_report(y_test, y_test_pred))\n", + " return accuracy" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "462e340f", + "metadata": {}, + "outputs": [], + "source": [ + "def cv(num,cv_arg=10):\n", + " name = names[num]\n", + " clf = classifiers[num]\n", + " clf = clf.fit(X_train, y_train)\n", + " cv = cross_validate(clf, X_train, y_train, cv=cv_arg, n_jobs=-1, return_estimator=True) \n", + " cv_clf = cv['estimator'][np.argmax(cv['test_score'])]\n", + " y_test_pred = cv_clf.predict(X_test)\n", + " accuracy = accuracy_score(y_test, y_test_pred, normalize=True)*100\n", + " print(f\"Pipeline: {name} ({accuracy:.4f}%)\")\n", + " print(classification_report(y_test, y_test_pred))\n", + " return accuracy" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "cbca3b1f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pipeline: knn (baseline) (96.9857%)\n", + " precision recall f1-score support\n", + "\n", + " 0 0.96 0.99 0.98 1404\n", + " 1 0.97 0.99 0.98 1590\n", + " 2 0.98 0.97 0.97 1395\n", + " 3 0.98 0.96 0.97 1462\n", + " 4 0.98 0.97 0.97 1374\n", + " 5 0.96 0.96 0.96 1245\n", + " 6 0.98 0.98 0.98 1334\n", + " 7 0.97 0.97 0.97 1447\n", + " 8 0.99 0.92 0.95 1321\n", + " 9 0.95 0.96 0.96 1428\n", + "\n", + " accuracy 0.97 14000\n", + " macro avg 0.97 0.97 0.97 14000\n", + "weighted avg 0.97 0.97 0.97 14000\n", + "\n" + ] + } + ], + "source": [ + "from sklearn.model_selection import LeaveOneOut\n", + "# accuracies.append(cv(0,5))\n", + "accuracies.append(cv(0,10))" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "ad92d1f0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pipeline: scalar+knn (94.2143%)\n", + " precision recall f1-score support\n", + "\n", + " 0 0.95 0.98 0.96 1404\n", + " 1 0.96 0.99 0.97 1590\n", + " 2 0.93 0.95 0.94 1395\n", + " 3 0.94 0.94 0.94 1462\n", + " 4 0.95 0.93 0.94 1374\n", + " 5 0.93 0.92 0.93 1245\n", + " 6 0.96 0.97 0.96 1334\n", + " 7 0.93 0.94 0.94 1447\n", + " 8 0.97 0.88 0.92 1321\n", + " 9 0.91 0.91 0.91 1428\n", + "\n", + " accuracy 0.94 14000\n", + " macro avg 0.94 0.94 0.94 14000\n", + "weighted avg 0.94 0.94 0.94 14000\n", + "\n" + ] + } + ], + "source": [ + "# accuracies.append(cv(1,5))\n", + "accuracies.append(cv(1,10))" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "881d8a07", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pipeline: minmax+knn (96.9857%)\n", + " precision recall f1-score support\n", + "\n", + " 0 0.96 0.99 0.98 1404\n", + " 1 0.97 0.99 0.98 1590\n", + " 2 0.98 0.97 0.97 1395\n", + " 3 0.98 0.96 0.97 1462\n", + " 4 0.98 0.97 0.97 1374\n", + " 5 0.96 0.96 0.96 1245\n", + " 6 0.98 0.98 0.98 1334\n", + " 7 0.97 0.97 0.97 1447\n", + " 8 0.99 0.92 0.95 1321\n", + " 9 0.95 0.96 0.96 1428\n", + "\n", + " accuracy 0.97 14000\n", + " macro avg 0.97 0.97 0.97 14000\n", + "weighted avg 0.97 0.97 0.97 14000\n", + "\n" + ] + } + ], + "source": [ + "# accuracies.append(cv(2,5))\n", + "accuracies.append(cv(2,10))" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "1402e10b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pipeline: standard+pca95+knn (94.7000%)\n", + " precision recall f1-score support\n", + "\n", + " 0 0.95 0.98 0.97 1404\n", + " 1 0.96 0.99 0.98 1590\n", + " 2 0.94 0.95 0.94 1395\n", + " 3 0.94 0.94 0.94 1462\n", + " 4 0.96 0.94 0.95 1374\n", + " 5 0.93 0.93 0.93 1245\n", + " 6 0.96 0.97 0.97 1334\n", + " 7 0.94 0.95 0.94 1447\n", + " 8 0.97 0.89 0.93 1321\n", + " 9 0.92 0.92 0.92 1428\n", + "\n", + " accuracy 0.95 14000\n", + " macro avg 0.95 0.95 0.95 14000\n", + "weighted avg 0.95 0.95 0.95 14000\n", + "\n" + ] + } + ], + "source": [ + "# accuracies.append(cv(3,5))\n", + "accuracies.append(cv(3,10))" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "24035514", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pipeline: minmax+pca95+knn (97.2571%)\n", + " precision recall f1-score support\n", + "\n", + " 0 0.97 0.99 0.98 1404\n", + " 1 0.98 0.99 0.99 1590\n", + " 2 0.98 0.97 0.97 1395\n", + " 3 0.98 0.97 0.97 1462\n", + " 4 0.98 0.97 0.97 1374\n", + " 5 0.97 0.96 0.97 1245\n", + " 6 0.98 0.99 0.98 1334\n", + " 7 0.97 0.98 0.97 1447\n", + " 8 0.99 0.93 0.96 1321\n", + " 9 0.95 0.97 0.96 1428\n", + "\n", + " accuracy 0.97 14000\n", + " macro avg 0.97 0.97 0.97 14000\n", + "weighted avg 0.97 0.97 0.97 14000\n", + "\n" + ] + } + ], + "source": [ + "# accuracies.append(cv(4,5))\n", + "accuracies.append(cv(4,10))" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "1c27528e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pipeline: standard+pca99+knn (94.2929%)\n", + " precision recall f1-score support\n", + "\n", + " 0 0.95 0.98 0.96 1404\n", + " 1 0.96 0.99 0.97 1590\n", + " 2 0.94 0.95 0.94 1395\n", + " 3 0.94 0.94 0.94 1462\n", + " 4 0.96 0.93 0.94 1374\n", + " 5 0.93 0.92 0.92 1245\n", + " 6 0.96 0.97 0.96 1334\n", + " 7 0.93 0.94 0.94 1447\n", + " 8 0.97 0.88 0.92 1321\n", + " 9 0.91 0.91 0.91 1428\n", + "\n", + " accuracy 0.94 14000\n", + " macro avg 0.94 0.94 0.94 14000\n", + "weighted avg 0.94 0.94 0.94 14000\n", + "\n" + ] + } + ], + "source": [ + "# accuracies.append(cv(5,5))\n", + "accuracies.append(cv(5,10))" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "46bcb35f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pipeline: minmax+pca99+knn (96.9929%)\n", + " precision recall f1-score support\n", + "\n", + " 0 0.96 0.99 0.98 1404\n", + " 1 0.97 0.99 0.98 1590\n", + " 2 0.97 0.97 0.97 1395\n", + " 3 0.97 0.96 0.97 1462\n", + " 4 0.98 0.97 0.97 1374\n", + " 5 0.97 0.96 0.96 1245\n", + " 6 0.98 0.98 0.98 1334\n", + " 7 0.97 0.97 0.97 1447\n", + " 8 0.99 0.93 0.96 1321\n", + " 9 0.95 0.96 0.96 1428\n", + "\n", + " accuracy 0.97 14000\n", + " macro avg 0.97 0.97 0.97 14000\n", + "weighted avg 0.97 0.97 0.97 14000\n", + "\n" + ] + } + ], + "source": [ + "# accuracies.append(cv(6,5))\n", + "accuracies.append(cv(6,10))" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "45d8092d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pipeline: maxabs+pca95+knn (96.9929%)\n", + " precision recall f1-score support\n", + "\n", + " 0 0.96 0.99 0.98 1404\n", + " 1 0.97 0.99 0.98 1590\n", + " 2 0.97 0.97 0.97 1395\n", + " 3 0.97 0.96 0.97 1462\n", + " 4 0.98 0.97 0.97 1374\n", + " 5 0.97 0.96 0.96 1245\n", + " 6 0.98 0.98 0.98 1334\n", + " 7 0.97 0.97 0.97 1447\n", + " 8 0.99 0.93 0.96 1321\n", + " 9 0.95 0.96 0.96 1428\n", + "\n", + " accuracy 0.97 14000\n", + " macro avg 0.97 0.97 0.97 14000\n", + "weighted avg 0.97 0.97 0.97 14000\n", + "\n" + ] + } + ], + "source": [ + "# accuracies.append(cv(7,5))\n", + "accuracies.append(cv(7,10))" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "a805b3fd", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pipeline: maxabs+pca99+knn (97.2571%)\n", + " precision recall f1-score support\n", + "\n", + " 0 0.97 0.99 0.98 1404\n", + " 1 0.98 0.99 0.99 1590\n", + " 2 0.98 0.97 0.97 1395\n", + " 3 0.98 0.97 0.97 1462\n", + " 4 0.98 0.97 0.97 1374\n", + " 5 0.97 0.96 0.97 1245\n", + " 6 0.98 0.99 0.98 1334\n", + " 7 0.97 0.98 0.97 1447\n", + " 8 0.99 0.93 0.96 1321\n", + " 9 0.95 0.97 0.96 1428\n", + "\n", + " accuracy 0.97 14000\n", + " macro avg 0.97 0.97 0.97 14000\n", + "weighted avg 0.97 0.97 0.97 14000\n", + "\n" + ] + } + ], + "source": [ + "# accuracies.append(cv(8,5))\n", + "accuracies.append(cv(8,10))" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "3af8abf8", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/jupyterhub/lib/python3.8/site-packages/sklearn/preprocessing/_data.py:3237: RuntimeWarning: divide by zero encountered in log\n", + " loglike = -n_samples / 2 * np.log(x_trans.var())\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pipeline: power+pca95+knn (94.1071%)\n", + " precision recall f1-score support\n", + "\n", + " 0 0.95 0.98 0.97 1404\n", + " 1 0.96 0.99 0.97 1590\n", + " 2 0.94 0.95 0.94 1395\n", + " 3 0.94 0.93 0.94 1462\n", + " 4 0.95 0.93 0.94 1374\n", + " 5 0.93 0.91 0.92 1245\n", + " 6 0.95 0.97 0.96 1334\n", + " 7 0.94 0.94 0.94 1447\n", + " 8 0.95 0.89 0.92 1321\n", + " 9 0.90 0.92 0.91 1428\n", + "\n", + " accuracy 0.94 14000\n", + " macro avg 0.94 0.94 0.94 14000\n", + "weighted avg 0.94 0.94 0.94 14000\n", + "\n" + ] + } + ], + "source": [ + "# accuracies.append(cv(9,5))\n", + "accuracies.append(cv(9,10)) # likes to die" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "d971b4df", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/jupyterhub/lib/python3.8/site-packages/sklearn/preprocessing/_data.py:3237: RuntimeWarning: divide by zero encountered in log\n", + " loglike = -n_samples / 2 * np.log(x_trans.var())\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pipeline: power+pca99+knn (94.4429%)\n", + " precision recall f1-score support\n", + "\n", + " 0 0.95 0.98 0.97 1404\n", + " 1 0.96 0.99 0.98 1590\n", + " 2 0.94 0.95 0.94 1395\n", + " 3 0.94 0.93 0.94 1462\n", + " 4 0.95 0.93 0.94 1374\n", + " 5 0.94 0.91 0.93 1245\n", + " 6 0.95 0.97 0.96 1334\n", + " 7 0.94 0.94 0.94 1447\n", + " 8 0.95 0.90 0.93 1321\n", + " 9 0.91 0.92 0.92 1428\n", + "\n", + " accuracy 0.94 14000\n", + " macro avg 0.94 0.94 0.94 14000\n", + "weighted avg 0.94 0.94 0.94 14000\n", + "\n" + ] + } + ], + "source": [ + "# accuracies.append(cv(10,5))\n", + "accuracies.append(cv(10,10)) # likes to die" + ] + }, + { + "cell_type": "markdown", + "id": "281e0f59", + "metadata": {}, + "source": [ + "# Auswertung" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "e3eeabc7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Maximum accuracy (97.2571%) at: ['minmax+pca95+knn', 'maxabs+pca99+knn']\n" + ] + } + ], + "source": [ + "print(f\"Maximum accuracy ({max(accuracies):.6}%) at: {[names[n] for n in np.where(accuracies==max(accuracies))[0]]}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "7754b1e8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "name: knn (baseline) (96.9857%)\n", + "name: scalar+knn (94.2143%)\n", + "name: minmax+knn (96.9857%)\n", + "name: standard+pca95+knn (94.7000%)\n", + "name: minmax+pca95+knn (97.2571%)\n", + "name: standard+pca99+knn (94.2929%)\n", + "name: minmax+pca99+knn (96.9929%)\n", + "name: maxabs+pca95+knn (96.9929%)\n", + "name: maxabs+pca99+knn (97.2571%)\n", + "name: power+pca95+knn (94.1071%)\n", + "name: power+pca99+knn (94.4429%)\n" + ] + } + ], + "source": [ + "for n, a in zip(names, accuracies):\n", + " print(f\"name: {n:20} ({a:.4f}%)\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "22316563", + "metadata": {}, + "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.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/0-pilot-project/MNIST-kNN-prepoc-vis.ipynb b/0-pilot-project/MNIST-kNN-prepoc-vis.ipynb new file mode 100644 index 0000000..b6d7a5a --- /dev/null +++ b/0-pilot-project/MNIST-kNN-prepoc-vis.ipynb @@ -0,0 +1,410 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "804dacb6", + "metadata": {}, + "source": [ + "### Load MNIST dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "7d09885b", + "metadata": {}, + "outputs": [], + "source": [ + "# Python ≥3.5 is required\n", + "import sys\n", + "assert sys.version_info >= (3, 5)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "bf4121a0", + "metadata": {}, + "outputs": [], + "source": [ + "# scikit-learn ≥0.20 is required\n", + "import sklearn\n", + "assert sklearn.__version__ >= \"0.20\"" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "71d91fd8", + "metadata": {}, + "outputs": [], + "source": [ + "# common imports\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "1dc68441", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "sklearn.utils.Bunch" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# import function to scikit-learn datasets\n", + "from sklearn.datasets import fetch_openml\n", + "\n", + "# load specified dataset (MNIST)\n", + "mnist = fetch_openml('mnist_784', version=1, as_frame=False)\n", + "\n", + "# print type of dataset\n", + "type(mnist)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "2c7a4966", + "metadata": {}, + "outputs": [], + "source": [ + "X, y = mnist[\"data\"], mnist[\"target\"]" + ] + }, + { + "cell_type": "markdown", + "id": "e2684670", + "metadata": {}, + "source": [ + "### Fix labels" + ] + }, + { + "cell_type": "code", + "execution_count": 113, + "id": "dbdbc64f", + "metadata": {}, + "outputs": [], + "source": [ + "# import plotting libraries\n", + "import matplotlib as mpl\n", + "import matplotlib.pyplot as plt\n", + "from math import isqrt, sqrt" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "4c94aaf6", + "metadata": {}, + "outputs": [], + "source": [ + "# convert string labels to int\n", + "y = y.astype(np.uint8)" + ] + }, + { + "cell_type": "code", + "execution_count": 126, + "id": "f1ba6703", + "metadata": {}, + "outputs": [], + "source": [ + "# function to quickly plot an image\n", + "def plot_digit(data):\n", + " image = data.reshape(28, 28)\n", + " plt.imshow(image, cmap = mpl.cm.binary, interpolation=\"nearest\")\n", + " plt.axis(\"off\")" + ] + }, + { + "cell_type": "markdown", + "id": "eec5415d", + "metadata": {}, + "source": [ + "### Prepare data for machine learning" + ] + }, + { + "cell_type": "markdown", + "id": "27ed1cdb", + "metadata": {}, + "source": [ + "### Identify Train Set and Test Set" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "09446324", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "X_train: 56000, (56000, 784)\n", + "X_test: 14000, (14000, 784)\n", + "y_train: 56000, (56000,)\n", + "y_test: 14000, (14000,)\n" + ] + } + ], + "source": [ + "from sklearn.model_selection import train_test_split\n", + "\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1337)\n", + "\n", + "print(f\"X_train: {len(X_train)}, {X_train.shape}\")\n", + "print(f\"X_test: {len(X_test)}, {X_test.shape}\")\n", + "print(f\"y_train: {len(y_train)}, {y_train.shape}\")\n", + "print(f\"y_test: {len(y_test)}, {y_test.shape}\")" + ] + }, + { + "cell_type": "markdown", + "id": "2c3041ac", + "metadata": {}, + "source": [ + "## Pipeline Declaration" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "99f24362", + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.pipeline import Pipeline\n", + "from sklearn.decomposition import PCA\n", + "from sklearn.preprocessing import StandardScaler, MinMaxScaler, MaxAbsScaler\n", + "from sklearn.neighbors import KNeighborsClassifier\n", + "from sklearn.model_selection import cross_val_predict\n", + "from sklearn.metrics import classification_report, accuracy_score\n", + "\n", + "n_neighbors = 3\n", + "n95_components = 0.95\n", + "n99_components = 0.99" + ] + }, + { + "cell_type": "code", + "execution_count": 122, + "id": "a6ee7588", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(3, 3)" + ] + }, + "execution_count": 122, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "names = ['scaler', \n", + " 'minmax', \n", + " 'maxabs', \n", + " ]\n", + "\n", + "classifiers = [\n", + " Pipeline([('scaler', StandardScaler())]),\n", + " Pipeline([('minmax', MinMaxScaler())]),\n", + " Pipeline([('maxabs', MaxAbsScaler())]),\n", + "]\n", + "\n", + "len(names), len(classifiers)" + ] + }, + { + "cell_type": "markdown", + "id": "650c96b4", + "metadata": {}, + "source": [ + "# Crossvalidation" + ] + }, + { + "cell_type": "code", + "execution_count": 123, + "id": "584cb66b", + "metadata": {}, + "outputs": [], + "source": [ + "def cv(num):\n", + " name = names[num]\n", + " clf = classifiers[num]\n", + " i = 10000\n", + " _X_train = clf.fit_transform(X_train, y_train)\n", + " print(y_train[i])\n", + " plot_digit(_X_train[i])\n", + " return _X_train[i]" + ] + }, + { + "cell_type": "code", + "execution_count": 128, + "id": "0b815be6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "i = 10000\n", + "print(y_train[i])\n", + "plot_digit(X_train[i])" + ] + }, + { + "cell_type": "code", + "execution_count": 132, + "id": "8640f2ad", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "a = cv(0)" + ] + }, + { + "cell_type": "code", + "execution_count": 133, + "id": "3ef8cf89", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "a = cv(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 134, + "id": "fe0246a2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAOcAAADnCAYAAADl9EEgAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Z1A+gAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGuElEQVR4nO3dS4jNcR/H8TOPy9ggyXVHKQtKUohsFKGsrWRBiFwWMxasXGpqIpKVHaVcFoqdLGaShYUdi9lYTIlYSFEUnt2z8v/+e87MmM/h9Vr69Dtzanp3yq/zn75fv351gDz/me43APyeOCGUOCGUOCGUOCHUzJbdf+XC1Ov73T/65IRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQbX8CkCkwPj7euI2MjJRnHz16VO737t0r9x07dpT748ePG7dZs2aVZ5lcPjkhlDghlDghlDghlDghlDghlDghVN+vX7+qvRz/Vrdv3y73u3fvTuj1nz592rh9+/ZtQq/d8vvs9PX1lfvu3bsbt4cPH5ZnZ850bd6l3/5SfHJCKHFCKHFCKHFCKHFCKHFCKHFCqH/ynvPWrVvlfuLEiXL//PnzhH7+zp07G7dVq1aVZ/fu3Vvu169fL/e274NWhoaGyn1wcLDr1/7HueeEXiJOCCVOCCVOCCVOCCVOCNWzVyk/fvwo9wsXLjRuV69eLc+2XZX09/eX+8DAQLmfO3eucZs9e3Z5ts3Pnz/Lfdu2beX+/Pnzxm3Dhg3l2RcvXpQ7jVylQC8RJ4QSJ4QSJ4QSJ4QSJ4QSJ4Tq2WcZtt2pnT9/vuvXXrFiRbm3PRqz7T5wOk3k8ZWLFy+exHdCG5+cEEqcEEqcEEqcEEqcEEqcEEqcEKpn7znb7usWLFjQuB04cKA8e+TIkXJve3zldHr//n25j46Odv3amzZt6vos/z+fnBBKnBBKnBBKnBBKnBBKnBBKnBCqZ59b2+bDhw+N26JFi/7gO/mzDh8+XO43b94s9yVLljRub968Kc/OmTOn3GnkubXQS8QJocQJocQJocQJocQJocQJoXr2+5xtevUu8+PHj+V+9OjRcn/w4EG59/X99krtf6p7UveYf5ZPTgglTgglTgglTgglTgglTgj1135lLNnly5cbt0uXLpVnP336VO4tv8/Wq5T+/v7GbdeuXeXZtkeO7t27t9z/Yb4yBr1EnBBKnBBKnBBKnBBKnBBKnBDKPecUGBsbK/f169c3bl+/fp3Qz57oPedEtL328ePHy/3atWuT+XZ6iXtO6CXihFDihFDihFDihFDihFDihFDuOafBsmXLGre2R2OeOnWq3IeHh8v9+/fv5V49WvPMmTPl2bdv35b7z58/y31oaKhxGxwcLM9O5f3tH+CeE3qJOCGUOCGUOCGUOCGUOCGUOCGUe85p8PTp08Zt/vz55dkNGzZM9tuZNNXzeDudTmdgYKDr175z506579u3r+vXDuCeE3qJOCGUOCGUOCGUOCGUOCGUOCGUe04mzbt378q97Y62+j7o9u3by7NPnjwp93DuOaGXiBNCiRNCiRNCiRNCiRNCzZzuN8DfY+nSpeV+7Nixcj979uxkvp2e55MTQokTQokTQokTQokTQokTQokTQvnKWBfGxsbK/eDBg+W+ZcuWxu3ixYvl2RkzZpR7spcvX5Z79ZWyefPmlWfHx8fLfe7cueU+zXxlDHqJOCGUOCGUOCGUOCGUOCGUOCGU73N24fbt2+X+7NmzrveVK1eWZw8dOlTuyV6/ft312UWLFpX7rFmzun7tVD45IZQ4IZQ4IZQ4IZQ4IZQ4IZQ4IZR7zi5s3Lix3Pv7+8v927dvjdvp06fLs5s3by73NWvWlPtU+vr1a7m33Q9X1q9fX+5z5szp+rVT+eSEUOKEUOKEUOKEUOKEUOKEUB6NOQXu379f7vv372/cqmuWTqf9ymDt2rXlfvLkyXKv/ozfly9fyrNXrlwp95GRkXKfP39+4/bq1avy7PLly8s9nEdjQi8RJ4QSJ4QSJ4QSJ4QSJ4QSJ4RyzzkNRkdHG7c9e/aUZ9vuGlt+n52+vt9eqf0R1T1mp9PpPHr0qHHbunXrZL+dJO45oZeIE0KJE0KJE0KJE0KJE0KJE0K55wzT9n3OGzdulHvbnx98+PBhuVffF123bl15dvXq1eU+PDxc7gsXLiz3v5h7Tugl4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ7jlh+rnnhF4iTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgglTgg1s2X/7Z8mA6aeT04IJU4IJU4IJU4IJU4IJU4I9V9xQCui+SkYGAAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "a = cv(2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "87a073e1", + "metadata": {}, + "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.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/0-pilot-project/MNIST-kNN.ipynb b/0-pilot-project/MNIST-kNN.ipynb deleted file mode 100644 index 2634644..0000000 --- a/0-pilot-project/MNIST-kNN.ipynb +++ /dev/null @@ -1,725 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "b857abc2", - "metadata": {}, - "source": [ - "### Load MNIST dataset" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "cf588d8d", - "metadata": {}, - "outputs": [], - "source": [ - "# Python ≥3.5 is required\n", - "import sys\n", - "assert sys.version_info >= (3, 5)" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "12b23f05", - "metadata": {}, - "outputs": [], - "source": [ - "# scikit-learn ≥0.20 is required\n", - "import sklearn\n", - "assert sklearn.__version__ >= \"0.20\"" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "cd447696", - "metadata": {}, - "outputs": [], - "source": [ - "# common imports\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "72617a69", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "sklearn.utils.Bunch" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# import function to scikit-learn datasets\n", - "from sklearn.datasets import fetch_openml\n", - "\n", - "# load specified dataset (MNIST)\n", - "mnist = fetch_openml('mnist_784', version=1, as_frame=False)\n", - "\n", - "# print type of dataset\n", - "type(mnist)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "44a852a7", - "metadata": {}, - "outputs": [], - "source": [ - "X, y = mnist[\"data\"], mnist[\"target\"]" - ] - }, - { - "cell_type": "markdown", - "id": "2df276ee", - "metadata": {}, - "source": [ - "### Plot data" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "653e8b2d", - "metadata": {}, - "outputs": [], - "source": [ - "# import plotting libraries\n", - "import matplotlib as mpl\n", - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "ae3655b4", - "metadata": {}, - "outputs": [], - "source": [ - "# convert string labels to int\n", - "y = y.astype(np.uint8)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "9bcf3722", - "metadata": {}, - "outputs": [], - "source": [ - "# function to quickly plot an image\n", - "def plot_digit(data):\n", - " image = data.reshape(28, 28)\n", - " plt.imshow(image, cmap = mpl.cm.binary, interpolation=\"nearest\")\n", - " plt.axis(\"off\")" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "7d6cadc8", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plot_digit(X[10000])" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "0e764d62", - "metadata": {}, - "outputs": [], - "source": [ - "# function to quickly plot several digits\n", - "def plot_digits(instances, **options):\n", - " size = 28\n", - " images = [instance.reshape(size,size) for instance in instances]\n", - " image = np.concatenate(images, axis=1)\n", - " plt.imshow(image, cmap = mpl.cm.binary, **options)\n", - " plt.axis(\"off\")" - ] - }, - { - "cell_type": "markdown", - "id": "6198035d", - "metadata": {}, - "source": [ - "### Prepare data for machine learning" - ] - }, - { - "cell_type": "markdown", - "id": "a0606a56", - "metadata": {}, - "source": [ - "### Identify Train Set and Test Set" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "52cd17f4", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "X_train: 56000, (56000, 784)\n", - "X_test: 14000, (14000, 784)\n", - "y_train: 56000, (56000,)\n", - "y_test: 14000, (14000,)\n" - ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "from sklearn.model_selection import train_test_split\n", - "\n", - "k = 3\n", - "\n", - "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1337)\n", - "\n", - "print(f\"X_train: {len(X_train)}, {X_train.shape}\")\n", - "print(f\"X_test: {len(X_test)}, {X_test.shape}\")\n", - "print(f\"y_train: {len(y_train)}, {y_train.shape}\")\n", - "print(f\"y_test: {len(y_test)}, {y_test.shape}\")\n", - "\n", - "plot_digit(X_test[10000])" - ] - }, - { - "cell_type": "markdown", - "id": "45056d70", - "metadata": {}, - "source": [ - "## Train kNN classifier" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "f7711356", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CPU times: user 80.6 ms, sys: 183 µs, total: 80.7 ms\n", - "Wall time: 80.3 ms\n" - ] - }, - { - "data": { - "text/plain": [ - "KNeighborsClassifier(n_neighbors=3)" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%%time\n", - "from sklearn.neighbors import KNeighborsClassifier\n", - "\n", - "classifier = KNeighborsClassifier(n_neighbors=k)\n", - "classifier.fit(X_train, y_train)" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "c1888789", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "3\n" - ] - } - ], - "source": [ - "# take a test digit\n", - "td = 4000\n", - "test_digit = X_test[td]\n", - "print(y_test[td])" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "1e2e2a1f", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plot_digit(test_digit)" - ] - }, - { - "cell_type": "markdown", - "id": "87c511b2", - "metadata": {}, - "source": [ - "### Evaluation" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "90636a49", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Accuracy Train 98.57321428571429\n", - "CPU times: user 7min 45s, sys: 16min 28s, total: 24min 14s\n", - "Wall time: 49.4 s\n" - ] - } - ], - "source": [ - "%%time\n", - "\n", - "# trainings accuracy\n", - "wrong_images = X_train[(classifier.predict(X_train)-y_train) != 0]\n", - "percentage = ((1-len(wrong_images)/len(X_train)) * 100)\n", - "print(\"Accuracy Train \" + str(percentage))" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "0b545276", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Accuracy Test 97.14285714285714\n", - "CPU times: user 1min 54s, sys: 4min 7s, total: 6min 2s\n", - "Wall time: 12.3 s\n" - ] - } - ], - "source": [ - "%%time\n", - "\n", - "# test accuracy\n", - "wrong_images = X_test[(classifier.predict(X_test)-y_test) != 0]\n", - "percentage = ((1-len(wrong_images)/len(X_test)) * 100)\n", - "print(\"Accuracy Test \" + str(percentage))" - ] - }, - { - "cell_type": "markdown", - "id": "90959859", - "metadata": {}, - "source": [ - "Accuracy is strongly influenced by the distribution of the classes in the test data." - ] - }, - { - "cell_type": "markdown", - "id": "22a52196", - "metadata": {}, - "source": [ - "#### Cross Validation\n", - "[Find more information on cross validation here.](https://scikit-learn.org/stable/modules/cross_validation.html#cross-validation)" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "cad28e74", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[0.96866127 0.9686077 0.9694632 ]\n", - "CPU times: user 4min 41s, sys: 11min 10s, total: 15min 51s\n", - "Wall time: 33 s\n" - ] - } - ], - "source": [ - "%%time\n", - "\n", - "# cross validation score\n", - "from sklearn.model_selection import cross_val_score\n", - "\n", - "print(cross_val_score(classifier, X_train, y_train, cv=3, scoring=\"accuracy\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "9ad4da9b", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[5 8 0 ... 9 3 7]\n", - "CPU times: user 4min 40s, sys: 11min 5s, total: 15min 45s\n", - "Wall time: 33 s\n" - ] - } - ], - "source": [ - "%%time\n", - "\n", - "# prediction of classifier\n", - "from sklearn.model_selection import cross_val_predict\n", - "\n", - "y_train_pred = cross_val_predict(classifier, X_train, y_train, cv=3)\n", - "print(y_train_pred)" - ] - }, - { - "cell_type": "markdown", - "id": "515fa5cd", - "metadata": {}, - "source": [ - "#### Precision" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "d0b1d476", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.9691263682630111" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from sklearn.metrics import precision_score\n", - "\n", - "precision_score(y_train, y_train_pred, average='weighted')" - ] - }, - { - "cell_type": "markdown", - "id": "72e1dd8c", - "metadata": {}, - "source": [ - "#### Recall" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "21efc1ec", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.9689107142857143" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from sklearn.metrics import recall_score\n", - "\n", - "recall_score(y_train, y_train_pred, average='weighted')" - ] - }, - { - "cell_type": "markdown", - "id": "abd47e74", - "metadata": {}, - "source": [ - "#### F1 Score" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "db7ea5c6", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.9688480125980605" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from sklearn.metrics import f1_score\n", - "\n", - "f1_score(y_train, y_train_pred, average='weighted')" - ] - }, - { - "cell_type": "markdown", - "id": "1e307e68", - "metadata": {}, - "source": [ - "#### Confusion Matrix" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "6c0f7b1e", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[5465 4 2 0 0 8 15 1 1 3]\n", - " [ 1 6252 11 2 2 1 4 9 2 3]\n", - " [ 36 57 5381 14 3 4 9 78 11 2]\n", - " [ 6 18 37 5484 2 58 3 25 33 13]\n", - " [ 3 48 3 1 5251 0 14 11 2 117]\n", - " [ 18 10 5 67 13 4874 50 4 8 19]\n", - " [ 27 15 1 0 5 18 5473 0 3 0]\n", - " [ 1 72 12 2 12 1 0 5684 2 60]\n", - " [ 25 75 25 80 31 88 19 17 5098 46]\n", - " [ 12 17 8 44 60 15 3 66 8 5297]]\n" - ] - } - ], - "source": [ - "# confusing matrix\n", - "from sklearn.metrics import confusion_matrix\n", - "\n", - "print(confusion_matrix(y_train, y_train_pred))" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "id": "4338b3bb", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[9.93817058e-01 7.27404983e-04 3.63702491e-04 0.00000000e+00\n", - " 0.00000000e+00 1.45480997e-03 2.72776869e-03 1.81851246e-04\n", - " 1.81851246e-04 5.45553737e-04]\n", - " [1.59058374e-04 9.94432957e-01 1.74964212e-03 3.18116749e-04\n", - " 3.18116749e-04 1.59058374e-04 6.36233498e-04 1.43152537e-03\n", - " 3.18116749e-04 4.77175123e-04]\n", - " [6.43431635e-03 1.01876676e-02 9.61751564e-01 2.50223414e-03\n", - " 5.36193029e-04 7.14924039e-04 1.60857909e-03 1.39410188e-02\n", - " 1.96604111e-03 3.57462020e-04]\n", - " [1.05652404e-03 3.16957211e-03 6.51523155e-03 9.65662969e-01\n", - " 3.52174679e-04 1.02130657e-02 5.28262018e-04 4.40218348e-03\n", - " 5.81088220e-03 2.28913541e-03]\n", - " [5.50458716e-04 8.80733945e-03 5.50458716e-04 1.83486239e-04\n", - " 9.63486239e-01 0.00000000e+00 2.56880734e-03 2.01834862e-03\n", - " 3.66972477e-04 2.14678899e-02]\n", - " [3.55169692e-03 1.97316496e-03 9.86582478e-04 1.32202052e-02\n", - " 2.56511444e-03 9.61720600e-01 9.86582478e-03 7.89265983e-04\n", - " 1.57853197e-03 3.74901342e-03]\n", - " [4.87188741e-03 2.70660411e-03 1.80440274e-04 0.00000000e+00\n", - " 9.02201371e-04 3.24792494e-03 9.87549621e-01 0.00000000e+00\n", - " 5.41320823e-04 0.00000000e+00]\n", - " [1.71057133e-04 1.23161136e-02 2.05268560e-03 3.42114266e-04\n", - " 2.05268560e-03 1.71057133e-04 0.00000000e+00 9.72288744e-01\n", - " 3.42114266e-04 1.02634280e-02]\n", - " [4.54215116e-03 1.36264535e-02 4.54215116e-03 1.45348837e-02\n", - " 5.63226744e-03 1.59883721e-02 3.45203488e-03 3.08866279e-03\n", - " 9.26235465e-01 8.35755814e-03]\n", - " [2.16998192e-03 3.07414105e-03 1.44665461e-03 7.95660036e-03\n", - " 1.08499096e-02 2.71247740e-03 5.42495479e-04 1.19349005e-02\n", - " 1.44665461e-03 9.57866184e-01]]\n" - ] - } - ], - "source": [ - "cm = confusion_matrix(y_train, y_train_pred, normalize='true')\n", - "print(cm)" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "id": "dbccf666", - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd\n", - "import seaborn as sn" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "83cfa9e4", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "set_digits = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }\n", - "\n", - "df_cm = pd.DataFrame(cm, index=set_digits, columns=set_digits)\n", - "plt.figure(figsize = (10,7))\n", - "sn_plot = sn.heatmap(df_cm, annot=True, cmap=\"Greys\")\n", - "plt.ylabel(\"True Label\")\n", - "plt.xlabel(\"Predicted Label\")\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "id": "69dc2a66", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " precision recall f1-score support\n", - "\n", - " 0 0.98 0.99 0.99 5499\n", - " 1 0.95 0.99 0.97 6287\n", - " 2 0.98 0.96 0.97 5595\n", - " 3 0.96 0.97 0.96 5679\n", - " 4 0.98 0.96 0.97 5450\n", - " 5 0.96 0.96 0.96 5068\n", - " 6 0.98 0.99 0.98 5542\n", - " 7 0.96 0.97 0.97 5846\n", - " 8 0.99 0.93 0.96 5504\n", - " 9 0.95 0.96 0.96 5530\n", - "\n", - " accuracy 0.97 56000\n", - " macro avg 0.97 0.97 0.97 56000\n", - "weighted avg 0.97 0.97 0.97 56000\n", - "\n" - ] - } - ], - "source": [ - "from sklearn.metrics import classification_report\n", - "\n", - "print(classification_report(y_train, y_train_pred))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8d64b441", - "metadata": {}, - "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.8.5" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -}