README.md 17.2 KB
Newer Older
C
choijulie 已提交
1
# Linear Regression
Y
Yan Xu 已提交
2

C
choijulie 已提交
3
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.
Z
zhouxiao-coder 已提交
4

T
update  
tink2123 已提交
5
The source code for this tutorial lives on [book/fit_a_line](https://github.com/PaddlePaddle/book/tree/develop/01.fit_a_line). For instructions on getting started with this book,see [Running This Book](https://github.com/PaddlePaddle/book/blob/develop/README.md#running-the-book).
L
Luo Tao 已提交
6

C
choijulie 已提交
7
## Problem Setup
Y
Yan Xu 已提交
8

J
julie 已提交
9
Suppose we have a dataset of $n$ real estate properties. Each real estate property will be referred to as **homes** in this chapter for clarity.
Z
zhouxiao-coder 已提交
10

11
Each home is associated with $d$ attributes. The attributes describe characteristics such as the number of rooms in the home, the number of schools or hospitals in the neighborhood, and the traffic condition nearby.
Z
zhouxiao-coder 已提交
12

C
choijulie 已提交
13
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,
Z
zhouxiao-coder 已提交
14

C
choijulie 已提交
15
$$y_i = \omega_1x_{i,1} + \omega_2x_{i,2} + \ldots + \omega_dx_{i,d} + b,  i=1,\ldots,n$$
Z
zhouxiao-coder 已提交
16

C
choijulie 已提交
17 18 19
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)\].

