From 6e7aa747395b5be9d403806014da1cb9f14038b5 Mon Sep 17 00:00:00 2001 From: Qi Zhang Date: Sat, 2 Sep 2023 12:41:21 +0800 Subject: [PATCH] migrate linear and polynomial regression from md to ipynb. --- .../linear-and-polynomial-regression.ipynb | 1718 +++++++++++++++++ .../linear-and-polynomial-regression.md | 444 ----- 2 files changed, 1718 insertions(+), 444 deletions(-) create mode 100644 open-machine-learning-jupyter-book/ml-fundamentals/regression/linear-and-polynomial-regression.ipynb delete mode 100644 open-machine-learning-jupyter-book/ml-fundamentals/regression/linear-and-polynomial-regression.md diff --git a/open-machine-learning-jupyter-book/ml-fundamentals/regression/linear-and-polynomial-regression.ipynb b/open-machine-learning-jupyter-book/ml-fundamentals/regression/linear-and-polynomial-regression.ipynb new file mode 100644 index 0000000000..932660e780 --- /dev/null +++ b/open-machine-learning-jupyter-book/ml-fundamentals/regression/linear-and-polynomial-regression.ipynb @@ -0,0 +1,1718 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 38, + "id": "95868c2f-5abf-4fc4-bd6b-256d55d051eb", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [ + "hide-cell" + ] + }, + "outputs": [], + "source": [ + "# Install the necessary dependencies\n", + "\n", + "import os\n", + "import sys\n", + "!{sys.executable} -m pip install --quiet pandas scikit-learn numpy matplotlib jupyterlab_myst\n" + ] + }, + { + "cell_type": "markdown", + "id": "663dea79", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "# Linear and polynomial regression\n", + "\n", + ":::{figure} ../../../images/ml-regression/linear-polynomial.png\n", + "---\n", + "name: 'Linear vs polynomial regression infographic'\n", + "width: 100%\n", + "---\n", + "Infographic by [Dasani Madipalli](https://twitter.com/dasani_decoded)\n", + ":::\n" + ] + }, + { + "cell_type": "markdown", + "id": "d0525b63-aae3-492a-b251-8131622648d0", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "## Build a regression model using Scikit-learn: regression four ways" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "f3a0efe9-db96-4df7-a495-7d25504f6828", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [ + "hide-input" + ] + }, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "

\n", + "\n", + "A demo of linear-regression. [source]\n", + "

\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from IPython.display import HTML\n", + "\n", + "display(HTML(\"\"\"\n", + "

\n", + "\n", + "A demo of linear-regression. [source]\n", + "

\n", + "\"\"\"))" + ] + }, + { + "cell_type": "markdown", + "id": "d08017d2", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "\n", + "\n", + "### Introduction\n", + "\n", + "So far you have explored what regression is with sample data gathered from the pumpkin pricing dataset that we will use throughout this lesson. You have also visualized it using Matplotlib.\n", + "\n", + "Now you are ready to dive deeper into regression for Machine Learning. While visualization allows you to make sense of data, the real power of Machine Learning comes from _training models_. Models are trained on historical data to automatically capture data dependencies, and they allow you to predict outcomes for new data, which the model has not seen before.\n", + "\n", + "In this lesson, you will learn more about two types of regression: _basic linear regression_ and _polynomial regression_, along with some of the math underlying these techniques. Those models will allow us to predict pumpkin prices depending on different input data.\n", + "\n", + ":::{note}\n", + "Throughout this curriculum, we assume minimal knowledge of math, and seek to make it accessible for students coming from other fields, so watch for notes, callouts, diagrams, and other learning tools to aid in comprehension.\n", + ":::\n", + "\n", + "### Prerequisite\n", + "\n", + "You should be familiar by now with the structure of the pumpkin data that we are examining. You can find it preloaded and pre-cleaned in this section's [linear and polynomial regression.ipynb](../../assignments/ml-fundamentals/linear-and-polynomial-regression.ipynb) file. In the file, the pumpkin price is displayed per bushel in a new data frame. Make sure you can run these notebooks in kernels in Visual Studio Code.\n", + "\n", + "### Preparation\n", + "\n", + "As a reminder, you are loading this data so as to ask questions about it.\n", + "\n", + "- When is the best time to buy pumpkins? \n", + "- What price can I expect of a case of miniature pumpkins?\n", + "- Should I buy them in half-bushel baskets or by the 1 1/9 bushel box?\n", + "Let's keep digging into this data.\n", + "\n", + "In the previous lesson, you created a Pandas data frame and populated it with part of the original dataset, standardizing the pricing by bushel. By doing that, however, you were only able to gather about 400 data points and only for the fall months.\n", + "\n", + "Take a look at the data that we preloaded in this lesson's accompanying notebook. The data is preloaded and an initial scatterplot is charted to show monthly data. Maybe we can get a little more detail about the nature of the data by cleaning it more.\n", + "\n", + "## A linear regression line\n", + "\n", + "As you learned in section 1, the goal of a linear regression exercise is to be able to plot a line to:\n", + "\n", + "- **Show variable relationships**. Show the relationship between variables\n", + "- **Make predictions**. Make accurate predictions on where a new data point would fall in relationship to that line.\n", + "\n", + "It is typical of **Least-Squares Regression** to draw this type of line. The term 'least-squares' means that all the data points surrounding the regression line are squared and then added up. Ideally, that final sum is as small as possible, because we want a low number of errors or `least-squares``.\n", + "\n", + "We do so since we want to model a line that has the least cumulative distance from all of our data points. We also square the terms before adding them since we are concerned with their magnitude rather than their direction.\n", + "\n", + ":::{seealso}\n", + "**Show me the math** \n", + " \n", + "This line, called the _line of best fit_ can be expressed by [an equation](https://en.wikipedia.org/wiki/Simple_linear_regression): \n", + "\n", + "> ```\n", + "> Y = a + bX\n", + "> ```\n", + "\n", + "`X` is the 'explanatory variable'. `Y` is the 'dependent variable'. The slope of the line is `b` and `a` is the y-intercept, which refers to the value of `Y` when `X = 0`. \n", + "\n", + ">:::{figure} ../../../images/ml-regression/slope.png\n", + ">---\n", + ">name: 'calculate the slope'\n", + ">width: 60%\n", + ">---\n", + ">Infographic by [Jen Looper](https://twitter.com/jenlooper)\n", + ">:::\n", + "\n", + "First, calculate the slope `b`.\n", + "\n", + "In other words, and referring to our pumpkin data's original question: \"predict the price of a pumpkin per bushel by month\", `X` would refer to the price and `Y` would refer to the month of sale.\n", + "\n", + ">:::{figure} ../../../images/ml-regression/calculation.png\n", + ">---\n", + ">name: 'complete the equation'\n", + ">width: 60%\n", + ">---\n", + ">Infographic by [Jen Looper](https://twitter.com/jenlooper)\n", + ">:::\n", + "\n", + "Calculate the value of Y. If you're paying around $4, it must be April!\n", + "\n", + "The math that calculates the line must demonstrate the slope of the line, which is also dependent on the intercept, or where `Y` is situated when `X = 0`.\n", + "\n", + "You can observe the method of calculation for these values on the [Math is Fun](https://www.mathsisfun.com/data/least-squares-regression.html) website. Also, visit [this Least-squares calculator](https://www.mathsisfun.com/data/least-squares-calculator.html) to watch how the numbers' values impact the line.\n", + ":::\n", + "\n", + "## Correlation\n", + "\n", + "One more term to understand is the **Correlation Coefficient** between given X and Y variables. Using a scatterplot, you can quickly visualize this coefficient. A plot with data points scattered in a neat line has a high correlation, but a plot with data points scattered everywhere between X and Y has a low correlation.\n", + "\n", + "A good linear regression model will be one that has a high (nearer to 1 than 0) Correlation Coefficient using the Least-Squares Regression method with a line of regression.\n", + "\n", + ":::{seealso}\n", + "Run the notebook accompanying this lesson and look at the Month to Price scatterplot. Does the data associating Month to Price for pumpkin sales seem to have a high or low correlation, according to your visual interpretation of the scatterplot? Does that change if you use a more fine-grained measure instead of `Month`, eg. *day of the year* (i.e. number of days since the beginning of the year)?\n", + ":::\n", + "\n", + "In the code below, we will assume that we have cleaned up the data, and obtained a data frame called `new_pumpkins`, similar to the following:" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "93a478b1", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [ + "output_scroll" + ] + }, + "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", + "
City NameTypePackageVarietySub VarietyGradeDateLow PriceHigh PriceMostly Low...Unit of SaleQualityConditionAppearanceStorageCropRepackTrans ModeUnnamed: 24Unnamed: 25
0BALTIMORENaN24 inch binsNaNNaNNaN4/29/17270.0280.0270.0...NaNNaNNaNNaNNaNNaNENaNNaNNaN
1BALTIMORENaN24 inch binsNaNNaNNaN5/6/17270.0280.0270.0...NaNNaNNaNNaNNaNNaNENaNNaNNaN
2BALTIMORENaN24 inch binsHOWDEN TYPENaNNaN9/24/16160.0160.0160.0...NaNNaNNaNNaNNaNNaNNNaNNaNNaN
3BALTIMORENaN24 inch binsHOWDEN TYPENaNNaN9/24/16160.0160.0160.0...NaNNaNNaNNaNNaNNaNNNaNNaNNaN
4BALTIMORENaN24 inch binsHOWDEN TYPENaNNaN11/5/1690.0100.090.0...NaNNaNNaNNaNNaNNaNNNaNNaNNaN
\n", + "

