{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "(sup_reg_ex: develop)=\n", "## Data product Model Development\n", "\n", "Supervised algorithms use inputs (independent variables) and labeled outputs (dependent variable -the \"answers\") to create a model that can measure its performance and learn over time. Splitting the data into independent and dependent variables, we have the following (again, this will be very similar to the [previous example](sup_class_ex:develop)):" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "#Note: we only repeat this step from before, because this is a new .ipyb page.\n", "# it only needs to be executed once per file.\n", "\n", "#We'll import libraries as needed, but when submitting, having them all at the top is best practice\n", "import pandas as pd\n", "\n", "# Reloading the dataset\n", "url = \"https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.csv\"\n", "df = pd.read_csv(url) #read CSV into Python as a dataframe\n", "\n", "column_names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'type']\n", "df = pd.read_csv(url, names = column_names) #read CSV into Python as a dataframe\n", "\n", "#Choosing the variables. \n", "X = df.drop(columns=['sepal-length']) #indpendent variables\n", "y = df[['sepal-length']].copy() #dependent variables" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "(sup_reg_ex: develop: train)=\n", "### Train Model\n", "\n", "Recall, splitting the data into training and testing sets is not required, but it is good practice. Furthermore, it provides content for part D. \n", "\n", "As with the previous example [previous example](sup_class_ex:develop)), we'll use [scikit-learn aka sklearn](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html) built-ins for this." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from sklearn.model_selection import train_test_split\n", "\n", "#split the variable sets into training and testing subsets\n", "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.333, random_state=41)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "tags": [ "hide-input" ] }, "outputs": [ { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Independents variables
 sepal-widthpetal-lengthpetal-widthtype
1112.7000005.3000001.900000Iris-virginica
822.7000003.9000001.200000Iris-versicolor
1302.8000006.1000001.900000Iris-virginica
273.5000001.5000000.200000Iris-setosa
334.2000001.4000000.200000Iris-setosa
\n", "          \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Dependents variables
 sepal-length
1116.400000
825.800000
1307.400000
275.200000
335.500000
\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "#Nice displays are nice but not required. \n", "from IPython.display import display_html \n", "X_train_styler = X_train.head(5).style.set_table_attributes(\"style='display:inline'\").set_caption('Independents variables')\n", "y_train_styler = y_train.head(5).style.set_table_attributes(\"style='display:inline'\").set_caption('Dependents variables')\n", "space = \"\\xa0\" * 10 #space between columns\n", "display_html(X_train_styler._repr_html_()+ space + y_train_styler._repr_html_(), raw=True)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "\n", "We'll stick with sklearn's nice [supervised learning library](https://scikit-learn.org/stable/supervised_learning.html). Note that many of these models have both classification and regression extensions." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "from sklearn.linear_model import LinearRegression " ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Our data is mostly quantitative and the scatterplots do indicate the variables may be linearly related. So linear regression isn't a bad place to start. Once we've trained and tested a linear regression model, we'll easily be able to experiment with different algorithms. \n", "\n", "```{margin}Is linear regression ML?\n", "It depends who you ask. Google \"Is linear regression machine learning?\" and you'll see some interesting (and enterntaining) discussion. For the purposes of the capstone, the answer is -yes. \n", "```" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "ename": "ValueError", "evalue": "could not convert string to float: 'Iris-virginica'", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", "Cell \u001b[1;32mIn[18], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m linear_reg_model \u001b[39m=\u001b[39m LinearRegression()\n\u001b[1;32m----> 2\u001b[0m linear_reg_model\u001b[39m.\u001b[39;49mfit(X_train,y_train)\n", "File \u001b[1;32mc:\\Users\\ashej\\.virtualenvs\\jupyter-books-WZpnkDri\\Lib\\site-packages\\sklearn\\linear_model\\_base.py:649\u001b[0m, in \u001b[0;36mLinearRegression.fit\u001b[1;34m(self, X, y, sample_weight)\u001b[0m\n\u001b[0;32m 645\u001b[0m n_jobs_ \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mn_jobs\n\u001b[0;32m 647\u001b[0m accept_sparse \u001b[39m=\u001b[39m \u001b[39mFalse\u001b[39;00m \u001b[39mif\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mpositive \u001b[39melse\u001b[39;00m [\u001b[39m\"\u001b[39m\u001b[39mcsr\u001b[39m\u001b[39m\"\u001b[39m, \u001b[39m\"\u001b[39m\u001b[39mcsc\u001b[39m\u001b[39m\"\u001b[39m, \u001b[39m\"\u001b[39m\u001b[39mcoo\u001b[39m\u001b[39m\"\u001b[39m]\n\u001b[1;32m--> 649\u001b[0m X, y \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_validate_data(\n\u001b[0;32m 650\u001b[0m X, y, accept_sparse\u001b[39m=\u001b[39;49maccept_sparse, y_numeric\u001b[39m=\u001b[39;49m\u001b[39mTrue\u001b[39;49;00m, multi_output\u001b[39m=\u001b[39;49m\u001b[39mTrue\u001b[39;49;00m\n\u001b[0;32m 651\u001b[0m )\n\u001b[0;32m 653\u001b[0m sample_weight \u001b[39m=\u001b[39m _check_sample_weight(\n\u001b[0;32m 654\u001b[0m sample_weight, X, dtype\u001b[39m=\u001b[39mX\u001b[39m.\u001b[39mdtype, only_non_negative\u001b[39m=\u001b[39m\u001b[39mTrue\u001b[39;00m\n\u001b[0;32m 655\u001b[0m )\n\u001b[0;32m 657\u001b[0m X, y, X_offset, y_offset, X_scale \u001b[39m=\u001b[39m _preprocess_data(\n\u001b[0;32m 658\u001b[0m X,\n\u001b[0;32m 659\u001b[0m y,\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 662\u001b[0m sample_weight\u001b[39m=\u001b[39msample_weight,\n\u001b[0;32m 663\u001b[0m )\n", "File \u001b[1;32mc:\\Users\\ashej\\.virtualenvs\\jupyter-books-WZpnkDri\\Lib\\site-packages\\sklearn\\base.py:554\u001b[0m, in \u001b[0;36mBaseEstimator._validate_data\u001b[1;34m(self, X, y, reset, validate_separately, **check_params)\u001b[0m\n\u001b[0;32m 552\u001b[0m y \u001b[39m=\u001b[39m check_array(y, input_name\u001b[39m=\u001b[39m\u001b[39m\"\u001b[39m\u001b[39my\u001b[39m\u001b[39m\"\u001b[39m, \u001b[39m*\u001b[39m\u001b[39m*\u001b[39mcheck_y_params)\n\u001b[0;32m 553\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[1;32m--> 554\u001b[0m X, y \u001b[39m=\u001b[39m check_X_y(X, y, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mcheck_params)\n\u001b[0;32m 555\u001b[0m out \u001b[39m=\u001b[39m X, y\n\u001b[0;32m 557\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mnot\u001b[39;00m no_val_X \u001b[39mand\u001b[39;00m check_params\u001b[39m.\u001b[39mget(\u001b[39m\"\u001b[39m\u001b[39mensure_2d\u001b[39m\u001b[39m\"\u001b[39m, \u001b[39mTrue\u001b[39;00m):\n", "File \u001b[1;32mc:\\Users\\ashej\\.virtualenvs\\jupyter-books-WZpnkDri\\Lib\\site-packages\\sklearn\\utils\\validation.py:1104\u001b[0m, in \u001b[0;36mcheck_X_y\u001b[1;34m(X, y, accept_sparse, accept_large_sparse, dtype, order, copy, force_all_finite, ensure_2d, allow_nd, multi_output, ensure_min_samples, ensure_min_features, y_numeric, estimator)\u001b[0m\n\u001b[0;32m 1099\u001b[0m estimator_name \u001b[39m=\u001b[39m _check_estimator_name(estimator)\n\u001b[0;32m 1100\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mValueError\u001b[39;00m(\n\u001b[0;32m 1101\u001b[0m \u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39m{\u001b[39;00mestimator_name\u001b[39m}\u001b[39;00m\u001b[39m requires y to be passed, but the target y is None\u001b[39m\u001b[39m\"\u001b[39m\n\u001b[0;32m 1102\u001b[0m )\n\u001b[1;32m-> 1104\u001b[0m X \u001b[39m=\u001b[39m check_array(\n\u001b[0;32m 1105\u001b[0m X,\n\u001b[0;32m 1106\u001b[0m accept_sparse\u001b[39m=\u001b[39;49maccept_sparse,\n\u001b[0;32m 1107\u001b[0m accept_large_sparse\u001b[39m=\u001b[39;49maccept_large_sparse,\n\u001b[0;32m 1108\u001b[0m dtype\u001b[39m=\u001b[39;49mdtype,\n\u001b[0;32m 1109\u001b[0m order\u001b[39m=\u001b[39;49morder,\n\u001b[0;32m 1110\u001b[0m copy\u001b[39m=\u001b[39;49mcopy,\n\u001b[0;32m 1111\u001b[0m force_all_finite\u001b[39m=\u001b[39;49mforce_all_finite,\n\u001b[0;32m 1112\u001b[0m ensure_2d\u001b[39m=\u001b[39;49mensure_2d,\n\u001b[0;32m 1113\u001b[0m allow_nd\u001b[39m=\u001b[39;49mallow_nd,\n\u001b[0;32m 1114\u001b[0m ensure_min_samples\u001b[39m=\u001b[39;49mensure_min_samples,\n\u001b[0;32m 1115\u001b[0m ensure_min_features\u001b[39m=\u001b[39;49mensure_min_features,\n\u001b[0;32m 1116\u001b[0m estimator\u001b[39m=\u001b[39;49mestimator,\n\u001b[0;32m 1117\u001b[0m input_name\u001b[39m=\u001b[39;49m\u001b[39m\"\u001b[39;49m\u001b[39mX\u001b[39;49m\u001b[39m\"\u001b[39;49m,\n\u001b[0;32m 1118\u001b[0m )\n\u001b[0;32m 1120\u001b[0m y \u001b[39m=\u001b[39m _check_y(y, multi_output\u001b[39m=\u001b[39mmulti_output, y_numeric\u001b[39m=\u001b[39my_numeric, estimator\u001b[39m=\u001b[39mestimator)\n\u001b[0;32m 1122\u001b[0m check_consistent_length(X, y)\n", "File \u001b[1;32mc:\\Users\\ashej\\.virtualenvs\\jupyter-books-WZpnkDri\\Lib\\site-packages\\sklearn\\utils\\validation.py:877\u001b[0m, in \u001b[0;36mcheck_array\u001b[1;34m(array, accept_sparse, accept_large_sparse, dtype, order, copy, force_all_finite, ensure_2d, allow_nd, ensure_min_samples, ensure_min_features, estimator, input_name)\u001b[0m\n\u001b[0;32m 875\u001b[0m array \u001b[39m=\u001b[39m xp\u001b[39m.\u001b[39mastype(array, dtype, copy\u001b[39m=\u001b[39m\u001b[39mFalse\u001b[39;00m)\n\u001b[0;32m 876\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[1;32m--> 877\u001b[0m array \u001b[39m=\u001b[39m _asarray_with_order(array, order\u001b[39m=\u001b[39;49morder, dtype\u001b[39m=\u001b[39;49mdtype, xp\u001b[39m=\u001b[39;49mxp)\n\u001b[0;32m 878\u001b[0m \u001b[39mexcept\u001b[39;00m ComplexWarning \u001b[39mas\u001b[39;00m complex_warning:\n\u001b[0;32m 879\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mValueError\u001b[39;00m(\n\u001b[0;32m 880\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mComplex data not supported\u001b[39m\u001b[39m\\n\u001b[39;00m\u001b[39m{}\u001b[39;00m\u001b[39m\\n\u001b[39;00m\u001b[39m\"\u001b[39m\u001b[39m.\u001b[39mformat(array)\n\u001b[0;32m 881\u001b[0m ) \u001b[39mfrom\u001b[39;00m \u001b[39mcomplex_warning\u001b[39;00m\n", "File \u001b[1;32mc:\\Users\\ashej\\.virtualenvs\\jupyter-books-WZpnkDri\\Lib\\site-packages\\sklearn\\utils\\_array_api.py:185\u001b[0m, in \u001b[0;36m_asarray_with_order\u001b[1;34m(array, dtype, order, copy, xp)\u001b[0m\n\u001b[0;32m 182\u001b[0m xp, _ \u001b[39m=\u001b[39m get_namespace(array)\n\u001b[0;32m 183\u001b[0m \u001b[39mif\u001b[39;00m xp\u001b[39m.\u001b[39m\u001b[39m__name__\u001b[39m \u001b[39min\u001b[39;00m {\u001b[39m\"\u001b[39m\u001b[39mnumpy\u001b[39m\u001b[39m\"\u001b[39m, \u001b[39m\"\u001b[39m\u001b[39mnumpy.array_api\u001b[39m\u001b[39m\"\u001b[39m}:\n\u001b[0;32m 184\u001b[0m \u001b[39m# Use NumPy API to support order\u001b[39;00m\n\u001b[1;32m--> 185\u001b[0m array \u001b[39m=\u001b[39m numpy\u001b[39m.\u001b[39masarray(array, order\u001b[39m=\u001b[39morder, dtype\u001b[39m=\u001b[39mdtype)\n\u001b[0;32m 186\u001b[0m \u001b[39mreturn\u001b[39;00m xp\u001b[39m.\u001b[39masarray(array, copy\u001b[39m=\u001b[39mcopy)\n\u001b[0;32m 187\u001b[0m \u001b[39melse\u001b[39;00m:\n", "File \u001b[1;32mc:\\Users\\ashej\\.virtualenvs\\jupyter-books-WZpnkDri\\Lib\\site-packages\\pandas\\core\\generic.py:2070\u001b[0m, in \u001b[0;36mNDFrame.__array__\u001b[1;34m(self, dtype)\u001b[0m\n\u001b[0;32m 2069\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39m__array__\u001b[39m(\u001b[39mself\u001b[39m, dtype: npt\u001b[39m.\u001b[39mDTypeLike \u001b[39m|\u001b[39m \u001b[39mNone\u001b[39;00m \u001b[39m=\u001b[39m \u001b[39mNone\u001b[39;00m) \u001b[39m-\u001b[39m\u001b[39m>\u001b[39m np\u001b[39m.\u001b[39mndarray:\n\u001b[1;32m-> 2070\u001b[0m \u001b[39mreturn\u001b[39;00m np\u001b[39m.\u001b[39masarray(\u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_values, dtype\u001b[39m=\u001b[39mdtype)\n", "\u001b[1;31mValueError\u001b[0m: could not convert string to float: 'Iris-virginica'" ] } ], "source": [ "linear_reg_model = LinearRegression()\n", "linear_reg_model.fit(X_train,y_train)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "*Wait what happened!?!* This error returns a lot of output, but one line makes things clear:\n", "\n", "> ValueError: could not convert string to float: 'Iris-virginica' \n", "\n", "The algorithm expected numbers; it does not know what to do with the flower types. So how do we fix this?\n", "\n", "(sup_reg_ex: develop: train: categorical_1)=\n", "#### Processing Categorical Data -option 1\n", "\n", "One way to fix a problem is to avoid it. You are not required to use all the data -only some of it. Sometimes choosing the right variables is the real trick. [Dimensionality reduction](https://en.wikipedia.org/wiki/Dimensionality_reduction) is an important part of the data sciences. Here, those flower types DO matter, and it would be best to include that data -but goal #1 is to get things working. Improving things is step #2 and step #3 and step #4 and ... step $\\# \\infty$.\n", "\n", "Remove the column with categorical data:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepal-widthpetal-lengthpetal-width
1192.25.01.5
1282.85.62.1
1353.06.12.3
913.04.61.4
1123.05.52.1
712.84.01.3
1232.74.91.8
853.44.51.6
1473.05.22.0
1433.25.92.3
1273.04.91.8
393.41.50.2
383.01.30.2
932.33.31.0
233.31.70.5
1332.85.11.5
303.11.60.2
832.75.11.6
373.11.50.1
412.31.30.3
812.43.71.0
1203.25.72.3
433.51.60.6
23.21.30.2
642.93.61.3
622.24.01.0
563.34.71.6
672.74.11.0
493.31.40.2
632.94.71.4
792.63.51.0
542.84.61.5
1062.54.51.7
902.64.41.2
1453.05.22.3
144.01.20.2
1413.15.12.3
513.24.51.5
1393.15.42.1
703.24.81.8
972.94.31.3
552.84.51.3
324.11.50.1
1043.05.82.2
1363.45.62.4
183.81.70.3
1082.55.81.8
982.53.01.1
453.01.40.3
682.24.51.5
\n", "
" ], "text/plain": [ " sepal-width petal-length petal-width\n", "119 2.2 5.0 1.5\n", "128 2.8 5.6 2.1\n", "135 3.0 6.1 2.3\n", "91 3.0 4.6 1.4\n", "112 3.0 5.5 2.1\n", "71 2.8 4.0 1.3\n", "123 2.7 4.9 1.8\n", "85 3.4 4.5 1.6\n", "147 3.0 5.2 2.0\n", "143 3.2 5.9 2.3\n", "127 3.0 4.9 1.8\n", "39 3.4 1.5 0.2\n", "38 3.0 1.3 0.2\n", "93 2.3 3.3 1.0\n", "23 3.3 1.7 0.5\n", "133 2.8 5.1 1.5\n", "30 3.1 1.6 0.2\n", "83 2.7 5.1 1.6\n", "37 3.1 1.5 0.1\n", "41 2.3 1.3 0.3\n", "81 2.4 3.7 1.0\n", "120 3.2 5.7 2.3\n", "43 3.5 1.6 0.6\n", "2 3.2 1.3 0.2\n", "64 2.9 3.6 1.3\n", "62 2.2 4.0 1.0\n", "56 3.3 4.7 1.6\n", "67 2.7 4.1 1.0\n", "49 3.3 1.4 0.2\n", "63 2.9 4.7 1.4\n", "79 2.6 3.5 1.0\n", "54 2.8 4.6 1.5\n", "106 2.5 4.5 1.7\n", "90 2.6 4.4 1.2\n", "145 3.0 5.2 2.3\n", "14 4.0 1.2 0.2\n", "141 3.1 5.1 2.3\n", "51 3.2 4.5 1.5\n", "139 3.1 5.4 2.1\n", "70 3.2 4.8 1.8\n", "97 2.9 4.3 1.3\n", "55 2.8 4.5 1.3\n", "32 4.1 1.5 0.1\n", "104 3.0 5.8 2.2\n", "136 3.4 5.6 2.4\n", "18 3.8 1.7 0.3\n", "108 2.5 5.8 1.8\n", "98 2.5 3.0 1.1\n", "45 3.0 1.4 0.3\n", "68 2.2 4.5 1.5" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.333, random_state=41)\n", "#https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.drop.html\n", "\n", "X_train_no_type = X_train.drop(columns = ['type'])\n", "X_test_no_type = X_test.drop(columns = ['type'])\n", "\n", "X_test_no_type" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Now the models will train fine:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
LinearRegression()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" ], "text/plain": [ "LinearRegression()" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "linear_reg_model.fit(X_train_no_type, y_train)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Now the model can make predictions for an entire set:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[5.98770812],\n", " [6.42220879],\n", " [6.81026327],\n", " [6.3038615 ],\n", " [6.48153317],\n", " [5.75587752],\n", " [6.02106191],\n", " [6.34587216],\n", " [6.31716812],\n", " [6.788514 ],\n", " [6.23165894],\n", " [5.01764515],\n", " [4.57470184],\n", " [5.07393461],\n", " [4.87302581],\n", " [6.48997581],\n", " [4.88812177],\n", " [6.34092093],\n", " [4.885904 ],\n", " [4.00445291],\n", " [5.46842817],\n", " [6.62636673],\n", " [4.85349432],\n", " [4.71509986],\n", " [5.50178197],\n", " [5.57125107],\n", " [6.43782043],\n", " [6.00331976],\n", " [4.86637251],\n", " [6.31473613],\n", " [5.44667891],\n", " [6.08460761],\n", " [5.63522521],\n", " [6.01862993],\n", " [6.08060051],\n", " [5.19561829],\n", " [6.06972588],\n", " [6.28433001],\n", " [6.47065854],\n", " [6.29098332],\n", " [6.06929744],\n", " [6.16124571],\n", " [5.58789409],\n", " [6.64589822],\n", " [6.60683523],\n", " [5.3817326 ],\n", " [6.61032665],\n", " [4.89225584],\n", " [4.57691961],\n", " [5.58233992]])" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y_pred_no_type = linear_reg_model.predict(X_test_no_type)\n", "y_pred_no_type" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Or a single input:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[4.71509986]]\n" ] } ], "source": [ "# The model was trained with a datafram, so you can only predict on dataframes\n", "# Recall we removed the petal type, and we are predicting the sepal-length\n", "column_names_short = ['sepal-width', 'petal-length', 'petal-width']\n", "input_df = pd.DataFrame(np.array([[3.2, 1.3, .2]]), columns = column_names_short)\n", "\n", "print(linear_reg_model.predict(input_df))" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "```{note}\n", "Your model can only predict on data simliar to what it was trained with. Since this model was trained with a dataframe, a matching new dataframe, 'input_df' needed to be created to predict a single input. Alternatively, we could have converted the original data to an array (see the [previous example](sup_class_ex:develop:train). \n", "```" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "TRAIN OTHER MODELS" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "(sup_reg_ex: develop: accuracy)=\n", "### Accuracy Analysis\n", "\n", "As we are trying to predict a continuous number, even the very best model will have errors in almost every prediction. So we need a way to measure how much those predictions deviate from actual values. See sklearn's list of [metrics and scoring](https://scikit-learn.org/stable/modules/model_evaluation.html) for regression. Which metric is best depends on the needs of your project. However, any accuracy metric appropriate to your model will be accepted. \n", "\n", "(sup_reg_ex: develop: accuracy: MSE)=\n", "##### Mean Squared Error\n", "\n", "The mean square error (MSE) measures the average of the squares of errors (difference between predicted and actual values). See details in the next section [below](sup_reg_ex: develop: accuracy: MSE_example). Applying the MSE to the *test* data, we have:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.12264182555541722" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.metrics import mean_squared_error\n", "\n", "mean_squared_error(y_test, y_pred_no_type)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Using the squares of the errors is standard but ME is sometimes easier for non-technical audiences to understand. But XXXXXX \n", "\n", "TEST OTHER MODELS" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "(sup_reg_ex: develop: accuracy: MSE_example)=\n", "##### MSE explanation and example in 2D \n", "Using just the *petal-length* to predict the *sepal-length* with linear regression on 15 random values, the regression line looks like this: " ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "tags": [ "hide-input" ] }, "outputs": [ { "data": { "image/png": "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gX379mn8+PEqLi5WQkKCUlJStGTJEl1xxRVWlwZ47dq1S2PHjtX+/fvVqlUrDRo0SKtXr1arVq2sLi1iXXTRRVqwYIGysrI0depUnXfeecrOzta4ceOsLi3qMYEVAABYigmsAADAUoQRAABgKcIIAACwFGEEAABYijACAAAsRRgBAACWIowAAABLEUYAAIClCCMAAMBShBEAAGApwggAALAUYQQAAFiKMAIAACxFGAEAAJYijAAAAEsRRgAAgKUIIwAAwFKEEQAAYCnCCAAAsBRhJIYlJyerc+fOSk1NVdeuXXXDDTfop59+kiTl5uZq9OjRdf7cK1asUGpqasD7bdiwQcnJyX7HrVu3Tu+9917ghTWQ7Oxs7dmzp96f54knntDkyZPrX9D/qe/3NRTHbYiaMjIylJub63dcsL5vVjl06JBsNpv3eWpqqsrKymrdJzc3V5s2barT8V599VXdcsstddq3plqs+PmE9QgjMe5vf/ub1q1bp40bN6qkpMTUf9jhIFbCCBpWOH7f3G53nfddt26dWrRoUeuY+oQRIFgII5AkHTt2TIcPH1bLli2rfGzPnj1KS0tT37591b17d917772qqKjwfvzZZ59Vz5491atXL1166aU6fPiwz/6lpaW68sorNXXq1GqP/cQTT6hTp07q27dvlYDx17/+VSkpKUpJSdGIESNUVFSkffv26Q9/+IM+++wzpaam6q677tKRI0d03XXXqVu3burVq5euvPLKILwqHg8++KAuuugipaam6rLLLtPmzZu9H1u1apUGDRqkXr16KSUlRR9++KGmTp2q3bt367rrrlNqaqrWrVtXpcNx8m+U69ev16BBg9SnTx9169ZNTz/9tN+a3n33Xf3iF7/wPjcMQ+eff77+/e9/+/1+VTq1e3VqV2rJkiUaNGiQ+vbtq4svvlifffaZJGnLli0aOHCgevXqpZ49e+rRRx+VJK1du1bXXHNNjTWXlpbql7/8pbp166bLLrtMP/zwQ9BqOtWmTZs0YMAAde/eXaNHj1Zpaan3Y/v27VN6erp69uypHj166PXXX5ekar9v//jHP5SSkqLU1FT16NFDH374YY1fXyByc3M1dOjQal+P3NxcpaWl6Ve/+pV69uypr776SmvWrNHQoUPVr18/9e7dWx988IH3c73++uvq1KmTevfurZdfftnnODabTQcPHpQk/ec//9Hw4cO9/55mzpyp2bNna+3atbrvvvuUmpqqjz76SJL0wgsv6OKLL1afPn101VVXaefOnZKksrIyXXfddercubMGDRqk9evXV/v1WfnziQhlIGZ16NDBuPDCC41evXoZCQkJxtChQ43jx48bhmEYc+bMMUaNGmUYhmEcOXLEKCsrMwzDME6cOGGMGDHCmDdvnmEYhpGbm2tcdNFFxsGDBw3DMIz//d//NU6cOGF89tlnRq9evYyCggKjT58+xltvvVVtDYsWLTK6detmlJSUGBUVFca4ceOMDh06GIZhGOvXrzfatGlj7Nq1yzAMw3j66aeNq666qkp9hmEYLpfLuPLKK73P9+/fX+3xnnvuOaNXr17VPlwuV7X77Nu3z/v3efPmGcOHD/ceo3Xr1sYXX3xhGIZhuN1u73E7dOhgfPvtt979Hn/8cSMzM9P7/JVXXjFuvvlmwzAMo7S01Dh69KhhGIZx+PBhIzU11Vi1alW1+1U6fPiwcfbZZxvFxcWGYRjGp59+avTp08cwjNq/Xye/bpXfo0rr16/3vvbbtm0zLr30UqOkpMQwDMPYsmWL0bZtW+Po0aPGpEmTjGnTpnn3q+m1PtmcOXOMpk2bGt9//71hGIbx7LPPGldccUXQajpVv379jNmzZxuGYRjfffed0bRpU2POnDmGYRjGr3/9a+ORRx4xDMMw9u7dazgcDu/rfer3LSUlxVi5cqVhGJ7v74EDB6ocq7S0tMafqZN/JgN5PZo3b25s2rTJMAzDOHDggJGammrs3r3bMAzD+PHHH42kpCRj165d3n8jlR/LysoyTv5vXZJx4MAB4/jx40anTp2MuXPnej/2448/GoZhGIMHDzYWLFjg3f7uu+8at99+u3HixAnDMAzj7bffNq655hrDMAzjwQcfNG666SajoqLCOHjwoNGlSxfvz/HJrPz5RGRqbHUYgrX+9re/KTU1VSdOnNCdd96phx9+WC+++KLPmIqKCj388MP68ssvZRiG9u3bpx49euj666/XokWLdNdddykhIUGSfDore/fu1WWXXabZs2fr8ssvr/b4y5cv169//WvFx8dLku688059+eWXkqTPPvtMV111ldq3by9JuueeezR16tRq29a9evXSf/7zH91zzz0aPHhwjb+hT5kyRVOmTAnoNVq6dKleeeUVlZWVqaKiQv/7v/8rydMV6dy5s5xOpySpUaNGOuusswL63JJ05MgR3XPPPVq3bp0aNWqkwsJCrVu3TpdeemmN+zRv3ly/+tWv9Ne//lVTpkxRbm6uJkyYIKn275dZn3zyibZu3arLLrvMu61Ro0YqKCjQZZddpilTpujQoUMaPHiwhg0bZupzDhgwQF27dpUk/eY3v9Gjjz4a0CmI2mrq1KmTd1tpaanWrVvn7Tz17NlTgwYN8n582bJl+vrrryVJrVu3Vnp6upYtW1bt63355ZcrMzNTGRkZuvLKK6udB9WiRQutW7fO9NdRqbbXY8CAAercubMkaeXKldq+fbuuvvpqn/03b96sDRs26Oqrr1ZiYqIk6e6779b06dOrHGvz5s06evSoxo4d6912zjnnVFvXwoULtWbNGvXt21eS72mi5cuX6+WXX5bNZlNCQoJuuOEGbdu2rcrnsPLn8+SfBUQOwggkSY0bN9avfvUrTZkypUoYeemll7Rv3z79z//8j5o1a6b7779fR48e9fs5zzzzTHXs2FGLFi3S0KFDfSbW1aS2MbV97Pzzz9f333+vTz/9VMuWLdNDDz2kdevWVTnt9Pzzz+vdd9+t9nM8/vjjuvbaa322FRQU6N5779WaNWt0wQUX6LvvvvP5D9Csxo0b+/ynfvLr97vf/U7nnHOOvv32WzVu3Fjp6emmXt9bb71VEyZM0N13361FixZ5W/Rmv1+11WQYhq644grNnTu3yn6dOnXSgAEDtHTpUr366qvKzs72tvfrq641+VPXn6uXXnpJGzdu1Geffaabb75Z48aN00MPPeQzpqyszBtIT9WmTRstWbIk4HrPOOMM798Nw1D37t21cuXKKuM2bNjg89zMvzF/DMNQVlaWfvOb3/gdW9vxrPr5RGRizgi8Pv30U+9vYyc7cOCA2rZtq2bNmmnPnj0+56t/+ctfaubMmSopKZEkHTx40PsfSFxcnFwul3bv3q077rij2vPCw4YN0wcffKCysjIZhqFZs2Z5P5aWlqZPPvlEu3fvliTNnDlTl19+uex2u+Lj473HlKRdu3bJZrPpl7/8pV544QUZhqHCwsIqx5syZYrWrVtX7ePUICJJJSUlatKkiRITE2UYhl599VXvxwYMGKAtW7YoPz9fkny6JqfW17FjR61du1Zut1uHDx/W/PnzfV5fh8Ohxo0ba/PmzVq6dGmVOqpzySWXSPLMaRk2bJi3K1Pb9+tk559/vnbu3Kkff/xRkmd+TqXhw4dr2bJl+u6777zbvvrqK0meOSNt2rTR+PHj9dxzz2n16tXej9fUAZM8naTKiZKzZ89WWlqa7HZ7UGo6WXx8vHr37q23335bkrRx40Zvt03y/My98cYbkqQff/xRLpdLV1xxhXffk79vmzZt8s5ruPvuu71f68kqOyPVPWoLImZeD8nzc7Zjxw4tW7bMu23dunU6duyYhg4dqk8++cQ76XbmzJnVHqtz58467bTTNG/ePO+2//f//l+1X/Po0aM1c+ZM78/y8ePH9e2333pfuzlz5sgwDJWWlvp8vlNZ9fOJyERnJMZdd911at68uU6cOKEOHTpU+59ZZZu6e/fuateunU9b/qabbtLu3bs1YMAANW7cWKeffrrPf5pNmjTR3Llzdfvtt2vcuHH661//qsaNf/6xu+aaa/TVV1+pT58+io+P92lF9+jRQ88//7yuuuoqSVJSUpL3TeTyyy/XCy+8oJSUFA0YMECjRo1SVlaWDMPQiRMndNNNNyklJaXer0/Pnj11/fXXq3v37jr77LN9Ljts2bKlFixYoAceeEBlZWVq1KiRnnrqKY0cOVKTJk3SHXfcodNOO025ublKT0/XBx98oK5du8rhcKh3797eib6PPvqobrrpJr311lu64IILNHToUNP1TZgwQQ899JA+/vhj77bavl8na9eunR566CFdfPHFatOmjc9r37FjR82dO1d33nmnDh8+rGPHjql3796aO3eu8vLy9M4776hp06aqqKjw/sz88MMPat68eY21DhgwQA8//LC2bt2qs88+2xsWglHTqd5++21NmDBBL774ojp16uTTzfrTn/6ku+++Wz179pRhGPr973/vfeM89fs2depUbd68WU2bNtVpp52mGTNm1Pj1BcrM6yF5fs4WL16sBx98UA888ICOHz+uc889VwsXLlSPHj30xBNPyOl06owzzlB6enq1n6Nx48b68MMP9dvf/lbTpk1To0aNdM899+jOO+/Ub37zGz3wwAN6+eWXNW3aNI0bN0779+9XWlqaJOnEiRO69dZb1bt3bz322GO6/fbb1aVLF7Vq1UqDBg1SeXl5jV+jFT+fiEw2wzAMq4sAEPkmTpyosWPH+szPQPVyc3O1cOFCLVy40OpSgLBAZwRAUPz5z3+2ugQAEYrOCAAAsBQTWAEAgKUIIwAAwFKEEQAAYCnCCAAAsBRhBAAAWIowAgAALEUYAQAAliKMAAAAS/1/HRl56D+HXGkAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "\n", "x = X_train[['petal-length']]\n", "x = x[-15:]\n", "y = y_train[-15:]\n", "\n", "# Create linear regression object\n", "regr_ex = LinearRegression()\n", "# Train the model using the training sets\n", "regr_ex.fit(x, y)\n", "y_pred_ex = regr_ex.predict(x)\n", "\n", "fig, ax = plt.subplots()\n", "\n", "plt.scatter(x, y, color=\"black\")\n", "plt.scatter(x, y_pred_ex, color=\"blue\")\n", "plt.plot(x, y_pred_ex, color=\"blue\", linewidth=3);\n", "plt.figtext(0.5, 0.01, \"Black dots = actual values; blue dots = predicted value\", wrap=True, horizontalalignment='center', fontsize=8);" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The error squared looks like:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "tags": [ "hide-input" ] }, "outputs": [ { "data": { "image/png": "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0loGgZps3759AoAGj5kzZ4pdmt3R9z4BENavXy92aXZp9uzZQlBQkNC2bVvB29tbGDFihPDdd9+JXZbDGDJkiJCUlCR2GXbp0UcfFfz8/IS2bdsKXbt2FR599FHh3LlzYpdl1/79738Lffr0EVxcXITQ0FBh7dq1YpfUYkgEQRBEykFEREREnMBKRERE4mIYISIiIlExjBAREZGoGEaIiIhIVAwjREREJCqGESIiIhIVwwgRERGJimGEiIiIRMUwQkRERKJiGCEiIiJRMYwQERGRqBhGiIiISFQMI0RERCQqhhEiIiISFcMIERERiYphhIiIiETFMEJERESiYhghIiIiUTGMEBERkagYRlqx4OBghISEICIiAnK5HI8//jiuX78OAMjIyMCECRMafez9+/cjIiLC4v1OnDiB4OBgk+1ycnKwdetWywuzkdTUVBQXFzf5OIsXL8aCBQuaXtAdTf2+Nsd5bVFTQkICMjIyTLaz1vdNLBUVFZBIJNrnERERKC8vN7pPRkYGTp061ajzrVq1Ck888USj9jVUixg/nyQ+hpFW7l//+hdycnJw8uRJlJWVmfUftj1oLWGEbMsev29qtbrR++bk5MDd3d1om6aEESJrYRghAMCtW7dQWVmJTp06NXituLgYw4YNQ//+/dG7d28888wz0Gg02tffeecd9O3bF+Hh4Rg4cCAqKyt19lepVBg1ahSWLl2q99yLFy9Gjx490L9//wYB49NPP0VYWBjCwsIwduxYFBYW4sqVK/jrX/+Kffv2ISIiAk899RRu3LiBRx99FL169UJ4eDhGjRplhXelxksvvYR7770XERERuP/++3H69Gnta4cPH8bgwYMRHh6OsLAwfPHFF1i6dCmKiorw6KOPIiIiAjk5OQ16OOr+Rnn8+HEMHjwY/fr1Q69evfDmm2+arGnTpk0YN26c9rkgCLj77rvxv//9z+T3q1b93qv6vVLffvstBg8ejP79++O+++7Dvn37AABnz57FoEGDEB4ejr59++K1114DAGRnZ+PBBx80WLNKpcLDDz+MXr164f7778fFixetVlN9p06dQkxMDHr37o0JEyZApVJpX7ty5Qri4+PRt29f9OnTB+np6QCg9/v273//G2FhYYiIiECfPn3wxRdfGPz6LJGRkYHhw4frfT8yMjIwbNgwPPLII+jbty9++uknHDly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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from matplotlib.patches import Rectangle\n", "\n", "fig, ax = plt.subplots()\n", "\n", "i = 0\n", "while i < len(x):\n", " a = float(x.values[i])\n", " b = float(y.values[i])\n", " c = float(y_pred_ex[i])\n", " error = float(y_pred_ex[i])-float(y.values[i])\n", " ax.add_patch(Rectangle((a, b), \n", " error, \n", " error,\n", " fc=(1,0,0,0.5), ec=(0,0,0,1), lw=1)\n", " )\n", " i = i+1\n", "\n", "plt.scatter(x, y, color=\"black\")\n", "plt.scatter(x, y_pred_ex, color=\"blue\")\n", "plt.plot(x, y_pred_ex, color=\"blue\", linewidth=3);\n", "plt.figtext(0.5, 0.01, \"Black dots = actual values; blue dots = predicted value\", wrap=True, horizontalalignment='center', fontsize=8);\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The MSE just takes the average of these squares. The math:\n", "\n", "$$\\text{MSE} = \\frac{1}{n} \\sum^{n}_{i=1} (Y_i - \\hat{Y}_i)^{2}$$\n", "\n", "Where $Y_i$ and $\\bar{Y}_i$ are the $i^{\\text{th}}$ actual and predicted values respectively." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "In addition to giving positive values, squaring in the MSE emphasizes larger differences. Which can be good or bad depending on your needs. If your data has many or very large outliers, consider removing outliers or using the [mean absolute error](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.mean_absolute_error.html#sklearn.metrics.mean_absolute_error). See the [sklearn MSE docs](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.mean_squared_error.html#sklearn.metrics.mean_squared_error) for more info and examples. \n", "\n", "Increasing the number of variables uses the same concept only the regression line becomes multi-dimensional. For example, additionally, including 'sepal-length' and 'petal-length' creates a *4-dimensional* line. So it's a little hard to visualize. " ] } ], "metadata": { "kernelspec": { "display_name": "jupyter-books-WZpnkDri", "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.11.1" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 }