diff --git a/04_lab_supervised_learning_sklearn.ipynb b/04_lab_supervised_learning_sklearn.ipynb new file mode 100644 index 0000000..b3131f1 --- /dev/null +++ b/04_lab_supervised_learning_sklearn.ipynb @@ -0,0 +1,1548 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "dbbPhFWyrNFi" + }, + "source": [ + "# Before your start:\n", + "- Read the README.md file\n", + "- Comment as much as you can and use the resources in the README.md file\n", + "- Happy learning!" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "id": "qGpZPuUVrNFm" + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "\n", + "from sklearn.tree import export_graphviz\n", + "from sklearn.model_selection import cross_validate\n", + "from sklearn.linear_model import LogisticRegression\n", + "from sklearn.metrics import confusion_matrix, classification_report, recall_score, precision_score" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "beEVEuZPrNFo" + }, + "source": [ + "# Challenge 1 - Explore the Scikit-Learn Datasets\n", + "\n", + "Before starting to work on our own datasets, let's first explore the datasets that are included in this Python library. These datasets have been cleaned and formatted for use in ML algorithms." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "amsj-DKYrNFo" + }, + "source": [ + "First, we will load the diabetes dataset. Do this in the cell below by importing the datasets and then loading the dataset to the `diabetes` variable using the `load_diabetes()` function ([documentation](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_diabetes.html))." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "FmrMpXQHrNFp" + }, + "outputs": [], + "source": [ + "from sklearn.datasets import load_diabetes\n", + "\n", + "diabetes = load_diabetes()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "2AkbTjYYrNFp" + }, + "source": [ + "Let's explore this variable by looking at the different attributes (keys) of `diabetes`. Note that the `load_diabetes` function does not return dataframes. It returns you a Python dictionary." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "k21bfo8QrNFp", + "outputId": "9f586b6e-5678-4663-8d26-4e4e354696ca" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "dict_keys(['data', 'target', 'frame', 'DESCR', 'feature_names', 'data_filename', 'target_filename', 'data_module'])" + ] + }, + "metadata": {}, + "execution_count": 75 + } + ], + "source": [ + "diabetes.keys()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ONtwtUK8rNFp" + }, + "source": [ + "#### The next step is to read the description of the dataset.\n", + "\n", + "Print the description in the cell below using the `DESCR` attribute of the `diabetes` variable. Read the data description carefully to fully understand what each column represents.\n", + "\n", + "*Hint: If your output is ill-formatted by displaying linebreaks as `\\n`, it means you are not using the `print` function.*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": false, + "id": "YI60EaQbrNFq" + }, + "outputs": [], + "source": [ + "print(diabetes[\"DESCR\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "32gbLqbHrNFq" + }, + "source": [ + "#### Based on the data description, answer the following questions:\n", + "\n", + "1. How many attributes are there in the data? What do they mean?\n", + "\n", + "1. What is the relation between `diabetes['data']` and `diabetes['target']`?\n", + "\n", + "1. How many records are there in the data?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "toLljdNprNFq" + }, + "outputs": [], + "source": [ + "# 1. Number of Attributes: First 10 columns are numeric predictive values < ----- FEATURES\n", + "# Ten baseline variables, age, sex, body mass index, average blood pressure, and six blood serum measurements were obtained for each of n = 442 diabetes patients" + ] + }, + { + "cell_type": "code", + "source": [ + "# 2. The 10 x variables [data -> features] have been standardized to have mean 0 and squared length = 1\n", + "# Given a collection of possible predictors [data -> features] we select the one having largest absolute correlation with the response y [--> the target]\n", + "# \"Target\" is a quantitative measure of disease progression one year after baseline <------ TARGET" + ], + "metadata": { + "id": "DVUPbRzV8mwW" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "# 3. n = 442 diabetes patients" + ], + "metadata": { + "id": "NmMhgfdu9NgK" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "xCIJqUJdrNFr" + }, + "source": [ + "#### Now explore what are contained in the *data* portion as well as the *target* portion of `diabetes`.\n", + "\n", + "Scikit-learn typically takes in 2D numpy arrays as input (though pandas dataframes are also accepted). Inspect the shape of `data` and `target`. Confirm they are consistent with the data description." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "oE16uUNfrNFr" + }, + "outputs": [], + "source": [ + "features = pd.DataFrame(diabetes[\"data\"], columns = diabetes[\"feature_names\"])\n", + "label = pd.Series(diabetes[\"target\"], name = \"label\")\n", + "\n", + "display(features.head())" + ] + }, + { + "cell_type": "code", + "source": [ + "display(label.head())" + ], + "metadata": { + "id": "PHonlsg--Irl" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "XucRkAourNFr" + }, + "source": [ + "# Challenge 2 - Perform Supervised Learning on the Dataset" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "iyCOP8_orNFr" + }, + "source": [ + "The data have already been split to predictor (*data*) and response (*target*) variables. Given this information, we'll apply what we have previously learned about linear regression and apply the algorithm to the diabetes dataset.\n", + "\n", + "#### Let's briefly revisit the linear regression formula:\n", + "\n", + "```\n", + "y = β0 + β1X1 + β2X2 + ... + βnXn + ϵ\n", + "```\n", + "\n", + "...where:\n", + "\n", + "- X1-Xn: data\n", + "- β0: intercept\n", + "- β1-βn: coefficients\n", + "- ϵ: error (cannot explained by model)\n", + "- y: target\n", + "\n", + "Also take a look at the `sklearn.linear_model.LinearRegression` [documentation](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html).\n", + "\n", + "#### In the cell below, import the `linear_model` class from `sklearn`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "G0SgGP44rNFs" + }, + "outputs": [], + "source": [ + "from sklearn.linear_model import LinearRegression" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "6Y7RinPerNFs" + }, + "source": [ + "#### Create a new instance of the linear regression model and assign the new instance to the variable `diabetes_model`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "5rUdXQburNFt" + }, + "outputs": [], + "source": [ + "diabetes_model = LinearRegression()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "hd7X7E8wrNFt" + }, + "source": [ + "#### Next, let's split the training and test data.\n", + "\n", + "Define `diabetes_data_train`, `diabetes_target_train`, `diabetes_data_test`, and `diabetes_target_test`. Use the last 20 records for the test data and the rest for the training data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "AoLyYTN6rNFt" + }, + "outputs": [], + "source": [ + "from sklearn.model_selection import train_test_split\n", + "import matplotlib.pyplot as plt\n", + "\n", + "diabetes_data_train, diabetes_data_test, diabetes_target_train, diabetes_target_test = train_test_split(features, label, test_size = 0.20, random_state = 0)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "65vSZuJrrNFu" + }, + "source": [ + "Fit the training data and target to `diabetes_model`. Print the *intercept* and *coefficients* of the model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "U6cJIAiirNFu" + }, + "outputs": [], + "source": [ + "diabetes_model.fit(diabetes_data_train, diabetes_target_train)" + ] + }, + { + "cell_type": "code", + "source": [ + "model = LinearRegression()\n", + "\n", + "# we will train the model (fit). This allows LinearRegression model do understand our data and pick the best reg line\n", + "diabetes_model.fit(diabetes_data_train, diabetes_target_train)\n", + "\n", + "slope = diabetes_model.coef_\n", + "interception = diabetes_model.intercept_\n", + "\n", + "print(f\"Slope of our Reg line is {slope} \\n Y-intercept is {interception}\")" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "6RYMGaG6hqJO", + "outputId": "1b013d16-c1c3-4263-940e-72f229cf04e8" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Slope of our Reg line is [ -35.55025079 -243.16508959 562.76234744 305.46348218 -662.70290089\n", + " 324.20738537 24.74879489 170.3249615 731.63743545 43.0309307 ] \n", + " Y-intercept is 152.5380470138517\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "#reg_line = interception + slope*diabetes_data_train #(b0 + b1 * SAT)\n", + "\n", + "#plt.plot(diabetes_data_train, reg_line,c=\"orange\")\n", + "#plt.scatter(diabetes_data_train, diabetes_target_train)\n", + "#plt.show()" + ], + "metadata": { + "id": "MFU9ohAAuLrz" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "z0KqquxrrNFu" + }, + "source": [ + "#### Inspecting the results\n", + "\n", + "From the outputs you should have seen:\n", + "\n", + "- The intercept is a float number.\n", + "- The coefficients are an array containing 10 float numbers.\n", + "\n", + "This is the linear regression model fitted to your training dataset.\n", + "\n", + "#### Using your fitted linear regression model, predict the *y* of `diabetes_data_test`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "NqBi1XzorNFu" + }, + "outputs": [], + "source": [ + "diabetes_model.score(diabetes_data_train, diabetes_target_train)\n", + "pred_y = diabetes_model.predict(diabetes_data_test)\n", + "pred_y" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "wF480_strNFv" + }, + "source": [ + "#### Print your `diabetes_target_test` and compare with the prediction." + ] + }, + { + "cell_type": "code", + "source": [ + "diabetes_target_test.values" + ], + "metadata": { + "id": "8oudwF4R-LaH" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "POBibVRArNFv" + }, + "source": [ + "#### Is `diabetes_target_test` exactly the same as the model prediction? Explain." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "0ZfK-SdUrNFv" + }, + "outputs": [], + "source": [ + "pred_tt_vs_y = diabetes_target_test.values - pred_y\n", + "pred_tt_vs_y\n", + "# Our prediction is based on the model, but won't be exactly the same - and it never will !!!" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "UZn2tX-hrNFv" + }, + "source": [ + "# Bonus Challenge 1 - Hypothesis Testing with `statsmodels`\n", + "\n", + "After generating the linear regression model from the dataset, you probably wonder: then what? What is the statistical way to know if my model is reliable or not?\n", + "\n", + "Good question. We'll discuss that using Scikit-Learn in Challenge 5. But for now, let's use a fool-proof way by using the ([Linear Regression class of StatsModels](https://www.statsmodels.org/dev/regression.html)) which can also conduct linear regression analysis plus much more such as calcuating the F-score of the linear model as well as the standard errors and t-scores for each coefficient. The F-score and t-scores will tell you whether you can trust your linear model.\n", + "\n", + "To understand the statistical meaning of conducting hypothesis testing (e.g. F-test, t-test) for slopes, read [this webpage](https://onlinecourses.science.psu.edu/stat501/node/297/) at your leisure time. We'll give you a brief overview next.\n", + "\n", + "* The F-test of your linear model is to verify whether at least one of your coefficients is significantly different from zero. Translating that into the *null hypothesis* and *alternative hypothesis*, that is:\n", + "\n", + " ```\n", + " H0 : β1 = β2 = ... = β10 = 0\n", + " HA : At least one βj ≠ 0 (for j = 1, 2, ..., 10)\n", + " ```\n", + "\n", + "* The t-tests on each coefficient is to check whether the confidence interval for the variable contains zero. If the confidence interval contains zero, it means the null hypothesis for that variable is not rejected. In other words, this particular vaiable is not contributing to your linear model and you can remove it from your formula.\n", + "\n", + "Read the documentations of [StatsModels Linear Regression](https://www.statsmodels.org/dev/regression.html) as well as its [`OLS` class](https://www.statsmodels.org/dev/generated/statsmodels.regression.linear_model.OLS.html) which stands for *ordinary least squares*.\n", + "\n", + "#### In the next cell, analyze `diabetes_data_train` and `diabetes_target_train` with the linear regression model of `statsmodels`. Print the fit summary.\n", + "\n", + "Your output should look like:\n", + "\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "v5vS8ZXxrNFw" + }, + "outputs": [], + "source": [ + "# Your code here:\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "WILUW-x1rNFw" + }, + "source": [ + "#### Interpreting hypothesis testing results\n", + "\n", + "Answer the following questions in the cell below:\n", + "\n", + "1. What is the F-score of your linear model and is the null hypothesis rejected?\n", + "\n", + "1. Does any of the t-tests of the coefficients produce a confidence interval containing zero? What are they?\n", + "\n", + "1. How will you modify your linear reguression model according to the test results above?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Ic65poP8rNFw" + }, + "outputs": [], + "source": [ + "# Your answers here:" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "EpbI9bUyrNFw" + }, + "source": [ + "# Challenge 3 - Peform Supervised Learning on a Pandas Dataframe" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "nkSKmL0ErNFx" + }, + "source": [ + "Now that we have dealt with data that has been formatted for scikit-learn, let's look at data that we will need to format ourselves.\n", + "\n", + "In the next cell, load the `auto-mpg.csv` file included in this folder and assign it to a variable called `auto`." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "id": "2DSTlJEgrNFx" + }, + "outputs": [], + "source": [ + "auto = pd.read_csv(\"/content/auto-mpg.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "print(f\"The actual shape of my data is {auto.shape[0]} rows and {auto.shape[1]} columns\")" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "_oTM6TgVDH4x", + "outputId": "1f9a0f60-c2c3-4c00-f0f3-b4836b4c7ccf" + }, + "execution_count": 5, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "The actual shape of my data is 398 rows and 8 columns\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Lm-6aD2CrNFx" + }, + "source": [ + "Look at the first 5 rows using the `head()` function:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "id": "IRvXKwbzrNFx", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 206 + }, + "outputId": "d899bd4e-678e-444a-c423-e12d4ee6e443" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + " mpg cylinders displacement horse_power weight acceleration \\\n", + "0 18.0 8 307.0 130.0 3504 12.0 \n", + "1 15.0 8 350.0 165.0 3693 11.5 \n", + "2 18.0 8 318.0 150.0 3436 11.0 \n", + "3 16.0 8 304.0 150.0 3433 12.0 \n", + "4 17.0 8 302.0 140.0 3449 10.5 \n", + "\n", + " model_year car_name \n", + "0 70 \\t\"chevrolet chevelle malibu\" \n", + "1 70 \\t\"buick skylark 320\" \n", + "2 70 \\t\"plymouth satellite\" \n", + "3 70 \\t\"amc rebel sst\" \n", + "4 70 \\t\"ford torino\" " + ], + "text/html": [ + "\n", + "
| \n", + " | mpg | \n", + "cylinders | \n", + "displacement | \n", + "horse_power | \n", + "weight | \n", + "acceleration | \n", + "model_year | \n", + "car_name | \n", + "
|---|---|---|---|---|---|---|---|---|
| 0 | \n", + "18.0 | \n", + "8 | \n", + "307.0 | \n", + "130.0 | \n", + "3504 | \n", + "12.0 | \n", + "70 | \n", + "\\t\"chevrolet chevelle malibu\" | \n", + "
| 1 | \n", + "15.0 | \n", + "8 | \n", + "350.0 | \n", + "165.0 | \n", + "3693 | \n", + "11.5 | \n", + "70 | \n", + "\\t\"buick skylark 320\" | \n", + "
| 2 | \n", + "18.0 | \n", + "8 | \n", + "318.0 | \n", + "150.0 | \n", + "3436 | \n", + "11.0 | \n", + "70 | \n", + "\\t\"plymouth satellite\" | \n", + "
| 3 | \n", + "16.0 | \n", + "8 | \n", + "304.0 | \n", + "150.0 | \n", + "3433 | \n", + "12.0 | \n", + "70 | \n", + "\\t\"amc rebel sst\" | \n", + "
| 4 | \n", + "17.0 | \n", + "8 | \n", + "302.0 | \n", + "140.0 | \n", + "3449 | \n", + "10.5 | \n", + "70 | \n", + "\\t\"ford torino\" | \n", + "
LinearRegression()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
LinearRegression()