{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "rF2trPuyzm9C" }, "source": [ "# Exercise 3.2\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "id": "ipcsUFDUzm9C" }, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "metadata": { "id": "MCJe_ITJzm9G" }, "source": [ "**Linear Regression**\n", "\n", "The goal of this exercise is to explore a simple linear regression problem based on Portugese white wine.\n", "\n", "The dataset is based on \n", "Cortez, A. Cerdeira, F. Almeida, T. Matos and J. Reis. **Modeling wine preferences by data mining from physicochemical properties**. Published in Decision Support Systems, Elsevier, 47(4):547-553, 2009. \n", "\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "NopU99AT9G7s", "outputId": "d7e8848e-b9c0-4eb4-8f18-5acda9d8c343" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "/bin/sh: wget: command not found\r\n" ] } ], "source": [ "# The code snippet below is responsible for downloading the dataset\n", "# - for example when running via Google Colab.\n", "#\n", "# You can also directly download the file using the link if you work\n", "# with a local setup (in that case, ignore the !wget)\n", "\n", "!wget https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-white.csv" ] }, { "cell_type": "markdown", "metadata": { "id": "zEiZ19s5zm9G" }, "source": [ "**Before we start**\n", "\n", "The downloaded file contains data on 4989 wines. For each wine 11 features are recorded (column 0 to 10). The final columns contains the quality of the wine. This is what we want to predict. More information on the features and the quality measurement is provided in the original publication.\n", "\n", "List of columns/features: \n", "0. fixed acidity\n", "1. volatile acidity\n", "2. citric acid\n", "3. residual sugar\n", "4. chlorides\n", "5. free sulfur dioxide\n", "6. total sulfur dioxide\n", "7. density\n", "8. pH\n", "9. sulphates\n", "10. alcohol\n", "11. quality\n", "\n", "\n", "\n", "[file]: https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-white.csv" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "5ONqeI5Uzm9H", "outputId": "d31ba8d4-cf0a-4f25-8a93-9091c0dd041a" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('data:', (4898, 12))\n", "First example:\n", "('Features:', array([7.600e+00, 3.800e-01, 2.800e-01, 4.200e+00, 2.900e-02, 7.000e+00,\n", " 1.120e+02, 9.906e-01, 3.000e+00, 4.100e-01, 1.260e+01]))\n", "('Quality:', 6.0)\n" ] } ], "source": [ "# Before working with the data, \n", "# we download and prepare all features\n", "\n", "# load all examples from the file\n", "data = np.genfromtxt('winequality-white.csv',delimiter=\";\",skip_header=1)\n", "\n", "print(\"data:\", data.shape)\n", "\n", "# Prepare for proper training\n", "np.random.shuffle(data) # randomly sort examples\n", "\n", "# take the first 3000 examples for training\n", "# (remember array slicing from last week)\n", "X_train = data[:3000,:11] # all features except last column\n", "y_train = data[:3000,11] # quality column\n", "\n", "# and the remaining examples for testing\n", "X_test = data[3000:,:11] # all features except last column\n", "y_test = data[3000:,11] # quality column\n", "\n", "print(\"First example:\")\n", "print(\"Features:\", X_train[0])\n", "print(\"Quality:\", y_train[0])" ] }, { "cell_type": "markdown", "metadata": { "id": "jiwnyNHpzm9L" }, "source": [ "# Problems\n", "\n", "\n", "* First we want to understand the data better. Plot (plt.hist) the distribution of each of the features for the training data as well as the 2D distribution (either plt.scatter or plt.hist2d) of each feature versus quality. Also calculate the correlation coefficient (np.corrcoef) for each feature with quality. Which feature by itself seems most predictive for the quality?\n", "\n", "* Calculate the linear regression weights. Numpy provides functions for matrix multiplication (np.matmul), matrix transposition (.T) and matrix inversion (np.linalg.inv).\n", "\n", "* Use the weights to predict the quality for the test dataset. How\n", "does your predicted quality compare with the true quality of the test data? Calculate the correlation coefficient between predicted and true quality and draw a scatter plot." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Hints" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Formally, we want to find weights $w_i$ that minimize:\n", "$$\n", "\\sum_{j}\\left(\\sum_{i} X_{i j} w_{i}-y_{j}\\right)^{2}\n", "$$\n", "The index $i$ denotes the different features (properties of the wines) while the index $j$ runs over the different wines. The matrix $X_{ij}$ contains the training data, $y_j$ is the 'true' quality for sample $j$. The weights can be found by taking the first derivative of the above expression with respect to the weights and setting it to zero (the standard strategy for finding an extremum), and solving the corresponding system of equations (for a detailed derivation, see [here](https://en.wikipedia.org/wiki/Ordinary_least_squares)). The result is:\n", "$$\n", "\\overrightarrow{\\mathbf{w}}=\\left(\\mathbf{X}^{T} \\mathbf{X}\\right)^{-1} \\mathbf{X}^{T} \\overrightarrow{\\mathbf{y}}\n", "$$\n", "\n", "In the end, you should have as many components of $w_i$ as there are features in the data (i.e. eleven in this case). \n", "\n", "You can use .shape to inspect the dimensions of numpy tensors.\n" ] } ], "metadata": { "colab": { "collapsed_sections": [], "name": "Exercise 4", "provenance": [] }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.9" } }, "nbformat": 4, "nbformat_minor": 1 }