5 rows × 26 columns

\n", + "
" + ], + "text/plain": [ + " City Name Type Package Variety Sub Variety Grade Date \\\n", + "0 BALTIMORE NaN 24 inch bins NaN NaN NaN 4/29/17 \n", + "1 BALTIMORE NaN 24 inch bins NaN NaN NaN 5/6/17 \n", + "2 BALTIMORE NaN 24 inch bins HOWDEN TYPE NaN NaN 9/24/16 \n", + "3 BALTIMORE NaN 24 inch bins HOWDEN TYPE NaN NaN 9/24/16 \n", + "4 BALTIMORE NaN 24 inch bins HOWDEN TYPE NaN NaN 11/5/16 \n", + "\n", + " Low Price High Price Mostly Low ... Unit of Sale Quality Condition \\\n", + "0 270.0 280.0 270.0 ... NaN NaN NaN \n", + "1 270.0 280.0 270.0 ... NaN NaN NaN \n", + "2 160.0 160.0 160.0 ... NaN NaN NaN \n", + "3 160.0 160.0 160.0 ... NaN NaN NaN \n", + "4 90.0 100.0 90.0 ... NaN NaN NaN \n", + "\n", + " Appearance Storage Crop Repack Trans Mode Unnamed: 24 Unnamed: 25 \n", + "0 NaN NaN NaN E NaN NaN NaN \n", + "1 NaN NaN NaN E NaN NaN NaN \n", + "2 NaN NaN NaN N NaN NaN NaN \n", + "3 NaN NaN NaN N NaN NaN NaN \n", + "4 NaN NaN NaN N NaN NaN NaN \n", + "\n", + "[5 rows x 26 columns]" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from datetime import datetime\n", + "\n", + "pumpkins = pd.read_csv('https://static-1300131294.cos.accelerate.myqcloud.com/data/us-pumpkins.csv')\n", + "\n", + "pumpkins.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "351f7c01", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "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", + "
MonthDayOfYearVarietyCityPackageLow PriceHigh PricePrice
709267PIE TYPEBALTIMORE1 1/9 bushel cartons15.015.013.636364
719267PIE TYPEBALTIMORE1 1/9 bushel cartons18.018.016.363636
7210274PIE TYPEBALTIMORE1 1/9 bushel cartons18.018.016.363636
7310274PIE TYPEBALTIMORE1 1/9 bushel cartons17.017.015.454545
7410281PIE TYPEBALTIMORE1 1/9 bushel cartons15.015.013.636364
\n", + "
" + ], + "text/plain": [ + " Month DayOfYear Variety City Package Low Price \\\n", + "70 9 267 PIE TYPE BALTIMORE 1 1/9 bushel cartons 15.0 \n", + "71 9 267 PIE TYPE BALTIMORE 1 1/9 bushel cartons 18.0 \n", + "72 10 274 PIE TYPE BALTIMORE 1 1/9 bushel cartons 18.0 \n", + "73 10 274 PIE TYPE BALTIMORE 1 1/9 bushel cartons 17.0 \n", + "74 10 281 PIE TYPE BALTIMORE 1 1/9 bushel cartons 15.0 \n", + "\n", + " High Price Price \n", + "70 15.0 13.636364 \n", + "71 18.0 16.363636 \n", + "72 18.0 16.363636 \n", + "73 17.0 15.454545 \n", + "74 15.0 13.636364 " + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pumpkins = pumpkins[pumpkins['Package'].str.contains('bushel', case=True, regex=True)]\n", + "\n", + "new_columns = ['Package', 'Variety', 'City Name', 'Month', 'Low Price', 'High Price', 'Date']\n", + "pumpkins = pumpkins.drop([c for c in pumpkins.columns if c not in new_columns], axis=1)\n", + "\n", + "price = (pumpkins['Low Price'] + pumpkins['High Price']) / 2\n", + "\n", + "month = pd.DatetimeIndex(pumpkins['Date']).month\n", + "day_of_year = pd.to_datetime(pumpkins['Date']).apply(lambda dt: (dt-datetime(dt.year,1,1)).days)\n", + "\n", + "new_pumpkins = pd.DataFrame(\n", + " {'Month': month, \n", + " 'DayOfYear' : day_of_year, \n", + " 'Variety': pumpkins['Variety'], \n", + " 'City': pumpkins['City Name'], \n", + " 'Package': pumpkins['Package'], \n", + " 'Low Price': pumpkins['Low Price'],\n", + " 'High Price': pumpkins['High Price'], \n", + " 'Price': price})\n", + "\n", + "new_pumpkins.loc[new_pumpkins['Package'].str.contains('1 1/9'), 'Price'] = price/1.1\n", + "new_pumpkins.loc[new_pumpkins['Package'].str.contains('1/2'), 'Price'] = price*2\n", + "\n", + "new_pumpkins.head()" + ] + }, + { + "cell_type": "markdown", + "id": "75dff0fd", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "A basic scatterplot reminds us that we only have monthly data from August through December. We probably need more data to be able to draw conclusions in a linear fashion." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "62162c46", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.scatter('Month', 'Price', data=new_pumpkins)" + ] + }, + { + "cell_type": "markdown", + "id": "025f014e", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + ":::{note}\n", + "We have performed the same cleaning steps as in the previous section, and have calculated `DayOfYear` column using the following expression: \n", + ":::" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "bc1d5493", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "day_of_year = pd.to_datetime(pumpkins['Date']).apply(lambda dt: (dt-datetime(dt.year,1,1)).days)" + ] + }, + { + "cell_type": "markdown", + "id": "83b08051", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "Now that you have an understanding of the math behind linear regression, let's create a Regression model to see if we can predict which package of pumpkins will have the best pumpkin prices. Someone buying pumpkins for a holiday pumpkin patch might want this information to be able to optimize their purchases of pumpkin packages for the patch.\n", + "\n", + "## Looking for Correlation\n", + "\n", + "From the previous section, you have probably seen that the average price for different months looks like this:\n", + "\n", + ":::{figure} ../../../images/ml-regression/barchart.png\n", + "---\n", + "name: 'Average price by month'\n", + "width: 70%\n", + "---\n", + "Average price by month{cite}`Average_price_by_month`\n", + ":::\n", + "\n", + "This suggests that there should be some correlation, and we can try training a linear regression model to predict the relationship between `Month` and `Price`, or between `DayOfYear` and `Price`. Here is the scatter plot that shows the latter relationship:\n", + "\n", + ":::{figure} ../../../images/ml-regression/scatter-dayofyear.png\n", + "---\n", + "name: 'Scatter plot of Price vs. Day of Year'\n", + "width: 70%\n", + "---\n", + "Scatter plot of Price vs. Day of Year{cite}`Scatter_plot_of_Price_vs._Day_of_Year`\n", + ":::\n", + "\n", + "It looks like there are different clusters of prices corresponding to different pumpkin varieties. To confirm this hypothesis, let's plot each pumpkin category using a different color. By passing an `ax` parameter to the `scatter` plotting function we can plot all points on the same graph:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "9864740b", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [ + { + "data": { + "image/png": "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ReLatWvi8ccfF23bthV+fn5i9OjRori42OgY/L3fZOl87t271+x3uKioyHAMns+brH0/63OH65FGCCEcc++HiIiIyL7YRoaIiIhcFhMZIiIicllMZIiIiMhlMZEhIiIil8VEhoiIiFwWExkiIiJyWUxkiIiIyGUxkSEiIiKXxUSGiNzGl19+ib59+8Lb2xujRo2SXRwicgAmMkTUaFOmTIFGo4FGo4G3tzc6dOiA5ORkrF692jDZpD1t27YN99xzDwICAuDn54dBgwYhPT29wX5PPfUUBgwYgKKiIsybNw/e3t744osvjPa5cuUKunfvjgULFti9nETkeExkiKhJUlJSUFxcjB9//BE7duzAvffeiyeffBL3338/bty4Ybc4f//73/Hggw/izjvvRE5ODr777js8+uijmDlzZoNkpLCwEMOGDUPnzp1xzz33YM6cOZgyZQquXLli2GfhwoVo3bo1XnzxRbuVsdb169ftfkwiskL2ZE9E5HomT54sHnzwwQbrd+/eLQCIf/7zn0IIIV577TXRp08f4efnJzp37ixmzZplmGzy559/FgEBAWLjxo1Gx9i8ebPw8/MT5eXl4tSpU8Lb21s89dRTDWK98cYbAoA4dOiQKCoqMjkx5rVr10SvXr3E7NmzhRBC7NmzR/j4+IgjR46I6upq8fLLL4tu3bqJVq1aiX79+hmV5caNG2Lq1KmG7bGxsWLlypUmz8OLL74oIiIiRLdu3Zp1Xomo8XhHhojsZtiwYejfvz82bdoEAGjRogXeeOMNfP/991izZg327NmDhQsXAgDatGmDRx99FGlpaUbHSEtLw0MPPYSAgAB89NFHqKqqMvkYaMaMGfD398f69esRGRmJ4uJiBAYGYuXKlSguLsYjjzyCVq1aYe3atXj33XfxySefYOrUqViyZAkGDhyI5cuXY+3atXj77bfx/fffY968eZg4cSL2798PAKipqUHnzp2xceNGHD9+HEuXLsWSJUvw4YcfGpVj9+7dOHHiBHbt2oVt27apcVqJyBLZmRQRuR5zd2SEEOKRRx4RvXr1Mrlt48aNIjQ01PA6JydHeHl5ibNnzwohhDh37pxo2bKl2LdvnxBCiJkzZ4qgoCCz5ejXr58YMWKE4XVQUJBIS0trsN/SpUtFixYtxMCBA0VVVZWoqKgQfn5+4uDBg0b7TZs2TYwbN85svNmzZ4uxY8caXk+ePFl06NBBVFZWmn0PEamLd2SIyK6EENBoNACArKwsJCYmolOnTggICMCkSZNQWlqKq1evAgB+9atfoXfv3lizZg0A4F//+he6du2KIUOG2LVMf/zjH1FTU4NFixahZcuWKCgowNWrV5GcnAx/f3/DsnbtWhQWFhre9+abb2LgwIFo3749/P398e677+LUqVNGx+7bty98fHzsWl4ish0TGSKyqx9++AFRUVH48ccfcf/996Nfv374+OOPcfToUbz55psAjBvF/u53vzP0QEpLS8Njjz1mSIRiY2Oh1+tx9uzZBnGuX7+OwsJCxMbGWi1Ty5Ytjf77888/AwA+++wz5ObmGpbjx4/jo48+AgBs2LABCxYswLRp07Bz507k5ubisccea9Cgt02bNo05PURkZ0xkiMhu9uzZg2PHjmHs2LE4evQoampq8Nprr+GOO+5AbGysyYRk4sSJ+Omnn/DGG2/g+PHjmDx5smHb2LFj4e3tjddee63B+95++21cuXIF48aNa3Q5b7nlFvj6+uLUqVOIjo42WiIjIwEoY9IMHjwYjz/+OG699VZER0cb3a0hIufQUnYBiMg1VVZWoqSkBNXV1Th37hwyMjKwfPly3H///fjtb3+LvLw8VFVV4e9//zseeOABfPnll3j77bcbHKdt27YYM2YMnn76aQwfPhydO3c2bOvSpQv+8pe/YP78+WjVqhUmTZoEb29vfPLJJ1iyZAnmz5+P+Pj4Rpc9ICAACxYswLx581BTU4O77roLer0eX375JQIDAzF58mTExMRg7dq1yMzMRFRUFN5//30cPnwYUVFRzTpvRGRnshvpEJHrmTx5sqGbc8uWLUX79u1FUlKSWL16taiurjbs99e//lVERESI1q1bC61WK9auXSsAiIsXLxodr7bb9ocffmgy3ieffCLuvvtu0aZNG9GqVSsxcOBAsXr16gb7mWvsK4QQAMTmzZsNr2tqasTKlStFXFyc8Pb2Fu3btxdarVbs379fCCFERUWFmDJliggKChLBwcFi1qxZYtGiRaJ///5G58Fco2cicgyNEEJIzaSIyOO9//77mDdvHs6ePcuGs0TUKHy0RETSXL16FcXFxVixYgVmzJjBJIaIGo2NfYlImr/85S/o2bMnwsPDsXjxYtnFISIXxEdLRERE5LJ4R4aIiIhcFhMZIiIicllMZIiIiMhlMZEhIiIil8VEhoiIiFwWExkiIiJyWUxkiIiIyGUxkSEiIiKX9f9PmheX/r+mHwAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "ax=None\n", + "colors = ['red','blue','green','yellow']\n", + "for i,var in enumerate(new_pumpkins['Variety'].unique()):\n", + " df = new_pumpkins[new_pumpkins['Variety']==var]\n", + " ax = df.plot.scatter('DayOfYear','Price',ax=ax,c=colors[i],label=var)" + ] + }, + { + "cell_type": "markdown", + "id": "f6bb5fa9", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "Our investigation suggests that variety has more effect on the overall price than the actual selling date. So let us focus for the moment only on one pumpkin variety, and see what effect the date has on the price:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "115f94ab", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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jIwM07dvX+N0Os2dd95pTpw40Y098R8dGdMvv/zS3HTTTSY2NtaEh4ebUaNGNZuqzZiedtddd5khQ4aYXr16mZiYGHPNNdd4vEl888035r777jP9+/c34eHh5gc/+IE5ePCgx2Pwev9WW+O5cePGVp+/xcXF7sdgPD219xw9WyC8JzmMMaZ7PgMCAADwPs6ZAQAAtkaYAQAAtkaYAQAAtkaYAQAAtkaYAQAAtkaYAQAAtkaYAQAAtkaYAQAAtkaYARAw8vLyNHLkSIWGhmrGjBlWNwdANyHMAOi0O+64Qw6HQw6HQ6GhoRo4cKC+973v6fnnn3cvTulN69ev14QJExQZGanw8HCNHTtWK1eubHbc/fffr0suuUTFxcVauHChQkND9eGHH3ocU11draFDh+rBBx/0ejsBWIMwA6BLrr32Wh08eFD79u3Tm2++qUmTJunf/u3fdN1116m+vt5rdbKysnTjjTcqLS1NH3/8sT799FP96Ec/0j333NMskOzZs0dXX3214uLiNGHCBM2bN0933HGHqqur3cf85Cc/UVhYmB599FGvtbHJqVOnvP6YADrA6sWhANjPrFmzzI033ths+/vvv28kmWeffdYYY8wTTzxhLr74YhMeHm7i4uLMvffe616csqqqykRGRpo1a9Z4PEZ2drYJDw83lZWVpqSkxISGhpr777+/Wa2nn37aSDIfffSRKS4ubnEhzW+++cYMHz7cZGZmGmOM2bBhg+nVq5fZtm2baWhoML/85S9NYmKi6dOnjxk1apRHW+rr681dd93l3n/BBReYp556qsVxePTRR815551nEhMTz2lcAXQNn8wA8Jqrr75ao0eP1quvvipJ6tGjh55++ml9/vnneuGFF7Rhwwb95Cc/kSRFREToRz/6kVasWOHxGCtWrNAPf/hDRUZG6pVXXlFdXV2LXwndfffd6tu3r1avXq34+HgdPHhQTqdTTz31lA4ePKhbbrlFffr00apVq/THP/5Rr732mu666y4tWbJEY8aM0bJly7Rq1So988wz+vzzz7Vw4ULdeuutysnJkSQ1NjYqLi5Oa9as0e7du/Xwww9ryZIlevnllz3a8f7776ugoEDvvvuu1q9f74thBdAeq9MUAPtp7ZMZY4y55ZZbzPDhw1vct2bNGhMVFeX++eOPPzY9e/Y0paWlxhhjvv76axMSEmI2bdpkjDHmnnvuMS6Xq9V2jBo1ykybNs39s8vlMitWrGh23MMPP2x69OhhxowZY+rq6szJkydNeHi42bx5s8dxs2fPNhkZGa3Wy8zMNDNnznT/PGvWLDNw4EBTW1vb6n0A+B6fzADwKmOMHA6HJOm9997TNddco/PPP1+RkZG67bbbdOTIEdXU1EiSLrvsMl100UV64YUXJEl/+ctfNGTIEKWnp3u1TT//+c/V2NioRYsWKSQkREVFRaqpqdH3vvc99e3b131btWqV9uzZ477f8uXLNWbMGMXExKhv37764x//qJKSEo/HHjlypHr16uXV9gLoHMIMAK/64osvlJSUpH379um6667TqFGj9Le//U3bt2/X8uXLJXmeKPuv//qv7plJK1as0J133ukOQxdccIEqKipUWlrarM6pU6e0Z88eXXDBBe22KSQkxOO/VVVVkqTXX39d+fn57tvu3bv1yiuvSJJefPFFPfjgg5o9e7beeecd5efn684772x2km9ERERnhgeADxBmAHjNhg0b9Nlnn2nmzJnavn27Ghsb9cQTT+iKK67QBRdc0GIoufXWW7V//349/fTT2r17t2bNmuXeN3PmTIWGhuqJJ55odr9nnnlG1dXVysjI6HQ7R4wYod69e6ukpETJycket/j4eEmnr1lz5ZVX6r777lNqaqqSk5M9PrUB4D9CrG4AAHuqra3VoUOH1NDQoK+//lpvvfWWli1bpuuuu0633367du3apbq6OmVlZen6669XXl6ennnmmWaP079/f91000166KGHNGXKFMXFxbn3JSQk6LHHHtMDDzygPn366LbbblNoaKhee+01LVmyRA888IAuv/zyTrc9MjJSDz74oBYuXKjGxkaNHz9eFRUVysvLk9Pp1KxZs5SSkqJVq1bp7bffVlJSkv785z9r69atSkpKOqdxA+ADVp+0A8B+Zs2a5Z4CHRISYmJiYszkyZPN888/bxoaGtzH/eY3vzHnnXeeCQsLM1OnTjWrVq0yksyxY8c8Hq9pSvfLL7/cYr3XXnvNXHXVVSYiIsL06dPHjBkzxjz//PPNjmvtBGBjjJFksrOz3T83Njaap556ygwbNsyEhoaamJgYM3XqVJOTk2OMMebkyZPmjjvuMC6Xy/Tr18/ce++9ZtGiRWb06NEe49DaidAAuo/DGGMsTVMAgt6f//xnLVy4UKWlpZxMC6DT+JoJgGVqamp08OBB/epXv9Ldd99NkAHQJZwADMAyjz32mC688EINGjRIixcvtro5AGyKr5kAAICt8ckMAACwNcIMAACwNcIMAACwNcIMAACwNcIMAACwNcIMAACwNcIMAACwNcIMAACwtf8PBnCWtEJg2EcAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "pie_pumpkins = new_pumpkins[new_pumpkins['Variety']=='PIE TYPE']\n", + "pie_pumpkins.plot.scatter('DayOfYear','Price') " + ] + }, + { + "cell_type": "markdown", + "id": "2527b9e5", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "If we now calculate the correlation between `Price` and `DayOfYear` using `corr` function, we will get something like `-0.27` - which means that training a predictive model makes sense.\n", + "\n", + ":::{note}\n", + "Before training a linear regression model, it is important to make sure that our data is clean. Linear regression does not work well with missing values, thus it makes sense to get rid of all empty cells:\n", + ":::" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "242febdf", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Int64Index: 144 entries, 70 to 1630\n", + "Data columns (total 8 columns):\n", + " # Column Non-Null Count Dtype \n", + "--- ------ -------------- ----- \n", + " 0 Month 144 non-null int64 \n", + " 1 DayOfYear 144 non-null int64 \n", + " 2 Variety 144 non-null object \n", + " 3 City 144 non-null object \n", + " 4 Package 144 non-null object \n", + " 5 Low Price 144 non-null float64\n", + " 6 High Price 144 non-null float64\n", + " 7 Price 144 non-null float64\n", + "dtypes: float64(3), int64(2), object(3)\n", + "memory usage: 10.1+ KB\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/h0/kqxjp1r14yggzhpqx_gpx6580000gn/T/ipykernel_58993/3144308612.py:1: SettingWithCopyWarning: \n", + "A value is trying to be set on a copy of a slice from a DataFrame\n", + "\n", + "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", + " pie_pumpkins.dropna(inplace=True)\n" + ] + } + ], + "source": [ + "pie_pumpkins.dropna(inplace=True)\n", + "pie_pumpkins.info()" + ] + }, + { + "cell_type": "markdown", + "id": "92709a1f", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "Another approach would be to fill those empty values with mean values from the corresponding column.\n", + "\n", + "## Simple Linear Regression\n", + "\n", + "To train our Linear Regression model, we will use the **Scikit-learn** library." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "c3d17ae6", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "from sklearn.linear_model import LinearRegression\n", + "from sklearn.metrics import mean_squared_error\n", + "from sklearn.model_selection import train_test_split" + ] + }, + { + "cell_type": "markdown", + "id": "02c3a570", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "We start by separating input values (features) and the expected output (label) into separate NumPy arrays:" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "8a96563a", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "X = pie_pumpkins['DayOfYear'].to_numpy().reshape(-1,1)\n", + "y = pie_pumpkins['Price']" + ] + }, + { + "cell_type": "markdown", + "id": "6bfab9bb", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + ":::{note}\n", + "Note that we had to perform `reshape` on the input data in order for the Linear Regression package to understand it correctly. Linear Regression expects a 2D-array as an input, where each row of the array corresponds to a vector of input features. In our case, since we have only one input - we need an array with shape N×1, where N is the dataset size.\n", + ":::\n", + "\n", + "Then, we need to split the data into train and test datasets, so that we can validate our model after training:" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "63a5c90e", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)" + ] + }, + { + "cell_type": "markdown", + "id": "975937b9", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "Finally, training the actual Linear Regression model takes only two lines of code. We define the `LinearRegression` object, and fit it to our data using the `fit` method:" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "cc303abf", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "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": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "lin_reg = LinearRegression()\n", + "lin_reg.fit(X_train,y_train)" + ] + }, + { + "cell_type": "markdown", + "id": "4c93426e", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "The `LinearRegression` object after `fit`-ting contains all the coefficients of the regression, which can be accessed using `.coef_` property. In our case, there is just one coefficient, which should be around `-0.017`. It means that prices seem to drop a bit with time, but not too much, around 2 cents per day. We can also access the intersection point of the regression with the Y-axis using `lin_reg`.intercept_` - it will be around `21` in our case, indicating the price at the beginning of the year.\n", + "\n", + "To see how accurate our model is, we can predict prices on a test dataset, and then measure how close our predictions are to the expected values. This can be done using mean square error (MSE) metrics, which is the mean of all squared differences between expected and predicted values." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "cd436fa3", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Mean error: 2.77 (17.2%)\n" + ] + } + ], + "source": [ + "pred = lin_reg.predict(X_test)\n", + "\n", + "mse = np.sqrt(mean_squared_error(y_test,pred))\n", + "print(f'Mean error: {mse:3.3} ({mse/np.mean(pred)*100:3.3}%)')" + ] + }, + { + "cell_type": "markdown", + "id": "43014d87", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "Our error seems to be around 2 points, which is ~17%. Not too good. Another indicator of model quality is the **coefficient of determination**, which can be obtained like this:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "2803d5e1", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model determination: 0.04460606335028361\n" + ] + } + ], + "source": [ + "score = lin_reg.score(X_train,y_train)\n", + "print('Model determination: ', score)" + ] + }, + { + "cell_type": "markdown", + "id": "d64ea140", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "If the value is 0, it means that the model does not take input data into account, and acts as the *worst linear predictor*, which is simply a mean value of the result. The value of 1 means that we can perfectly predict all expected outputs. In our case, the coefficient is around 0.06, which is quite low.\n", + "\n", + "We can also plot the test data together with the regression line to better see how regression works in our case:" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "337d38c5", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.scatter(X_test,y_test)\n", + "plt.plot(X_test,pred)" + ] + }, + { + "cell_type": "markdown", + "id": "c2831e2f", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "## Polynomial Regression\n", + "\n", + "Another type of Linear Regression is Polynomial Regression. While sometimes there's a linear relationship between variables - the bigger the pumpkin in volume, the higher the price - sometimes these relationships can't be plotted as a plane or straight line.\n", + "\n", + ":::{seealso}\n", + "Here are [some more examples](https://online.stat.psu.edu/stat501/lesson/9/9.8) of data that could use Polynomial Regression\n", + ":::\n", + "\n", + "Take another look at the relationship between Date and Price. Does this scatterplot seem like it should necessarily be analyzed by a straight line? Can't prices fluctuate? In this case, you can try polynomial regression.\n", + "\n", + ":::{note}\n", + "Polynomials are mathematical expressions that might consist of one or more variables and coefficients.\n", + ":::\n", + "\n", + "Polynomial regression creates a curved line to better fit nonlinear data. In our case, if we include a squared `DayOfYear` variable in input data, we should be able to fit our data with a parabolic curve, which will have a minimum at a certain point within the year.\n", + "\n", + "Scikit-learn includes a helpful [pipeline API](https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.make_pipeline.html?highlight=pipeline#sklearn.pipeline.make_pipeline) to combine different steps of data processing together. A **pipeline** is a chain of **estimators**. In our case, we will create a pipeline that first adds polynomial features to our model, and then trains the regression:" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "bf0c99b8", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
Pipeline(steps=[('polynomialfeatures', PolynomialFeatures()),\n",
+       "                ('linearregression', 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": [ + "Pipeline(steps=[('polynomialfeatures', PolynomialFeatures()),\n", + " ('linearregression', LinearRegression())])" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from sklearn.preprocessing import PolynomialFeatures\n", + "from sklearn.pipeline import make_pipeline\n", + "\n", + "pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression())\n", + "\n", + "pipeline.fit(X_train,y_train)" + ] + }, + { + "cell_type": "markdown", + "id": "5181be18", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "Using `PolynomialFeatures(2)` means that we will include all second-degree polynomials from the input data. In our case, it will just mean $DayOfYear^2$, but given two input variables X and Y, this will add $X^2$, XY and $Y^2$. We may also use higher-degree polynomials if we want.\n", + "\n", + "Pipelines can be used in the same manner as the original `LinearRegression` object, i.e. we can `fit` the pipeline, and then use `predict` to get the prediction results. Here is the graph showing test data, and the approximation curve:\n", + "\n", + ":::{figure} ../../../images/ml-regression/poly-results.png\n", + "---\n", + "name: 'Polynomial regression'\n", + "width: 70%\n", + "---\n", + "Polynomial regression{cite}`Polynomial_regression`\n", + ":::\n", + "\n", + "Using Polynomial Regression, we can get slightly lower MSE and higher determination, but not significantly. We need to take into account other features!\n", + "\n", + ":::{seealso}\n", + "You can see that the minimal pumpkin prices are observed somewhere around Halloween. How can you explain this? \n", + ":::\n", + "\n", + "🎃 Congratulations, you just created a model that can help predict the price of pie pumpkins. You can probably repeat the same procedure for all pumpkin types, but that would be tedious. Let's learn now how to take pumpkin variety into account in our model!\n", + "\n", + "## Categorical Features\n", + "\n", + "In the ideal world, we want to be able to predict prices for different pumpkin varieties using the same model. However, the `Variety` column is somewhat different from columns like `Month`, because it contains non-numeric values. Such columns are called **categorical**.\n", + "\n", + "Here you can see how the average price depends on variety:\n", + "\n", + ":::{figure} ../../../images/ml-regression/price-by-variety.png\n", + "---\n", + "name: 'Average price by variety'\n", + "width: 70%\n", + "---\n", + "Average price by variety{cite}`Average_price_by_variety`\n", + ":::\n", + "\n", + "To take variety into account, we first need to convert it to numeric form or **encode**** it. There are several ways we can do it:\n", + "\n", + "* Simple **numeric encoding** will build a table of different varieties, and then replace the variety name by an index in that table. This is not the best idea for linear regression, because linear regression takes the actual numeric value of the index, and adds it to the result, multiplying by some coefficient. In our case, the relationship between the index number and the price is clearly non-linear, even if we make sure that indices are ordered in some specific way.\n", + "* **One-hot encoding** will replace the `Variety` column by 4 different columns, one for each variety. Each column will contain `1` if the corresponding row is of a given variety and `0`` otherwise. This means that there will be four coefficients in linear regression, one for each pumpkin variety, responsible for the \"starting price\" (or rather \"additional price\") for that particular variety.\n", + "\n", + "The code below shows how we can one-hot encode a variety:" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "246bfdd0", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "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", + "
FAIRYTALEMINIATUREMIXED HEIRLOOM VARIETIESPIE TYPE
700001
710001
720001
730001
740001
...............
17380100
17390100
17400100
17410100
17420100
\n", + "

415 rows × 4 columns

\n", + "
" + ], + "text/plain": [ + " FAIRYTALE MINIATURE MIXED HEIRLOOM VARIETIES PIE TYPE\n", + "70 0 0 0 1\n", + "71 0 0 0 1\n", + "72 0 0 0 1\n", + "73 0 0 0 1\n", + "74 0 0 0 1\n", + "... ... ... ... ...\n", + "1738 0 1 0 0\n", + "1739 0 1 0 0\n", + "1740 0 1 0 0\n", + "1741 0 1 0 0\n", + "1742 0 1 0 0\n", + "\n", + "[415 rows x 4 columns]" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pd.get_dummies(new_pumpkins['Variety'])" + ] + }, + { + "cell_type": "markdown", + "id": "968fa4ea", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "To train linear regression using one-hot encoded variety as input, we just need to initialize `X` and `y` data correctly:" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "f0bc3720", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "X = pd.get_dummies(new_pumpkins['Variety'])\n", + "y = new_pumpkins['Price']" + ] + }, + { + "cell_type": "markdown", + "id": "cc63ccc2", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "The rest of the code is the same as what we used above to train Linear Regression. If you try it, you will see that the mean squared error is about the same, but we get the much higher coefficient of determination (~77%). To get even more accurate predictions, we can take more categorical features into account, as well as numeric features, such as `Month` or `DayOfYear`. To get one large array of features, we can use `join`:" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "6fd52a7f", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "X = pd.get_dummies(new_pumpkins['Variety']) \\\n", + " .join(new_pumpkins['Month']) \\\n", + " .join(pd.get_dummies(new_pumpkins['City'])) \\\n", + " .join(pd.get_dummies(new_pumpkins['Package']))\n", + "y = new_pumpkins['Price']" + ] + }, + { + "cell_type": "markdown", + "id": "e113e574", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "Here we also take into account `City` and `Package` type, which gives us MSE 2.84 (10%), and determination 0.94!\n", + "\n", + "## Putting it all together\n", + "\n", + "To make the best model, we can use combined (one-hot encoded categorical + numeric) data from the above example together with Polynomial Regression. Here is the complete code for your convenience:" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "fffe46b9", + "metadata": { + "attributes": { + "classes": [ + "code-cell" + ], + "id": "" + }, + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Mean error: 2.29 (8.47%)\n", + "Model determination: 0.9647780491582084\n" + ] + } + ], + "source": [ + "# set up training data\n", + "X = pd.get_dummies(new_pumpkins['Variety']) \\\n", + " .join(new_pumpkins['Month']) \\\n", + " .join(pd.get_dummies(new_pumpkins['City'])) \\\n", + " .join(pd.get_dummies(new_pumpkins['Package']))\n", + "y = new_pumpkins['Price']\n", + "\n", + "# make train-test split\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)\n", + "\n", + "# setup and train the pipeline\n", + "pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression())\n", + "pipeline.fit(X_train,y_train)\n", + "\n", + "# predict results for test data\n", + "pred = pipeline.predict(X_test)\n", + "\n", + "# calculate MSE and determination\n", + "mse = np.sqrt(mean_squared_error(y_test,pred))\n", + "print(f'Mean error: {mse:3.3} ({mse/np.mean(pred)*100:3.3}%)')\n", + "\n", + "score = pipeline.score(X_train,y_train)\n", + "print('Model determination: ', score)" + ] + }, + { + "cell_type": "markdown", + "id": "28aa766b", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "This should give us the best determination coefficient of almost 97%, and MSE=2.23 (~8% prediction error).\n", + "\n", + "| Model | MSE | Determination |\n", + "|-------|-----|---------------|\n", + "| `DayOfYear` Linear | 2.77 (17.2%) | 0.07 |\n", + "| `DayOfYear` Polynomial | 2.73 (17.0%) | 0.08 |\n", + "| `Variety` Linear | 5.24 (19.7%) | 0.77 |\n", + "| All features Linear | 2.84 (10.5%) | 0.94 |\n", + "| All features Polynomial | 2.23 (8.25%) | 0.97 |\n", + "\n", + "🏆 Well done! You created four Regression models in one section and improved the model quality to 97%. In the final section on Regression, you will learn about Logistic Regression to determine categories.\n", + "\n", + "## Self study\n", + "\n", + "In this section, we learned about Linear Regression. There are other important types of Regression. Read about Stepwise, Ridge, Lasso and Elasticnet techniques. A good course to study to learn more is the [Stanford Statistical Learning course](https://online.stanford.edu/courses/sohs-ystatslearning-statistical-learning)\n", + "\n", + "## Your turn! 🚀\n", + "\n", + "Test several different variables in this notebook to see how correlation corresponds to model accuracy.\n", + "\n", + "Assignment - [Create a regression model](../../assignments/ml-fundamentals/create-a-regression-model.md)\n", + "\n", + "## Acknowledgments\n", + "\n", + "Thanks to Microsoft for creating the open-source course [ML-For-Beginners](https://github.com/microsoft/ML-For-Beginners). It inspires the majority of the content in this chapter.\n", + "\n", + "---\n", + "\n", + ":::{bibliography}\n", + ":filter: docname in docnames\n", + ":::" + ] + } + ], + "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.16" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/open-machine-learning-jupyter-book/ml-fundamentals/regression/linear-and-polynomial-regression.md b/open-machine-learning-jupyter-book/ml-fundamentals/regression/linear-and-polynomial-regression.md deleted file mode 100644 index 2443833043..0000000000 --- a/open-machine-learning-jupyter-book/ml-fundamentals/regression/linear-and-polynomial-regression.md +++ /dev/null @@ -1,444 +0,0 @@ ---- -jupytext: - cell_metadata_filter: -all - formats: md:myst - text_representation: - extension: .md - format_name: myst - format_version: 0.13 - jupytext_version: 1.11.5 -kernelspec: - display_name: Python 3 - language: python - name: python3 ---- - -# Linear and polynomial regression - -```{figure} ../../../images/ml-regression/linear-polynomial.png ---- -name: 'Linear vs polynomial regression infographic' -width: 100% ---- -Infographic by [Dasani Madipalli](https://twitter.com/dasani_decoded) -``` - -## Build a regression model using Scikit-learn: regression four ways - -

- -A demo of linear-regression. [source] -

- -### Introduction - -So far you have explored what regression is with sample data gathered from the pumpkin pricing dataset that we will use throughout this lesson. You have also visualized it using Matplotlib. - -Now you are ready to dive deeper into regression for Machine Learning. While visualization allows you to make sense of data, the real power of Machine Learning comes from _training models_. Models are trained on historic data to automatically capture data dependencies, and they allow you to predict outcomes for new data, which the model has not seem before. - -In this lesson, you will learn more about two types of regression: _basic linear regression_ and _polynomial regression_, along with some of the math underlying these techniques. Those models will allow us to predict pumpkin prices depending on different input data. - -```{note} -Throughout this curriculum, we assume minimal knowledge of math, and seek to make it accessible for students coming from other fields, so watch for notes, callouts, diagrams, and other learning tools to aid in comprehension. -``` - -### Prerequisite - -You should be familiar by now with the structure of the pumpkin data that we are examining. You can find it preloaded and pre-cleaned in this section's [linear and polynomial regression.ipynb](../../assignments/ml-fundamentals/linear-and-polynomial-regression.ipynb) file. In the file, the pumpkin price is displayed per bushel in a new data frame. Make sure you can run these notebooks in kernels in Visual Studio Code. - -### Preparation - -As a reminder, you are loading this data so as to ask questions of it. - -- When is the best time to buy pumpkins? -- What price can I expect of a case of miniature pumpkins? -- Should I buy them in half-bushel baskets or by the 1 1/9 bushel box? -Let's keep digging into this data. - -In the previous lesson, you created a Pandas data frame and populated it with part of the original dataset, standardizing the pricing by the bushel. By doing that, however, you were only able to gather about 400 datapoints and only for the fall months. - -Take a look at the data that we preloaded in this lesson's accompanying notebook. The data is preloaded and an initial scatterplot is charted to show month data. Maybe we can get a little more detail about the nature of the data by cleaning it more. - -## A linear regression line - -As you learned in section 1, the goal of a linear regression exercise is to be able to plot a line to: - -- **Show variable relationships**. Show the relationship between variables -- **Make predictions**. Make accurate predictions on where a new datapoint would fall in relationship to that line. - -It is typical of **Least-Squares Regression** to draw this type of line. The term 'least-squares' means that all the datapoints surrounding the regression line are squared and then added up. Ideally, that final sum is as small as possible, because we want a low number of errors, or `least-squares`. - -We do so since we want to model a line that has the least cumulative distance from all of our data points. We also square the terms before adding them since we are concerned with its magnitude rather than its direction. - -```{seealso} -**Show me the math** - -This line, called the _line of best fit_ can be expressed by [an equation](https://en.wikipedia.org/wiki/Simple_linear_regression): - -> ``` -> Y = a + bX -> ``` - -`X` is the 'explanatory variable'. `Y` is the 'dependent variable'. The slope of the line is `b` and `a` is the y-intercept, which refers to the value of `Y` when `X = 0`. - ->```{figure} ../../../images/ml-regression/slope.png ->--- ->name: 'calculate the slope' ->width: 60% ->--- ->Infographic by [Jen Looper](https://twitter.com/jenlooper) ->``` - -First, calculate the slope `b`. - -In other words, and referring to our pumpkin data's original question: "predict the price of a pumpkin per bushel by month", `X` would refer to the price and `Y` would refer to the month of sale. - ->```{figure} ../../../images/ml-regression/calculation.png ->--- ->name: 'complete the equation' ->width: 60% ->--- ->Infographic by [Jen Looper](https://twitter.com/jenlooper) ->``` - -Calculate the value of Y. If you're paying around $4, it must be April! - -The math that calculates the line must demonstrate the slope of the line, which is also dependent on the intercept, or where `Y` is situated when `X = 0`. - -You can observe the method of calculation for these values on the [Math is Fun](https://www.mathsisfun.com/data/least-squares-regression.html) web site. Also visit [this Least-squares calculator](https://www.mathsisfun.com/data/least-squares-calculator.html) to watch how the numbers' values impact the line. -``` - -## Correlation - -One more term to understand is the **Correlation Coefficient** between given X and Y variables. Using a scatterplot, you can quickly visualize this coefficient. A plot with datapoints scattered in a neat line have high correlation, but a plot with datapoints scattered everywhere between X and Y have a low correlation. - -A good linear regression model will be one that has a high (nearer to 1 than 0) Correlation Coefficient using the Least-Squares Regression method with a line of regression. - -```{seealso} -Run the notebook accompanying this lesson and look at the Month to Price scatterplot. Does the data associating Month to Price for pumpkin sales seem to have high or low correlation, according to your visual interpretation of the scatterplot? Does that change if you use more fine-grained measure instead of `Month`, eg. *day of the year* (i.e. number of days since the beginning of the year)? -``` - -In the code below, we will assume that we have cleaned up the data, and obtained a data frame called `new_pumpkins`, similar to the following: - -```{code-cell} -:tags: [output_scroll] -import pandas as pd -import matplotlib.pyplot as plt -import numpy as np -from datetime import datetime - -pumpkins = pd.read_csv('../../assets/data/us-pumpkins.csv') - -pumpkins.head() -``` - -```{code-cell} -pumpkins = pumpkins[pumpkins['Package'].str.contains('bushel', case=True, regex=True)] - -new_columns = ['Package', 'Variety', 'City Name', 'Month', 'Low Price', 'High Price', 'Date'] -pumpkins = pumpkins.drop([c for c in pumpkins.columns if c not in new_columns], axis=1) - -price = (pumpkins['Low Price'] + pumpkins['High Price']) / 2 - -month = pd.DatetimeIndex(pumpkins['Date']).month -day_of_year = pd.to_datetime(pumpkins['Date']).apply(lambda dt: (dt-datetime(dt.year,1,1)).days) - -new_pumpkins = pd.DataFrame( - {'Month': month, - 'DayOfYear' : day_of_year, - 'Variety': pumpkins['Variety'], - 'City': pumpkins['City Name'], - 'Package': pumpkins['Package'], - 'Low Price': pumpkins['Low Price'], - 'High Price': pumpkins['High Price'], - 'Price': price}) - -new_pumpkins.loc[new_pumpkins['Package'].str.contains('1 1/9'), 'Price'] = price/1.1 -new_pumpkins.loc[new_pumpkins['Package'].str.contains('1/2'), 'Price'] = price*2 - -new_pumpkins.head() -``` - -A basic scatterplot reminds us that we only have month data from August through December. We probably need more data to be able to draw conclusions in a linear fashion. - -```{code-cell} -import matplotlib.pyplot as plt -plt.scatter('Month','Price',data=new_pumpkins) -``` - -```{note} -We have performed the same cleaning steps as in the previous section, and have calculated `DayOfYear` column using the following expression: -``` - -```{code-cell} -day_of_year = pd.to_datetime(pumpkins['Date']).apply(lambda dt: (dt-datetime(dt.year,1,1)).days) -``` - -Now that you have an understanding of the math behind linear regression, let's create a Regression model to see if we can predict which package of pumpkins will have the best pumpkin prices. Someone buying pumpkins for a holiday pumpkin patch might want this information to be able to optimize their purchases of pumpkin packages for the patch. - -## Looking for Correlation - -From the previous section you have probably seen that the average price for different months looks like this: - -```{figure} ../../../images/ml-regression/barchart.png ---- -name: 'Average price by month' -width: 70% ---- -Average price by month{cite}`Average_price_by_month` -``` - -This suggests that there should be some correlation, and we can try training linear regression model to predict the relationship between `Month` and `Price`, or between `DayOfYear` and `Price`. Here is the scatter plot that shows the latter relationship: - -```{figure} ../../../images/ml-regression/scatter-dayofyear.png ---- -name: 'Scatter plot of Price vs. Day of Year' -width: 70% ---- -Scatter plot of Price vs. Day of Year{cite}`Scatter_plot_of_Price_vs._Day_of_Year` -``` - -It looks like there are different clusters of prices corresponding to different pumpkin varieties. To confirm this hypothesis, let's plot each pumpkin category using a different color. By passing an `ax` parameter to the `scatter` plotting function we can plot all points on the same graph: - -```{code-cell} -ax=None -colors = ['red','blue','green','yellow'] -for i,var in enumerate(new_pumpkins['Variety'].unique()): - df = new_pumpkins[new_pumpkins['Variety']==var] - ax = df.plot.scatter('DayOfYear','Price',ax=ax,c=colors[i],label=var) -``` - -Our investigation suggests that variety has more effect on the overall price than the actual selling date. So let us focus for the moment only on one pumpkin variety, and see what effect the date has on the price: - -```{code-cell} -pie_pumpkins = new_pumpkins[new_pumpkins['Variety']=='PIE TYPE'] -pie_pumpkins.plot.scatter('DayOfYear','Price') -``` - -If we now calculate the correlation between `Price` and `DayOfYear` using `corr` function, we will get something like `-0.27` - which means that training a predictive model makes sense. - -```{note} -Before training a linear regression model, it is important to make sure that our data is clean. Linear regression does not work well with missing values, thus it makes sense to get rid of all empty cells: -``` - -```{code-cell} -pie_pumpkins.dropna(inplace=True) -pie_pumpkins.info() -``` - -Another approach would be to fill those empty values with mean values from the corresponding column. - -## Simple Linear Regression - -To train our Linear Regression model, we will use the **Scikit-learn** library. - -```{code-cell} -from sklearn.linear_model import LinearRegression -from sklearn.metrics import mean_squared_error -from sklearn.model_selection import train_test_split -``` - -We start by separating input values (features) and the expected output (label) into separate numpy arrays: - -```{code-cell} -X = pie_pumpkins['DayOfYear'].to_numpy().reshape(-1,1) -y = pie_pumpkins['Price'] -``` - -```{note} -Note that we had to perform `reshape` on the input data in order for the Linear Regression package to understand it correctly. Linear Regression expects a 2D-array as an input, where each row of the array corresponds to a vector of input features. In our case, since we have only one input - we need an array with shape N×1, where N is the dataset size. -``` - -Then, we need to split the data into train and test datasets, so that we can validate our model after training: - -```{code-cell} -X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0) -``` - -Finally, training the actual Linear Regression model takes only two lines of code. We define the `LinearRegression` object, and fit it to our data using the `fit` method: - -```{code-cell} -lin_reg = LinearRegression() -lin_reg.fit(X_train,y_train) -``` - -The `LinearRegression` object after `fit`-ting contains all the coefficients of the regression, which can be accessed using `.coef_` property. In our case, there is just one coefficient, which should be around `-0.017`. It means that prices seem to drop a bit with time, but not too much, around 2 cents per day. We can also access the intersection point of the regression with Y-axis using `lin_reg.intercept_` - it will be around `21` in our case, indicating the price at the beginning of the year. - -To see how accurate our model is, we can predict prices on a test dataset, and then measure how close our predictions are to the expected values. This can be done using mean square error (MSE) metrics, which is the mean of all squared differences between expected and predicted value. - -```{code-cell} -pred = lin_reg.predict(X_test) - -mse = np.sqrt(mean_squared_error(y_test,pred)) -print(f'Mean error: {mse:3.3} ({mse/np.mean(pred)*100:3.3}%)') -``` - -Our error seems to be around 2 points, which is ~17%. Not too good. Another indicator of model quality is the **coefficient of determination**, which can be obtained like this: - -```{code-cell} -score = lin_reg.score(X_train,y_train) -print('Model determination: ', score) -``` - -If the value is 0, it means that the model does not take input data into account, and acts as the *worst linear predictor*, which is simply a mean value of the result. The value of 1 means that we can perfectly predict all expected outputs. In our case, the coefficient is around 0.06, which is quite low. - -We can also plot the test data together with the regression line to better see how regression works in our case: - -```{code-cell} -plt.scatter(X_test,y_test) -plt.plot(X_test,pred) -``` - -## Polynomial Regression - -Another type of Linear Regression is Polynomial Regression. While sometimes there's a linear relationship between variables - the bigger the pumpkin in volume, the higher the price - sometimes these relationships can't be plotted as a plane or straight line. - -```{seealso} -Here are [some more examples](https://online.stat.psu.edu/stat501/lesson/9/9.8) of data that could use Polynomial Regression -``` - -Take another look at the relationship between Date and Price. Does this scatterplot seem like it should necessarily be analyzed by a straight line? Can't prices fluctuate? In this case, you can try polynomial regression. - -```{note} -Polynomials are mathematical expressions that might consist of one or more variables and coefficients. -``` - -Polynomial regression creates a curved line to better fit nonlinear data. In our case, if we include a squared `DayOfYear` variable into input data, we should be able to fit our data with a parabolic curve, which will have a minimum at a certain point within the year. - -Scikit-learn includes a helpful [pipeline API](https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.make_pipeline.html?highlight=pipeline#sklearn.pipeline.make_pipeline) to combine different steps of data processing together. A **pipeline** is a chain of **estimators**. In our case, we will create a pipeline that first adds polynomial features to our model, and then trains the regression: - -```{code-cell} -from sklearn.preprocessing import PolynomialFeatures -from sklearn.pipeline import make_pipeline - -pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression()) - -pipeline.fit(X_train,y_train) -``` - -Using `PolynomialFeatures(2)` means that we will include all second-degree polynomials from the input data. In our case it will just mean $DayOfYear^2$, but given two input variables X and Y, this will add $X^2$, XY and $Y^2$. We may also use higher degree polynomials if we want. - -Pipelines can be used in the same manner as the original `LinearRegression` object, i.e. we can `fit` the pipeline, and then use `predict` to get the prediction results. Here is the graph showing test data, and the approximation curve: - -```{figure} ../../../images/ml-regression/poly-results.png ---- -name: 'Polynomial regression' -width: 70% ---- -Polynomial regression{cite}`Polynomial_regression` -``` - -Using Polynomial Regression, we can get slightly lower MSE and higher determination, but not significantly. We need to take into account other features! - -```{seealso} -You can see that the minimal pumpkin prices are observed somewhere around Halloween. How can you explain this? -``` - -🎃 Congratulations, you just created a model that can help predict the price of pie pumpkins. You can probably repeat the same procedure for all pumpkin types, but that would be tedious. Let's learn now how to take pumpkin variety into account in our model! - -## Categorical Features - -In the ideal world, we want to be able to predict prices for different pumpkin varieties using the same model. However, the `Variety` column is somewhat different from columns like `Month`, because it contains non-numeric values. Such columns are called **categorical**. - -Here you can see how average price depends on variety: - -```{figure} ../../../images/ml-regression/price-by-variety.png ---- -name: 'Average price by variety' -width: 70% ---- -Average price by variety{cite}`Average_price_by_variety` -``` - -To take variety into account, we first need to convert it to numeric form, or **encode** it. There are several way we can do it: - -* Simple **numeric encoding** will build a table of different varieties, and then replace the variety name by an index in that table. This is not the best idea for linear regression, because linear regression takes the actual numeric value of the index, and adds it to the result, multiplying by some coefficient. In our case, the relationship between the index number and the price is clearly non-linear, even if we make sure that indices are ordered in some specific way. -* **One-hot encoding** will replace the `Variety` column by 4 different columns, one for each variety. Each column will contain `1` if the corresponding row is of a given variety, and `0` otherwise. This means that there will be four coefficients in linear regression, one for each pumpkin variety, responsible for "starting price" (or rather "additional price") for that particular variety. - -The code below shows how we can one-hot encode a variety: - -```{code-cell} -pd.get_dummies(new_pumpkins['Variety']) -``` - -To train linear regression using one-hot encoded variety as input, we just need to initialize `X` and `y` data correctly: - -```{code-cell} -X = pd.get_dummies(new_pumpkins['Variety']) -y = new_pumpkins['Price'] -``` - -The rest of the code is the same as what we used above to train Linear Regression. If you try it, you will see that the mean squared error is about the same, but we get much higher coefficient of determination (~77%). To get even more accurate predictions, we can take more categorical features into account, as well as numeric features, such as `Month` or `DayOfYear`. To get one large array of features, we can use `join`: - -```{code-cell} -X = pd.get_dummies(new_pumpkins['Variety']) \ - .join(new_pumpkins['Month']) \ - .join(pd.get_dummies(new_pumpkins['City'])) \ - .join(pd.get_dummies(new_pumpkins['Package'])) -y = new_pumpkins['Price'] -``` - -Here we also take into account `City` and `Package` type, which gives us MSE 2.84 (10%), and determination 0.94! - -## Putting it all together - -To make the best model, we can use combined (one-hot encoded categorical + numeric) data from the above example together with Polynomial Regression. Here is the complete code for your convenience: - -```{code-cell} -# set up training data -X = pd.get_dummies(new_pumpkins['Variety']) \ - .join(new_pumpkins['Month']) \ - .join(pd.get_dummies(new_pumpkins['City'])) \ - .join(pd.get_dummies(new_pumpkins['Package'])) -y = new_pumpkins['Price'] - -# make train-test split -X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0) - -# setup and train the pipeline -pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression()) -pipeline.fit(X_train,y_train) - -# predict results for test data -pred = pipeline.predict(X_test) - -# calculate MSE and determination -mse = np.sqrt(mean_squared_error(y_test,pred)) -print(f'Mean error: {mse:3.3} ({mse/np.mean(pred)*100:3.3}%)') - -score = pipeline.score(X_train,y_train) -print('Model determination: ', score) -``` - -This should give us the best determination coefficient of almost 97%, and MSE=2.23 (~8% prediction error). - -| Model | MSE | Determination | -|-------|-----|---------------| -| `DayOfYear` Linear | 2.77 (17.2%) | 0.07 | -| `DayOfYear` Polynomial | 2.73 (17.0%) | 0.08 | -| `Variety` Linear | 5.24 (19.7%) | 0.77 | -| All features Linear | 2.84 (10.5%) | 0.94 | -| All features Polynomial | 2.23 (8.25%) | 0.97 | - -🏆 Well done! You created four Regression models in one section and improved the model quality to 97%. In the final section on Regression, you will learn about Logistic Regression to determine categories. - -## Self study - -In this section, we learned about Linear Regression. There are other important types of Regression. Read about Stepwise, Ridge, Lasso and Elasticnet techniques. A good course to study to learn more is the [Stanford Statistical Learning course](https://online.stanford.edu/courses/sohs-ystatslearning-statistical-learning) - -## Your turn! 🚀 - -Test several different variables in this notebook to see how correlation corresponds to model accuracy. - -Assignment - [Create a regression model](../../assignments/ml-fundamentals/create-a-regression-model.md) - -## Acknowledgments - -Thanks to Microsoft for creating the open-source course [ML-For-Beginners](https://github.com/microsoft/ML-For-Beginners). It inspires the majority of the content in this chapter. - ---- - -```{bibliography} -:filter: docname in docnames -```