-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmodel_building.Rmd
744 lines (490 loc) · 33.5 KB
/
model_building.Rmd
1
2
3
4
5
6
7
8
9
10
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
387
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
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
# Model Building {#model-building}
Model building methods are used mainly in exploratory situations where many independent variables have been measured, but a final model explaining the dependent variable has not been reached. You want to build a model that contains enough covariates to explain the model well, but still be parsimonious such that the model is still interpretable.
This chapter introduces how to use and interpret different types of covariates, how to choose covariates, and then cover some methods to compare between competing models using measures of model fit.
```{block2, type='rmdnote'}
This section uses functions from the `gtsummary` and `survey` packages to help tidy and visualize results from regression models. It also uses functions from the `performance` and `glmnet` packages to perform model selection and assessment.
```
```{r, echo=FALSE}
library(gtsummary); library(performance); library(leaps)
pen <- palmerpenguins::penguins
```
## Interactions (PMA6 8.8) {#interactions}
In this _main effects_ model, Species only changes the intercept. The effect of species is not multiplied by Sepal length. Reviewing the scatterplot below, do you think this is a reasonable model to fit the observed relationship?
```{r}
ggplot(iris, aes(x=Sepal.Length, y=Petal.Length, color = Species)) +
geom_point() + geom_smooth(method="lm", se=FALSE)
```
If we care about how species _changes_ the relationship between petal and sepal length, we can fit a model with an **interaction** between sepal length ($x_{1}$) and species. For this first example let $x_{2}$ be an indicator for when `species == setosa`. Note that both _main effects_ of sepal length, and setosa species are also included in the model. Interactions are mathematically represented as a multiplication between the two variables that are interacting.
$$ Y_{i} \sim \beta_{0} + \beta_{1}x_{i} + \beta_{2}x_{2i} + \beta_{3}x_{1i}x_{2i}$$
If we evaluate this model for both levels of $x_{2}$, the resulting models are the same as the stratified models.
When $x_{2} = 0$, the record is on an iris not from the _setosa_ species.
$$ Y_{i} \sim \beta_{0} + \beta_{1}x_{i} + \beta_{2}(0) + \beta_{3}x_{1i}(0)$$
which simplifies to
$$ Y_{i} \sim \beta_{0} + \beta_{1}x_{i}$$
When $x_{2} = 1$, the record is on an iris of the _setosa_ species.
$$ Y_{i} \sim \beta_{0} + \beta_{1}x_{i} + \beta_{2}(1) + \beta_{3}x_{1i}(1)$$
which simplifies to
$$ Y_{i} \sim (\beta_{0} + \beta_{2}) + (\beta_{1} + \beta_{3})x_{i}$$
Each subgroup model has a different intercept and slope, but we had to estimate 4 parameters in the interaction model, and 6 for the fully stratified model.
### Fitting interaction models & interpreting coefficients
Interactions are fit in `R` by simply multiplying `*` the two variables together in the model statement.
```{r}
iris$setosa <- ifelse(iris$Species == "setosa", 1, 0)
lm(Petal.Length ~ Sepal.Length + setosa + Sepal.Length*setosa, data=iris) |> tbl_regression()
```
The coefficient $b_{3}$ for the interaction term is significant, confirming that species changes the relationship between sepal length and petal length. Thus, species is a **moderator** (Chapter \@ref(mod-strat)).
**Interpreting Coefficients**
* If $x_{2}=0$, then the effect of $x_{1}$ on $Y$ simplifies to: $\beta_{1}$
* $b_{1}$ The effect of sepal length on petal length **for non-setosa species of iris** (`setosa=0`)
* For non-setosa species, the petal length increases 1.03cm for every additional cm of sepal length.
* If $x_{2}=1$, then the effect of $x_{1}$ on $Y$ model simplifies to: $\beta_{1} + \beta_{3}$
* For setosa species, the petal length increases by `1.03-0.9=0.13` cm for every additional cm of sepal length.
```{block2, type='rmdcaution'}
The main effects ($b_{1}$, $b_{2}$) cannot be interpreted by themselves when there is an interaction in the model.
```
### Categorical Interaction variables {#interactions-catvars}
Let's up the game now and look at the full interaction model with a categorical version of species.
Recall $x_{1}$ is Sepal Length, $x_{2}$ is the indicator for _versicolor_, and $x_{3}$ the indicator for _virginica_ . Refer to \@ref(cat-predictors) for information on how to interpret categorical predictors as main effects.
$$ Y_{i} \sim \beta_{0} + \beta_{1}x_{i} + \beta_{2}x_{2i} + \beta_{3}x_{3i} + \beta_{4}x_{1i}x_{2i} + \beta_{5}x_{1i}x_{3i}+\epsilon_{i}$$
```{r}
summary(lm(Petal.Length ~ Sepal.Length + Species + Sepal.Length*Species, data=iris))
```
The slope of the relationship between sepal length and petal length is calculated as follows, for each species:
* _setosa_ $(x_{2}=0, x_{3}=0): b_{1}=0.13$
* _versicolor_ $(x_{2}=1, x_{3}=0): b_{1} + b_{2} + b_{4} = 0.13+0.55 = 0.68$
* _virginica_ $(x_{2}=0, x_{3}=1): b_{1} + b_{3} + b_{5} = 0.13+0.62 = 0.75$
Compare this to the estimates gained from the stratified model:
```{r}
by(iris, iris$Species, function(x){
lm(Petal.Length ~ Sepal.Length, data=x) %>% coef()
})
```
They're the same! Proof that an interaction is equivalent to stratification.
### Example 2
What if we now wanted to include other predictors in the model? How does sepal length relate to petal length after controlling for petal width? We add the variable for petal width into the model
```{r}
summary(lm(Petal.Length ~ Sepal.Length + setosa + Sepal.Length*setosa + Petal.Width, data=iris))
```
So far, petal width, and the combination of species and sepal length are both significantly associated with petal length.
_Note of caution: Stratification implies that the stratifying variable interacts with all other variables._
So if we were to go back to the stratified model where we fit the model of petal length on sepal length AND petal width, stratified by species, we would be implying that species interacts with both sepal length and petal width.
E.g. the following stratified model
* $Y = A + B + C + D + C*D$, when D=1
* $Y = A + B + C + D + C*D$, when D=0
is the same as the following interaction model:
* $Y = A + B + C + D + A*D + B*D + C*D$
### Example 3:
Let's explore the relationship between income, employment status and depression.
This example follows a logistic regression example from section \@ref(mlogreg).
Here I create the binary indicators of `lowincome` (annual income <$10k/year) and underemployed (part time or unemployed).
```{r}
depress$lowincome <- ifelse(depress$income < 10, 1, 0)
table(depress$lowincome, depress$income, useNA="always")
depress$underemployed <- ifelse(depress$employ %in% c("PT", "Unemp"), 1, 0 )
table(depress$underemployed, depress$employ, useNA="always")
```
The **Main Effects** model assumes that the effect of income on depression is independent of employment status, and the effect of employment status on depression is independent of income.
```{r}
me_model <- glm(cases ~ lowincome + underemployed, data=depress, family="binomial")
summary(me_model)
```
To formally test whether an interaction term is necessary, we add the interaction term into the model and assess whether the coefficient for the interaction term is significantly different from zero.
```{r}
me_intx_model <- glm(cases ~ lowincome + underemployed + lowincome*underemployed, data=depress, family="binomial")
summary(me_intx_model)
```
## Simultaneous test of multiple variables (PMA6 9.5) {#general-F}
The General-F test is used for simultaneous tests of $Q$ variables in a model. This is used primarily in two situations:
1. Testing if a categorical variable (with more than 2 levels) as a whole improves model fit.
2. Testing whether or not the regression model is helpful in predicting values of Y at all.
Consider a model with $P$ variables and you want to test if $Q$ additional variables are useful.
* $H_{0}: Q$ additional variables are useless, i.e., their $\beta$'s all = 0
* $H_{A}: Q$ additional variables are useful to explain/predict $Y$
We can leverage the ANOVA framework to compare the residual sum of squares between the model including the $Q$ variables, and the one without.
$$
F = \frac{({\mbox{RSS}}_P-{\mbox{RSS}_{P+Q})}/Q}{{\mbox
{RSS}}_{P+Q}{/}(N-P-Q-1)}
$$
The numerator quantifies improvement in the model from adding the additional $Q$ variables. This ratio has a $F$ distribution with $Q$ and $N-P-Q-1$ degrees of freedom.
**Example**
Consider the following model, where $X_{1}$ and $X_{2}$ are continuous predictors and $X_{3}, X_{4}, X_{5}$ are binary indicators from a 4 level categorical variable.
$$
Y = \beta_{0} + \beta_{1}X_{1} + \beta_{2}X_{2} + \beta_{3}X_{3} + \beta_{4}x_{4} + \beta_{5}X_{5}+\epsilon_{i}
$$
If you wanted to test (1) whether or not the categorical variable as a whole improves model fit, then
$\mathbf{R} =
\begin{bmatrix}
0 , 0 ,1,1,1
\end{bmatrix}$
If we want to test (2) that the regression plane is useful to predict $Y$, then we are testing $\beta_{1}=\beta_{2}=...\beta_{5}=0$, then
$\mathbf{R} =
\begin{bmatrix}
1 , 1 ,1,1,1
\end{bmatrix}$.
### Example: Modeling depression score
Consider a model to predict depression using age, employment status and whether or not the person was chronically ill in the past year as covariates. This example uses the cleaned depression data set.
```{r}
employ.depression.model <- lm(cesd ~ age + chronill + employ, data=depress)
summary(employ.depression.model)
```
The results of this model show that age and chronic illness are statistically associated with CESD (each p<.006). However employment status shows mixed results. Some employment statuses are significantly different from the reference group, some are not. So overall, is employment status associated with depression?
**(1) Testing if a categorical variable as a whole improves model fit**
Since employment is a categorical variable, all the coefficient estimates shown are the effect of being in that income category has on depression _compared to_ being employed full time. For example, the coefficient for PT employment is greater than zero, so they have a higher CESD score compared to someone who is fully employed.
To test that employment status affects CESD we need to do a global test that all $\beta$'s related to employment status are 0.
$H_{0}: \beta_{3} = \beta_{4} = \beta_{5} = \beta_{6} = \beta_{7} = \beta_{8} = 0$
$H_{A}$: At least one $\beta_{j}$ is not 0.
ANOVA to the rescue! Since ANOVA partitions the variance in our outcome $Y$ into amounts due to each variable, we get an ANOVA table that has one row per term:
```{r}
aov(employ.depression.model) %>% summary()
```
* The last row for `employ` is what we are interested in here.
* First confirm that the degrees of freedom are correct. It should equal the # of categories in the variable you are testing, minus 1.
- Employment has 7 levels, so $df=6$.
- Or equivalently, the degrees of freedom are the number of $beta$'s you are testing to be 0.
The p-value of this Wald test is significant, thus not $beta$'s are equal to zero, which implies employment status significantly predicts CESD score.
```{block2, type='rmdcaution'}
Note the p-values for the individual coefficients `age` and `chronill` are not the same as in the regression model. ANOVA models are order dependent as they describe a "reduction" in variance in the outcome due to that variable. A deeper explanation of this is not included in these notes at this time.
```
**(2) Testing that the regression plane is useful to predict $Y$**
This information is provided to us directly in the last line of the summary output from a linear model.
```{r}
summary(employ.depression.model)
```
### Testing for a moderation effect in a multiple regression model.
Moderation is introduced in Chapter \@ref(mod-strat), and helps to set the motivation for stratified models. Later, in Chapter \@ref(interactions-catvars), we show that an interaction term in a regression model is equivelant to stratification.
Well what if you have other predictors in the model, not just the ones that you have an interaction on? We can use the Wald test to assess if a measure is a significant moderator without stratifying.
Continuing with the depression example we saw that employment affects CESD depression score. What if we think that the effect (slope) of age on CESD may be different depending on their employment? That is, is the effect of age on depression different for those that are employed versus retired?
```{r}
emp.dep.intx <- lm(cesd ~ age + chronill + employ + age*employ, data=depress)
summary(emp.dep.intx)
```
Let's revisit our list of beta coefficients:
* $\beta_{1}$: Age
* $\beta_{2}$: Chronic illness
* $\beta_{3} \ldots \beta_{7}$: Effects of different levels of employment (Houseperson to Unemployed)
* $\beta_{8} \ldots \beta_{12}$: Multiplicative effect that levels of employment have on the slope of age.
To see if the interaction term `age*employ` is significant, we run an F test via `aov()` and interpret the p-value for the interaction term `age:employ`. Here the pvalue is very large, so there is no reason to believe that employment moderates the relationship between age and CESD score. This is a two way relationship. There is also no reason to believe that age moderates the relationship between employment and CESD score.
```{r}
aov(emp.dep.intx) |> summary()
```
This last table is also known as a "Two Factor" or "Two way" ANOVA with an interaction term. This is quite often used in scientific experiments where two treatments (and their combination) is being investigated.
## Multicollinearity (PMA6 8.9)
* Occurs when some of the X variables are highly intercorrelated.
* Computed estimates of regression coefficients are unstable and have large standard errors.
For example, the squared standard error of the $i$th slope coefficient ($[SE(\beta_{i})]^2$) can be written as:
$$
[SE(\beta_{i})]^2 = \frac{S^{2}}{(N-1)(S_{i}^{2})}*\frac{1}{1 - (R_{i})^2}
$$
where $S^{2}$ is the residual mean square, $S_{i}$ the standard deviation of $X_{i}$, and $R_{i}$ the multiple correlation between $X_{i}$ and all other $X$'s.
When $R_{i}$ is close to 1 (very large), $1 - (R_{i})^2$ becomes close to 0, which makes $\frac{1}{1 - (R_{i})^2}$ very large.
This fraction is called the **variance inflation factor** and is available in most model diagnostics.
```{r}
big.pen.model <- lm(body_mass_g ~ bill_length_mm + bill_depth_mm + flipper_length_mm, data=pen)
performance::check_collinearity(big.pen.model) |> plot()
```
* Solution: use variable selection to delete some X variables.
* Alternatively, use dimension reduction techniques such as Principal Components (Chapter \@ref(pca)).
## Variable Selection Process
```{block2, type='rmdnote'}
Corresponding PMA6 Ch 9
```
Variable selection methods such as the ones described in this section, are most often used when performing an _Exploratory_ analysis, where many independent variables have been measured, but a final model to explain the variability of a dependent variable has not yet been determined.
When building a model, we want to choose a set of independent variables that both will yield a good prediction using as few variables as possible (_parsimony_). We also need to consider controlling for moderators and confounders. In many situations where regression is used, the investigator has strong justification for including certain variables in the model.
* previous studies
* accepted theory
The investigator may have prior justification for using certain variables but may be open to suggestions for the remaining variables.
The set of independent variables can be broken down into logical subsets
1. **Factors of primary interest**. (such as an exposure or treatment)
2. **Potential confounders**. These are measures that could be associated with both the response, and explanatory variables, and which could _explain_ the relationship between the primary factor of interest and the outcome. These are typically a set of demographics such as age, gender, ethnicity, and tend to be factors found to be important in prior studies.
3. **Effect Modifiers (Moderators)**. A set of variables that other studies have shown to change or affect the relationship between the explanatory and response variables.
4. **Precision variables (covariates)**. Variables associated with the dependent variable, but not the primary factor of interest.
How variables are chosen for inclusion into a model is heavily driven by the purpose of the model:
* descriptive
* predictive
### Automated selection procedures (PMA6 9.6)
> This example uses the penguins data to model the body mass
```{block2, type='rmdcaution'}
The model fitting must apply the models to the same dataset. This may be a problem if there are missing values. We suggest you remove the missing values first. (From the R help file)
```
```{r}
pen.nomiss <- pen %>% na.omit()
```
#### Forward selection: Variables are added one at a time until optimal model reached.
1. Choose the variable with the highest absolute correlation $\mid r \mid$ with the outcome.
2. Choose the next variable that maximizes the model adjusted $R^{2}$.
3. Repeat until adding additional variables does not improve the model fit significantly.
#### Backward elimination: Variables are removed one at a time until optimal model reached
1. Put all variables into the model.
2. Remove the least useful variable in the model. This can be done by choosing the variable with the largest $p$-value.
3. Repeat until removing additional variables reduces the model fit significantly.
#### Stepwise selection: Combination of forward and backward.
0. Start with no variables (just $\bar{Y}$)
1. Add the variable that results in the greatest improvement in model fit.
2. Add another variable that results in the greatest improvement in model fit after controlling for the first.
3. Check to see if removing any variable currently in the model improves the fit.
4. Add another variable...
5. Check to remove variables...
6. Repeat until no variables can be added or removed.
Most programs have the option to **force** variables to be included in the model. This is important in cases where there is a primary factor of interest such as a treatment effect.
**Doing stepwise selection in R**
First you need to specify your null model - just the outcome, no covariates, and the full model - the outcome against ALL of your covariates.
```{r}
null.model <- lm(body_mass_g ~ 1, data=pen.nomiss)
full.model <- lm(body_mass_g ~ ., data=pen.nomiss)
```
**Forward selection**
```{r}
step(null.model,
scope=list(lower=null.model, upper=full.model),
direction='forward', trace=1) |> summary()
```
**Backward selection**
```{r}
step(full.model, direction='backward', trace=1) |> summary()
```
**Stepwise**
```{r}
step(null.model,
scope=list(lower=null.model, upper=full.model),
direction='both', trace=1) |> summary()
```
Warnings:
* Stopping criteria and algorithm can be different for different software programs.
* Can reject perfectly plausible models from later consideration
* Hides relationships between variables (X3 is added and now X1 is no longer significant. X1 vs X3 should be looked at)
**Other references** Stats 191 at Stanford. This one uses cross-validation on the **stepwise procedures**, and demonstrates the dangers of trusting models that come out of blind use of variable selection methods. https://web.stanford.edu/class/stats191/notebooks/Selection.html
#### Best Subsets
* Select one X with highest simple $r$ with Y
* Select two X’s with highest multiple $r$ with Y
* Select three X’s with highest multiple $r$ with Y
etc.
* Compute adjusted R2, AIC or BIC each time.
* Compare and choose among the "best subsets" of various sizes.
```{r, fig.width=10, fig.height=6}
oc.ht <- regsubsets(body_mass_g ~ ., data=pen.nomiss)
par(mfrow=c(1,3)) # set plotting window to be 1 row and 3 columns
plot(oc.ht, scale='adjr2');plot(oc.ht, scale='bic');plot(oc.ht, scale='Cp')
```
* The black squares are when the variable is in the model, the white is when it's not
* The vertical axis are chosen fit metrics such as adjusted R2, BIC and Mallows Cp. The higher the better
In this example variables that show up as improving model fit include `species`, `sex`, `flipper_length_mm`, `bill_length`, and possibly `year`. For sure island is out.
**Other references** from STDHA: http://www.sthda.com/english/articles/37-model-selection-essentials-in-r/155-best-subsets-regression-essentials-in-r/
**Notable problems:** categorical variables are not treated as a group. that is, they are not "all in" or "all out". If at least one level is frequently chosen as improving model fit, add the entire categorical variable to the model.
### LASSO Regression (PMA6 9.7)
**L**east **A**bsolute **S**hrinkage and **S**election **O**perator.
The goal of LASSO is to minimize
$$
RSS + \lambda \sum_{j}\mid \beta_{j} \ \mid
$$
where $\lambda$ is a model complexity penalty parameter.
* "Shrinks" the coefficients, setting some to exactly 0.
- Thus essentially choosing a simpler model
* Balances model accuracy with interpretation.
The lasso fits many regression models and selects those variables that show the strongest association with the response variable using the data at hand. This is also described as a method of _selective inference_ (Taylor and Tibshirani, 2015) and is an example of exploratory research, where the data may influence what type and how many analyses are performed.
#### Example
```{block2, type='rmdnote'}
This section uses functions `glmnet` package, and the `Chemical` data set from PMA6. Also it uses the `model.matrix` function from the `stats` package (automatically loaded). This function takes a set of input predictors and turns them into the variables that are used directly in the model. For example, categorical variables will be converted into multiple binary indicators. This typically happens in the background.
```
The `glmnet` function works best when the outcome `y` and predictors `x` are not contained within a data frame. The `alpha` argument is the tuning parameter, where a value of 1 specifies the lasso.
```{r}
library(glmnet)
chem <- read.table("data/Chemical.txt", header = TRUE)
y <- chem$PE
x <- model.matrix(PE~., chem)[,-1] # the -1 drops the intercept
chem.lasso <- glmnet(x, y, alpha = 1)
```
We can visualize the effect of the coefficient shrinkage using the following plot.
```{r}
plot(chem.lasso, xvar = "lambda")
mtext(side=3, "Number of Variables", line=2)
```
* Each line represents the value of a coefficient as $ln(\lambda)$ changes.
* The red line on the bottom and the purple on the top must be important, since they are the last two to be shrunk to 0 and they are relatively stable.
Examining the coefficients of the `chem.lasso` model object gives us a very large matrix (7x61), listing the coefficients for each value of $\lambda$ that was tried. A sample of columns are shown below:
```{r}
coef(chem.lasso)[,1:8]
coef(chem.lasso)[,56:60]
```
Comparing the plot to the coefficient model output above, we see that the variables that show up being shrunk last are `DE` and `PAYOUTR1`.
**Using Cross validation to find minimum lambda**
Cross-validation is a resampling method that uses different portions of the data to test and train a model on different iterations [Wikipedia](https://en.wikipedia.org/wiki/Cross-validation_(statistics)).
By applying a cross-validation technique, we can identify the specific value for $\lambda$ that
results in the lowest cross-validated Mean Squared Error (MSE) ($\lambda_{min}$). To ensure
reproducibility of these results we set a seed for the random number generator prior to analysis.
```{r}
set.seed(123) # Setting a seed to ensure I get the same results each time I knit
cv.lasso <- cv.glmnet(x, y, alpha = 1) # note change in function
# Fit the final model using the min lambda
model <- glmnet(x, y, alpha = 1, lambda = cv.lasso$lambda.min)
```
The resulting table of shrunk regression coefficients then is;
```{r}
coef(model)
```
In this case we would keep variables: DE, SALESGR5, NPM1 and PAYOUTR1. Estimates for ROR5 and EPS56 are very small, and so can be reasonably excluded.
* The lasso procedure normalizes the data prior to fitting a model, so the coefficient values that are returned _cannot_ be interpreted directly in context of the problem.
- This does allow us the ability to make "judgement" calls on what is a 'small' estimate since it's no longer dependent on the units of the data.
* Appropriate inference after model selection is currently under research. No unifying theory exists yet.
* For now, use lasso to choose variables, then fit a model with only those selected variables in the final model.
* Variables chosen in this manner are important, yet biased estimates.
```{r}
lm(PE ~ DE + SALESGR5 + NPM1 + PAYOUTR1, data = chem) |> tbl_regression()
```
#### Ridge Regression (PMA6 10.6)
Often compared to LASSO, Ridge regression also minimizes the RSS, but the penalty function is different:
$$
RSS + \lambda \sum_{j} \beta_{j}^2
$$
Ridge regression only shrinks the magnitude of the coefficients, not set them exactly to zero.
```{block2, type='rmdwarning'}
This means Ridge regression is **not** a method of variable selection.
```
## Comparing between models (PMA6 9.4) {#model-fit-criteria}
The goal: Find the subset of independent variables that optimizes (either minimize or maximize) a certain criteria. In other words, the goal is to find the optimal model.
![q](images/q.png) How do we measure "optimal"?
First we need to look at two quantities:
### RSS: Residual Sum of Squares
Recall the method of least squares introduced in section \@ref(mlr) minimizes the residual sum of squares around the regression plane. This value is central to all following model comparison. How "far away" are the model estimates from the observed?
$$
\sum(Y - \bar{Y})^{2}(1-R^{2})
$$
### General F Test
> See also Section \@ref(general-F).
Two nested models are similar if the p-value for the General F-test is non-significant at a .15 level. _Nested_: The list of variables in one model is a subset of the list of variables from a bigger model. Similar to all other ANOVA models, you are essentially comparing the difference in RSS between nested models.
```{r}
# Full model
full.employ.model <- lm(cesd ~ age + chronill + employ, data=depress)
# Reduced model
reduced.employ.model <- lm(cesd ~ age, data=depress)
anova(reduced.employ.model, full.employ.model)
```
```{block2, type='rmdcaution'}
Caution: this uses `anova()` not `aov()`.
```
Other references: https://online.stat.psu.edu/stat501/lesson/6/6.2
### Likelihood function
What is the likelihood that we observed the data $x$, given parameter values $\theta$.
$$
\mathcal{L}(\theta \mid x)=p_{\theta }(x)=P_{\theta }(X=x)
$$
* For strictly convenient mathematical matters, we tend to work with the **log-likelihood** (LL).
* Great because $log$ is a monotonic increasing function, maximizing the LL = maximizing the likelihood function.
* We can compare between models using functions based off the LL.
There are several measures we can use to compare between competing models.
### Multiple $R^{2}$
If the model explains a large amount of variation in the outcome that's good right? So we could consider using $R^{2}$ as a selection criteria and trying to find the model that maximizes this value.
* Problem: The multiple $R^{2}$ _always_ increases as predictors are added to the model.
- Ex. 1: N = 100, P = 1, E($R^{2}$) = 0.01
- Ex. 2: N = 21, P = 10, E($R^{2}$) = 0.5
* Problem: $R^{2} = 1-\frac{Model SS}{Total SS}$ is biased: If population $R^{2}$ is really zero, then E($R^{2}$) = P/(N-1).
Reference PMA6 Figure 9.1
### Adjusted $R^{2}$
To alleviate bias use Mean squares instead of SS.
$R^{2} = 1-\frac{Model MS}{Total MS}$
equivalently,
$R^{2}_{adj} = R^{2} - \frac{p(1-R^{2})}{n-p-1}$
Now Adjusted $R^{2}$ is approximately unbiased and won't inflate as $p$ increases.
### Mallows $C_{p}$
$$
C_{p} = (N-P-1)\left(\frac{RMSE}{\hat{\sigma}^{2}} -1 \right) + (P+1)
$$
where $RMSE = \frac{RSS}{N-P-1}$.
* Smaller is better
* When all variables are chosen, $P+1$ is at it's maximum but the other part of $C_{p}$ is zero since $RMSE$==$\hat{\sigma}^{2}$
### Akaike Information Criterion (AIC)
* A penalty is applied to the deviance that increases as the number of parameters $p$ increase.
* Tries to find a parsimonious model that is closer to the “truth”.
* Uses an information function, e.g., the likelihood function $(LL)$.
$$ AIC = -2LL + 2p$$
* Smaller is better
* Can also be written as a function of the residual sum of squares (RSS) (in book)
* Estimates the information in one model _relative to other models_
- So if all models suck, your AIC will just tell you which one sucks less.
* Built in `AIC()` function in R
* Rule of thumb: Model 1 and Model 2 are considered to have significantly different fit if the difference in AIC values is greater than 2.
$$\mid AIC_{1} - AIC_{2}\mid > 2$$
### Bayesian Information Criterion (BIC)
* Similar to AIC.
* Built in `BIC()` function in R
* Tries to find a parsimonious model that is more likely to be the “truth”. The smaller BIC, the better.
$$ BIC = -2LL + ln(N)*(P+1)$$
### AIC vs BIC
* Both are “penalized likelihood” functions
* Each = -2log likelihood + penalty
* AIC: penalty = 2, BIC: penalty = ln(N)
* For any N > 7, ln(N) > 2
* Thus, BIC penalizes larger models more heavily.
* They often agree.
- When they disagree, AIC chooses a larger model than BIC.
## Model Diagnostics
Recall from Section \@ref(mathematical-model) the assumptions for linear regression model are;
* **Linearity** The relationship between $x_j$ and $y$ is linear, for all $j$.
* **Normality, Homogeneity of variance** The residuals are identically distributed $\epsilon_{i} \sim N(0, \sigma^{2})$
* **Uncorrelated/Independent** Distinct error terms are uncorrelated: $\text{Cov}(\epsilon_{i},\epsilon_{j})=0,\forall i\neq j.$
There are a few ways to visually assess these assumptions. We'll look at this using a penguin model of body mass as an example.
```{r}
pen.bmg.model <- lm(body_mass_g ~ bill_length_mm + flipper_length_mm, data=pen)
```
### Linearity
Create a scatterplot with lowess AND linear regression line. See how close the lowess trend line is to the best fit line. Do this for all variables.
```{r}
bill.plot <- ggplot(pen, aes(y=body_mass_g, x=bill_length_mm)) +
geom_point() + theme_bw() +
geom_smooth(col = "red") +
geom_smooth(method = "lm" , col = "blue")
flipper.plot <- ggplot(pen, aes(y=body_mass_g, x=flipper_length_mm)) +
geom_point() + theme_bw() +
geom_smooth(col = "red") +
geom_smooth(method = "lm" , col = "blue")
gridExtra::grid.arrange(bill.plot, flipper.plot, ncol=2)
```
Both variables appear to have a mostly linear relationship with body mass. For penguins with bill length over 50mm the slope may decrease, but the data is sparse in the tails.
### Normality of residuals.
There are two common ways to assess normality.
1. A histogram or density plot with a normal distribution curve overlaid.
2. A qqplot. This is also known as a 'normal probability plot'. It is used to compare the theoretical quantiles of the data _if it were to come from a normal distribution_ to the observed quantiles. PMA6 Figure 5.4 has more examples and an explanation.
```{r}
gridExtra::grid.arrange(
plot(check_normality(pen.bmg.model)),
plot(check_normality(pen.bmg.model), type = "qq"),
ncol=2
)
```
In both cases you want to assess how close the dots/distribution is to the reference curve/line.
### Homogeneity of variance
The variability of the residuals should be constant, and independent of the value of the fitted value $\hat{y}$.
```{r}
plot(check_heteroskedasticity(pen.bmg.model))
```
This assumption is often the hardest to be fully upheld. Here we see a slightly downward trend. However, this is not a massive violation of assumptions.
### Posterior Predictions
Not really an assumption, but we can also assess the fit of a model by how well it does to predict the outcome. Using a Bayesian sampling method, the distribution of the predictions from the model should resemble the observed distribution.
```{r}
plot(check_posterior_predictions(pen.bmg.model))
```
This looks like a good fit.
### All at once
```{r, fig.height = 8}
check_model(pen.bmg.model)
```
Refer to PMA6 8.8 to learn about _leverage_.
## General Advice (PMA6 9.9)
* Model selection is not a hard science.
* Some criteria have "rules of thumb" that can guide your exploration (such as difference in AIC < 2)
* _**Use common sense**_: A sub-optimal subset may make more sense than optimal one
* p-values: When you compare two criteria, often the difference has a known distribution.
- Wald F Test, the difference in RSS between the two models has a F distribution.
* All criterion should be used as guides.
* Perform multiple methods of variable selection, find the commonalities.
* Let science and the purpose of your model be your ultimate guide
- If the purpose of the model is for explanation/interpretation, error on the side of parsimony (smaller model) than being overly complex.
- If the purpose is prediction, then as long as you're not overfitting the model (as checked using cross-validation techniques), use as much information as possible.
* Automated versions of variable selection processes should not be used blindly.
* "... perhaps the most serious source of error lies in letting statistical procedures make decisions for you."..."Don't be too quick to turn on the computer. Bypassing the brain to compute by reflex is a sure recipe for disaster." _Good and Hardin, Common Errors in Statistics (and How to Avoid Them), p. 3, p. 152_
## What to watch out for (PMA6 9.10)
* Multicollinearity
* Missing Data
* Use previous research as a guide
* Variables not included can bias the results
* Significance levels are only a guide
* Perform model diagnostics after selection to check model fit.