智慧医疗:FHIR R5、联邦学习与MLOps三位一体的AI产品化实战指南(下)

2.3 实战演练:使用Flower搭建一个3节点联邦学习糖尿病预测模型
让我们把理论付诸实践。我们将模拟一个场景:3家医院希望协作训练一个基于表格数据的糖尿病预测模型,但任何一方的患者数据都不能离开本地。我们将使用PyTorch作为模型框架,Flower作为联邦学习框架。
2.3.1 项目结构
fl-medical-fl-demo/
├── client.py # 模拟医院客户端的训练逻辑
├── server.py # 联邦学习服务器,负责聚合模型
├── utils.py # 共享的工具函数(模型定义、数据加载等)
├── requirements.txt # 项目依赖
├── docker-compose.yml # 用于一键启动3个客户端和1个服务器
└── README.md # 运行说明
2.3.2 步骤1:准备环境和依赖
requirements.txt
# 核心框架
flwr
torch
scikit-learn
numpy
pandas
运行 pip install -r requirements.txt 安装依赖。
2.3.3 步骤2:定义共享部分(模型、数据)
utils.py
import torch
import torch.nn as nn
from torch.utils.data import TensorDataset, DataLoader
from sklearn.datasets import load_diabetes
from sklearn.preprocessing import StandardScaler
import numpy as np# --- 模型定义 ---
# 简单的神经网络
class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.layer1 = nn.Linear(10, 16)self.relu = nn.ReLU()self.layer2 = nn.Linear(16, 1) # 输出1个值def forward(self, x):return self.layer2(self.relu(self.layer1(x)))# --- 数据准备 ---
# 为了模拟Non-IID数据,我们将数据集切分成3份,并给每份添加不同的偏置
def load_data(partition_id: int, num_partitions: int):# 加载标准数据集X, y = load_diabetes(return_X_y=True)scaler = StandardScaler()X = scaler.fit_transform(X)# 简单的Non-IID切分:按索引顺序切分partition_size = len(X) // num_partitionsstart_idx = partition_id * partition_sizeend_idx = start_idx + partition_size# 添加偏置以模拟数据分布差异bias = np.random.normal(loc=partition_id * 0.5, scale=0.2, size=X[start_idx:end_idx].shape)X_partition = X[start_idx:end_idx] + biasy_partition = y[start_idx:end_idx]# 转换为PyTorch TensorX_tensor = torch.tensor(X_partition, dtype=torch.float32)y_tensor = torch.tensor(y_partition, dtype=torch.float32).view(-1, 1)dataset = TensorDataset(X_tensor, y_tensor)trainloader = DataLoader(dataset, batch_size=32, shuffle=True)num_examples = len(dataset)return trainloader, num_examples# --- 模型训练/评估函数 ---
