Hospital Readmission Prediction and Risk Stratification
Module: Healthcare AI | Difficulty: Advanced
LACE Index
where L = length of stay, A = acuity, C = comorbidities, E = ED visits.
Logistic Regression Baseline
SHAP Value
Readmission Risk Factors
| Factor | Odds Ratio | p-value | |--------|-----------|---------| | Length of stay > 7 days | 1.45 | <0.001 | | Heart failure | 1.82 | <0.001 | | COPD | 1.56 | <0.001 | | Prior readmission | 2.34 | <0.001 | | Low albumin | 1.38 | <0.01 | | No follow-up | 1.67 | <0.001 |
import torch
import torch.nn as nn
import numpy as np
class ReadmissionPredictor(nn.Module):
def __init__(self, num_features=100, hidden_dim=64):
super().__init__()
self.encoder = nn.Sequential(
nn.Linear(num_features, hidden_dim), nn.BatchNorm1d(hidden_dim),
nn.ReLU(), nn.Dropout(0.3),
nn.Linear(hidden_dim, hidden_dim), nn.BatchNorm1d(hidden_dim),
nn.ReLU(), nn.Dropout(0.2))
self.readmission_head = nn.Linear(hidden_dim, 1)
self.time_to_event = nn.Linear(hidden_dim, 1)
def forward(self, x):
features = self.encoder(x)
readmit_prob = torch.sigmoid(self.readmission_head(features))
time_pred = torch.relu(self.time_to_event(features))
return readmit_prob, time_pred
def evaluate_readmission(y_true, y_pred_prob, threshold=0.5):
y_pred = (y_pred_prob > threshold).astype(int)
tp = ((y_pred == 1) & (y_true == 1)).sum()
fp = ((y_pred == 1) & (y_true == 0)).sum()
fn = ((y_pred == 0) & (y_true == 1)).sum()
tn = ((y_pred == 0) & (y_true == 0)).sum()
sensitivity = tp / (tp + fn) if (tp + fn) > 0 else 0
specificity = tn / (tn + fp) if (tn + fp) > 0 else 0
ppv = tp / (tp + fp) if (tp + fp) > 0 else 0
npv = tn / (tn + fn) if (tn + fn) > 0 else 0
accuracy = (tp + tn) / len(y_true)
return {'sensitivity': sensitivity, 'specificity': specificity,
'ppv': ppv, 'npv': npv, 'accuracy': accuracy}
model = ReadmissionPredictor(num_features=100)
x = torch.randn(200, 100)
readmit_prob, time_pred = model(x)
print(f'Readmission predictions: {readmit_prob.shape}')
print(f'Time predictions: {time_pred.shape}')
y_true = np.random.randint(0, 2, 200)
y_prob = readmit_prob.detach().numpy().squeeze()
metrics = evaluate_readmission(y_true, y_prob)
print(f'Metrics: {metrics}')
Research Insight: Readmission prediction models are prone to learning socioeconomic bias rather than true clinical risk. Models that include insurance type, zip code, and socioeconomic indicators may inadvertently discriminate against underserved populations. Fairness-aware approaches are essential for equitable readmission prediction.