😊

ICU患者のバイタルデータを用いた敗血症予測モデルの実装

2025/02/27に公開

はじめに

敗血症はICU(集中治療室)における重大な合併症の一つであり、早期発見が生存率向上の鍵となります。本記事では、ICU患者のバイタルデータを用いて、PyTorchを活用した機械学習モデルを構築し、敗血症の早期予測を試みます。

本記事で扱う内容は以下の通りです。

  1. ICUデータの特徴と前処理方法
  2. PyTorchを用いた敗血症予測モデルの実装
  3. モデルの学習と評価

ICUデータの特徴と必要な前処理

ICUにおけるバイタルデータは、患者の生理的指標を時系列データとして記録したものです。一般的なバイタルデータには以下のような指標が含まれます。

  • 心拍数(HR: Heart Rate)
  • 血圧(BP: Blood Pressure)
  • 体温(Temperature)
  • 呼吸数(RR: Respiratory Rate)
  • 酸素飽和度(SpO2)
  • 白血球数(WBC: White Blood Cell Count)

これらのデータは、患者ごとに異なる長さの時系列データとして記録されます。時系列データを機械学習に適用するには、いくつかの前処理が必要になります。

1. 欠損値処理

ICUのデータはしばしば欠損値を含んでいます。これを適切に処理する方法として、以下のような手法が挙げられます。

  • 直近の値で補完(前方/後方補完)
  • 移動平均による補完
  • 線形補間
  • データ削除(あまりにも欠損が多い場合)

2. 正規化

異なるスケールを持つ特徴量を統一するために、標準化(Zスコア正規化)またはMin-Max正規化を適用します。

3. データのスライディングウィンドウ化

LSTMなどの時系列モデルに適用するため、データを一定の時間間隔(例:過去10時間分)でスライディングウィンドウとして整理します。

4. ラベル付け

敗血症のラベルは、敗血症診断基準(Sepsis-3)に基づき、SOFAスコアやqSOFAスコアを利用して付与します。

PyTorchを用いた敗血症予測モデルの実装

前処理が完了したデータをもとに、PyTorchを用いてLSTMモデルを実装します。

1. データセットの作成

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
import numpy as np

# ICUデータセットの作成
class SepsisDataset(Dataset):
    def __init__(self, num_samples=1000, seq_length=10, num_features=6):
        self.data = np.random.rand(num_samples, seq_length, num_features).astype(np.float32)  # 特徴量
        self.labels = np.random.randint(0, 2, num_samples).astype(np.int64)  # 敗血症(1) or 健康(0)
    
    def __len__(self):
        return len(self.data)
    
    def __getitem__(self, idx):
        return torch.tensor(self.data[idx]), torch.tensor(self.labels[idx])

2. LSTMモデルの構築

class SepsisLSTM(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, output_size):
        super(SepsisLSTM, self).__init__()
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)
    
    def forward(self, x):
        lstm_out, _ = self.lstm(x)
        out = self.fc(lstm_out[:, -1, :])  # 最後の時間ステップの出力を利用
        return out

3. モデルの学習

# ハイパーパラメータ
input_size = 6  # 特徴量の数
hidden_size = 64
num_layers = 2
output_size = 2  # 敗血症(1) or 健康(0)
num_epochs = 10
batch_size = 32
learning_rate = 0.001

# データローダー
dataset = SepsisDataset()
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)

# モデル、損失関数、オプティマイザ
model = SepsisLSTM(input_size, hidden_size, num_layers, output_size)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

# 学習ループ
for epoch in range(num_epochs):
    for inputs, labels in dataloader:
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
    print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

モデルの評価

学習後、モデルの性能を評価するために、以下の指標を計算します。

  • AUC-ROC: モデルの分類能力を測る指標
  • F1スコア: PrecisionとRecallのバランスを考慮した指標
  • 混同行列: クラスごとの正解/不正解の分布を確認
from sklearn.metrics import roc_auc_score, f1_score, confusion_matrix

def evaluate_model(model, dataloader):
    all_labels = []
    all_preds = []
    with torch.no_grad():
        for inputs, labels in dataloader:
            outputs = model(inputs)
            _, preds = torch.max(outputs, 1)
            all_labels.extend(labels.numpy())
            all_preds.extend(preds.numpy())
    
    print("AUC-ROC:", roc_auc_score(all_labels, all_preds))
    print("F1スコア:", f1_score(all_labels, all_preds))
    print("混同行列:\n", confusion_matrix(all_labels, all_preds))

まとめ

本記事では、ICU患者のバイタルデータを用いた敗血症予測モデルを構築しました。時系列データの前処理、LSTMモデルの実装、学習および評価までを詳細に解説しました。

今後は、MIMIC-IIIのような実際のデータセットを用いてさらに高精度なモデルを構築することが期待されます。

Discussion