## Results Demonstration
20
We first show the result of our model. The dataset [UCI Housing Data Set](http://paddlemodels.bj.bcebos.com/uci_housing/housing.data) 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 similar 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 closer the point is to the dotted line, better the model's prediction.
Z
zhouxiao-coder 已提交
21
<p align="center">
C
choijulie 已提交
22 23
    <img src = "image/predictions_en.png" width=400><br/>
    Figure 1. Predicted Value V.S. Actual Value
Z
zhouxiao-coder 已提交
24 25
</p>

C
choijulie 已提交
26
## Model Overview
27

C
choijulie 已提交
28
### Model Definition
29

C
choijulie 已提交
30
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:
Z
zhouxiao-coder 已提交
31 32 33

$$\hat{Y} = \omega_1X_{1} + \omega_2X_{2} + \ldots + \omega_{13}X_{13} + b$$

C
choijulie 已提交
34
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**.
Z
zhouxiao-coder 已提交
35

C
choijulie 已提交
36
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.
Z
zhouxiao-coder 已提交
37

C
choijulie 已提交
38
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:
Z
zhouxiao-coder 已提交
39

40
$$MSE=\frac{1}{n}\sum_{i=1}^{n}{(\hat{Y_i}-Y_i)}^2$$
Z
zhouxiao-coder 已提交
41

C
choijulie 已提交
42 43
That is, for a dataset of size $n$, MSE is the average value of the the prediction sqaure errors.

D
daminglu 已提交
44
### Training Process
Z
zhouxiao-coder 已提交
45

C
choijulie 已提交
46 47 48 49
After setting up our model, there are several major steps to go through to train it:
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.
2. Feedforward. Evaluate the network output and compute the corresponding loss.
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.
50
4. Repeat steps 2~3, until the loss is below a predefined threshold or the maximum number of epochs is reached.
51

C
choijulie 已提交
52
## Dataset
Y
Yan Xu 已提交
53

C
choijulie 已提交
54
### An Introduction of the Dataset
55

C
choijulie 已提交
56
The UCI housing dataset has 506 instances. Each instance describes the attributes of a house in surburban Boston.  The attributes are explained below:
57

C
choijulie 已提交
58
| Attribute Name | Characteristic | Data Type |
Z
zhouxiao-coder 已提交
59
| ------| ------ | ------ |
C
choijulie 已提交
60 61 62 63 64 65 66 67 68
| CRIM | per capita crime rate by town | Continuous|
| ZN | proportion of residential land zoned for lots over 25,000 sq.ft. | Continuous |
| INDUS | proportion of non-retail business acres per town | Continuous |
| CHAS | Charles River dummy variable | Discrete, 1 if tract bounds river; 0 otherwise|
| NOX | nitric oxides concentration (parts per 10 million) | Continuous |
| RM | average number of rooms per dwelling | Continuous |
| AGE | proportion of owner-occupied units built prior to 1940 | Continuous |
| DIS | weighted distances to five Boston employment centres | Continuous |
| RAD | index of accessibility to radial highways | Continuous |
T
tink2123 已提交
69
| TAX | full-value property-tax rate per \$10,000 | Continuous |
C
choijulie 已提交
70 71 72 73 74 75 76 77
| PTRATIO | pupil-teacher ratio by town | Continuous |
| B | 1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town | Continuous |
| LSTAT | % lower status of the population | Continuous |
| MEDV | Median value of owner-occupied homes in $1000's | Continuous |

The last entry is the median home price.

### Preprocessing
Y
Yan Xu 已提交
78

C
choijulie 已提交
79
#### Continuous and Discrete Data
Y
Yan Xu 已提交
80

C
choijulie 已提交
81 82 83 84 85
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.

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.

#### Feature Normalization
Y
Yan Xu 已提交
86

87
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 the values of each feature into roughly the same range, perhaps $[-0.5, 0.5]$. Here, we adopt a popular normalization technique where we subtract the mean value from the feature value and divide the result by the width of the original range.
C
choijulie 已提交
88 89 90 91 92

There are at least three reasons for [Feature Normalization](https://en.wikipedia.org/wiki/Feature_scaling) (Feature Scaling):
- A value range that is too large or too small might cause floating number overflow or underflow during computation.
- 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.
- 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.
Z
zhouxiao-coder 已提交
93 94

<p align="center">
C
choijulie 已提交
95 96
    <img src = "image/ranges_en.png" width=550><br/>
    Figure 2. The value ranges of the features
Z
zhouxiao-coder 已提交
97 98
</p>

C
choijulie 已提交
99 100
#### Prepare Training and Test Sets

Y
Yan Xu 已提交
101
We split the dataset in two, one for adjusting the model parameters, namely, for training the model, and the other for 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 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$.
102

C
choijulie 已提交
103
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.
104

C
choijulie 已提交
105
## Training
Z
zhouxiao-coder 已提交
106

C
choijulie 已提交
107
`fit_a_line/trainer.py` demonstrates the training using [PaddlePaddle](http://paddlepaddle.org).
Y
Yi Wang 已提交
108

109
### Datafeeder Configuration
Y
Yan Xu 已提交
110

D
daminglu 已提交
111 112 113 114 115 116
Our program starts with importing necessary packages:

```python
import paddle
import paddle.fluid as fluid
import numpy
117
from __future__ import print_function
R
root 已提交
118 119 120 121 122 123 124 125 126 127
try:
    from paddle.fluid.contrib.trainer import *
    from paddle.fluid.contrib.inferencer import *
except ImportError:
    print(
        "In the fluid 1.0, the trainer and inferencer are moving to paddle.fluid.contrib",
        file=sys.stderr)
    from paddle.fluid.trainer import *
    from paddle.fluid.inferencer import *

D
daminglu 已提交
128 129
```

130
We encapsulated the [UCI Housing Data Set](http://paddlemodels.bj.bcebos.com/uci_housing/housing.data) in our Python module `uci_housing`.  This module can
D
daminglu 已提交
131 132 133

1. download the dataset to `~/.cache/paddle/dataset/uci_housing/housing.data`, if you haven't yet, and
2.  [preprocess](#preprocessing) the dataset.
Z
zhouxiao-coder 已提交
134

D
daminglu 已提交
135 136

We define data feeders for test and train. The feeder reads a `BATCH_SIZE` of data each time and feed them to the training/testing process. If the user wants some randomness on the data order, she can define both a `BATCH_SIZE` and a `buf_size`. That way the datafeeder will yield the first `BATCH_SIZE` data out of a shuffle of the first `buf_size` data.
Z
zhouxiao-coder 已提交
137

138 139
```python
BATCH_SIZE = 20
Z
zhouxiao-coder 已提交
140

141 142 143 144
train_reader = paddle.batch(
    paddle.reader.shuffle(
        paddle.dataset.uci_housing.train(), buf_size=500),
    batch_size=BATCH_SIZE)
Z
zhouxiao-coder 已提交
145

146 147 148 149
test_reader = paddle.batch(
    paddle.reader.shuffle(
        paddle.dataset.uci_housing.test(), buf_size=500),
    batch_size=BATCH_SIZE)
150
```
Q
qiaolongfei 已提交
151

152
### Train Program Configuration
Y
Yan Xu 已提交
153

D
daminglu 已提交
154
`train_program` sets up the network structure of this current training model. For linear regression, it is simply a fully connected layer from the input to the output. More complex structures like CNN and RNN will be introduced in later chapters. The `train_program` must return an avg_loss as its first returned parameter because it is needed in backpropagation.
Q
qiaolongfei 已提交
155 156

```python
157 158 159 160 161 162 163 164 165 166 167
def train_program():
    y = fluid.layers.data(name='y', shape=[1], dtype='float32')

    # feature vector of length 13
    x = fluid.layers.data(name='x', shape=[13], dtype='float32')
    y_predict = fluid.layers.fc(input=x, size=1, act=None)

    loss = fluid.layers.square_error_cost(input=y_predict, label=y)
    avg_loss = fluid.layers.mean(loss)

    return avg_loss
Q
qiaolongfei 已提交
168 169
```

170 171 172 173 174 175 176 177
### Optimizer Function Configuration

In the following `SGD` optimizer, `learning_rate` specifies the learning rate in the optimization procedure.

```python
def optimizer_program():
    return fluid.optimizer.SGD(learning_rate=0.001)
```
Q
qiaolongfei 已提交
178

179
### Specify Place
Y
Yan Xu 已提交
180

181
Specify your training environment, you should specify if the training is on CPU or GPU.
Z
zhouxiao-coder 已提交
182

183
```python
184 185
use_cuda = False
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
Z
zhouxiao-coder 已提交
186 187
```

C
choijulie 已提交
188
### Create Trainer
Y
Yan Xu 已提交
189

D
daminglu 已提交
190
The trainer will take the `train_program` as input.
191

Z
zhouxiao-coder 已提交
192
```python
R
root 已提交
193
trainer = Trainer(
194 195
    train_func=train_program,
    place=place,
196
    optimizer_func=optimizer_program)
Z
zhouxiao-coder 已提交
197 198
```

C
choijulie 已提交
199
### Feeding Data
Y
Yi Wang 已提交
200

C
choijulie 已提交
201 202
PaddlePaddle provides the
[reader mechanism](https://github.com/PaddlePaddle/Paddle/tree/develop/doc/design/reader)
203
for loading the training data. A reader may return multiple columns, and we need a Python dictionary to specify the mapping from column index to data layers.
204

Z
zhouxiao-coder 已提交
205
```python
206
feed_order=['x', 'y']
Y
Yi Wang 已提交
207 208
```

C
choijulie 已提交
209
Moreover, an event handler is provided to print the training progress:
210

L
liaogang 已提交
211
```python
212
# Specify the directory to save the parameters
D
daminglu 已提交
213
params_dirname = "fit_a_line.inference.model"
L
liaogang 已提交
214

R
root 已提交
215

Q
qiaolongfei 已提交
216 217
train_title = "Train cost"
test_title = "Test cost"
D
daminglu 已提交
218

Q
qiaolongfei 已提交
219
step = 0
Q
qiaolongfei 已提交
220

221
# event_handler prints training and testing info
222
def event_handler(event):
Q
qiaolongfei 已提交
223
    global step
R
root 已提交
224
    if isinstance(event, EndStepEvent):
Y
Yan Xu 已提交
225
        if step % 10 == 0:   # record a train cost every 10 batches
226 227
            print("%s, Step %d, Cost %f" % (train_title, step, event.metrics[0]))

Y
Yan Xu 已提交
228
        if step % 100 == 0:  # record a test cost every 100 batches
229 230
            test_metrics = trainer.test(
                reader=test_reader, feed_order=feed_order)
R
root 已提交
231
            print("%s, Step %d, Cost %f" % (test_title, step, test_metrics[0]))
232
            if test_metrics[0] < 10.0:
233 234 235
                # If the accuracy is good enough, we can stop the training.
                print('loss is less than 10.0, stop')
                trainer.stop()
Y
Yan Xu 已提交
236
        step += 1
237

M
minqiyang 已提交
238
    if isinstance(event, EndEpochEvent):
Y
Yan Xu 已提交
239 240 241 242
        if event.epoch % 10 == 0:
            # We can save the trained parameters for the inferences later
            if params_dirname is not None:
                trainer.save_params(params_dirname)
243

Z
zhouxiao-coder 已提交
244
```
Y
Yi Wang 已提交
245

C
choijulie 已提交
246
### Start Training
Y
Yan Xu 已提交
247

248
We now can start training by calling `trainer.train()`.
Z
zhouxiao-coder 已提交
249

250
```python
251 252 253
%matplotlib inline

# The training could take up to a few minutes.
254
trainer.train(
255 256
    reader=train_reader,
    num_epochs=100,
257
    event_handler=event_handler,
258 259
    feed_order=feed_order)

Z
zhouxiao-coder 已提交
260 261
```

Q
qiaolongfei 已提交
262
![png](./image/train_and_test.png)
Q
qiaolongfei 已提交
263

D
daminglu 已提交
264
## Inference
265

D
daminglu 已提交
266
Initialize the Inferencer with the inference_program and the params_dirname, which is where we saved our params
Q
qiaolongfei 已提交
267

D
daminglu 已提交
268
### Setup the Inference Program
Y
Yan Xu 已提交
269

D
daminglu 已提交
270
Similar to the trainer.train, the Inferencer needs to take an inference_program to do inference.
271
Prune the train_program to only have the y_predict.
Q
qiaolongfei 已提交
272 273

```python
274 275 276 277
def inference_program():
    x = fluid.layers.data(name='x', shape=[13], dtype='float32')
    y_predict = fluid.layers.fc(input=x, size=1, act=None)
    return y_predict
Q
qiaolongfei 已提交
278 279
```

D
daminglu 已提交
280
### Infer
Y
Yan Xu 已提交
281

D
daminglu 已提交
282 283
Inferencer will load the trained model from `params_dirname` and use it to infer the unseen data.

Q
qiaolongfei 已提交
284
```python
R
root 已提交
285
inferencer = Inferencer(
D
daminglu 已提交
286
    infer_func=inference_program, param_path=params_dirname, place=place)
Q
qiaolongfei 已提交
287

288
batch_size = 10
289
test_reader = paddle.batch(paddle.dataset.uci_housing.test(),batch_size=batch_size)
290
test_data = next(test_reader())
Y
Yan Xu 已提交
291 292
test_x = numpy.array([data[0] for data in test_data]).astype("float32")
test_y = numpy.array([data[1] for data in test_data]).astype("float32")
Q
qiaolongfei 已提交
293

Y
Yan Xu 已提交
294
results = inferencer.infer({'x': test_x})
295 296

print("infer results: (House Price)")
Y
Yan Xu 已提交
297 298
for idx, val in enumerate(results[0]):
    print("%d: %.2f" % (idx, val))
299 300

print("\nground truth:")
Y
Yan Xu 已提交
301 302
for idx, val in enumerate(test_y):
    print("%d: %.2f" % (idx, val))
Q
qiaolongfei 已提交
303 304
```

C
choijulie 已提交
305
## Summary
Z
zhouxiao-coder 已提交
306

Y
Yan Xu 已提交
307
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.
Z
zhouxiao-coder 已提交
308

C
choijulie 已提交
309
## References
Y
Yan Xu 已提交
310

Z
zhouxiao-coder 已提交
311 312 313
1. https://en.wikipedia.org/wiki/Linear_regression
2. Friedman J, Hastie T, Tibshirani R. The elements of statistical learning[M]. Springer, Berlin: Springer series in statistics, 2001.
3. Murphy K P. Machine learning: a probabilistic perspective[M]. MIT press, 2012.
Z
zhouxiao-coder 已提交
314
4. Bishop C M. Pattern recognition[J]. Machine Learning, 2006, 128.
L
Luo Tao 已提交
315 316

<br/>
L
Luo Tao 已提交
317
This tutorial is contributed by <a xmlns:cc="http://creativecommons.org/ns#" href="http://book.paddlepaddle.org" property="cc:attributionName" rel="cc:attributionURL">PaddlePaddle</a>, and licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.