With an emphasis on prediction
2026-05-13
Understand the place of LASSO regression within association and prediction modeling for binary outcomes.
Understand how penalized regression is a form of model/variable selection.
Set up prediction model building steps and split data into training and testing sets.
Perform LASSO regression on a dataset using R and the general process for classification methods.
Understand how penalized regression is a form of model/variable selection.
Set up prediction model building steps and split data into training and testing sets.
Perform LASSO regression on a dataset using R and the general process for classification methods.
Model selection: picking the “best” model from a set of possible models
Models will have the same outcome, but typically differ by the covariates that are included, their transformations, and their interactions
“Best” model is defined by the research question and by how you want to answer it!
Model selection strategies: a process or framework that helps us pick our “best” model
Recall from 512/612: MSE can be written as a function of the bias and variance
\[ MSE = \text{bias}\big(\widehat\beta\big)^2 + \text{variance}\big(\widehat\beta\big) \]
No longer use MSE in logistic regression, BUT the idea between the bias and variance trade off holds!
For the same data, if our model has…
More covariates: less bias, more variance of coef. estimates
Less covariates: more bias, less variance of coef. estimates
From Data Science in a Box:
Association / Explanatory / One variable’s effect
Prediction
Goal: to calculate the most precise prediction of the response variable
Interpreting coefficients is not important
Choose only the variables that are strong predictors of the response variable
Association / Explanatory / One variable’s effect
Pre-specification of multivariable model
Purposeful model selection
Change in Estimate (CIE) approaches
Prediction
We CAN use purposeful selection from last quarter in any type of generalized linear model (GLM)
The best documented information on purposeful selection is in the Hosmer-Lemeshow textbook on logistic regression
Purposeful selection starts on page 89 (or page 101 in the pdf)
I will not discuss purposeful selection in this lesson
Classification: process of predicting categorical responses/outcomes
Note: we’ve already done a lot of work around predicting probabilities within logistic regression
Common classification models (good site on brief explanation of each)
Prediction depends on type of variable/model selection!
So the big question is: how do we select this model??
Set up prediction model building steps and split data into training and testing sets.
Perform LASSO regression on a dataset using R and the general process for classification methods.
Basic idea: We are running regression, but now we want to incentivize our model to have less predictors
We need a tuning parameter that determines the amount of shrinkage called lambda/\(\lambda\)
Main difference is the type of penalty used
Ridge regression
Penalty called L2 norm, uses squared values
Pros
Cons
Lasso regression
Elastic net regression
L1 and L2 used, best of both worlds
Pros
Cons
glmnet() and cv.glmnet() functionsglm() for fitting generalized linear models
glmnet() and cv.glmnet()
tidyverse compliant)
glmnet() fits the model for a sequence of lambda valuescv.glmnet() performs cross-validation to find the optimal lambdaUnderstand the place of LASSO regression within association and prediction modeling for binary outcomes.
Understand how penalized regression is a form of model/variable selection.
Build classification model using training set
Risk factor/variable of interest: history of prior fracture (PRIORFRAC: 0 or 1)
Potential confounder or effect modifier: age (AGE, a continuous variable)
Crossed out because we are no longer attached to specific predictors and their association with fracture
Rows: 500
Columns: 16
$ sub_id <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1…
$ site_id <int> 1, 4, 6, 6, 1, 5, 5, 1, 1, 4, 6, 1, 6, 1…
$ phy_id <int> 14, 284, 305, 309, 37, 299, 302, 36, 8, …
$ priorfrac <fct> No, No, Yes, No, No, Yes, No, Yes, Yes, …
$ age <int> 62, 65, 88, 82, 61, 67, 84, 82, 86, 58, …
$ weight <dbl> 70.3, 87.1, 50.8, 62.1, 68.0, 68.0, 50.8…
$ height <int> 158, 160, 157, 160, 152, 161, 150, 153, …
$ bmi <dbl> 28.16055, 34.02344, 20.60936, 24.25781, …
$ premeno <fct> No, No, No, No, No, No, No, No, No, No, …
$ momfrac <fct> No, No, Yes, No, No, No, No, No, No, No,…
$ armassist <fct> No, No, Yes, No, No, No, No, No, No, No,…
$ smoke <fct> No, No, No, No, No, Yes, No, No, No, No,…
$ raterisk <fct> Same, Same, Less, Less, Same, Same, Less…
$ fracscore <int> 1, 2, 11, 5, 1, 4, 6, 7, 7, 0, 4, 3, 1, …
$ fracture <fct> No, No, No, No, No, No, No, No, No, No, …
$ age_c <dbl> -7, -4, 19, 13, -8, -2, 15, 13, 17, -11,…
Training: act of creating our prediction model based on our observed data
When we use data to create a prediction model, we want to test our prediction model on new data

