AI for Electronic Health Records
Module: Healthcare AI | Difficulty: Advanced
Time-Aware LSTM
Clinical Feature Embedding
MIMIC-III Dataset Statistics
| Statistic | Value | |-----------|-------| | Patients | 38,597 | | ICU Stays | 53,423 | | Chart Events | 330M | | Lab Events | 27M | | Medication Orders | 1.7M |
import torch
import torch.nn as nn
class TemporalAttention(nn.Module):
def __init__(self, hidden_dim):
super().__init__()
self.attn = nn.Linear(hidden_dim, 1)
def forward(self, lstm_out, mask=None):
scores = self.attn(lstm_out).squeeze(-1)
if mask is not None:
scores = scores.masked_fill(mask == 0, -1e9)
weights = torch.softmax(scores, dim=-1)
context = torch.bmm(weights.unsqueeze(1), lstm_out).squeeze(1)
return context, weights
class EHRPredictor(nn.Module):
def __init__(self, num_lab_codes=500, num_med_codes=300, hidden_dim=128):
super().__init__()
self.lab_embed = nn.Embedding(num_lab_codes, 32)
self.med_embed = nn.Embedding(num_med_codes, 32)
self.value_nn = nn.Sequential(
nn.Linear(1, 16), nn.ReLU(), nn.Linear(16, 16))
self.temporal_attn = TemporalAttention(hidden_dim)
self.lstm = nn.LSTM(32 + 16, hidden_dim, batch_first=True, bidirectional=True)
self.classifier = nn.Sequential(
nn.Linear(hidden_dim * 2, 64), nn.ReLU(),
nn.Dropout(0.3), nn.Linear(64, 1))
def forward(self, lab_codes, lab_values, med_codes, mask=None):
lab_emb = self.lab_embed(lab_codes)
val_emb = self.value_nn(lab_values.unsqueeze(-1))
features = torch.cat([lab_emb, val_emb], dim=-1)
lstm_out, _ = self.lstm(features)
context, attn_weights = self.temporal_attn(lstm_out, mask)
output = self.classifier(context)
return torch.sigmoid(output), attn_weights
model = EHRPredictor()
lab_codes = torch.randint(0, 500, (1, 48))
lab_values = torch.randn(1, 48)
med_codes = torch.randint(0, 300, (1, 48))
mask = torch.ones(1, 48)
pred, weights = model(lab_codes, lab_values, med_codes, mask)
print(f'Prediction probability: {pred.item():.4f}')
print(f'Attention weights shape: {weights.shape}')
Research Insight: EHR data is inherently messy: irregular sampling, missing values, and code changes over time. Time-aware models that account for observation gaps significantly outperform standard RNNs. The key insight is that the time between observations is itself informative: a gap in lab tests may indicate stable condition or lack of monitoring.