R squared 0.0 in lm.score( ) meaning?

Viewed 618

on this page, R^2 is defined as:

The coefficient R^2 is defined as (1 - u/v), where u is the residual sum of squares ((y_true - y_pred) ** 2).sum() and v is the total sum of squares ((y_true - y_true.mean()) ** 2).sum(). The best possible score is 1.0 and it can be negative (because the model can be arbitrarily worse). A constant model that always predicts the expected value of y, disregarding the input features, would get a R^2 score of 0.0.

I'm unable to understand the line line:

A constant model that always predicts the expected value of y, disregarding the input features, would get a R^2 score of 0.0.

How a constant model will give R^2 as 0.0 other than the case in which this constant model gives y_true.mean() ?

Thanks.

1 Answers

So if you fit a constant model (i.e all predictions come to 1 value), it is an intercept only model where the intercept is the mean, because that explains the most variance.

Hence going by the formula you have provide, R is exactly zero. In instances where the predictor or the model has no predictive value at zero, it will give an R^2 close to zero (or even negative).

We can do this calculation manually below.

First the dataset:

import pandas as pd
from sklearn.datasets import load_iris
from sklearn.metrics import r2_score
from sklearn import linear_model
iris = load_iris()
df = pd.DataFrame(data= iris['data'],
                     columns= iris['feature_names'] )

We fit the a model and calculate the residuals:

mdl_full = linear_model.LinearRegression()
mdl_full.fit(df[['petal width (cm)']],df['petal length (cm)'])
pred = mdl.predict(df[['petal width (cm)']])
resid_full = np.linalg.norm(df['petal length (cm)'] - pred) ** 2

Fit a model with only the intercept:

mdl_constant = linear_model.LinearRegression()
mdl_constant.fit(X = np.repeat(0,150).reshape(-1, 1),y=df['petal length (cm)'])
pred = mdl_constant.predict(df[['petal width (cm)']])
resid_constant = np.linalg.norm(df['petal length (cm)'] - pred) ** 2

We can calculate the r^2 manually:

(1 - resid_full / resid_constant)
0.9265562307373204

And it is exactly what you get from .score :

mdl_full.score(df[['petal width (cm)']],df['petal length (cm)'])
0.9265562307373204

So you can see if the full model is exactly the same as your constant model, it gives r square of 0. You can refit the constant model with X = 1, X=2 etc but it gives you essentially the same result.

Related