# Regression Week 2: Multiple Regression (Interpretation)

The goal of this first notebook is to explore multiple regression and feature engineering with existing graphlab functions.

In this notebook you will use data on house sales in King County to predict prices using multiple regression. You will:

• Use SFrames to do some feature engineering
• Use built-in graphlab functions to compute the regression weights (coefficients/parameters)
• Given the regression weights, predictors and outcome write a function to compute the Residual Sum of Squares
• Look at coefficients and interpret their meanings
• Evaluate multiple models via RSS

# Fire up graphlab create

``````

In [1]:

import graphlab

``````

# Load in house sales data

Dataset is from house sales in King County, the region where the city of Seattle, WA is located.

``````

In [3]:

sales = graphlab.SFrame('../Data/kc_house_data.gl/')

``````

# Split data into training and testing.

We use seed=0 so that everyone running this notebook gets the same results. In practice, you may set a random seed (or let GraphLab Create pick a random seed for you).

``````

In [5]:

train_data,test_data = sales.random_split(.8,seed=0)

``````

# Learning a multiple regression model

Recall we can use the following code to learn a multiple regression model predicting 'price' based on the following features: example_features = ['sqft_living', 'bedrooms', 'bathrooms'] on training data with the following code:

(Aside: We set validation_set = None to ensure that the results are always the same)

``````

In [28]:

example_features = ['sqft_living', 'bedrooms', 'bathrooms']
example_model = graphlab.linear_regression.create(train_data, target = 'price', features = example_features,
validation_set = None)

``````
``````

PROGRESS: Linear regression:
PROGRESS: --------------------------------------------------------
PROGRESS: Number of examples          : 17384
PROGRESS: Number of features          : 3
PROGRESS: Number of unpacked features : 3
PROGRESS: Number of coefficients    : 4
PROGRESS: Starting Newton Method
PROGRESS: --------------------------------------------------------
PROGRESS: +-----------+----------+--------------+--------------------+---------------+
PROGRESS: | Iteration | Passes   | Elapsed Time | Training-max_error | Training-rmse |
PROGRESS: +-----------+----------+--------------+--------------------+---------------+
PROGRESS: | 1         | 2        | 0.031763     | 4146407.600631     | 258679.804477 |
PROGRESS: +-----------+----------+--------------+--------------------+---------------+
PROGRESS: SUCCESS: Optimal solution found.
PROGRESS:

``````

Now that we have fitted the model we can extract the regression weights (coefficients) as an SFrame as follows:

``````

In [29]:

example_weight_summary = example_model.get("coefficients")
print example_weight_summary

``````
``````

+-------------+-------+----------------+
|     name    | index |     value      |
+-------------+-------+----------------+
| (intercept) |  None | 87910.0724924  |
| sqft_living |  None | 315.403440552  |
|   bedrooms  |  None | -65080.2155528 |
|  bathrooms  |  None | 6944.02019265  |
+-------------+-------+----------------+
[4 rows x 3 columns]

``````

# Making Predictions

In the gradient descent notebook we use numpy to do our regression. In this book we will use existing graphlab create functions to analyze multiple regressions.

Recall that once a model is built we can use the .predict() function to find the predicted values for data we pass. For example using the example model above:

``````

In [30]:

example_predictions = example_model.predict(train_data)
print example_predictions[0] # should be 271789.505878

``````
``````

271789.505878

``````

Now that we can make predictions given the model, let's write a function to compute the RSS of the model. Complete the function below to calculate RSS given the model, data, and the outcome.

``````

In [32]:

def get_residual_sum_of_squares(model, data, outcome):
# First get the predictions
predictions = model.predict(data)

# Then compute the residuals/errors
residuals = predictions - outcome

# Then square and add them up

``````

Test your function by computing the RSS on TEST data for the example model:

``````

In [33]:

print rss_example_train # should be 2.7376153833e+14

``````
``````

2.7376153833e+14

``````

# Create some new features

