Today

  • Why compare models?
  • Residuals, explained variation, and \(R^2\)
  • Why plain \(R^2\) can reward overfitting
  • Nested models and anova() comparisons
  • Coefficients before overall tests
  • Interactions and multi-level predictors
  • Using emmeans to compare levels
  • Choosing and reporting a selected model

Why Compare Models?

Models are alternative explanations of the data.

Model comparison helps us ask whether a more complex model is justified.

For example:

  • does adding sex improve the age model?
  • does adding smoker status improve the model further?
  • are we explaining meaningful variation, or just adding complexity?

The aim is not to find the biggest model.

The aim is to choose one model that is useful, justified, and interpretable.

When Coefficients Are Not Enough

A single coefficient can be easy to interpret. For example, an age slope tells us how much reaction time changes for one year of age.

But coefficient interpretation becomes harder with:

  • categorical predictors with more than two levels
  • interactions
  • more complex model terms

Model comparison asks whether the whole term improves the model:

  • does smoker status improve the model overall?
  • does the age-by-smoker interaction improve the model overall?

We interpret relevant coefficients, predictions, or emmeans comparisons.

Assumptions Behind Model Comparison

For anova() comparisons of linear models:

  • models must use the same outcome
  • models must use the same rows of data
  • models must be nested
  • added predictors should be theoretically plausible
  • the usual linear-model assumptions still matter

We focus on sums of squares: total, explained, and unexplained variation.

Likelihood / deviance become more important for binomial and count models.

Residuals and Unexplained Variation

A residual is the difference between an observed value and the value predicted by the model.

model_age <- lm(rt ~ age, data = blomkvist)
residuals(model_age)
     1      2      3      4      5      6 
 -97.9  -57.6  -33.9  -97.4 -128.8 -148.2 

Residuals close to zero mean the model predictions are close to the observed values.

Residuals far from zero mean the prediction errors are larger.

Residuals Are Differences

For each observation:

\[ \text{residual} = \text{observed value} - \text{predicted value} \]

observed predicted residual
702 800 -98
471 528 -58
639 673 -34
708 805 -97
607 736 -129

A positive residual means the observed value was higher than predicted.

A negative residual means the observed value was lower than predicted.

From Residuals to Unexplained Variation

To measure unexplained variation, we square the residuals and add them up.

The official name is the residual sum of squares, or RSS.

\[ \text{unexplained variation} = \sum \text{residuals}^2 \]

sum(residuals(model_age)^2)
[1] 5880557

This is the amount of variation the model has not explained.

Total, Explained, and Unexplained

We can split variation in the outcome into three ideas:

  • total variation, or TSS: how much observations vary around the mean
  • unexplained variation, or RSS: what remains in the residuals
  • explained variation, or ESS: what the model accounts for

\[ \text{TSS} = \text{ESS} + \text{RSS} \]

A useful model should reduce unexplained variation and increase explained variation.

\(R^2\)

\(R^2\) describes the proportion of total variation explained by the model.

\[ R^2 = \frac{\text{explained variation}}{\text{total variation}} \]

In R, deviance() gives us the residual sum of squares for an lm() model. So here, deviance is the unexplained variation, or RSS.

model unexplained explained R2
rt ~ age 5880557 3702302 0.386
rt ~ age + sex 5659365 3923495 0.409

\(R^2\) is useful because it tells us how much variation the model explains.

The Limitation of \(R^2\)

Plain \(R^2\) almost always goes up when we add predictors.

That can be useful when the added predictor is meaningful.

But it can also reward overfitting: a model can fit the current data better by chasing noise.

Example: brain size and body mass for seven hominin species, adapted from McElreath (2016).

Data source: Leonard et al. (2010), Table 1.2, compiled mainly from McHenry & Coffing (2000).

Adjusted \(R^2\)

Adjusted \(R^2\) asks whether the extra explained variation is worth the extra complexity. In simplified terms:

\[ \text{adjusted } R^2 \approx R^2 - \text{penalty for extra coefficients} \]

model R2 adjusted_R2
Linear 0.490 0.388
3rd-order polynomial 0.680 0.360
6th-order polynomial 1.000 undefined

The 6th-order curve fits the seven data points perfectly, so plain \(R^2\) is 1.

Adjusted \(R^2\) is more cautious: for the 3rd-order model it drops, and for the 6th-order model it is undefined because no residual degrees of freedom are left.

Nested Models

Two models are nested when the simpler model is contained inside the more complex model.