Training set
Testing set
When splitting data, we need to be conscious of the proportions of our outcomes
Is there imbalance within our outcome?
We want to randomly select observations but make sure the proportions of No and Yes stay the same
We stratify by the outcome, meaning we pick Yes’s and No’s separately for the training set
From package rsample within tidyverse, we can use initial_split() to create training and testing data
strata to stratify by fractureprop to set the proportion of training data<Training/Testing/Total>
<400/100/500>
Rows: 400
Columns: 9
$ priorfrac <fct> No, No, Yes, No, No, Yes, No, Yes, Yes, No, No, No, No, No, …
$ height <int> 158, 160, 157, 160, 152, 161, 150, 153, 156, 166, 153, 160, …
$ premeno <fct> No, No, No, No, No, No, No, No, No, No, No, Yes, No, No, No,…
$ momfrac <fct> No, No, Yes, No, No, No, No, No, No, No, Yes, No, No, No, No…
$ armassist <fct> No, No, Yes, No, No, No, No, No, No, No, No, No, Yes, No, No…
$ smoke <fct> No, No, No, No, No, Yes, No, No, No, No, Yes, No, No, No, No…
$ raterisk <fct> Same, Same, Less, Less, Same, Same, Less, Same, Same, Less, …
$ fracture <fct> No, No, No, No, No, No, No, No, No, No, No, No, No, No, No, …
$ age_c <dbl> -7, -4, 19, 13, -8, -2, 15, 13, 17, -11, -2, -5, -1, -2, 0, …
Rows: 100
Columns: 9
$ priorfrac <fct> No, No, No, No, No, No, No, Yes, Yes, No, No, No, No, No, No…
$ height <int> 167, 162, 165, 170, 154, 160, 171, 142, 152, 166, 154, 163, …
$ premeno <fct> No, No, No, Yes, Yes, No, Yes, Yes, No, No, No, No, Yes, No,…
$ momfrac <fct> No, No, No, Yes, No, No, No, Yes, No, No, No, No, Yes, No, N…
$ armassist <fct> Yes, No, Yes, No, Yes, Yes, No, No, No, No, No, No, Yes, No,…
$ smoke <fct> Yes, Yes, No, No, No, No, No, No, No, No, No, No, Yes, No, N…
$ raterisk <fct> Same, Less, Less, Same, Same, Less, Same, Same, Same, Same, …
$ fracture <fct> No, No, No, No, No, No, No, No, No, No, No, No, No, No, No, …
$ age_c <dbl> -13, -10, 3, 0, 6, -3, -5, 1, 17, -11, -6, -10, -10, 0, -12,…
Prevents overfitting to one set of training data
Split training set into folds that train and validate model selection
We can train and validate several times within the training set 
Understand the place of LASSO regression within association and prediction modeling for binary outcomes.
Understand how penalized regression is a form of model/variable selection.
Set up prediction model building steps and split data into training and testing sets.
cv.glmnet() needs a specific input for the datafracture ~ .
num [1:400, 1:9] 0 0 1 0 0 1 0 1 1 0 ...
- attr(*, "dimnames")=List of 2
..$ : chr [1:400] "1" "2" "3" "4" ...
..$ : chr [1:9] "priorfracYes" "height" "premenoYes" "momfracYes" ...
Build classification model using training set
Using Lasso penalized regression!
We can simply set up a penalized regression model
cv.glmnet uses cross validation and finds the best penalty (lambda)
alpha option let’s us pick the penalty
alpha = 0 for Ridge regressionalpha = 1 for Lasso regression0 < alpha < 1 for Elastic net regressionlambda.min in the output of cv.glmnet()10 x 1 sparse Matrix of class "dgCMatrix"
lambda.min
(Intercept) 3.87740705
priorfracYes 0.76550436
height -0.03648382
premenoYes 0.28439319
momfracYes 0.79923255
armassistYes 0.26670345
smokeYes -0.23118903
rateriskSame 0.41350772
rateriskGreater 0.64369667
age_c 0.03397730
[1] 0.00198163
# A tibble: 9 × 3
Variable Importance Sign
<chr> <dbl> <chr>
1 momfracYes 0.799 POS
2 priorfracYes 0.766 POS
3 rateriskGreater 0.644 POS
4 rateriskSame 0.414 POS
5 premenoYes 0.284 POS
6 armassistYes 0.267 POS
7 smokeYes 0.231 NEG
8 height 0.0365 NEG
9 age_c 0.0340 POS
Looks like nothing is removed! (Importance would be 0)
[1] 0.0202826
45 x 1 sparse Matrix of class "dgCMatrix"
lambda.min
(Intercept) 2.0850976952
priorfracYes 0.4943898067
height -0.0225868202
premenoYes .
momfracYes .
armassistYes .
smokeYes .
rateriskSame .
rateriskGreater .
age_c .
priorfracYes:height .
priorfracYes:premenoYes .
priorfracYes:momfracYes .
priorfracYes:armassistYes 0.3544339464
priorfracYes:smokeYes .
priorfracYes:rateriskSame .
priorfracYes:rateriskGreater .
priorfracYes:age_c .
height:premenoYes .
height:momfracYes 0.0004091542
height:armassistYes .
height:smokeYes .
height:rateriskSame .
height:rateriskGreater 0.0016221169
height:age_c 0.0001517309
premenoYes:momfracYes .
premenoYes:armassistYes .
premenoYes:smokeYes .
premenoYes:rateriskSame .
premenoYes:rateriskGreater 0.4755109044
premenoYes:age_c .
momfracYes:armassistYes .
momfracYes:smokeYes .
momfracYes:rateriskSame 1.1275503167
momfracYes:rateriskGreater 0.1980126090
momfracYes:age_c .
armassistYes:smokeYes .
armassistYes:rateriskSame 0.2851098186
armassistYes:rateriskGreater .
armassistYes:age_c .
smokeYes:rateriskSame .
smokeYes:rateriskGreater .
smokeYes:age_c 0.0027159535
rateriskSame:age_c .
rateriskGreater:age_c .
# A tibble: 44 × 3
Variable Importance Sign
<chr> <dbl> <chr>
1 momfracYes:rateriskSame 1.13 POS
2 priorfracYes 0.494 POS
3 premenoYes:rateriskGreater 0.476 POS
4 priorfracYes:armassistYes 0.354 POS
5 armassistYes:rateriskSame 0.285 POS
6 momfracYes:rateriskGreater 0.198 POS
7 height 0.0226 NEG
8 smokeYes:age_c 0.00272 POS
9 height:rateriskGreater 0.00162 POS
10 height:momfracYes 0.000409 POS
# ℹ 34 more rows
beta_int to calculate coefficient estimates conditional on fact that those variables were selected
Call:
fixedLassoInf(x = x_train_int, y = y_train, beta = beta_int,
lambda = lambda_int, family = "binomial")
Testing results at lambda = 0.020, with alpha = 0.100
Var Coef Z-score P-value LowConfPt UpConfPt LowTailArea UpTailArea
1 0.647 1.840 0.220 -0.750 1.568 0.049 0.050
2 -0.044 -2.173 0.347 -0.073 0.092 0.050 0.050
13 0.311 0.686 0.311 -1.427 2.970 0.050 0.050
19 -0.002 -0.303 0.244 -0.211 0.056 0.050 0.050
23 0.003 1.456 0.294 -0.007 0.012 0.050 0.050
24 0.000 1.985 0.025 0.000 0.002 0.050 0.050
29 0.786 1.642 0.194 -0.757 1.695 0.049 0.049
33 1.972 1.967 0.191 -7.231 34.991 0.050 0.050
34 0.888 0.881 0.286 -12.816 34.850 0.050 0.050
37 0.715 1.919 0.364 -1.632 1.335 0.050 0.049
42 0.052 0.955 0.929 -3.202 0.033 0.050 0.050
Note: coefficients shown are full regression coefficients
tibble to make tidy and take exponential of coefficients# A tibble: 11 × 7
term estimate std.error statistic p.value conf.low conf.high
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 priorfracYes 1.91 0.352 1.84 0.220 4.72e-1 4.80e 0
2 height 0.956 0.0205 -2.17 0.347 9.29e-1 1.10e 0
3 priorfracYes:armassi… 1.36 0.453 0.686 0.311 2.40e-1 1.95e 1
4 height:momfracYes 0.998 0.00534 -0.303 0.244 8.10e-1 1.06e 0
5 height:rateriskGreat… 1.00 0.00205 1.46 0.294 9.93e-1 1.01e 0
6 height:age_c 1.00 0.0000923 1.98 0.0250 1.00e+0 1.00e 0
7 premenoYes:rateriskG… 2.20 0.479 1.64 0.194 4.69e-1 5.45e 0
8 momfracYes:rateriskS… 7.18 1.00 1.97 0.191 7.23e-4 1.57e15
9 momfracYes:rateriskG… 2.43 1.01 0.881 0.286 2.72e-6 1.37e15
10 armassistYes:rateris… 2.05 0.373 1.92 0.364 1.95e-1 3.80e 0
11 smokeYes:age_c 1.05 0.0543 0.955 0.929 4.07e-2 1.03e 0
Build classification model using training set
Area under the curve: 0.6672
Why is this AUC worse than the one we saw with prior fracture, age, and their interaction?
Use a tuning parameter for our penalty
Basically, we need to figure out what the best penalty is for our model
We use the training set to determine the best penality
Videos that includes tuning parameter with LASSO
Performing cross-validation
For complete video of machine learning with LASSO, cross-validation, and tuning parameters
See “Unit 5 - Deck 4: Machine learning” on this Data Science in a Box page
You can switch methods if you want!
You can use purposeful selection, like we did last quarter
If you want to focus on association modeling!
But you will need to include at least one interaction!!
A good way to practice this again if you struggled with it previously
You can try out LASSO regression
Lesson 14: Model Building