README.en.ipynb 19.9 KB
Notebook
Newer Older
G
gongweibao 已提交
1 2 3 4 5 6 7 8 9
{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Linear Regression\n",
        "Let us begin the tutorial with a classical problem called Linear Regression \\[[1](#References)\\]. In this chapter, we will train a model from a realistic dataset to predict home prices. Some important concepts in Machine Learning will be covered through this example.\n",
        "\n",
G
gongweibao 已提交
10
        "The source code for this tutorial lives on [book/fit_a_line](https://github.com/PaddlePaddle/book/tree/develop/fit_a_line). For instructions on getting started with PaddlePaddle, see [PaddlePaddle installation guide](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/getstarted/build_and_install/docker_install_en.rst).\n",
G
gongweibao 已提交
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
        "\n",
        "## Problem Setup\n",
        "Suppose we have a dataset of $n$ real estate properties. These real estate properties will be referred to as *homes* in this chapter for clarity.\n",
        "\n",
        "Each home is associated with $d$ attributes. The attributes describe characteristics such the number of rooms in the home, the number of schools or hospitals in the neighborhood, and the traffic condition nearby.\n",
        "\n",
        "In our problem setup, the attribute $x_{i,j}$ denotes the $j$th characteristic of the $i$th home. In addition, $y_i$ denotes the price of the $i$th home. Our task is to predict $y_i$ given a set of attributes $\\{x_{i,1}, ..., x_{i,d}\\}$. We assume that the price of a home is a linear combination of all of its attributes, namely,\n",
        "\n",
        "$$y_i = \\omega_1x_{i,1} + \\omega_2x_{i,2} + \\ldots + \\omega_dx_{i,d} + b,  i=1,\\ldots,n$$\n",
        "\n",
        "where $\\vec{\\omega}$ and $b$ are the model parameters we want to estimate. Once they are learned, we will be able to predict the price of a home, given the attributes associated with it. We call this model **Linear Regression**. In other words, we want to regress a value against several values linearly. In practice, a linear model is often too simplistic to capture the real relationships between the variables. Yet, because Linear Regression is easy to train and analyze, it has been applied to a large number of real problems. As a result, it is an important topic in many classic Statistical Learning and Machine Learning textbooks \\[[2,3,4](#References)\\].\n",
        "\n",
        "## Results Demonstration\n",
        "We first show the result of our model. The dataset [UCI Housing Data Set](https://archive.ics.uci.edu/ml/datasets/Housing) is used to train a linear model to predict the home prices in Boston. The figure below shows the predictions the model makes for some home prices. The $X$-axis represents the median value of the prices of simlilar homes within a bin, while the $Y$-axis represents the home value our linear model predicts. The dotted line represents points where $X=Y$. When reading the diagram, the more precise the model predicts, the closer the point is to the dotted line.\n",
        "\u003cp align=\"center\"\u003e\n",
        "    \u003cimg src = \"image/predictions_en.png\" width=400\u003e\u003cbr/\u003e\n",
        "    Figure 1. Predicted Value V.S. Actual Value\n",
        "\u003c/p\u003e\n",
        "\n",
        "## Model Overview\n",
        "\n",
        "### Model Definition\n",
        "\n",
        "In the UCI Housing Data Set, there are 13 home attributes $\\{x_{i,j}\\}$ that are related to the median home price $y_i$, which we aim to predict. Thus, our model can be written as:\n",
        "\n",
        "$$\\hat{Y} = \\omega_1X_{1} + \\omega_2X_{2} + \\ldots + \\omega_{13}X_{13} + b$$\n",
        "\n",
        "where $\\hat{Y}$ is the predicted value used to differentiate from actual value $Y$. The model learns parameters $\\omega_1, \\ldots, \\omega_{13}, b$, where the entries of $\\vec{\\omega}$ are **weights** and $b$ is **bias**.\n",
        "\n",
        "Now we need an objective to optimize, so that the learned parameters can make $\\hat{Y}$ as close to $Y$ as possible. Let's refer to the concept of [Loss Function (Cost Function)](https://en.wikipedia.org/wiki/Loss_function). A loss function must output a non-negative value, given any pair of the actual value $y_i$ and the predicted value $\\hat{y_i}$. This value reflects the magnitutude of the model error.\n",
        "\n",
        "For Linear Regression, the most common loss function is [Mean Square Error (MSE)](https://en.wikipedia.org/wiki/Mean_squared_error) which has the following form:\n",
        "\n",
        "$$MSE=\\frac{1}{n}\\sum_{i=1}^{n}{(\\hat{Y_i}-Y_i)}^2$$\n",
        "\n",
        "That is, for a dataset of size $n$, MSE is the average value of the the prediction sqaure errors.\n",
        "\n",
        "### Training\n",
        "\n",
        "After setting up our model, there are several major steps to go through to train it:\n",
        "1. Initialize the parameters including the weights $\\vec{\\omega}$ and the bias $b$. For example, we can set their mean values as $0$s, and their standard deviations as $1$s.\n",
        "2. Feedforward. Evaluate the network output and compute the corresponding loss.\n",
        "3. [Backpropagate](https://en.wikipedia.org/wiki/Backpropagation) the errors. The errors will be propagated from the output layer back to the input layer, during which the model parameters will be updated with the corresponding errors.\n",
        "4. Repeat steps 2~3, until the loss is below a predefined threshold or the maximum number of repeats is reached.\n",
        "\n",
        "## Dataset\n",
        "\n",
        "### Python Dataset Modules\n",
        "\n",
        "Our program starts with importing necessary packages:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "editable": true
      },
      "source": [
        "import paddle.v2 as paddle\n",
        "import paddle.v2.dataset.uci_housing as uci_housing\n"
      ],
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n"
          ]
        }
      ],
      "execution_count": 1
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n",
        "We encapsulated the [UCI Housing Data Set](https://archive.ics.uci.edu/ml/datasets/Housing) in our Python module `uci_housing`.  This module can\n",
        "\n",
        "1. download the dataset to `~/.cache/paddle/dataset/uci_housing/housing.data`, if not yet, and\n",
        "2.  [preprocesses](#preprocessing) the dataset.\n",
        "\n",
        "### An Introduction of the Dataset\n",
        "\n",
        "The UCI housing dataset has 506 instances. Each instance describes the attributes of a house in surburban Boston.  The attributes are explained below:\n",
        "\n",
        "| Attribute Name | Characteristic | Data Type |\n",
        "| ------| ------ | ------ |\n",
        "| CRIM | per capita crime rate by town | Continuous|\n",
        "| ZN | proportion of residential land zoned for lots over 25,000 sq.ft. | Continuous |\n",
        "| INDUS | proportion of non-retail business acres per town | Continuous |\n",
        "| CHAS | Charles River dummy variable | Discrete, 1 if tract bounds river; 0 otherwise|\n",
        "| NOX | nitric oxides concentration (parts per 10 million) | Continuous |\n",
        "| RM | average number of rooms per dwelling | Continuous |\n",
        "| AGE | proportion of owner-occupied units built prior to 1940 | Continuous |\n",
        "| DIS | weighted distances to five Boston employment centres | Continuous |\n",
        "| RAD | index of accessibility to radial highways | Continuous |\n",
        "| TAX | full-value property-tax rate per $10,000 | Continuous |\n",
        "| PTRATIO | pupil-teacher ratio by town | Continuous |\n",
        "| B | 1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town | Continuous |\n",
        "| LSTAT | % lower status of the population | Continuous |\n",
        "| MEDV | Median value of owner-occupied homes in $1000's | Continuous |\n",
        "\n",
        "The last entry is the median home price.\n",
        "\n",
        "### Preprocessing\n",
        "#### Continuous and Discrete Data\n",
        "We define a feature vector of length 13 for each home, where each entry corresponds to an attribute. Our first observation is that, among the 13 dimensions, there are 12 continuous dimensions and 1 discrete dimension.\n",
        "\n",
        "Note that although a discrete value is also written as numeric values such as 0, 1, or 2, its meaning differs from a continuous value drastically.  The linear difference between two discrete values has no meaning. For example, suppose $0$, $1$, and $2$ are used to represent colors *Red*, *Green*, and *Blue* respectively. Judging from the numeric representation of these colors, *Red* differs more from *Blue* than it does from *Green*. Yet in actuality, it is not true that extent to which the color *Blue* is different from *Red* is greater than the extent to which *Green* is different from *Red*. Therefore, when handling a discrete feature that has $d$ possible values, we usually convert it to $d$ new features where each feature takes a binary value, $0$ or $1$, indicating whether the original value is absent or present. Alternatively, the discrete features can be mapped onto a continuous multi-dimensional vector through an embedding table. For our problem here, because CHAS itself is a binary discrete value, we do not need to do any preprocessing.\n",
        "\n",
        "#### Feature Normalization\n",
        "We also observe a huge difference among the value ranges of the 13 features (Figure 2). For instance, the values of feature *B* fall in $[0.32, 396.90]$, whereas those of feature *NOX* has a range of $[0.3850, 0.8170]$. An effective optimization would require data normalization. The goal of data normalization is to scale te values of each feature into roughly the same range, perhaps $[-0.5, 0.5]$. Here, we adopt a popular normalization technique where we substract the mean value from the feature value and divide the result by the width of the original range.\n",
        "\n",
        "There are at least three reasons for [Feature Normalization](https://en.wikipedia.org/wiki/Feature_scaling) (Feature Scaling):\n",
        "- A value range that is too large or too small might cause floating number overflow or underflow during computation.\n",
        "- Different value ranges might result in varying *importances* of different features to the model (at least in the beginning of the training process). This assumption about the data is often unreasonable, making the optimization difficult, which in turn results in increased training time.\n",
        "- Many machine learning techniques or models (e.g., *L1/L2 regularization* and *Vector Space Model*) assumes that all the features have roughly zero means and their value ranges are similar.\n",
        "\n",
        "\u003cp align=\"center\"\u003e\n",
        "    \u003cimg src = \"image/ranges_en.png\" width=550\u003e\u003cbr/\u003e\n",
        "    Figure 2. The value ranges of the features\n",
        "\u003c/p\u003e\n",
        "\n",
        "#### Prepare Training and Test Sets\n",
        "We split the dataset in two, one for adjusting the model parameters, namely, for model training, and the other for model testing. The model error on the former is called the **training error**, and the error on the latter is called the **test error**. Our goal in training a model is to find the statistical dependency between the outputs and the inputs, so that we can predict new outputs given new inputs. As a result, the test error reflects the performance of the model better than the training error does. We consider two things when deciding the ratio of the training set to the test set: 1) More training data will decrease the variance of the parameter estimation, yielding more reliable models; 2) More test data will decrease the variance of the test error, yielding more reliable test errors. One standard split ratio is $8:2$.\n",
        "\n",
        "\n",
        "When training complex models, we usually have one more split: the validation set. Complex models usually have [Hyperparameters](https://en.wikipedia.org/wiki/Hyperparameter_optimization) that need to be set before the training process, such as the number of layers in the network. Because hyperparameters are not part of the model parameters, they cannot be trained using the same loss function. Thus we will try several sets of hyperparameters to train several models and cross-validate them on the validation set to pick the best one; finally, the selected trained model is tested on the test set. Because our model is relatively simple, we will omit this validation process.\n",
        "\n",
        "\n",
        "## Training\n",
        "\n",
        "`fit_a_line/trainer.py` demonstrates the training using [PaddlePaddle](http://paddlepaddle.org).\n",
        "\n",
        "### Initialize PaddlePaddle\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "editable": true
      },
      "source": [
        "paddle.init(use_gpu=False, trainer_count=1)\n"
      ],
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n"
          ]
        }
      ],
      "execution_count": 1
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n",
        "### Model Configuration\n",
        "\n",
        "Logistic regression is essentially a fully-connected layer with linear activation:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "editable": true
      },
      "source": [
        "x = paddle.layer.data(name='x', type=paddle.data_type.dense_vector(13))\n",
        "y_predict = paddle.layer.fc(input=x,\n",
        "                                size=1,\n",
        "                                act=paddle.activation.Linear())\n",
        "y = paddle.layer.data(name='y', type=paddle.data_type.dense_vector(1))\n",
        "cost = paddle.layer.regression_cost(input=y_predict, label=y)\n"
      ],
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n"
          ]
        }
      ],
      "execution_count": 1
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Create Parameters\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "editable": true
      },
      "source": [
        "parameters = paddle.parameters.create(cost)\n"
      ],
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n"
          ]
        }
      ],
      "execution_count": 1
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n",
        "### Create Trainer\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "editable": true
      },
      "source": [
        "optimizer = paddle.optimizer.Momentum(momentum=0)\n",
        "\n",
        "trainer = paddle.trainer.SGD(cost=cost,\n",
        "                             parameters=parameters,\n",
        "                             update_equation=optimizer)\n"
      ],
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n"
          ]
        }
      ],
      "execution_count": 1
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n",
        "### Feeding Data\n",
        "\n",
        "PaddlePaddle provides the\n",
        "[reader mechanism](https://github.com/PaddlePaddle/Paddle/tree/develop/doc/design/reader)\n",
        "for loadinng training data. A reader may return multiple columns, and we need a Python dictionary to specify the mapping from column index to data layers.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "editable": true
      },
      "source": [
        "feeding={'x': 0, 'y': 1}\n"
      ],
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n"
          ]
        }
      ],
      "execution_count": 1
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n",
        "Moreover, an event handler is provided to print the training progress:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "editable": true
      },
      "source": [
        "# event_handler to print training and testing info\n",
        "def event_handler(event):\n",
        "    if isinstance(event, paddle.event.EndIteration):\n",
        "        if event.batch_id % 100 == 0:\n",
        "            print \"Pass %d, Batch %d, Cost %f\" % (\n",
        "                event.pass_id, event.batch_id, event.cost)\n",
        "\n",
        "    if isinstance(event, paddle.event.EndPass):\n",
        "        result = trainer.test(\n",
        "            reader=paddle.batch(\n",
        "                uci_housing.test(), batch_size=2),\n",
        "            feeding=feeding)\n",
        "        print \"Test %d, Cost %f\" % (event.pass_id, result.cost)\n"
      ],
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n"
          ]
        }
      ],
      "execution_count": 1
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n",
        "### Start Training\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "editable": true
      },
      "source": [
        "trainer.train(\n",
        "    reader=paddle.batch(\n",
        "        paddle.reader.shuffle(\n",
        "            uci_housing.train(), buf_size=500),\n",
        "        batch_size=2),\n",
        "    feeding=feeding,\n",
        "    event_handler=event_handler,\n",
        "    num_passes=30)\n"
      ],
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n"
          ]
        }
      ],
      "execution_count": 1
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n",
        "## Summary\n",
        "This chapter introduces *Linear Regression* and how to train and test this model with PaddlePaddle, using the UCI Housing Data Set. Because a large number of more complex models and techniques are derived from linear regression, it is important to understand its underlying theory and limitation.\n",
        "\n",
        "\n",
        "## References\n",
        "1. https://en.wikipedia.org/wiki/Linear_regression\n",
        "2. Friedman J, Hastie T, Tibshirani R. The elements of statistical learning[M]. Springer, Berlin: Springer series in statistics, 2001.\n",
        "3. Murphy K P. Machine learning: a probabilistic perspective[M]. MIT press, 2012.\n",
        "4. Bishop C M. Pattern recognition[J]. Machine Learning, 2006, 128.\n",
        "\n",
        "\u003cbr/\u003e\n",
G
gongweibao 已提交
387
        "This tutorial is contributed by \u003ca xmlns:cc=\"http://creativecommons.org/ns#\" href=\"http://book.paddlepaddle.org\" property=\"cc:attributionName\" rel=\"cc:attributionURL\"\u003ePaddlePaddle\u003c/a\u003e, and licensed under a \u003ca rel=\"license\" href=\"http://creativecommons.org/licenses/by-nc-sa/4.0/\"\u003eCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International License\u003c/a\u003e.\n"
G
gongweibao 已提交
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
      ]
    }
  ],
  "metadata": {
    "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.0"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}