Although we often think of multiple regression as including multiple different features (e.g. # of bedrooms, squarefeet, and # of bathrooms) but we can also consider transformations of existing features e.g. the log of the squarefeet or even "interaction" features such as the product of bedrooms and bathrooms.

You will use the logarithm function to create a new feature. so first you should import it from the math library.

``````

In [38]:

import numpy as np

train_data['bedrooms_squared'] = np.power(train_data['bedrooms'],2)
train_data['bed_bath_rooms'] = train_data['bedrooms']*train_data['bathrooms']
train_data['log_sqft_living'] = np.log(train_data['sqft_living'])
train_data['lat_plus_long'] = train_data['lat']+train_data['long']

test_data['bedrooms_squared'] = np.power(test_data['bedrooms'],2)
test_data['bed_bath_rooms'] = test_data['bedrooms']*test_data['bathrooms']
test_data['log_sqft_living'] = np.log(test_data['sqft_living'])
test_data['lat_plus_long'] = test_data['lat']+test_data['long']

``````
``````

Out[38]:

id
date
price
bedrooms
bathrooms
sqft_living
sqft_lot
floors
waterfront

0114101516
2014-05-28 00:00:00+00:00
310000.0
3.0
1.0
1430.0
19901
1.5
0

9297300055
2015-01-24 00:00:00+00:00
650000.0
4.0
3.0
2950.0
5000
2
0

1202000200
2014-11-03 00:00:00+00:00
233000.0
3.0
2.0
1710.0
4697
1.5
0

8562750320
2014-11-10 00:00:00+00:00
580500.0
3.0
2.5
2320.0
3980
2
0

7589200193
2014-11-10 00:00:00+00:00
535000.0
3.0
1.0
1090.0
3000
1.5
0

2078500320
2014-06-20 00:00:00+00:00
605000.0
4.0
2.5
2620.0
7553
2
0

7766200013
2014-08-11 00:00:00+00:00
775000.0
4.0
2.25
4220.0
24186
1
0

9478500640
2014-08-19 00:00:00+00:00
292500.0
4.0
2.5
2250.0
4495
2
0

9558200045
2014-08-28 00:00:00+00:00
289000.0
3.0
1.75
1260.0
8400
1
0

8820901275
2014-06-10 00:00:00+00:00
571000.0
4.0
2.0
2750.0
7807
1.5
0

view
condition
sqft_above
sqft_basement
yr_built
yr_renovated
zipcode
lat

0
4
7
1430
0
1927
0
98028
47.75584254

3
3
9
1980
970
1979
0
98126
47.57136955

0
5
6
1710
0
1941
0
98002
47.30482931

0
3
8
2320
0
2003
0
98027
47.5391103

0
4
8
1090
0
1929
0
98117
47.68889559

0
3
8
2620
0
1996
0
98056
47.53013988

0
3
8
2600
1620
1984
0
98166
47.44504345

0
3
7
2250
0
2008
0
98042
47.36628767

0
3
7
1260
0
1954
0
98148
47.43658598

0
5
7
2250
500
1916
0
98125
47.7168015

long
sqft_living15
sqft_lot15
bedrooms_squared
bed_bath_rooms
log_sqft_living
lat_plus_long

-122.22874498
1780.0
12697.0
9.0
3.0
7.26542972325
-74.47290244

-122.37541218
2140.0
4000.0
16.0
12.0
7.98956044933
-74.80404263

-122.21774909
1030.0
4705.0
9.0
6.0
7.4442486495
-74.91291978

-122.06971484
2580.0
3980.0
9.0
7.5
7.74932246466
-74.53060454

-122.3752359
1570.0
5080.0
9.0
3.0
6.99393297522
-74.68634031

-122.18000831
2620.0
11884.0
16.0
10.0
7.87092959676
-74.64986843

-122.34720874
2410.0
30617.0
16.0
9.0
8.34759040703
-74.90216529

-122.11356981
2250.0
4500.0
16.0
10.0
7.7186854952
-74.74728214

-122.3346675
1290.0
8750.0
9.0
5.25
7.13886699995
-74.89808152

-122.28694727
1510.0
7807.0
16.0
8.0
7.91935619066
-74.57014577

[10 rows x 25 columns]

``````
``````

In [39]:

#from math import log

``````

Next create the following 4 new features as column in both TEST and TRAIN data:

• bedrooms_squared = bedrooms*bedrooms
• bed_bath_rooms = bedrooms*bathrooms
• log_sqft_living = log(sqft_living)
• lat_plus_long = lat + long As an example here's the first one:
``````

In [40]:

#train_data['bedrooms_squared'] = train_data['bedrooms'].apply(lambda x: x**2)
#test_data['bedrooms_squared'] = test_data['bedrooms'].apply(lambda x: x**2)

``````
``````

In [41]:

# create the remaining 3 features in both TEST and TRAIN data

``````
• Squaring bedrooms will increase the separation between not many bedrooms (e.g. 1) and lots of bedrooms (e.g. 4) since 1^2 = 1 but 4^2 = 16. Consequently this feature will mostly affect houses with many bedrooms.
• bedrooms times bathrooms gives what's called an "interaction" feature. It is large when both of them are large.
• Taking the log of squarefeet has the effect of bringing large values closer together and spreading out small values.
• Adding latitude to longitude is totally non-sensical but we will do it anyway (you'll see why)

Quiz Question: What is the mean (arithmetic average) value of your 4 new features on TEST data? (round to 2 digits)

``````

In [42]:

print 'mean bedrooms_squared == ' + str(np.round(test_data['bedrooms_squared'].mean(),2))
print 'mean bed_bath_rooms == ' + str(np.round(test_data['bed_bath_rooms'].mean(),2))
print 'mean log_sqft_living == ' + str(np.round(test_data['log_sqft_living'].mean(),2))
print 'mean lat_plus_long == ' + str(np.round(test_data['lat_plus_long'].mean(),2))

``````
``````

mean bedrooms_squared == 12.45
mean bed_bath_rooms == 7.5
mean log_sqft_living == 7.55
mean lat_plus_long == -74.65

``````

# Learning Multiple Models

Now we will learn the weights for three (nested) models for predicting house prices. The first model will have the fewest features the second model will add one more feature and the third will add a few more:

• Model 1: squarefeet, # bedrooms, # bathrooms, latitude & longitude
• Model 3: Add log squarefeet, bedrooms squared, and the (nonsensical) latitude + longitude
``````

In [43]:

model_1_features = ['sqft_living', 'bedrooms', 'bathrooms', 'lat', 'long']
model_2_features = model_1_features + ['bed_bath_rooms']
model_3_features = model_2_features + ['bedrooms_squared', 'log_sqft_living', 'lat_plus_long']

``````

Now that you have the features, learn the weights for the three different models for predicting target = 'price' using graphlab.linear_regression.create() and look at the value of the weights/coefficients:

``````

In [44]:

# Learn the three models: (don't forget to set validation_set = None)
model_1 = graphlab.linear_regression.create(train_data, target='price', features=model_1_features, validation_set=None)
model_2 = graphlab.linear_regression.create(train_data, target='price', features=model_2_features, validation_set=None)
model_3 = graphlab.linear_regression.create(train_data, target='price', features=model_3_features, validation_set=None)

``````
``````

PROGRESS: Linear regression:
PROGRESS: --------------------------------------------------------
PROGRESS: Number of examples          : 17384
PROGRESS: Number of features          : 5
PROGRESS: Number of unpacked features : 5
PROGRESS: Number of coefficients    : 6
PROGRESS: Starting Newton Method
PROGRESS: --------------------------------------------------------
PROGRESS: +-----------+----------+--------------+--------------------+---------------+
PROGRESS: | Iteration | Passes   | Elapsed Time | Training-max_error | Training-rmse |
PROGRESS: +-----------+----------+--------------+--------------------+---------------+
PROGRESS: | 1         | 2        | 0.040030     | 4074878.213084     | 236378.596454 |
PROGRESS: +-----------+----------+--------------+--------------------+---------------+
PROGRESS: SUCCESS: Optimal solution found.
PROGRESS:
PROGRESS: Linear regression:
PROGRESS: --------------------------------------------------------
PROGRESS: Number of examples          : 17384
PROGRESS: Number of features          : 6
PROGRESS: Number of unpacked features : 6
PROGRESS: Number of coefficients    : 7
PROGRESS: Starting Newton Method
PROGRESS: --------------------------------------------------------
PROGRESS: +-----------+----------+--------------+--------------------+---------------+
PROGRESS: | Iteration | Passes   | Elapsed Time | Training-max_error | Training-rmse |
PROGRESS: +-----------+----------+--------------+--------------------+---------------+
PROGRESS: | 1         | 2        | 0.023531     | 4014170.932927     | 235190.935428 |
PROGRESS: +-----------+----------+--------------+--------------------+---------------+
PROGRESS: SUCCESS: Optimal solution found.
PROGRESS:
PROGRESS: Linear regression:
PROGRESS: --------------------------------------------------------
PROGRESS: Number of examples          : 17384
PROGRESS: Number of features          : 9
PROGRESS: Number of unpacked features : 9
PROGRESS: Number of coefficients    : 10
PROGRESS: Starting Newton Method
PROGRESS: --------------------------------------------------------
PROGRESS: +-----------+----------+--------------+--------------------+---------------+
PROGRESS: | Iteration | Passes   | Elapsed Time | Training-max_error | Training-rmse |
PROGRESS: +-----------+----------+--------------+--------------------+---------------+
PROGRESS: | 1         | 2        | 0.048813     | 3193229.177872     | 228200.043154 |
PROGRESS: +-----------+----------+--------------+--------------------+---------------+
PROGRESS: SUCCESS: Optimal solution found.
PROGRESS:

``````
``````

In [45]:

# Examine/extract each model's coefficients:
print model_1.get("coefficients")
print model_2.get("coefficients")
print model_3.get("coefficients")

``````
``````

+-------------+-------+----------------+
|     name    | index |     value      |
+-------------+-------+----------------+
| (intercept) |  None | -56140675.7493 |
| sqft_living |  None | 310.263325778  |
|   bedrooms  |  None | -59577.1160674 |
|  bathrooms  |  None | 13811.8405431  |
|     lat     |  None | 629865.789501  |
|     long    |  None | -214790.28522  |
+-------------+-------+----------------+
[6 rows x 3 columns]

+----------------+-------+----------------+
|      name      | index |     value      |
+----------------+-------+----------------+
|  (intercept)   |  None | -54410676.1197 |
|  sqft_living   |  None | 304.449298057  |
|    bedrooms    |  None | -116366.043226 |
|   bathrooms    |  None | -77972.3305067 |
|      lat       |  None | 625433.834969  |
|      long      |  None | -203958.602991 |
| bed_bath_rooms |  None | 26961.6249075  |
+----------------+-------+----------------+
[7 rows x 3 columns]

+------------------+-------+----------------+
|       name       | index |     value      |
+------------------+-------+----------------+
|   (intercept)    |  None | -52974974.0779 |
|   sqft_living    |  None | 529.196420567  |
|     bedrooms     |  None | 28948.5277529  |
|    bathrooms     |  None | 65661.2072384  |
|       lat        |  None | 704762.148539  |
|       long       |  None | -137780.020002 |
|  bed_bath_rooms  |  None | -8478.36410648 |
| bedrooms_squared |  None | -6072.38466304 |
| log_sqft_living  |  None | -563467.784272 |
|  lat_plus_long   |  None | -83217.1979766 |
+------------------+-------+----------------+
[10 rows x 3 columns]

``````

Quiz Question: What is the sign (positive or negative) for the coefficient/weight for 'bathrooms' in model 1?

#### positive

Quiz Question: What is the sign (positive or negative) for the coefficient/weight for 'bathrooms' in model 2?

# Comparing multiple models

Now that you've learned three models and extracted the model weights we want to evaluate which model is best.

First use your functions from earlier to compute the RSS on TRAINING Data for each of the three models.

``````

In [48]:

# Compute the RSS on TRAINING data for each of the three models and record the values:
print 'rss train model_1 == ' + str(get_residual_sum_of_squares(model_1, train_data, train_data['price']))
print 'rss train model_2 == ' + str(get_residual_sum_of_squares(model_2, train_data, train_data['price']))
print 'rss train model_3 == ' + str(get_residual_sum_of_squares(model_3, train_data, train_data['price']))

``````
``````

``````

Quiz Question: Which model (1, 2 or 3) has lowest RSS on TRAINING Data? Is this what you expected?

##### 3

Now compute the RSS on on TEST data for each of the three models.

``````

In [49]:

# Compute the RSS on TESTING data for each of the three models and record the values:
print 'rss test model_1 == ' + str(get_residual_sum_of_squares(model_1, test_data, test_data['price']))
print 'rss test model_2 == ' + str(get_residual_sum_of_squares(model_2, test_data, test_data['price']))
print 'rss test model_3 == ' + str(get_residual_sum_of_squares(model_3, test_data, test_data['price']))

``````
``````

``````

Quiz Question: Which model (1, 2 or 3) has lowest RSS on TESTING Data? Is this what you expected?Think about the features that were added to each model from the previous.

##### 2
``````

In [ ]:

``````