Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

📊 Logistic Regression

Before applying logistic regression to model our data, we will attempt to do so through simple linear regression. While linear regression is not suitable for dichotomous outcomes, visualizing it can help illustrate why logistic regression is a better fit for our research question.

Why Not Linear Regression?

<Figure size 640x480 with 1 Axes>

Linear regression assumes that the dependent variable is continuous and unbounded. When we apply it to a dichotomous outcome such as understanding display rules (0/1), the underlying assumptions break down:

Logistic Regression with Python

In this example, we will use the LogisticRegression() class from scikit-learn for modeling.

Intercept: [-2.83306013]
Coefficients: [[0.06612023]]

Interpreting the Model Outputs: Logits

The logistic regression still gives us an intercept and a slope, but they operate on the log-odds scale, not the probability scale:

This means the output of a logistic regression model is linear in the log-odds (logits). Each coefficient in the logistic regression tells us how a one-unit change in a predictor affects the log-odds of the outcome. While not as intuitive as probabilities, the transformation to logits is crucial because it allows us to use linear regression techniques for binary outcomes.

But what even are logits?

Logits are the natural logarithm of the odds of an event occurring in logistic regression. The odds of an event are defined as the ratio of the probability of the event occurring (PP) to the probability of the event not occurring (1−P)(1-P):

Odds=P1−P\text{Odds} = \frac{P}{1-P}

In logistic regression, we predict the logit (log-odds) as a linear combination of the independent variables (X1,X2,…,Xk)(X_1, X_2, \dots, X_k) and their corresponding regression coefficients (β1,β2,…βk)(\beta_1, \beta_2, \dots \beta_k):

Logit(P)=ln⁡(P1−P)=β0+β1X1+β2X2+⋯+βkXk\text{Logit}(P) = \ln\left(\frac{P}{1-P}\right) = \beta_0 + \beta_1X_1 + \beta_2X_2 + \dots + \beta_kX_k

If we plot the equation, we can see how the regression line looks like:

<Figure size 640x480 with 1 Axes>

From Logits to Probabilities

We can simply transform the logits back into probabilities (more specifically the conditional probability of an observation yy belonging to class 1 given predictor(s) XX):

P(Y=1∣X)=11+e−(b0+b1X)P(Y=1 \mid X) = \frac{1}{1 + e^{-(b_0 + b_1 X)}}

To better understand the model’s behavior, let’s plot its outputs. A simple way to do this is by creating an evenly spaced array of values for our range, and then use model.predict_proba() to predict the outcome for each value. This will generate the regression line:

<Figure size 640x480 with 1 Axes>

Model Evaluation

To evaluate our model, we can examine how many values of yy (understanding display rules) were predicted correctly by the model. For this, we could binarise the probabilities as returned from model.predict_proba() or we can also just simply use model.predict():

Model predictions: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 1 1 0 0
 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]

Accuracy: 0.7714285714285715

An accuracy of 77% indicates the that the model correctly predicts the outcome for about 77% of the children in our data. This suggests that the model performs reasonably well, although it still misclassifies some cases. For a more detailed investigation, a confusion matrix is a useful way to visualize the prediction accuracy:

Confusion matrix:
 [[24  7]
 [ 9 30]]

The output of the confusion matrix provides the following values:

Predicted NegativePredicted Positive
Actual NegativeTrue Negative (TN)False Positive (FP)
Actual PositiveFalse Negative (FN)True Positive (TP)

For an even deeper inspection of the model’s accuracy, we can print the classification report:

              precision    recall  f1-score   support

           0       0.73      0.77      0.75        31
           1       0.81      0.77      0.79        39

    accuracy                           0.77        70
   macro avg       0.77      0.77      0.77        70
weighted avg       0.77      0.77      0.77        70

The output can be interpreted as follows:

Precision: Proportion of correct predictions among all predictions for that class.

Precision=True Positives (TP)True Positives (TP)+False Positives (FP)\text{Precision} = \frac{\text{True Positives (TP)}}{\text{True Positives (TP)} + \text{False Positives (FP)}}

Recall: Proportion of actual samples of a class that the model correctly identifies.

Recall=True Positives (TP)True Positives (TP)+False Negatives (FN)\text{Recall} = \frac{\text{True Positives (TP)}}{\text{True Positives (TP)} + \text{False Negatives (FN)}}

F1-Score: harmonic mean of precision and recall, providing a balance between the two and offering a good overall measure of model performance.

F1=2⋅Precision⋅RecallPrecision+RecallF_1 = 2 \cdot \frac{\text{Precision} \cdot \text{Recall}}{\text{Precision} + \text{Recall}}

Support: the actual number of observations of each class in the dataset

Accuracy: The overall proportion of correctly predicted observations.

Accuracy=TP+TNTotal number of observations\text{Accuracy} = \frac{TP + TN}{\text{Total number of observations}}

Multiple Logistic Regression

You may want to use two or more variables as inputs for the regression. In our example, we will use age and TOM as predictors for display by simply adding them to XX.

              precision    recall  f1-score   support

           0       0.79      0.74      0.77        31
           1       0.80      0.85      0.82        39

    accuracy                           0.80        70
   macro avg       0.80      0.79      0.80        70
weighted avg       0.80      0.80      0.80        70