diff --git a/README.md b/README.md index 1a226a88e387bc1d179b85e3026d77748b606e86..d2b6e1c6cf1935945aad867800ae221f2e452ae6 100644 --- a/README.md +++ b/README.md @@ -3,36 +3,55 @@ ## Introduction This is a Renku project - basically a git repository with some -bells and whistles. You'll find we have already created some -useful things like `data` and `notebooks` directories and -a `Dockerfile`. +bells and whistles. This is how to do the exercises on Renku. -## Working with the project +## Fork the Project -The simplest way to start your project is right from the Renku -platform - just click on the `Environments` tab and start a new session. -This will start an interactive environment right in your browser. +After Clicking on the ADML HSLU HS22 Project, you have a button "Fork" on the overview tab. When clicking on it you can duplicate this repository in your own namespace. -To work with the project anywhere outside the Renku platform, -click the `Settings` tab where you will find the -git repo URLs - use `git` to clone the project on whichever machine you want. + -### Changing interactive environment dependencies +Below you see the prompt you get when clicking on the Fork Button, you don't need to change anything just click on "Fork Project". (You won't get the title error as I do, because you don't have this repository yet.) -Initially we install a very minimal set of packages to keep the images small. -However, you can add python and conda packages in `requirements.txt` and -`environment.yml` to your heart's content. If you need more fine-grained -control over your environment, please see [the documentation](https://renku.readthedocs.io/en/latest/user/advanced_interfaces.html#dockerfile-modifications). + -## Project configuration +This has the advantage that you can save the changes to your notebook while working on it. When now going on your project page you have two "ADML HSLU HS22" project one with your namespace - this is the one you need to use from now on. +**Always use the ADML HSLU HS22 project with your name below** -Project options can be found in `.renku/renku.ini`. In this -project there is currently only one option, which specifies -the default type of environment to open, in this case `/lab` for -JupyterLab. You may also choose `/tree` to get to the "classic" Jupyter -interface. + + +## Starting a Session + +Click on the project and go to the Sessions tab, and click on the "New Session button". You should then see the below screen. + + + +When opening a session the first time after forking the project, you will encounter the Docker Image no available Error. This is not a problem, just click on building the branch image. It will now build your docker image. This can take some minutes. Afterwards you have a running session which looks like this: + + + +Click on the Open button and your Session will start. Or click on the three dots and choose open in new tab to have a better readability. Now you should see the folder structure as it is in the repository, open the notebook folder and you can see the notebooks adn open them by clicking on them. + + + +To save your work you can click on the save button from time to time. + + + +Then in the menu bar on the left, click on the third symbol (git-symbol). + + + +Then click on the plus, next to the "Changed" tab, like this your changes are added in the repository. + + + +In a last step, write a short description of what you did e.g. "Worked on Exercise 08B", and then click on the commit button. In this way, when opening a news session your changes will be restored. + + + +## Advanced Use + +If you are familiar with git you can use the project as a normal git repository, open it on GitLab and even open Sessions from different commits. -## Moving forward -Once you feel at home with your project, we recommend that you replace -this README file with your own project documentation! Happy data wrangling! diff --git a/img/add_change.png b/img/add_change.png new file mode 100644 index 0000000000000000000000000000000000000000..e9057c098db53d9518d0ac6a416bfbc2867a4a5c Binary files /dev/null and b/img/add_change.png differ diff --git a/img/commit.png b/img/commit.png new file mode 100644 index 0000000000000000000000000000000000000000..52612c61ed52683ac997ff1a56dfa1158a4681ad Binary files /dev/null and b/img/commit.png differ diff --git a/img/folder_structure.png b/img/folder_structure.png new file mode 100644 index 0000000000000000000000000000000000000000..11f3c3841630804f4c87bda14e309e8ef540d33d Binary files /dev/null and b/img/folder_structure.png differ diff --git a/img/fork.png b/img/fork.png new file mode 100644 index 0000000000000000000000000000000000000000..4fcd5e458592fda2aa64cae00252289624b40b93 Binary files /dev/null and b/img/fork.png differ diff --git a/img/fork_prompt.png b/img/fork_prompt.png new file mode 100644 index 0000000000000000000000000000000000000000..d504c4ed7d3736b9a0a3c13d1b9ede331ea20207 Binary files /dev/null and b/img/fork_prompt.png differ diff --git a/img/git_interface.png b/img/git_interface.png new file mode 100644 index 0000000000000000000000000000000000000000..444eb06a17ae4d97afe944995ec4928dd40d402c Binary files /dev/null and b/img/git_interface.png differ diff --git a/img/saving.png b/img/saving.png new file mode 100644 index 0000000000000000000000000000000000000000..4239eb5f0b5db9d63dbd8372f3286882a8a3467c Binary files /dev/null and b/img/saving.png differ diff --git a/img/session_overview.png b/img/session_overview.png new file mode 100644 index 0000000000000000000000000000000000000000..0d581b8bcffa1b494eb25778b15dbf26918bb274 Binary files /dev/null and b/img/session_overview.png differ diff --git a/img/your_project.png b/img/your_project.png new file mode 100644 index 0000000000000000000000000000000000000000..5c89b639a71fc94865ed7a2507ee8113d3dbdb02 Binary files /dev/null and b/img/your_project.png differ diff --git a/notebooks/01A Data Quality Assessment/Data Quality Assessment Examples.ipynb b/notebooks/01A Data Quality Assessment/Data Quality Assessment Examples.ipynb deleted file mode 100644 index 5631bfe133cc6911f2ae5c400208347c52b464be..0000000000000000000000000000000000000000 --- a/notebooks/01A Data Quality Assessment/Data Quality Assessment Examples.ipynb +++ /dev/null @@ -1,378 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Data Quality Assessment" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "ename": "ModuleNotFoundError", - "evalue": "No module named 'wordcloud'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", - "Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m<cell line: 7>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msklearn\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mlinear_model\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m LinearRegression\n\u001b[1;32m 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msklearn\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmetrics\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m mean_squared_error\n\u001b[0;32m----> 7\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mwordcloud\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m WordCloud\n\u001b[1;32m 8\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mwarnings\u001b[39;00m\n\u001b[1;32m 9\u001b[0m warnings\u001b[38;5;241m.\u001b[39mfilterwarnings(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mignore\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", - "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'wordcloud'" - ] - } - ], - "source": [ - "import pandas as pd\n", - "import numpy as np\n", - "import seaborn as sns\n", - "import matplotlib.pyplot as plt\n", - "from sklearn.linear_model import LinearRegression\n", - "from sklearn.metrics import mean_squared_error\n", - "from wordcloud import WordCloud\n", - "import warnings\n", - "warnings.filterwarnings(\"ignore\")\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = pd.read_csv(\"cars.csv\")\n", - "df.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Skewed Data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "horsepower = df[\"Horsepower\"]\n", - "horsepower.plot.hist()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"Mean:\", horsepower.mean())\n", - "print(\"Mode:\", int(horsepower.mode()))\n", - "print(\"\")\n", - "print(\"Mean - Mode = \", horsepower.mean() - int(horsepower.mode()))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Log-Transform Data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "horsepower_log = horsepower.apply(lambda x: np.log(x))\n", - "horsepower_log.plot.hist()\n", - "\n", - "print(\"Mean:\", horsepower_log.mean())\n", - "print(\"Mode:\", int(horsepower_log.mode()))\n", - "print(\"\\nMean - Mode = \", horsepower_log.mean() - int(horsepower_log.mode()))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Boxplots" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Horsepower" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fig, ax = plt.subplots(figsize=(12,8))\n", - "horsepower.plot.box(ax=ax)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "horsepower.describe()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "q3 = horsepower.describe().loc['75%']\n", - "q1 = horsepower.describe().loc['25%']\n", - "iqr = q3 - q1\n", - "upper_boundary = q3 + 1.5 * iqr\n", - "lower_boundary = q1 - 1.5 * iqr\n", - "\n", - "print(\"Upper boundary:\", upper_boundary, \"Lower boundary:\", lower_boundary)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Year" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "year = df[\"Year\"]\n", - "\n", - "fig, ax = plt.subplots(figsize=(12,8))\n", - "year.plot.box(ax=ax)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "year.describe()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "q3 = year.describe().loc['75%']\n", - "q1 = year.describe().loc['25%']\n", - "iqr = q3 - q1\n", - "upper_boundary = q3 + 1.5 * iqr\n", - "lower_boundary = q1 - 1.5 * iqr\n", - "\n", - "print(\"Upper boundary:\", upper_boundary, \"Lower boundary:\", lower_boundary)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Correlation" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plt.subplots(figsize=(10, 8))\n", - "sns.heatmap(df.corr(), annot=True, cmap='RdYlGn_r', linewidths=0.5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Dummy Variable Trap" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "colors = pd.get_dummies(df.Color)\n", - "colors.head()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plt.subplots(figsize=(10, 8))\n", - "sns.heatmap(colors.corr(), annot=True, cmap='RdYlGn_r', linewidths=0.5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Avoid Trap" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "colors = pd.get_dummies(df.Color, drop_first=True)\n", - "colors.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Numerical Encoding of Text" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### TF-IDF" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from sklearn.feature_extraction.text import TfidfVectorizer" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "corpus = [\n", - " \"The Limmat flows out of the lake.\", \n", - " \"The bears are in the bear pit near the river.\",\n", - " \"The Rhône flows out of Lake Geneva.\",\n", - " ]\n", - "\n", - "vectorizer = TfidfVectorizer()\n", - "vectors= vectorizer.fit_transform(corpus)\n", - "feature_names = vectorizer.get_feature_names()\n", - "dense = vectors.todense().tolist()\n", - "pd.DataFrame(dense, columns=feature_names).transpose()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Word Embeddings" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "from gensim.models import KeyedVectors\n", - "\n", - "vectors = KeyedVectors.load(\"../../cc.de.300-distilled.vec\", mmap=\"r\")\n", - "vectors.syn0norm = vectors.syn0" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "vectors[\"Mann\"]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "most_similar = vectors.wv.most_similar(positive=[\"Frau\", \"König\"], negative=[\"Mann\"])[0]\n", - "print(\"König - Mann + Frau = \", most_similar)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Profile Report" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import pandas_profiling\n", - "profile = df.profile_report(html={'style':{'full_width':True}})\n", - "# Save report\n", - "profile.to_file(output_file=\"c\")\n", - "profile" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.12" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/notebooks/01A Data Quality Assessment/Data Quality Assessment_Solution.ipynb b/notebooks/01A Data Quality Assessment/Data Quality Assessment.ipynb similarity index 100% rename from notebooks/01A Data Quality Assessment/Data Quality Assessment_Solution.ipynb rename to notebooks/01A Data Quality Assessment/Data Quality Assessment.ipynb diff --git a/notebooks/02A ML Fundamentals/Machine Learning Fundamentals - AutoScout.ipynb b/notebooks/02A ML Fundamentals/Machine Learning Fundamentals - AutoScout.ipynb index cfc69f13611b82e36fcc714bcfb71f5d60e9f55a..0513748e7da43eaf641d4c2f306dfbd8536a13fb 100644 --- a/notebooks/02A ML Fundamentals/Machine Learning Fundamentals - AutoScout.ipynb +++ b/notebooks/02A ML Fundamentals/Machine Learning Fundamentals - AutoScout.ipynb @@ -35,7 +35,7 @@ "\n", "import warnings\n", "from sklearn.exceptions import DataConversionWarning\n", - "warnings.filterwarnings(action='ignore', category=DataConversionWarning)\n", + "warnings.filterwarnings(action='ignore')\n", "\n", "%matplotlib inline" ] diff --git a/notebooks/07B Support Vector Machines/Support Vector Machine as Demo.ipynb b/notebooks/07B Support Vector Machines/Support Vector Machine as Demo.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..b1255cad192ce113e013859152f8112cc78df698 --- /dev/null +++ b/notebooks/07B Support Vector Machines/Support Vector Machine as Demo.ipynb @@ -0,0 +1,520 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Support Vector Machines" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Support Vector Machines (SVMs) are a powerful supervised learning algorithm used for both **classification** and **regression**. SVMs establish a hyperplane that separates the two classes by maximizing the margin." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "import matplotlib.pyplot as plt\n", + "\n", + "from scipy import stats\n", + "\n", + "import random\n", + "import seaborn\n", + "\n", + "import numpy as np\n", + "import pandas as pd\n", + "import pylab as pl\n", + "\n", + "import sklearn\n", + "\n", + "from sklearn.tree import DecisionTreeClassifier\n", + "from sklearn.datasets import make_blobs, make_circles\n", + "from sklearn.model_selection import train_test_split\n", + "\n", + "from sklearn.svm import SVC\n", + "from sklearn.metrics import accuracy_score, f1_score\n", + "\n", + "seaborn.set()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## A Simple Example" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.60)\n", + "plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='spring')\n", + "plt.xlim(-1, 3.5);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We fit a support vector machine with a linear kernel." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "solution2": "shown" + }, + "outputs": [], + "source": [ + "clf = SVC(kernel='linear')\n", + "clf.fit(X, y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We plot the decision boundary. In the following plot the dashed lines touch the *support vectors*, which are stored in the ``support_vectors_`` attribute of the classifier." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_svc_decision_function(clf, ax=None):\n", + " \"\"\"Plot the decision function for a 2D SVC\"\"\"\n", + " if ax is None:\n", + " ax = plt.gca()\n", + " x = np.linspace(plt.xlim()[0], plt.xlim()[1], 30)\n", + " y = np.linspace(plt.ylim()[0], plt.ylim()[1], 30)\n", + " Y, X = np.meshgrid(y, x)\n", + " P = np.zeros_like(X)\n", + " for i, xi in enumerate(x):\n", + " for j, yj in enumerate(y):\n", + " P[i, j] = clf.decision_function([[xi, yj]])\n", + " # plot the margins\n", + " ax.contour(X, Y, P, colors='k', levels=[-1, 0, 1], alpha=0.5, linestyles=['--', '-', '--'])\n", + " \n", + "plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='spring')\n", + "plot_svc_decision_function(clf)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We additoonally highlight the support vectors" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='spring')\n", + "plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=200, facecolors='none',edgecolors=\"black\");\n", + "plot_svc_decision_function(clf)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The dataset above was non-overlapping (or linearly separable), which means we could come up with a hyperplane that separated the dataset perfectly. Let us now consider a dataset where no perfect separation is possible. In this case the SVM tries to minimize the datapoints lying on the wrong side of the hyperplane. These datapoints are considered support vectors as well." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "At first, we generate the datapoints of the first class by sampling from a normal distribution with standard deviation 1.3 and mean (2,4)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "num_entries=100\n", + "X=np.zeros((2*num_entries,2))\n", + "\n", + "for i in range(0,num_entries):\n", + " X[i,0]=np.random.normal()*1.3+2\n", + " X[i,1]=np.random.normal()*1.3+4\n", + "y = num_entries*[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we sample the data points from the second class with standard deviation 1.0 and mean (1,0). " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "solution2": "shown" + }, + "outputs": [], + "source": [ + "for i in range(num_entries,2*num_entries):\n", + " X[i,0]=np.random.normal()+1\n", + " X[i,1]=np.random.normal()\n", + "y2 = num_entries*[1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us combine the class vectors `y` and `y2`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "y.extend(y2)\n", + "\n", + "assert len(X) == len(y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us visualize the generated data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='spring')\n", + "_ = plt.xlim(-1, 3.5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now fit a linear SVM to find the best separating hyperplane." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "solution2": "shown" + }, + "outputs": [], + "source": [ + "clf = SVC(kernel='linear')\n", + "clf.fit(X, y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us again visualize the hyperplane and the support vectors." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='spring')\n", + "plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=200, facecolors='none',edgecolors=\"black\");\n", + "plot_svc_decision_function(clf)\n", + "_ = plt.xlim(-1, 3.5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Support Vector Machine with Kernels\n", + "\n", + "Kernels are useful when the decision boundary is not linear. A Kernel is a similarity measure of two data points after projection to some higher dimensional space. Let us generate a data set that is even less linearly separable than the one before." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "X_circles, y_circles = make_circles(100, factor=.1, noise=.1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create and visualize a linear SVM and fit it to X and y" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "clf = SVC(kernel='linear').fit(X_circles, y_circles)\n", + "\n", + "plt.scatter(X_circles[:, 0], X_circles[:, 1], c=y_circles, s=50, cmap='spring')\n", + "plot_svc_decision_function(clf);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The kernel called **radial basis function (rbf)** will do the job" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "solution2": "shown" + }, + "outputs": [], + "source": [ + "clf = SVC(kernel='rbf')\n", + "clf.fit(X_circles, y_circles)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.scatter(X_circles[:, 0], X_circles[:, 1], c=y_circles, s=50, cmap='spring')\n", + "plot_svc_decision_function(clf)\n", + "plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=200, facecolors='none');" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Skin Disease Dataset\n", + "\n", + "We want to apply the SVM to segment skin diseases. Each row is an image pixel to which 14 different image filters have been applied (feature engineering, column t0 to t13). The class (target variable) indidates whether the pixel shows healthy skin or a skin disease (labels from medical doctors)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv(\"skin_disease.csv\")\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "SVMs are not very fast. In order to save time, we only use 50000 entries for training and validation. We also display a histogram of the target variable and observe that the data is extremely disbalanced. This is why we will use the f1-score for performance measurement below. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = df.sample(10000)\n", + "\n", + "_ = df['class'].hist()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us split this dataset into training and validation set (we do not need a test set here)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "train, valid = train_test_split(df, test_size=0.5)\n", + "\n", + "X_train = train.drop('class', axis=1)\n", + "X_valid = valid.drop('class', axis=1)\n", + "\n", + "y_train = train[\"class\"]\n", + "y_valid = valid[\"class\"]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We train and evaluate an SVM classifier on this dataset, which can take some minutes. \n", + "Let us first use the `rbf` kernel and a `gamma` value of 0.1.\n", + "We measure the f1-score and accuracy on the test set" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "solution2": "hidden", + "solution2_first": true + }, + "outputs": [], + "source": [ + "classifiers = {\n", + " 'SVM with RBF kernel' : SVC(kernel='rbf', gamma=0.1),\n", + " 'SVM with linear kernel' : SVC(),\n", + " 'Decision Tree' : DecisionTreeClassifier(max_depth=5)\n", + "}\n", + "\n", + "\n", + "for name, model in classifiers.items():\n", + "\n", + " model.fit(X_train, y_train)\n", + " y_pred = model.predict(X_valid)\n", + " f1 = f1_score(y_valid, y_pred)\n", + " \n", + " print (\"Performance of {} is {:.3f}:\".format(name, f1))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Playground for Exercises" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "data = [[0,0,-1], [3,0,-1], [0,2,1], [2,3,1]]\n", + "df = pd.DataFrame(data, columns=['x', 'y', 'label'])\n", + "\n", + "_ = plt.scatter(df['x'], df['y'], c=df['label'], s=50, cmap='rainbow')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "clf = SVC(kernel='linear').fit(df[['x', 'y']].values, df['label'])\n", + "\n", + "plt.scatter(df['x'], df['y'], c=df['label'], s=50, cmap='rainbow')\n", + "plt.quiver([0], [1], [0], [1], angles='xy', scale_units='xy', scale=1)\n", + "plot_svc_decision_function(clf);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = np.linspace(-5,5,100)\n", + "\n", + "plt.scatter(df['x'], df['y'], c=df['label'], s=50, cmap='rainbow')\n", + "plt.plot(x, 1/3 * x + 1, '-r', label='y = 1/3 * x + 1')\n", + "plt.plot(x, 0*x + 1, '-b', label='y = 1')\n", + "plt.quiver([0,0], [1,1], [0,1/3], [1,-1], angles='xy', scale_units='xy', scale=1)\n", + "\n", + "plt.axis((-5,5,-5,5))\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "solution2": "hidden" + }, + "outputs": [], + "source": [ + "y_pred = clf.predict(X_test)\n", + "accuracy = accuracy_score(y_test, y_pred)\n", + "f1 = f1_score(y_test, y_pred)\n", + "\n", + "print (\"f1 SVM:\", f1)\n", + "print (\"accuracy SVM:\", accuracy)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "jupytext": { + "text_representation": { + "extension": ".py", + "format_name": "percent", + "format_version": "1.2", + "jupytext_version": "0.8.6" + } + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.9.12" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/07B Support Vector Machines/Support Vector Machines as Demo.ipynb b/notebooks/07B Support Vector Machines/Support Vector Machines as Demo.ipynb deleted file mode 100644 index c2394b839deed0ce2449213a573f220bc2847718..0000000000000000000000000000000000000000 --- a/notebooks/07B Support Vector Machines/Support Vector Machines as Demo.ipynb +++ /dev/null @@ -1,756 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Support Vector Machines" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Support Vector Machines (SVMs) are a powerful supervised learning algorithm used for **classification** or for **regression**. SVMs establish a hyperplane that separates the dataset by maximizing the margin." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "import matplotlib.pyplot as plt\n", - "from mpl_toolkits import mplot3d\n", - "\n", - "import numpy as np\n", - "import seaborn; \n", - "\n", - "import sklearn\n", - "from sklearn.linear_model import LinearRegression\n", - "from sklearn.linear_model import LogisticRegression\n", - "from sklearn.datasets import make_blobs\n", - "from sklearn.datasets import make_circles\n", - "from sklearn.model_selection import train_test_split\n", - "from sklearn.svm import SVC\n", - "from sklearn.metrics import accuracy_score\n", - "from sklearn.metrics import f1_score\n", - "\n", - "import warnings\n", - "warnings.filterwarnings(\"ignore\", category=FutureWarning)\n", - "\n", - "from scipy import stats\n", - "import pylab as pl\n", - "import random\n", - "import pandas as pd\n", - "#from IPython.html.widgets.interaction import interact\n", - "import ipywidgets as widgets\n", - "seaborn.set()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Before starting with the exercises, watch the video from Josh Starmer on youtube." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from IPython.display import YouTubeVideo\n", - "YouTubeVideo('efR1C6CvhmE')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Part 1 - Simple Example" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "X, y = make_blobs(n_samples=60, centers=2,\n", - " random_state=0, cluster_std=0.60)\n", - "xfit = np.linspace(-1, 3.5)\n", - "plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='spring')\n", - "plt.xlim(-1, 3.5);" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "> Now fit the model by using the [SVC](https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html) class from scikit-learn. Use a `linear` kernel." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "solution2": "hidden", - "solution2_first": true - }, - "outputs": [], - "source": [ - "# START YOUR CODE\n", - "# clf = ...\n", - "# END YOUR CODE" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "*Click on the dots to display the solution*" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "jupyter": { - "source_hidden": true - }, - "solution2": "hidden", - "tags": [] - }, - "outputs": [], - "source": [ - "clf = SVC(kernel='linear')\n", - "clf.fit(X, y)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We plot de decision boundary. In the following plot the dashed lines touch a couple of the points known as *support vectors*, which are stored in the ``support_vectors_`` attribute of the classifier." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def plot_svc_decision_function(clf, ax=None):\n", - " \"\"\"Plot the decision function for a 2D SVC\"\"\"\n", - " if ax is None:\n", - " ax = plt.gca()\n", - " x = np.linspace(plt.xlim()[0], plt.xlim()[1], 30)\n", - " y = np.linspace(plt.ylim()[0], plt.ylim()[1], 30)\n", - " Y, X = np.meshgrid(y, x)\n", - " P = np.zeros_like(X)\n", - " for i, xi in enumerate(x):\n", - " for j, yj in enumerate(y):\n", - " P[i, j] = clf.decision_function([[xi, yj]])\n", - " # plot the margins\n", - " ax.contour(X, Y, P, colors='k',\n", - " levels=[-1, 0, 1], alpha=0.5,\n", - " linestyles=['--', '-', '--'])\n", - " \n", - "plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='spring')\n", - "print(clf.decision_function([[2,2],[1,3]]))\n", - "plot_svc_decision_function(clf)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we want to indicate the support vectors by sourrounding circles." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='spring')\n", - "plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1],\n", - " s=200, facecolors='none',edgecolors=\"black\");\n", - "plot_svc_decision_function(clf)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The dataset above was non-overlapping, which means we could come up with a hyperplane that separated the dataset perfectly. Let us now consider a dataset where no perfect separation is possible. In this case the SVM tries to minimize the datapoints lying on the wrong side of the hyperplane. These datapoints are considered support vectors as well." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "At first, we generate the datapoints of the first class by sampling from a normal distribution with standard deviation 1.3 and mean (2,4)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "num_entries=100\n", - "X=np.zeros((2*num_entries,2))\n", - "for i in range(0,num_entries):\n", - " X[i,0]=np.random.normal()*1.3+2\n", - " X[i,1]=np.random.normal()*1.3+4\n", - "y = num_entries*[0]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "> Now we sample the data points from the second class with standard deviation 1.0 and mean (1,0). " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "solution2": "hidden", - "solution2_first": true - }, - "outputs": [], - "source": [ - "# START YOUR CODE\n", - "# y2 = \n", - "# END YOUR CODE" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "*Click on the dots to display the solution*" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "jupyter": { - "source_hidden": true - }, - "solution2": "hidden", - "tags": [] - }, - "outputs": [], - "source": [ - "for i in range(num_entries,2*num_entries):\n", - " X[i,0]=np.random.normal()+1\n", - " X[i,1]=np.random.normal()\n", - "y2 = num_entries*[1]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us combine the class vectors `y` and `y2`" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "y.extend(y2)\n", - "\n", - "print (\"len X: \",len(X))\n", - "print (\"len y: \",len(y))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us visualize the generated data samples. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='spring')\n", - "plt.xlim(-1, 3.5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "> Now we train a linear SVM to find the best separating hyperplane." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "solution2": "hidden", - "solution2_first": true - }, - "outputs": [], - "source": [ - "# START YOUR CODE\n", - "# clf = ...\n", - "# END YOUR CODE" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "*Click on the dots to display the solution*" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "jupyter": { - "source_hidden": true - }, - "solution2": "hidden", - "tags": [] - }, - "outputs": [], - "source": [ - "clf = SVC(kernel='linear')\n", - "clf.fit(X, y)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us again visualize the hyperplane and the support vectors." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='spring')\n", - "plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1],\n", - " s=200, facecolors='none',edgecolors=\"black\");\n", - "plot_svc_decision_function(clf)\n", - "plt.xlim(-1, 3.5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Part 2 - Support Vector Machine with Kernels Classifier\n", - "\n", - "Kernels are useful when the decision boundary is not linear. A Kernel is some functional transformation of the input data. SVMs have clever tricks to ensure kernel calculations are efficient. In the example below, a linear boundary is not useful in separating the groups of points." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "X_circles, y_circles = make_circles(100, factor=.1, noise=.1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "> Create a linear SVM and fit it to X and y" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "solution2": "hidden", - "solution2_first": true - }, - "outputs": [], - "source": [ - "# START YOUR CODE\n", - "# clf = \n", - "# END YOUR CODE" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "*Click on the dots to display the solution*" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "jupyter": { - "source_hidden": true - }, - "solution2": "hidden", - "tags": [] - }, - "outputs": [], - "source": [ - "clf = SVC(kernel='linear').fit(X_circles, y_circles)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plt.scatter(X_circles[:, 0], X_circles[:, 1], c=y_circles, s=50, cmap='spring')\n", - "plot_svc_decision_function(clf);" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A simple model that could be useful is a **radial basis function (rbf)**:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "r = np.exp(-(X_circles[:, 0] ** 2 + X_circles[:, 1] ** 2))\n", - "\n", - "@widgets.interact(elev=[-90, 90], azip=(-180, 180))\n", - "def plot_3D(elev=30, azim=30):\n", - " #fig = plt.figure(figsize=(12,12))\n", - " #ax = fig.add_subplot(1, 1, 1, projection='3d')\n", - " ax = plt.subplot(projection='3d')\n", - " ax.scatter3D(X_circles[:, 0], X_circles[:, 1], r, c=y_circles, s=50, cmap='spring')\n", - " ax.view_init(elev=elev, azim=azim)\n", - " ax.set_xlabel('x')\n", - " ax.set_ylabel('y')\n", - " ax.set_zlabel('r')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In three dimensions, there is a clear separation between the data. \n", - "> Run the SVM with the `rbf` kernel." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "solution2": "hidden", - "solution2_first": true - }, - "outputs": [], - "source": [ - "# START YOUR CODE\n", - "# clf = ... # create an SVM with kernel=\"rbf\" (abbreviation for Radial Basis Function)\n", - "# END YOUR CODE" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "*Click on the dots to display the solution*" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "jupyter": { - "source_hidden": true - }, - "solution2": "hidden", - "tags": [] - }, - "outputs": [], - "source": [ - "clf = SVC(kernel='rbf')\n", - "clf.fit(X_circles, y_circles)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plt.scatter(X_circles[:, 0], X_circles[:, 1], c=y_circles, s=50, cmap='spring')\n", - "plot_svc_decision_function(clf)\n", - "plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1],\n", - " s=200, facecolors='none');" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Part 3 - Skin disease dataset\n", - "Now we want to apply the SVM on our skin disease data. Load this dataset using pandas." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = pd.read_csv(\"skin_disease.csv\")\n", - "df.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In order to save time, we only use 100000 entries for training / testing" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = df.sample(frac=1) # shuffling the data\n", - "df = df.iloc[0:100000]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us split this dataset into training and test set" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "train, test = train_test_split(df, test_size=0.5)\n", - "X_train = train.drop('class', axis=1)\n", - "X_test = test.drop('class', axis=1)\n", - "y_train = train[\"class\"]\n", - "y_test = test[\"class\"]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "> Now train an SVM classifier on this dataset, which can take some minutes. Use the `rbf` kernel and a `gamma` value of 0.1." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "solution2": "hidden", - "solution2_first": true - }, - "outputs": [], - "source": [ - "# START YOUR CODE\n", - "\n", - "# END YOUR CODE" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "*Click on the dots to display the solution*" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "jupyter": { - "source_hidden": true - }, - "solution2": "hidden", - "tags": [] - }, - "outputs": [], - "source": [ - "clf = SVC(kernel='rbf', gamma=0.1)\n", - "clf.fit(X_train, y_train)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "> Next, determine f-score and accuracy on the testset." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "solution2": "shown", - "solution2_first": true - }, - "outputs": [], - "source": [ - "# START YOUR CODE\n", - "# print (\"f1 SVM:\", f1)\n", - "# print (\"accuracy SVM:\", accuracy)\n", - "# END YOUR CODE" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "*Click on the dots to display the solution*" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "jupyter": { - "source_hidden": true - }, - "solution2": "shown", - "tags": [] - }, - "outputs": [], - "source": [ - "y_pred = clf.predict(X_test)\n", - "accuracy = accuracy_score(y_test, y_pred)\n", - "f1 = f1_score(y_test, y_pred)\n", - "\n", - "print (\"f1 SVM:\", f1)\n", - "print (\"accuracy SVM:\", accuracy)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "> and compare the result with a logistic regression model. Use the class [LogisticRegression](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html) from scikit-learn." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "solution2": "hidden", - "solution2_first": true - }, - "outputs": [], - "source": [ - "# START YOUR CODE\n", - "# print (\"accuracy logistic regression: \", accuracy)\n", - "# print (\"f1 logistic regression: \", f1)\n", - "# END YOUR CODE" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "*Click on the dots to display the solution*" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "jupyter": { - "source_hidden": true - }, - "solution2": "hidden", - "tags": [] - }, - "outputs": [], - "source": [ - "logReg = LogisticRegression()\n", - "logReg.fit(X_train, y_train)\n", - "\n", - "y_pred = logReg.predict(X_test)\n", - "accuracy = accuracy_score(y_test, y_pred)\n", - "f1 = f1_score(y_test, y_pred)\n", - "\n", - "print (\"accuracy logistic regression: \", accuracy)\n", - "print (\"f score logistic regression: \", f1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Final remarks:\n", - "* When using an SVM you need to choose the right values for parameters such as `C` and `gamma`. Model validation can help to determine these optimal values by trial and error.\n", - "* SVMs run in $O(n^3)$ performance. [LinearSVC](https://scikit-learn.org/stable/modules/generated/sklearn.svm.LinearSVC.html) is scalable, [SVC](https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html) does not seem to be scalable. For large data sets try transforming the data to a smaller space and use LinearSVC with rbf." - ] - } - ], - "metadata": { - "jupytext": { - "text_representation": { - "extension": ".py", - "format_name": "percent", - "format_version": "1.2", - "jupytext_version": "0.8.6" - } - }, - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.12" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/notebooks/09A Convolutional Neural Network/convolutional_neural_network.ipynb b/notebooks/09A Convolutional Neural Network/convolutional_neural_network.ipynb index f5af201860f1b0e089f59eab43a5af61a33b3981..485171886a52e98adf5a99674bee37b7324ea22c 100644 --- a/notebooks/09A Convolutional Neural Network/convolutional_neural_network.ipynb +++ b/notebooks/09A Convolutional Neural Network/convolutional_neural_network.ipynb @@ -50,7 +50,7 @@ "from tensorflow.keras.optimizers import SGD, Adam\n", "\n", "import warnings\n", - "warnings.filterwarnings(\"ignore\", category=FutureWarning)" + "warnings.filterwarnings(\"ignore\")" ] }, { @@ -321,7 +321,7 @@ "# model.add(...)\n", "\n", "# Define stochastic gradient descent with a defined learning rate\n", - "opt = Adam(lr=initial_lr)\n", + "opt = Adam(learning_rate=initial_lr)\n", "\n", "# Compile the model, using the optimizer, cross-entropy loss and accuracy as metric\n", "# model.compile(...)\n", diff --git a/notebooks/09B Transfer Learning/transfer_learning.ipynb b/notebooks/09B Transfer Learning/transfer_learning.ipynb index 02c1c80cddb4570f5c6bb34f96aaa74ff5930984..ddaef6607d72b19b602260812eece3124c685f12 100644 --- a/notebooks/09B Transfer Learning/transfer_learning.ipynb +++ b/notebooks/09B Transfer Learning/transfer_learning.ipynb @@ -47,7 +47,7 @@ "from tensorflow.keras.optimizers import SGD, Adam\n", "\n", "import warnings\n", - "warnings.filterwarnings(\"ignore\", category=FutureWarning)" + "warnings.filterwarnings(\"ignore\")" ] }, { diff --git a/notebooks/11A Clustering/Clustering Examples.ipynb b/notebooks/11A Clustering/Clustering Examples.ipynb deleted file mode 100644 index 105c350e4e7fb77d84462cdaabc67c7bcd5a42ac..0000000000000000000000000000000000000000 --- a/notebooks/11A Clustering/Clustering Examples.ipynb +++ /dev/null @@ -1,815 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Examples for lecture Clustering" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "import seaborn as sns; sns.set()\n", - "from sklearn.datasets import make_blobs\n", - "from sklearn.cluster import KMeans\n", - "from tqdm.notebook import tqdm\n", - "import pandas as pd\n", - "from ipywidgets import interact\n", - "\n", - "from mlxtend.preprocessing import TransactionEncoder\n", - "from mlxtend.frequent_patterns import apriori, association_rules\n", - "\n", - "import warnings\n", - "warnings.filterwarnings(\"ignore\", category=FutureWarning)\n", - "\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# k-Means Clustering" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## k-Means from Scratch" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Generate Data" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "X, _ = make_blobs(n_samples=20, centers=3, n_features=2, random_state=0)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "<matplotlib.collections.PathCollection at 0x7f1ebcb4a130>" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "<Figure size 864x504 with 1 Axes>" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "fig, ax = plt.subplots(figsize=(12,7))\n", - "ax.scatter(X[:, 0], X[:, 1])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Randomly choose k cluster centers" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "def initialize_centroids(X, k):\n", - " centroids = X.copy()\n", - " np.random.shuffle(centroids)\n", - " return centroids[:k]" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "<matplotlib.collections.PathCollection at 0x7f1ed8a2e580>" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "<Figure size 864x504 with 1 Axes>" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "centroids = initialize_centroids(X, k=3)\n", - "\n", - "fig, ax = plt.subplots(figsize=(12,7))\n", - "ax.scatter(X[:, 0], X[:, 1])\n", - "ax.scatter(centroids[:, 0], centroids[:, 1], s=300, marker=\"*\", c=\"g\", edgecolor=\"k\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Assign each data point to its nearest cluster center" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "def closest_centroid(X, centroids):\n", - " distances = np.sqrt(((X - centroids[:, np.newaxis])**2).sum(axis=2))\n", - " return np.argmin(distances, axis=0)" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([2, 0, 1, 1, 1, 0, 2, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1])" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "closest = closest_centroid(X, centroids)\n", - "closest" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Initial')" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "<Figure size 1080x504 with 1 Axes>" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "fig, ax = plt.subplots(figsize=(15,7))\n", - "ax.scatter(X[:, 0], X[:, 1])\n", - "ax.scatter(centroids[:, 0], centroids[:, 1], s=300, marker=\"*\", c=\"g\", edgecolor=\"k\")\n", - "ax.set_title(\"Initial\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Update each cluster center to the mean of all assigned data points" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "def move_centroids(X, closest, centroids):\n", - " return np.array([X[closest==k].mean(axis=0) for k in range(centroids.shape[0])])" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[-1.18890637, 2.86477332],\n", - " [ 2.28681654, 2.14842427],\n", - " [-1.05643028, 5.31335925]])" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "move_centroids(X, closest, centroids)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/lib/python3.9/site-packages/ipykernel/pylab/backend_inline.py:10: DeprecationWarning: `ipykernel.pylab.backend_inline` is deprecated, directly use `matplotlib_inline.backend_inline`\n", - " warnings.warn(\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "7b2371eca72648f096ab2f8395d31a24", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "interactive(children=(IntSlider(value=0, description='iteration', max=11), Output()), _dom_classes=('widget-in…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "num_iterations = 10\n", - "centroids_hist = [centroids]\n", - "centroids_moved = centroids\n", - "\n", - "for i in range(num_iterations):\n", - " closest = closest_centroid(X, centroids_moved)\n", - " centroids_moved = move_centroids(X, closest, centroids_moved)\n", - " centroids_hist.append(centroids_moved)\n", - "\n", - "@interact(iteration=(0, len(centroids_hist)))\n", - "def k_means_centroids(iteration=0):\n", - " fig, ax = plt.subplots(figsize=(15,7))\n", - " centroids = centroids_hist[iteration]\n", - " ax.scatter(X[:, 0], X[:, 1])\n", - " ax.scatter(centroids[:, 0], centroids[:, 1], s=300, marker=\"*\", c=\"g\", edgecolor=\"k\")\n", - " ax.set_title(\"Iteration {}\".format(iteration))\n", - " plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Implement the algorithm" - ] - }, - { - "attachments": { - "image.png": { - "image/png": "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" - } - }, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "def fit(X, k):\n", - " centroids = initialize_centroids(X, k)\n", - " closest_before = closest_centroid(X, centroids)\n", - "\n", - " while True:\n", - " closest = closest_centroid(X, centroids)\n", - " centroids = move_centroids(X, closest, centroids)\n", - " \n", - " if np.all(closest == closest_before):\n", - " break\n", - " closest_before = closest\n", - " return closest, centroids " - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "<matplotlib.collections.PathCollection at 0x7f1ed88a48b0>" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA20AAAGeCAYAAAAHa+lUAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAAsTAAALEwEAmpwYAAAj70lEQVR4nO3dfXCd130n9i8hkJD4AkqGKNGi4qUCW0drWHIsrWfDWDZ2x13VdOxtA7ezcdeJZttOXrabbabTSbetU69s1VJcu91oLU/W2rHNRrYidQ27iiSaEpsEa20Zz9qUkhAePmtjJcpKg5iCbUH0SmBAoH/wxXwBKcK8xHOA+/nMcESc597DH/UbgPd7z3nOXTU/Px8AAADq1NN2AQAAAJyd0AYAAFAxoQ0AAKBiQhsAAEDFhDYAAICK9bZdQJK+JG9N8hdJjrRcCwAAwFK7JMlrk/zbJDOnX6whtL01yVfbLgIAAKBlb0/y5OmDHQttpZRLk/wfSf6jJK8k2dM0zS+dx1P/Ikm+//0fZm6uez4zbmBgfaamDrVdBifRk/roSV30oz56Uh89qY+e1EU/FtbTsypXXLEuOZaNTtfJlbaP5WhYu75pmvlSytXn+bwjSTI3N99VoS1J1/19lwM9qY+e1EU/6qMn9dGT+uhJXfTjnBa8Xawjoa2Usj7JLya5tmma+SRpmuYvOzE3AABAN+vUSttgkqkkHyql/O0kh5J8sGmaM/ZjAgAAcP5Wzc9f+PJkKeXmJN9I8vebpvlCKeVvJvn9JK9vmmb6VZ6+NckzF1wEAADA8nZdkmdPH+zUSttzSWaTPJAkTdN8rZTyQpLrk3z9fCaYmjrUVftbN23akIMHX2q7DE6iJ/XRk7roR330pD56Uh89qYt+LKynZ1UGBtaf/Xon/pCmaV5I8odJ/k6SlFKuT3JVkm93Yn4AAIBu1cnTI38lyWdKKZ9I8ldJfqFpmh90cH4AAICu07HQ1jTNv0/ytzo1HwAAAB3aHgkAAMDFIbQBAABUTGgDAAComNAGAABQsU6eHgkAVGjP+GRGxyYyNT2Tgf6+jAwPZtvQ5rbLAuA8CW0AsILtGZ/Mjp37c3h2LkkyNT2THTv3J4ngBrBM2B4JACvY6NjEicB23OHZuYyOTbRUEQCLJbQBwAo2NT2zqHEA6iO0AcAKNtDft6hxAOojtAHACjYyPJg1vaf+c7+mtycjw4MtVQTAYjmIBABWsOOHjTg9EmD5EtoAYIXbNrRZSANYxmyPBAAAqJjQBgAAUDGhDQAAoGJCGwAAQMWENgAAgIoJbQAAABUT2gAAAComtAEAAFRMaAMAAKiY0AYAAFAxoQ0AAKBiQhsAAEDFhDYAAICKCW0AAAAVE9oAAAAqJrQBAABUTGgDAAComNAGAABQMaENAACgYkIbAABAxYQ2AACAigltAAAAFRPaAAAAKia0AQAAVExoAwAAqJjQBgAAUDGhDQAAoGJCGwAAQMWENgAAgIoJbQAAABXr7dREpZRnk7xy7FeS/A9N0+zq1PwAAADdqGOh7Zj/rGmafR2eEwAAoGvZHgkAAFCxVfPz8x2Z6Nj2yBeTrEryZJL/qWmaH5zHU7cmeaYjRQAAACxf1yV59vTBTm6PfHvTNN8ppfQl+WdJPpnkA+f75KmpQ5mb60yAXA42bdqQgwdfarsMTqIn9dGTuuhHffSkPnpSHz2pi34srKdnVQYG1p/9eqf+oKZpvnPsvzNJPpXkbZ2aGwAAoFt1JLSVUtaVUjYe+/2qJD+f5OlOzA0AANDNOrU98uokXyylXJLkkiTfTPIPOzT3ktszPpnRsYlMTc9koL8vI8OD2Ta0ue2yAACALtSR0NY0zb9P8pZOzNW2PeOT2bFzfw7PziVJpqZnsmPn/iQR3AAAgCXnyP/TjI5NnAhsxx2encvo2ERLFQEAAN1MaDvN1PTMosYBAAAuJqHtNAP9fYsaBwAAuJiEttOMDA9mTe+p/1vW9PZkZHiwpYoAAIBu1skP114Rjh824vRIAACgBkLbArYNbRbSAACAKghtANAinw0KwKsR2gCgJT4bFIDz4SASAGiJzwYF4HwIbQDQEp8NCsD5sD0SAFoy0N+3YEBbKZ8N6n49gM6w0gYALVnJnw16/H6946H0+P16e8YnW64MYPkR2gCgJduGNuf27TecWFkb6O/L7dtvWBGrUe7XA+gc2yMBoEUr9bNB3a8H0DlW2gCAjjvbfXkr5X49gKUktAEAi3bkyJF8+r5P5ciRIwteX8n36wEsNaENAFi0p576Rj517z15+um9C15fyffrASw197QBAIv2lScey5oNfdn1xGO55Za3LviYlXq/HsBSs9IGACzK3Nxcdu/elZ983415YveuzM3NvfqTAPixCW0AwKLs2/enWdXXk4Gbrsn86lUZH/+ztksCWNFsjwQAFmXXEzvT/6YrkyT9b7oyX3l8Z2688c0tV3WmPeOTGR2byNT0TAb6+zIyPGi7JrAsCW0AwBlefPEHuePO38wrh18549qf7H0qr/+lW5IkV9y0OV/+9L/KM8+d+aHZl665NB/64EeycePlF7vcM+wZn8yOnftPfMD31PRMduzcnySCG7Ds2B4JAJxh7dp1ufTSy7LnXz+Z51ZPZmrryyd+bf3ATVm/ZWOSZP2Wjdn6gZtOuf5c72T2/Osnc9lla7Nu3fpW6h8dmzgR2I47PDuX0bEzwyVA7ay0AQBnWL16dT76kY/l7T/zjtx59x1Zs64vm99+XVb1rDrjsZe/4ehWyfm5+Ux+9Zn84OuTueuuj+dd7/rZpS77hKnpmUWNA9TMShsAcFbbt78nD33hS1n97SOZ+MzeHH7pzO2SSXL4pVcy8Zm9Wf3tI3nwC19qNbAlOfH5cOc7DlAzoQ0AOKctW67N/Z97KLcO3ZoDvze+4GMOPDCeW4duzf2feyhbtly7xBWeaWR4MGt6T32Zs6a3JyPDgy1VBPDjsz0SAHhVq1evzpUDV6bv6rULXu+7em02Xbkpq1evXuLKFnb8sBGnRwIrgdAGAJyXnY8/msvfvSVJ8vLBQ/nuv3kuV73tdbls0/psvPGqPLbzkfzKL/+jlqv8kW1Dm4U0YEWwPRIAeFUHDjybqe+9kA1bX5ODX38+++/9Wm6+4sbsv/drOfiN59O/9TV54YUX8txzB9ouFWDFEdoAgFf1xO6vpP8NA3n2oX059OR389n7Pp8P33FXPnvf53Poq9/NgYf2ZeP1V2b37l1tlwqw4ghtAMCreuzxRzK59zu55ZqfyhcffDil3JAkKeWGfPHBh/OW1745k3ufy6O7fr/lSgFWHve0AQDnNDs7m5kfvpLfuusTue227Wdcv+yytbnzjrvzjrcN57fv+URmZ2fT2+slBkCn+IkKAJxTb29vHn1k96s+7rbbti8Y6gC4MLZHAgAAVMxKGwDAq9gzPukz34DWCG0AAOewZ3wyO3buz+HZuSTJ1PRMduzcnySCG7AkhDaAZcS7/bD0RscmTgS24w7PzmV0bML3H7AkhDaAZcK7/dCOqemZRY0vN94Mgvo5iARgmTjXu/3AxTPQ37eo8eXk+JtBxwPo8TeD9oxPtlwZcDKhDWCZWOnv9kOtRoYHs6b31JdMa3p7MjI82FJFnePNIFgebI8EWCYG+vsWDGgr4d1+qNnxrYIrcQuhN4Ngeeh4aCulfCjJP01yY9M0+zo9P0C3GhkePOWetmTlvNsPtds2tHlFhLTTeTMIloeObo8spdyc5KeTHOjkvAAcfdF4+/YbTryYGujvy+3bb1iRLySBpbGSt37CStKxlbZSSl+Se5O8P8kfdWpeAH5kpb7bD7RjJW/9hJWkk9sjP5zk/qZpni2ldHBaAAAuFm8GQf06EtpKKduS/I0k/+THnWNgYH0nSllWNm3a0HYJnEZP6qMnddGP+uhJffSkPnpSF/1YvE6ttA0n+etJnjm2ynZtkl2llH/QNM3j5zPB1NShzM3Nd6ic+m3atCEHD77UdhmcRE/qoyd10Y/66El99KQ+elIX/VhYT8+qcy5idSS0NU1zd5K7j39dSnk2yXucHgkAAHBhfLg2AABAxS7Kh2s3TbP1YswLAADQbay0AQAAVExoAwAAqJjQBgAAUDGhDQAAoGJCGwAAQMWENgAAgIoJbQAAABUT2gAAAComtAEAAFRMaAMAAKiY0AYAAFAxoQ0AAKBiQhsAAEDFhDYAAICKCW0AAAAVE9oAAAAqJrQBAABUTGgDAAComNAGAABQMaENAACgYr1tFwAA1G/P+GRGxyYyNT2Tgf6+jAwPZtvQ5rbLAugKQhsAcE57xiezY+f+HJ6dS5JMTc9kx879SSK4ASwB2yMBgHMaHZs4EdiOOzw7l9GxiZYqAuguQhsAcE5T0zOLGgegs4Q2AOCcBvr7FjUOQGcJbQDAOY0MD2ZN76kvGdb09mRkeLCligC6i4NIAIBzOn7YiNMjAdohtAEAr2rb0GYhDaAltkcCAABUTGgDAAComNAGAABQMaENAACgYkIbAABAxYQ2AACAigltAAAAFRPaAAAAKia0AQAAVExoAwAAqJjQBgAAULHetguA5WjP+GRGxyYyNT2Tgf6+jAwPZtvQ5rbLAgBgBRLaYJH2jE9mx879OTw7lySZmp7Jjp37k0RwAwCg42yPhEUaHZs4EdiOOzw7l9GxiZYqAgBgJevYSlsp5ctJrksyl+RQkl9rmubpTs0PtZianlnUOAAAXIhObo+8vWmaF5OklPKfJPlMkps7OD9UYaC/b8GANtDf10I1AACsdB3bHnk8sB2zMUdX3GDFGRkezJreU7911vT2ZGR4sKWKAABYyTp6EEkp5V8muS3JqiTv6uTcUIvjh404PRIAgKWwan5+vuOTllJ+Icn7m6Z593k8fGuSZzpeBAAAwPJyXZJnTx+8KKEtSUopLye5tmmaqVd56NYkz0xNHcrc3MWppUabNm3IwYMvtV0GJ9GT+uhJXfSjPnpSHz2pj57URT8W1tOzKgMD65OzhLaO3NNWSllfSvmJk75+b5LvHfsFAADAj6lT97StS/J/lVLWJTmSo2HtvU3TdM/SGQAAwEXQkdDWNM1fJvnpTswFAADAj3TsyH8AAAA6T2gDAAComNBGVzty5Eg+fd+ncuTIkbZLAQCABQltdLWnnvpGPnXvPXn66b1tlwIAAAsS2uhqX3nisazZ0JddTzzWdikAALAgoY2uNTc3l927d+Un33djnti9K3Nzc22XBAAAZxDa6Fr79v1pVvX1ZOCmazK/elWefvrptksCAIAzCG10rV1P7Ez/m65MkvS/6co8/MjDLVcEAABn6siHa0OtXnzxB7njzt/MK4dfOePan+x9Kq//pVuSJFfctDkP3PdAxvfvP+Nxl665NB/64EeycePlF7tcAAA4g9DGirZ27bpceull+cPdu7Plna/Pui0bT1zb+sabsv7Y1+u3bMxf+/s3Zeo/vHzi+g+ffzF//gffzrvf+3ezbt36Ja8dAAASoY0VbvXq1fnoRz6Wt//MO3Ln3Xdkzbq+bH77dVnVs+qMx17+hqNbJefn5jP51Wfyg69P5q67Pp53vetnl7psAAA4QWijK2zf/p7cdNNP5b/7jV/LxLf25nV/byhrNlx6xuMOv/RKnntwPJev6s+DX/hStmy5NkmyZ3wyo2MTmZqeyUB/X0aGB7NtaPNS/zUAAOhCDiKha2zZcm3u/9xDuXXo1hz4vfEFH3PggfHcOnRr7v/cQ6cEth0792dqeiZJMjU9kx0792fP+OSS1Q4AQPcS2ugqq1evzpUDV6bv6rULXu+7em02Xbkpq1evPjE2OjaRw7Onfobb4dm5jI5NXNRaAQAgEdroQjsffzSXv+mqJMnLBw/lwJe/mZcPHkqSbLzxqjz2+COnPP74CtvpzjYOAACdJLTRVQ4ceDZT33shG7a+Jge//nz23/u13HzFjdl/79dy8BvPp3/ra/LCCy/kuecOnHjOQH/fgnOdbRwAADpJaKOrPLH7K+l/w0CefWhfDj353Xz2vs/nw3fclc/e9/m8/G9eyIGH9mXj9Vdm9+5dJ54zMjyYNb2nfqus6e3JyPDgUpcPAEAXEtroKo89/kgm934nt1zzU/nigw+nlBuSJKXckD944v/JW1775kzufS6P7vr9E8/ZNrQ5t2+/4cTK2kB/X27ffoPTIwEAWBKO/KdrzM7OZuaHr+S/+oe/mQMzr8t/89t/fMrx/WvXrs2dd9ydd7xtOL99zycyOzub3t6j3yLbhjYLaQAAtMJKG12jt7c3H/yt+7Pv+6895/H9t922PY8+svtEYAMAgDYJbXQVx/cDALDcCG10Fcf3AwCw3AhtdBXH9wMAsNwIbXQVx/cDALDcOGmBrnL8BMjRsYlMTc+ccnokAMBytGd80mubFU5oo+s4vh8AWCn2jE9mx879Jw5aO34ydhKvd1YQ2yMBAGCZcjJ2dxDaAABgmXIydncQ2gAAYJlyMnZ3ENoAAGCZcjJ2d3AQCQAALFNOxu4OQhsAACxjTsZe+WyPBAAAqJjQBgAAUDGhDQAAoGJCGwAAQMWENgAAgIoJbQAAABUT2gAAAComtAEAAFRMaAMAAKiY0AYAAFCx3k5MUkoZSPK7SQaTHE7yrSS/3DTNwU7MDwAA0K06tdI2n+RjTdOUpmluTDKR5O4OzQ0AANC1OrLS1jTN95L80UlDf5zkVzsxNwAAQDdbNT8/39EJSyk9SR5P8nDTNPecx1O2Jnmmo0UAAAAsP9clefb0wY6stJ3mnyc5lOSTi3nS1NShzM11NkDWbNOmDTl48KW2y+AkelIfPamLftRHT+qjJ/XRk7rox8J6elZlYGD9Wa93NLSVUj6e5A1J3ts0zVwn5wYAAOhGHQttpZSPJrklyc82TTPTqXkBAAC6WaeO/B9K8j8m+XdJ/t9SSpI80zTNz3VifgAAgG7VqdMjx5Os6sRcAAAA/EinPqcNAACAi0BoAwAAqJjQBgAAUDGhDQAAoGJCGwAAQMWENgAAgIoJbQAAABUT2gAAAComtAEAAFRMaAMAAKiY0AYAAFAxoQ0AAKBiQhsAAEDFhDYAAICK9bZdAMBKtWd8MqNjE5manslAf19GhgezbWhz22UBAMuM0AZwEewZn8yOnftzeHYuSTI1PZMdO/cnieAGACyK0MZZWSWAH9/o2MSJwHbc4dm5jI5N+D4CABZFaGNBVgngwkxNzyxqHADgbBxEwoLOtUoAvLqB/r5FjQMAnI3QxoKsEsCFGRkezJreU3/EruntycjwYEsVAQDLle2RLGigv2/BgGaVAM7P8W3E7gsFAC6U0MaCRoYHT7mnLbFKAIu1bWizkAYAXDChjQVZJQAAgDoIbZyVVQIAAGifg0gAAAAqJrQBAABUTGgDAAComNAGAABQMQeRAABUaM/4pFOcgSRCGwBAdfaMT57yealT0zPZsXN/kghu0IVsjwQAqMzo2MSJwHbc4dm5jI5NtFQR0CahDQCgMlPTM4saB1Y2oQ0AoDID/X2LGgdWNqENAKAyI8ODWdN76su0Nb09GRkebKkioE0OIgEAqMzxw0acHgkkQhsAQJW2DW0W0oAktkcCAABUTWgDAAComNAGAABQMaENAACgYkIbAABAxTp2emQp5eNJ3pdka5Ibm6bZ16m5AQAAulUnV9q+nOQdSQ50cE4AAICu1rGVtqZpnkySUkqnpgQAAOh67mkDAACoWMdW2i7UwMD6tktYcps2bWi7BE6jJ/XRk7roR330pD56Uh89qYt+LF41oW1q6lDm5ubbLmPJbNq0IQcPvtR2GZxET+qjJ3XRj/roSX30pD56Uhf9WFhPz6pzLmLZHgkAAFCxjoW2Uso9pZTnk1ybZHcpZbxTcwMAAHSrTp4e+Y+T/ONOzQcAAIDtkQAAAFUT2gAAAComtAEAAFRMaAMAAKiY0AYAAFAxoQ0AAKBiHTvyHwCAc9szPpnRsYlMTc9koL8vI8OD2Ta0ue2ygMoJbQAAS2DP+GR27Nyfw7NzSZKp6Zns2Lk/SQQ34JxsjwQAWAKjYxMnAttxh2fnMjo20VJFwHIhtAEALIGp6ZlFjQMcJ7QBACyBgf6+RY0DHCe0AQAsgZHhwazpPfWl15renowMD7ZUEbBcCG0AAEtg29Dm3L79hhMrawP9fbl9+w1dcwjJkSNH8un7PpUjR460XQosO06PBABYItuGNndNSDvdU099I5+6957ccvNbc8stb227HFhWrLQBAHDRfeWJx7JmQ192PfFY26XAsiO0AQBwUc3NzWX37l35yffdmCd278rc3NyrPwk4QWgDAOCi2rfvT7OqrycDN12T+dWrMj7+Z22XBMuK0AYAwEW164md6X/TlUmS/jddma88vrPlimB5cRAJAAAX7MUXf5A77vzNvHL4lTOu/cnep/L6X7olSXLFTZvz5U//qzzz3MQZj7t0zaX50Ac/ko0bL7/Y5cKyIrQBAHDB1q5dl0svvSx/uHt3trzz9Vm3ZeOJa1vfeFPWH/t6/ZaN2fqBmzL1H14+cf2Hz7+YP/+Db+fd7/27Wbdu/ZLXDrUT2gAAuGCrV6/ORz/ysbz9Z96RO+++I2vW9WXz26/Lqp5VZzz28jcc3So5Pzefya8+kx98fTJ33fXxvOtdP7vUZcOy4J42AAA6Zvv29+ShL3wpq799JBOf2ZvDL525XTJJDr/0SiY+szerv30kD37hSwIbnIPQBgBAR23Zcm3u/9xDuXXo1hz4vfEFH3PggfHcOnRr7v/cQ9my5dolrhCWF6ENAICOW716da4cuDJ9V69d8Hrf1Wuz6cpNWb169RJXBsuP0AYAwEWx8/FHc/mbrkqSvHzwUA58+Zt5+eChJMnGG6/KY48/0mZ5sGwIbQAAdNyBA89m6nsvZMPW1+Tg15/P/nu/lpuvuDH77/1aDn7j+fRvfU1eeOGFPPfcgbZLheoJbQAAdNwTu7+S/jcM5NmH9uXQk9/NZ+/7fD58x1357H2fz6GvfjcHHtqXjddfmd27d7VdKlRPaAMAoOMee/yRTO79Tm655qfyxQcfTik3JElKuSFffPDhvOW1b87k3ufy6K7fb7lSqJ/PaQMAoKNmZ2cz88NX8lt3fSK33bb9jOuXXbY2d95xd97xtuH89j2fyOzsbHp7vSyFs/HdAQBAR/X29ubRR3a/6uNuu237gqEOOJXtkQAAABUT2gAAAComtAEAAFRMaAMAAKiYg0gAAFhW9oxPZnRsIlPTMxno78vI8GC2DW1uuyy4aIQ2AACWjT3jk9mxc38Oz84lSaamZ7Jj5/4kEdxYsWyPBABg2RgdmzgR2I47PDuX0bGJliqCi09oAwBg2ZianlnUOKwEQhsAAMvGQH/fosZhJRDaAABYNkaGB7Om99SXsGt6ezIyPNhSRXDxOYgEAIBl4/hhI06PpJsIbQAALCvbhjYLaXSVjoW2Usr1SXYkGUgyleQXm6b5VqfmBwAA6EadvKftd5Lc2zTN9UnuTfIvOjg3AABAV+pIaCulXJXk5iQPHBt6IMnNpZRNnZgfAACgW62an5+/4ElKKbck+T+bphk6aeybST7QNM3eV3n61iTPXHARAAAAy9t1SZ49fbCag0impg5lbu7CA+RysWnThhw8+FLbZXASPamPntRFP+qjJ/XRk/roSV30Y2E9PasyMLD+7Nc79Od8J8mWUsolSXLsv9ccGwcAAODH1JHQ1jTNd5M8neT9x4ben+SppmkOdmJ+AACAbtXJ7ZG/kmRHKeV/SfL9JL/YwbkBAAC6UsdCW9M0+5P8zU7NBwAAQGc/pw0AAIAOE9oAAAAqJrQBAABUTGgDAAComNAGAABQMaENAACgYkIbAABAxYQ2AACAigltAAAAFRPaAAAAKia0AQAAVExoAwAAqJjQBgAAUDGhDQAAoGJCGwAAQMWENgAAgIoJbQAAABUT2gAAAComtAEAAFSst+0CAAAALrY945MZHZvI1PRMBvr7MjI8mG1Dm9su67wIbQAAwIq2Z3wyO3buz+HZuSTJ1PRMduzcnyTLIrjZHgkAAKxoo2MTJwLbcYdn5zI6NtFSRYsjtAEAACva1PTMosZrI7QBAAAr2kB/36LGayO0AQAAK9rI8GDW9J4afdb09mRkeLClihbHQSQAAMCKdvywEadHAgAAVGrb0OZlE9JOZ3skAABAxYQ2AACAigltAAAAFRPaAAAAKia0AQAAVExoAwAAqJjQBgAAUDGhDQAAoGJCGwAAQMWENgAAgIoJbQAAABUT2gAAAComtAEAAFRMaAMAAKhY74VOUEr5QJLfSPLGJL/eNM0nL7gqAAAAknRmpe3pJD+f5AsdmAsAAICTXPBKW9M0+5KklDJ34eUAAABwMve0AQAAVOxVV9pKKXuTvO4sl69umuZIJwoZGFjfiWmWlU2bNrRdAqfRk/roSV30oz56Uh89qY+e1EU/Fu9VQ1vTNDcvRSFTU4cyNze/FH9UFTZt2pCDB19quwxOoif10ZO66Ed9LqQne8YnMzo2kanpmQz092VkeDDbhjZ3uMLu4/ukPnpSF/1YWE/PqnMuYl3wPW0AwPKyZ3wyO3buz+HZo7ejT03PZMfO/UkiuAFU6ILvaSulvL+U8nyS/zzJR0opz5dS3njhpQEAF8Po2MSJwHbc4dm5jI5NtFQRAOfSidMjH0jyQAdqAQCWwNT0zKLGAWiX0yMBoMsM9PctahyAdgltANBlRoYHs6b31JcAa3p7MjI82FJFAJyLg0gAoMscP2zE6ZEAy4PQBgBdaNvQZiENYJmwPRIAAKBiQhsAAEDFhDYAAICKCW0AAAAVE9oAAAAqJrQBAABUTGgDAAComNAGAABQMaENAACgYkIbAABAxYQ2AACAivW2XUCSS5Kkp2dV23UsuW78O9dOT+qjJ3XRj/roSX30pD56Uhf9ONNJ/08uWej6qvn5+aWrZmG3Jvlq20UAAAC07O1Jnjx9sIbQ1pfkrUn+IsmRlmsBAABYapckeW2Sf5tk5vSLNYQ2AAAAzsJBJAAAABUT2gAAAComtAEAAFRMaAMAAKiY0AYAAFAxoQ0AAKBiQhsAAEDFetsuoJuVUv7nJH8vRz9UfFWSu5qmebDdqrpbKeXeJO/M0Q81PJTkv22a5uvtVtXdSikfSPIbSd6Y5NebpvlkyyV1pVLK9Ul2JBlIMpXkF5um+Va7VXWvUsrHk7wvydYkNzZNs6/dirpbKWUgye8mGUxyOMm3kvxy0zQHWy2sy5VSvpzkuiRzOfpv+q81TfN0mzWRlFI+lOSfxs+uRbHS1q5PNk1zU9M0b0ny7iT3lVKuaLuoLrczR3+IvDnJXUmE6PY9neTnk3yh5Tq63e8kubdpmuuT3JvkX7RcT7f7cpJ3JDnQch0cNZ/kY03TlKZpbkwykeTulmsiub1pmjcfe5318SSfabugbldKuTnJT8fPrkUT2lrUNM2LJ325Pkd/6OtJi5qmeaRpmr869uWeJNeWUvSkRU3T7Gua5ps5+k4pLSilXJXk5iQPHBt6IMnNpZRN7VXV3ZqmebJpmu+0XQdHNU3zvaZp/uikoT9O8tdaKodjTnudtTH+HWlVKaUvR9/0+9W2a1mObI9sWSnlV5L8epKfSPJfNk0z1W5FnOQfJXm0aRo/5Ol2P5Hkz5umOZIkTdMcKaX8f8fGbf+Ckxx7o+9Xkzzcdi0kpZR/meS2HL0N5V0tl9PtPpzk/qZpni2ltF3LsiO0XUSllL1JXneWy1c3TXOkaZrfSfI7pZQbk3y+lLJbcLt4zqcnxx7380n+ixzdfsRFdL49AVgm/nmO3j/l/tsKNE3zXydJKeUXkvxvOXo7CkuslLItyd9I8k/armW5EtouoqZpbl7EY//s2DvXfyvJFy9aUV3ufHpSSvm5JP9rknc2TfOXF7+q7raY7xNa850kW0oplxxbZbskyTXHxoFjjh0Q84Yk77VLoy5N0/xuKeXTpZQBb463YjjJX0/yzLFVtmuT7Cql/IOmaR5vtbJlwr06LSqlvPGk31+X5C1JvtleRZRS3pPkf0/yHzdN82zL5UAVmqb5bo4eCPP+Y0PvT/KUk/HgR0opH01yS5L/tGmambbr6XallPWllJ846ev3JvnesV8ssaZp7m6a5pqmabY2TbM1yfM5+lpLYDtPq+bn59uuoWuVUh5KMpTkr3L02P+POfK/XaWUgzl6XPPJL0bf6V259pRS3p+jW1quyNHe/DDJbccOJ2GJlFJuyNEj/69I8v0cPfK/abeq7lVKuSfJSJLNSV5IMtU0zVC7VXWvUspQkn1J/l2Sl48NP9M0zc+1V1V3K6VcneT/TrIuR19jfS/Jf980zd5WCyNJUkp5Nsl7HPl//oQ2AACAitkeCQAAUDGhDQAAoGJCGwAAQMWENgAAgIoJbQAAABUT2gAAAComtAEAAFRMaAMAAKjY/w8FSzFayYvijwAAAABJRU5ErkJggg==\n", - "text/plain": [ - "<Figure size 1080x504 with 1 Axes>" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "closest, centroids = fit(X, k=3)\n", - "\n", - "fig, ax = plt.subplots(figsize=(15,7))\n", - "ax.scatter(X[:, 0], X[:, 1])\n", - "ax.scatter(centroids[:, 0], centroids[:, 1], s=300, marker=\"*\", c=\"g\", edgecolor=\"k\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Scikit-Learn" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "model = KMeans(n_clusters=3, random_state=0).fit(X)" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([2, 0, 2, 1, 1, 0, 0, 1, 2, 2, 1, 2, 0, 1, 2, 0, 2, 0, 1, 2],\n", - " dtype=int32)" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "model.labels_" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "<matplotlib.collections.PathCollection at 0x7f1ed884a190>" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "<Figure size 1080x504 with 1 Axes>" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "centroids = model.cluster_centers_\n", - "\n", - "fig, ax = plt.subplots(figsize=(15,7))\n", - "ax.scatter(X[:, 0], X[:, 1])\n", - "ax.scatter(centroids[:, 0], centroids[:, 1], s=300, marker=\"*\", c=\"g\", edgecolor=\"k\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Distortion" - ] - }, - { - "attachments": { - "image.png": { - "image/png": "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" - } - }, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "33.94471513755734" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "model.inertia_" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Average Distortion" - ] - }, - { - "attachments": { - "image.png": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPkAAABpCAYAAAD4KYXTAAAOFklEQVR4Ae2dK5TVMBCGFwcOHBIcEolEIpFIJBKJwyGRSCQSiUQikTiQOJA4uJzvnvPvyXaT3D7StMn9xT3ppm1eM9/MJE27F//+/Tv45zGwDvSrAxcWbr/CtWwtW3TAkDuScSTXuQ4Y8s4FbG9ub27IDbk9eec6YMg7F7A9uT25ITfk9uSd64Ah71zA9uT25IbckNuTd64DhrxzAduT25MbckNuT965DhjyzgVsT25PfhaQf/369fD27dvDjx8/Lr3Wt2/fjnkfPnw4/Pnz5zLfUBiK3nSge8gB/M2bN8ffzZs3j6C/fv368OrVq8Pnz5+PoJPPcW/CdX9ssNCB7iF/8eLF0VPjuS8uLg537949gh0CQN6zZ88MuacuXepA15D//v37AOQA/e7duyPkL1++vCZI4Dfk9nqh4e/puGvIERSgkwI7MP/8+fMK5ITz5BPS9yRY98VGSzrQPeTq6L179w4PHz68BjJwA/mXL1+undO9Tg1MyzpwFpCzqg7IsVAd8DEAEuLQ0yvfqUFvVQdWhRxgPn78eAnQVoP0/v37I+SkYRsUqrPSTj6P01h5D6/xseFuXQdWgZx5MAtdt2/fPjx//nxzaGgDnhyoQ4EpVNfjs6dPn16bs4fX+9jAt6gDxSAHoMePHx9/PJJ68ODBEaw9QE5IHpuPE2nwjJyNMqyuf/r06YoRaFGgbrMN0VAHikGO98Yj8jyaShQi7wFy4E3NtZmvE6anzg8HzH8botZ0oBjkw47vCfJh2/y3QT0nHTDk3uXlKUrnOmDIOxfwOXks9zUeoRlyQ25P3rkOGPLOBWzvFvdu5zQuhtyQ25N3rgOGvHMBn5PHcl/jUYshN+T25J3rQDOQ83IJu9PYnrqHX+xlF3uSuCfxuGw7Ls1ArvfBQ8DZPssLJSV+lK9tuey5D+uJHWNw/G24bZW3V+OhXaOl+tcM5ACl/fAhdMM3y0oNDNtc9Q04XlyJRRHseS9Vn8s5b4PB9wyePHly6WjQN/Ru+FLVHD1pBnI6h4UbwobXDb/COmcQxtzD3nwMCtGDjEzspZcxZfma8wZ6KH8Brq8YcR4ng36h70s/aNIU5HQe7ynIlD569KiaRyWi4P1zGZulAhgK3H+fnwFAf2PfXcCL37hx4wj7379/Z+t4c5ADAWGMAFda+2MPRBV8UcYfgDw/KEsb4lu3bh31+fv379dA1rlfv35dOze2HatBrq+jMs8Y25ix1xHWhGGzQK/tVQGddkx5TZXXXnPzLM75o5LtGQ50Ul8YSukxT2RiukI+oXlsIffOnTtJA5CqZ5hfDHI6qVVuGh2uUPNOuc7pKyzDhkz9m3IEt1I8azivmVrmnOuZPkyBklX83GIh58Jvzs1pk++pbyRwMOhhbuw5P0X/cSKE6ziSXYTrWCE6cOpXcpEMwyHAldb+SAX9JmrJCTc8R/sMeX0IQxmscSynkyt7KuQ4S+6Zol+x+ot58ljhNfJYtBDgSnMQ1WhTrg5D3h/gyLs05EQGLO6WWGtqHnIig3BqAOi1HqvlYE6dM+SGPKUbymfKef/+/UnTQN0bS5uHnE7x+EFeXGnNx2qxgU3lGXJDntIN8pn+obslo9EuIGdwgEeAKy0R6uQEMuecITfkKb0BcB4PD78azFRgyYJyN5AzQLFtr7Ufq6UEqHxDbsilC2GK/qY+Cw74nA+vn3LcDeR0OrbtdYvHajkBGHJDPtQPvDQvRwGzHjUr5dn7bh6hDRu+1d+xba+AtVV7hvXOhZx+SfDDNAzlWJ8Ynufv8Jphm1r9mzEp+Uh2yTgsWV2PPSHSlJN06Yayrjy5hBTb9lpyIUP1zEnnQk4oh7XXnnmEzzF54S4qyg8VRMd7gWHOmMXu4R9i0LfURiT6y/jU2na8BPKYUQ7zYvvaY2OSyusScrzWcNvrXh6rzYVcAmRRRuCSDjdKMHdjiyT9RfF0X2+pDHkKACBhfEhr9H0J5Gu3r0vIGTQNegjEHh6rLYWcvoVTErxVuLhI+eTl9seHSoVRCCOB8Nyej7U3IjUNIcJB9mPHYWlfpW+5cmjPFoa3W8gZbFnzEPRalj0l7BKQU3b4pRyiFsJT9Xf4CCbVFgDn3tbeiwdcZJpqN/3C0PFL9b10fpeQM9B0bOmPFfHSAx6WF1vUCD1feG2N41KQo8gsyMiA8RSB4ylrD5RB2DvlHo0RhgSjMvfHXHqul1Ukw95utSdMBRzePMxf81h15upAPlyXu2aNc7M9OcrBIC794ZHW6JjKxMMptBMQKInO105LQU67CVXDvQEpz1a6j9S7VO7cz1jMadve5uP0oUvI5whnq3vCba8oyFbtoN6SkFOelEsGLLXavGWfS9cto31qPl7Ta0oOub4258lzndnbOb3Rg6cjRN2yfSUhJ0ohTB9OSXi8dKqP3Lv2VOlUG+ac13ycCCZ2fzgfHytrxgFIx14fq9eQb/jxepSZxSUtTsUEVDOvFOR4MYwWP441T8VbsOCU82LsomIuzZy21nPkUmOsfqYiMsHGdEB1suYQe4LAGDB+pNzHWMydPqpe1RlL7clXMAQoPxZ/yiOlmHBK5pWAHI+D9x4arnDFnZAWAzdsOwtmCulRbhQvFfYO793D35qPpxbd9KGF8FNMgBy2nfHDCAB12HfKTq3Ih9eFZenYkK8AsAY3l2r1ObVhInfvWueWQo6C0i8gHq5OS3kBl19s3z71S2FRfgzFWn1do1zNx2OePHx3QU8MyBtGKxhDYNY4qJ04hJjxwGAMy9A9Sg35BpDLostrSRhbp3MgRxkVXgMlAKOkMYVUvwW6wlEpvby7ds7Fyth6jFL1az5O34Ado6ZrWXcBfIXz6i9Ah/sGuI77p/QbQ8FPdcVSQ14Zcgn6lPWNCWvtvDmQM5+MPbKK9S92HXlDpaYdGIrYXHXtMZhbvuRKJAPQMmD0L4xQ8LycA3CMY1ifpiil90oY8oqQy0Mh+NDSh4Le8ngO5KXby7jgCWNGonRdJcsDbLzwmKcHqXopg76nzof5RD0YljEGwZBXgpyQCgHG5qKh8LY83gPkMoSChRQl3XJcxtSNbIF8OJcec6+uwbvn1iEoGyOILhH9kBLxnHIYhrwC5AgHuFGEU/MnCXyLdA+QE7JKcVHePby4c0oWmo8ToZ26NndeG6Ni3pk8pgKMCWOETqFLGBatZaTKNuQrQy5FRRjhIktKIKXzh6975srfA+QAgzFkrAhfYwqf68MW5zQfH86x57QFGWAsFMGwSMfUBc+tKEEp9eE8TtVjyFeGHAEB+BTYTglt7Hk8A0oz9vo9QE5b8VAoeSsLb5qPl5pWYOjov0AX1KEccR6E9hiYMD92bMhXhJxHZAA+XD2OCaJ0HkrAKu4UxdsL5KXHYu3yGGeiD8Z87bpUPnJlWoMBwCjkokRDvhLkWGEAZx4lwdRKUTbqHRPKhW3i8Y6e4Yb5Oubc1DJ1b88pc+LaUQeOgygRyElzBkZz95wM0NUpDiFX1pRzs181VSV0nMHAQzEQoSCwfuSj2IRbpLGwSGVNSZlHYmXZpVSqzLH1o3DM6RDa1Dki45NTFtpwapFnbDt93bIvwwIuq/Ho7RiZcH1uzMeUkbt/7rnFkDNfkXUCOH40hjCawZFCAyLhVomVXAaLuRK/mgMHoBg04NavZv1zhez7lsHe+vgtghyA8dAaBLw2yo9Hjy2CEd5yPje3UVmpFGPB/AwvXmNVGLAJodV2wU1awmCl+un88wazpPwXQY4HD8NVlB7lB/ZYI7VCmpuTxu4L8wQbdVH3Gj/qIBzHkIRQD49jhixsq48N6h50YBHkAKZQHa8OFPzCeXnYSUJ5QJnryYeh8hC6mn/Tz9prAeFY+tgGZKwOLII8rATYgSwM38PzAMH5uXDg/WtCfKoupiRh/3xs6PaqA8Ugx6sDRiqE1eOupdsS9zqQbpch36sOFIOcxTAgT6024/lyRmCvA+R2Gd7WdaAI5ArFU5s4NF8H8nC+Hh63PpBuv43BXnWgCOR6syc1T42F6oT15O91YNwuQ9uLDhSBXKveqY38enQWnucxlT25QeoFpD33owjkmo+zjTXWWT0/13yd6zAMsWudZ/CtA2V1YDHkzLeZa+e+toEH59EZ1wI6XpxjC7OsMD2eHs+YDiyGnEKBNje/ZmGOjf6E7eyGc5huZYwpo/PW0YsikG8pHHbP5QxMqbZhqIhISEuV6XLWUWqP69VxbRpyPZpb60UR7c0n+mA6ktsHYMW6qlgej/2MR9OQo0hsd9WCXmnFEuQsFGpH31p1lW67y9sPZFvLonnIaw2gITc0tXStdD2GfOSnqQy5IS8NX63ymoSc1XmgY8W+xocjEIYhN+S1oCxdT3OQs9jGQhir3GyNHe6XVz5QTv3p3fjYIBtyQx7TixbymoOcx1jaWcd35LTJRoPNx/Smwq3rc/8B1ZAbculYa2mTkGuQ2U5b6/10Q27IpXetpc1BrgHGm/Pcesn34lTWmNSQG/IxerLHa5qFnNdaa/5HDUNuyPcI8Jg2NQk5q+vMxfUmGxtUtB8eD08IP+eXeh+egTTkhnwMUHu8pknIWXwjVNcCHLALclbfWSWf81N5MUEZckMe04sW8pqEnEdnhOoMMGDmPHApIfDfYDAsfAWnVJkux4ajhg40CTlem5dS9PrqWu+mY0Dw4EQKYfhPHr8aAnIdNgRLdaBJyJd22vcbnHPSAUM+cu/6OSmF+9qXETTkhtzTjs51wJB3LmB75b688hx5GnJDbk/euQ4Y8s4FPMfy+56+vL8hN+T25J3rgCHvXMD2yn155TnyNOSG3J68cx34D6fTBQTcrFQAAAAAAElFTkSuQmCC" - } - }, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1.6972357568778669" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "model.inertia_ / len(X)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Convergence" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "<matplotlib.collections.PathCollection at 0x7f1ebca93640>" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "<Figure size 864x504 with 1 Axes>" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "X = np.array([\n", - " [2, 2],\n", - " [2, 8],\n", - " [10, 8],\n", - " [10, 2]\n", - "])\n", - "\n", - "fig, ax = plt.subplots(figsize=(12,7))\n", - "ax.set_xlim(0, 12)\n", - "ax.set_ylim(0, 10)\n", - "ax.scatter(X[:, 0], X[:, 1])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Our implementation" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "<matplotlib.collections.PathCollection at 0x7f1ebc9a7670>" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "<Figure size 1080x504 with 1 Axes>" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "closest, centroids = fit(X, k=2)\n", - "\n", - "fig, ax = plt.subplots(figsize=(15,7))\n", - "ax.scatter(X[:, 0], X[:, 1])\n", - "ax.scatter(centroids[:, 0], centroids[:, 1], s=300, marker=\"*\", c=\"g\", edgecolor=\"k\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Scikit-Learn" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "<matplotlib.collections.PathCollection at 0x7f1ebc998400>" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "<Figure size 1080x504 with 1 Axes>" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "model = KMeans(n_clusters=2, random_state=0, n_init=10, init=\"k-means++\").fit(X)\n", - "centroids = model.cluster_centers_\n", - "\n", - "fig, ax = plt.subplots(figsize=(15,7))\n", - "ax.scatter(X[:, 0], X[:, 1])\n", - "ax.scatter(centroids[:, 0], centroids[:, 1], s=300, marker=\"*\", c=\"g\", edgecolor=\"k\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Number of Clusters" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "<matplotlib.collections.PathCollection at 0x7f1ebc9db2b0>" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "<Figure size 864x504 with 1 Axes>" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "X, _ = make_blobs(n_samples=100, centers=4, n_features=2, random_state=0)\n", - "fig, ax = plt.subplots(figsize=(12,7))\n", - "ax.scatter(X[:, 0], X[:, 1])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Elbow Plot" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "data": { - "application/json": { - "ascii": false, - "bar_format": null, - "colour": null, - "elapsed": 0.19910264015197754, - "initial": 0, - "n": 0, - "ncols": null, - "nrows": null, - "postfix": null, - "prefix": "", - "rate": null, - "total": 9, - "unit": "it", - "unit_divisor": 1000, - "unit_scale": false - }, - "application/vnd.jupyter.widget-view+json": { - "model_id": "ef68a6d987de4bb3a56051c1363d3767", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/9 [00:00<?, ?it/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "<AxesSubplot:xlabel='x'>" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "<Figure size 576x432 with 1 Axes>" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "distortions = []\n", - "k_values = range(1,10)\n", - "for k in tqdm(k_values):\n", - " model = KMeans(n_clusters=k, random_state=0).fit(X)\n", - " distortions.append(model.inertia_)\n", - " \n", - "pd.DataFrame(dict(x=k_values, y=distortions)).plot(x=\"x\", y=\"y\", xticks=k_values, grid=True, figsize=(8,6))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.12" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/notebooks/11A Clustering/Clustering.ipynb b/notebooks/11A Clustering/Clustering.ipynb index 1460ec9dad8053d61552d2c8728f8049acc47bb0..b327d1df7a44bedd69f0ba19c144c059bce67495 100644 --- a/notebooks/11A Clustering/Clustering.ipynb +++ b/notebooks/11A Clustering/Clustering.ipynb @@ -31,7 +31,7 @@ "\n", "from tqdm.notebook import tqdm\n", "import warnings\n", - "warnings.filterwarnings(\"ignore\", category=FutureWarning)\n", + "warnings.filterwarnings(\"ignore\")\n", "\n", "%matplotlib inline" ] @@ -211,9 +211,6 @@ { "cell_type": "markdown", "metadata": { - "jupyter": { - "source_hidden": true - }, "solution2": "hidden", "tags": [] }, diff --git a/notebooks/12A Association Rules/Association Rules Examples.ipynb b/notebooks/12A Association Rules/Association Rules Examples.ipynb deleted file mode 100644 index 59d06fd321364a6adf1755a4c6fe71ad75a797d1..0000000000000000000000000000000000000000 --- a/notebooks/12A Association Rules/Association Rules Examples.ipynb +++ /dev/null @@ -1,152 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Examples for lecture Association Rules" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "import seaborn as sns; sns.set()\n", - "from tqdm.notebook import tqdm\n", - "import pandas as pd\n", - "from ipywidgets import interact\n", - "\n", - "from mlxtend.preprocessing import TransactionEncoder\n", - "from mlxtend.frequent_patterns import apriori, association_rules\n", - "import warnings\n", - "warnings.filterwarnings(\"ignore\", category=FutureWarning)\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Association Rules" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "transactions = [\n", - " [\"burger\", \"salad\", \"coke\", \"ice cream\"],\n", - " [\"burger\", \"salad\", \"coke\", \"ice cream\"],\n", - " [\"burger\", \"fries\", \"coke\", \"pie\"],\n", - " [\"burger\", \"salad\", \"coke\", \"choc bar\"],\n", - " [\"burger\", \"salad\", \"coke\", \"muffin\"],\n", - " [\"sandwich\", \"fries\", \"fanta\", \"pie\"],\n", - " [\"sandwich\", \"fries\", \"coke\", \"pie\"],\n", - " [\"sandwich\", \"onion rings\", \"water\", \"muffin\"]\n", - "]\n", - "\n", - " \n", - "transactions = pd.DataFrame(data={\"Items\":transactions}, index=range(1,9))\n", - "transactions.index.name = 'Id'\n", - "\n", - "with pd.option_context('display.max_colwidth', 80):\n", - " print(transactions)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Apriori Algorithm" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 1. Encode ransactions" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "te = TransactionEncoder()\n", - "te_ary = te.fit_transform(transactions.Items.values.tolist())\n", - "df = pd.DataFrame(te_ary, columns=te.columns_)\n", - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2. Extract frequent item sets" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "freq_itemsets = apriori(df, use_colnames=True, min_support=0.5)\n", - "freq_itemsets" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3. Generate rules" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Execute the following code to show the solution\n", - "association_rules(freq_itemsets, metric='confidence', min_threshold=0.75)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.12" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -}