Inference: Logistic Regression
IMS2 Ch. 26
Math 219
Diagnosing spread of cancer to lymph nodes
Can spread to lymph nodes from prostate cancer be diagnosed without surgery?
Data “lymph” from package HH
Deciding whether cancer has spread to lymph nodes is important for treating prostate cancer
The question is so critical in prognosis and treatment that it was customary to
Operate on the patient for the sole purpose of examining the nodes
However, certain variables can be measured without surgery predicting spread to these nodes
Data using these variables was evaluated to see how well it predicted this spread
lymph 1 data from 53 patients
7 variables, including
nodes
Whether cancer spread to lymph nodes (0=“no”, 1=“yes”)
X.ray
Indicated by x-ray, 1 is serious, 0 is less serious
stage
Size and location of tumor, 1 serious, 0 less serious
age
Patient age at diagnosis
acid.ph
level of serum acid phosphatase
Proportions of patients with cancer in lymph nodes
Serious
0.400
0.900
Less
0.143
0.353
Logistic Model
Fit logistic model to predict whether patient has cancer in lymph nodes based on all predictors
lymph_mod <- glm (nodes ~ X.ray + stage + age + acid.ph,
family = binomial, data = lymph)
tidy (lymph_mod)
# A tibble: 5 × 5
term estimate std.error statistic p.value
<chr> <dbl> <dbl> <dbl> <dbl>
1 (Intercept) 0.446 3.41 0.131 0.896
2 X.ray1 2.10 0.795 2.64 0.00833
3 stage1 1.76 0.747 2.36 0.0182
4 age -0.0703 0.0574 -1.22 0.221
5 acid.ph 0.0222 0.0128 1.73 0.0828
The resulting model is
\[\begin{array}{rcl}\log\left(\frac{\hat{p}}{1-\hat{p}}\right) &=& 0.0446 \\ & + & 2.10\times X.ray1 \\ & + & 1.76 \times stage1 \\ & - & 0.0703 \times age \\ & + & 0.0222 \times acid.ph \end{array} \]
# A tibble: 5 × 5
term estimate std.error statistic p.value
<chr> <dbl> <dbl> <dbl> <dbl>
1 (Intercept) 0.446 3.41 0.131 0.896
2 X.ray1 2.10 0.795 2.64 0.00833
3 stage1 1.76 0.747 2.36 0.0182
4 age -0.0703 0.0574 -1.22 0.221
5 acid.ph 0.0222 0.0128 1.73 0.0828
Two of the predictors (X.ray, stage) are statistically significant
Focusing on X.ray, it is unlikely (p-value < 0.05) to obtain a value of \(b_{1}\) as as far from 0 as 2.10 if X.ray is unrelated to nodes (\(\beta_{1}=0\) ) and the model contains the other predictors
Manual Variable Selection
Multicollinearity is not a problem here, because the data are from a well-designed experiment
VIF are all near 1 (smallest possible value)
library (car)
vif (lymph_mod)
X.ray stage age acid.ph
1.020128 1.056722 1.028123 1.062850
The coefficient for age is not significantly different from 0, so we drop it from the model
# A tibble: 4 × 5
term estimate std.error statistic p.value
<chr> <dbl> <dbl> <dbl> <dbl>
1 (Intercept) -3.58 1.18 -3.03 0.00247
2 X.ray1 2.06 0.778 2.65 0.00802
3 stage1 1.76 0.739 2.38 0.0175
4 acid.ph 0.0206 0.0126 1.63 0.103
The coefficient for acid.ph is not significantly different from 0, so we drop it from the model
The remaining two coefficients are significant
Ironically, since the response is categorical and the remaining predictors (explanatory variables) are categorical
We could analyze this data using a chi-squared test
# A tibble: 3 × 5
term estimate std.error statistic p.value
<chr> <dbl> <dbl> <dbl> <dbl>
1 (Intercept) -2.04 0.610 -3.35 0.000802
2 X.ray1 2.12 0.747 2.84 0.00454
3 stage1 1.59 0.700 2.27 0.0233
Spam
We would like to create a model that predicts whether an email is spam or not
email 1 data from 3,921 emails
Variables
spam
Whether email was spam (0 = “no”, 1 = “yes”)
to_multiple
Indicator: whether email was addressed to more than one recipient
attach
Number of files attached
winner
Indicator: whether the word “winner” appeared in the email
format
Indicator: whether email was written using HTML
re_subj
Indicator: whether subject started with “Re:”, “RE:”, etc.
exclaim_mess
Number of exclamation points in the message
number
Factor: whether there was no number, a small number (< 1 million), or a big number
About 9.4% of the emails were spam.
Logistic Model
# A tibble: 9 × 5
term estimate std.error statistic p.value
<chr> <dbl> <dbl> <dbl> <dbl>
1 (Intercept) -0.335 0.111 -3.02 2.55e- 3
2 to_multiple1 -2.56 0.309 -8.28 1.21e-16
3 attach 0.197 0.0597 3.29 9.90e- 4
4 winneryes 1.73 0.325 5.33 9.79e- 8
5 format1 -1.28 0.130 -9.80 1.09e-22
6 re_subj1 -2.86 0.365 -7.83 5.06e-15
7 exclaim_mess 0.000229 0.000872 0.263 7.92e- 1
8 numbersmall -1.07 0.141 -7.54 4.83e-14
9 numberbig -0.424 0.202 -2.10 3.57e- 2
All but one of the predictors (exclaim_mess) is statistically significant
None of these variables is colinear because VIF of each is close to 1.
Email Classification
We would like to use the model to predict whether an email is spam or not
The model predicts the log-odds that an email is spam
One way to classify emails is to label an email as spam if the predicted probability exceeds 0.5
Most emails, including spam, have a low predicted probability of being spam
If we used a threshold of 0.5, only 1% of emails in the data would be classified as spam
Instead, we will use a lower threshold, 0.1
This allows us to classify more emails as spam
We expect to correctly classify a larger number of emails as spam
However, we also expect to incorrectly classify emails as spam that are not actually spam
Single-Predictor Model
We will compare the full model to a model that uses a single predictor (to_multiple)
We will use 4-fold cross-validation to evaluate the model performance
# A tibble: 2 × 5
term estimate std.error statistic p.value
<chr> <dbl> <dbl> <dbl> <dbl>
1 (Intercept) -2.12 0.0562 -37.7 1.84e-310
2 to_multiple1 -1.81 0.297 -6.09 1.10e- 9
Cross-Validation Results
Confusion Matrix for Single-Predictor Model (holdouts)
Predicted
Truth
Spam
Not Spam
Spam
355
12
Not Spam
2946
608
Overall accuracy: 0.246
Not spam, predicted correctly: 0.171
Spam, predicted correctly: 0.967
Confusion Matrix for Full Model (holdouts)
Predicted
Truth
Spam
Not Spam
Spam
260
107
Not Spam
778
2776
Overall accuracy: 0.774
Not spam, predicted correctly: 0.781
Spam, predicted correctly: 0.708