model_0 <- lm(rt ~ 1, data = blomkvist)
model_1 <- lm(rt ~ age, data = blomkvist)
model_2 <- lm(rt ~ age + smoker, data = blomkvist)
model_3 <- lm(rt ~ age * smoker, data = blomkvist)

Each model adds something to the model before it.

Nested or Not Nested?

Nested:

  • rt ~ age compared with rt ~ age + sex
  • rt ~ age + smoker compared with rt ~ age * smoker
  • rt ~ 1 compared with rt ~ age

Not nested:

  • rt ~ age compared with rt ~ sex
  • rt ~ age + sex compared with rt ~ age + smoker

For anova(), the simpler model must be contained in the more complex model.

What Is Being Compared?

Nested model comparison asks whether the more complex model reduces unexplained variation enough to justify the added term.

model unexplained extra_explained
Intercept only 9582860 NA
Age 5880557 3702302
Age + sex 5659365 221192

extra_explained is the extra variation explained by moving to the more complex model.

Exercise

Before opening the exercise file:

  1. Download week-03-exercises.zip from NOW.
  2. Move the zip file into the RStudio Project folder you created earlier.
  3. Unzip it there.
  4. In RStudio, open part-1-nested-comparison.Rmd.

You will:

  1. fit a sequence of nested models
  2. compare them with anova()
  3. compare adjusted \(R^2\)
  4. choose a model
  5. write a short model comparison paragraph

Discussion

  • What did each model add?
  • Which model improved fit?
  • Is the most complex model always best?
  • Which model would you report and why?

Where the F Value Comes From

The F value asks whether the complex model explains substantially more variation than the simpler model, taking model complexity into account.

\[ F = \frac{\text{extra explained variation per added parameter}}{\text{remaining unexplained variation per remaining df}} \] In words:

  • numerator: how much more variation the complex model explains, adjusted for the added parameter(s)
  • denominator: how much unexplained variation is still left, adjusted for remaining degrees of freedom

An F value of 10 means that the extra explained variation per added parameter is 10 times larger than the remaining unexplained variation per residual degree of freedom.

Calculate the F Value

simple_model <- model_age
complex_model <- model_age_sex

extra_explained <- deviance(simple_model) - deviance(complex_model)
added_parameters <- df.residual(simple_model) - df.residual(complex_model)

remaining_unexplained <- deviance(complex_model)
remaining_df <- df.residual(complex_model)

F_value <- (extra_explained / added_parameters) / (remaining_unexplained / remaining_df)

F_value
[1] 10.2

Same F value that appears when we compare the two nested models with anova().

Compare With an F-Test

anova(model_0, model_age, model_age_sex)
Analysis of Variance Table

Model 1: rt ~ 1
Model 2: rt ~ age
Model 3: rt ~ age + sex
  Res.Df     RSS Df Sum of Sq     F Pr(>F)    
1    264 9582860                              
2    263 5880557  1   3702302 171.4 <2e-16 ***
3    262 5659365  1    221192  10.2 0.0015 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Broadly speaking, the F statistic compares:

  • extra explained variation from the added predictor
  • with variation still left unexplained by the model

A larger F value means the added predictor explains more variation relative to the remaining noise.

Reading the anova() Table

Each row compares a more complex model with the model just above it.

In R’s table:

  • RSS is unexplained variation
  • Sum of Sq is extra explained variation from the added predictor
  • Sum of Sq = previous RSS - new RSS

Focus on:

  • which predictor was added
  • how much unexplained variation decreased
  • the F statistic for that added predictor
  • the p-value for that comparison
  • whether the more complex model is worth reporting

Predictors With More Than Two Levels

smoker has more than two levels.

table(blomkvist$smoker)
former     no    yes 
    76    163     26 

The model has more than one coefficient for this predictor, so interpreting one coefficient is not the same as testing the overall effect.

model_age <- lm(rt ~ age, data = blomkvist)
model_age_smoker <- lm(rt ~ age + smoker, data = blomkvist)
coef(model_age_smoker)
(Intercept)         age    smokerno   smokeryes 
     252.15        6.14       56.97       70.61 

Each smoker coefficient compares one smoker level with the reference level.

Testing Smoker Status Overall

Now compare the model with smoker to the model without smoker.

anova(model_age, model_age_smoker)
Analysis of Variance Table

Model 1: rt ~ age
Model 2: rt ~ age + smoker
  Res.Df     RSS Df Sum of Sq    F Pr(>F)  
1    263 5880557                           
2    261 5703617  2    176941 4.05  0.019 *
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

This asks whether smoker status improves the model overall, after age is already included.

Testing an Interaction With smoker

An age-by-smoker interaction allows the age slope to differ across smoker-status levels.

model_age_smoker_interaction <- lm(rt ~ age * smoker, data = blomkvist)

First inspect the coefficients. The interaction is represented by more than one coefficient.

term estimate std.error statistic p.value conf.low conf.high
(Intercept) 306.39 68.13 4.50 0.00 172.23 440.54
age 5.31 1.01 5.25 0.00 3.31 7.30
smokerno -9.02 74.95 -0.12 0.90 -156.60 138.57
smokeryes 5.94 113.19 0.05 0.96 -216.96 228.84
age:smokerno 1.05 1.15 0.92 0.36 -1.21 3.32
age:smokeryes 1.04 1.97 0.53 0.60 -2.84 4.92

Testing the Interaction Overall

Now compare the model without the interaction to the model with the interaction.

anova(model_age_smoker, model_age_smoker_interaction)
Analysis of Variance Table

Model 1: rt ~ age + smoker
Model 2: rt ~ age * smoker
  Res.Df     RSS Df Sum of Sq    F Pr(>F)
1    261 5703617                         
2    259 5684854  2     18763 0.43   0.65

This asks whether allowing the age slope to differ across smoker-status levels improves the model overall.

The anova() comparison tests the interaction term as a whole.

Comparing Levels With emmeans

If the model comparison suggests an overall effect, we can ask which levels differ.

smoker_means <- emmeans(model_age_smoker, pairwise ~ smoker)
smoker_means$contrasts
 contrast     estimate   SE  df t.ratio p.value
 former - no     -57.0 21.3 261  -2.676  0.0220
 former - yes    -70.6 34.3 261  -2.061  0.1000
 no - yes        -13.6 31.2 261  -0.437  0.9000

P value adjustment: tukey method for comparing a family of 3 estimates 

These comparisons estimate differences between smoker-status levels while using the fitted model.

This is often easier to interpret than reading the smoker coefficients one at a time.

Reporting the Selected Model

A common mistake is to present full results from every model that was fitted.

For most assessment reports, use this order:

  1. Fit models that match plausible hypotheses.
  2. Compare those models.
  3. Select the best-supported final model.
  4. Interpret coefficients and predictions from the selected model.

The comparison explains the choice. If an added predictor improved fit, report the F-test result briefly, for example: adding smoker status improved fit compared with the age-only model, \(F\)(2, 261) = 4.05, \(p\) = .019. The detailed interpretation belongs to the selected model.

Reporting Model Comparison

A useful paragraph says:

  • which models were compared
  • what predictors were added
  • what the comparison showed
  • the F-test result when a model improved fit
  • which model was selected
  • why that model was selected

Model Comparison and Assumptions

Model comparison helps choose between plausible models.

It does not prove that the selected model is appropriate.

After selecting a normal linear model, we still need residual checks for:

  • linearity
  • equality of variance
  • approximate normality of residuals
  • unusual observations

We will practise these checks in the next session.

Transfer Exercise Time

Choose one transfer file:

  • part-1-transfer-own-data-model-comparison.Rmd if you have your own data
  • part-1-transfer-chinese-model-comparison.Rmd if you do not yet have your own data

Use this time to:

  • practise one nested model comparison
  • check that the comparison is valid
  • draft model comparison text
  • note which residual checks the selected model will need

Recommended Reading

References

Baguley, T. (2012). Serious stats: A guide to advanced statistics for the behavioral sciences. Macmillan International Higher Education.

Faraway, J. J. (2015). Linear models with R (Vol. 2). CRC press.

Gelman, A., Hill, J., & Vehtari, A. (2020). Regression and other stories. Cambridge University Press.

Leonard, W. R., Snodgrass, J. J., & Robertson, M. L. (2010). Evolutionary perspectives on fat ingestion and metabolism in humans. In J.-P. Montmayeur & J. le Coutre (Eds.), Fat detection: Taste, texture, and post ingestive effects. CRC Press/Taylor & Francis.

McElreath, R. (2016). Statistical rethinking: A Bayesian course with examples in R and Stan. CRC Press.

McHenry, H. M., & Coffing, K. (2000). Australopithecus to homo: Transformations in body and mind. Annual Review of Anthropology, 29, 125–146. https://doi.org/10.1146/annurev.anthro.29.1.125