1. 项目概述
这个项目是一个基于PyTorch框架实现的COVID-19病例预测模型。通过分析包含93个特征的医疗数据,模型能够预测"tested_positive"(阳性检测率)这一目标变量。项目完整展示了从数据预处理、模型构建到训练评估的整个深度学习流程。
1.1 核心组件解析
项目主要包含三个核心部分:
- 数据预处理模块:
CovidDataset类负责加载和标准化CSV格式的原始数据 - 神经网络模型:
myModel类定义了一个简单的全连接网络结构 - 训练评估流程:
train_val和evaluate函数实现了模型的训练和预测功能
提示:虽然项目中使用的是COVID-19数据,但同样的框架可以迁移到其他回归预测任务中,只需调整输入特征的维度即可。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据预处理深度解析
2.1 数据集类实现
CovidDataset类继承自PyTorch的Dataset类,主要完成以下关键操作:
python复制class CovidDataset(Dataset):
def __init__(self, file_path, mode):
with open(file_path, "r") as f:
ori_data = list(csv.reader(f))
csv_data = np.array(ori_data)[1:, 1:].astype(float)
# 数据分割策略
if mode == "train":
indices = [i for i in range(len(csv_data)) if i % 5 != 0]
elif mode == "val":
indices = [i for i in range(len(csv_data)) if i % 5 == 0]
elif mode == "test":
indices = [i for i in range(len(csv_data))]
# 数据标准化处理
X = torch.tensor(csv_data[indices, :93])
if mode != "test":
self.Y = torch.tensor(csv_data[indices, -1])
self.X = (X - X.mean(dim=0, keepdim=True)) / X.std(dim=0, keepdim=True)
2.1.1 关键设计选择解析
-
数据分割策略:
- 训练集:取80%数据(跳过每5个样本中的第5个)
- 验证集:取20%数据(每5个样本中的第5个)
- 测试集:使用全部测试数据
-
数据标准化:
- 采用Z-score标准化:(X - μ)/σ
keepdim=True保持维度不变,便于广播运算- 标准化可以加速模型收敛,防止某些特征因尺度差异过大而主导训练过程
2.2 数据加载器配置
python复制batch_size = 16
train_loader = DataLoader(train_set, batch_size=batch_size, shuffle=True)
val_loader = DataLoader(val_set, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_set, batch_size=1, shuffle=False)
- batch_size选择16:中等大小的batch既能利用GPU并行计算优势,又不会导致内存溢出
- shuffle设置:训练时打乱数据防止模型记忆样本顺序,测试时保持原始顺序便于结果分析
- 测试集batch_size=1:适合逐条预测的场景,但会降低预测速度
3. 模型架构与实现
3.1 网络结构设计
python复制class myModel(nn.Module):
def __init__(self, inDim):
super(myModel, self).__init__()
self.fc1 = nn.Linear(inDim, 128)
self.relu1 = nn.ReLU()
self.fc2 = nn.Linear(128, 1)
def forward(self, x):
x = self.fc1(x)
x = self.relu1(x)
x = self.fc2(x)
if len(x.size()) > 1:
x = x.squeeze(1)
return x
3.1.1 架构选择考量
-
输入层到隐藏层:
- 输入维度:93(对应数据特征数)
- 隐藏层维度:128,这个中等大小的隐藏层可以在保持模型容量的同时避免过拟合
-
激活函数选择:
- 使用ReLU而非Sigmoid/Tanh:避免梯度消失问题,计算效率更高
- 只在隐藏层使用激活函数,输出层保持线性(回归任务的标准做法)
-
输出处理:
squeeze(1)操作:当batch_size>1时去除多余的维度,保持输出形状一致性
3.2 损失函数设计
python复制def mseLoss(pred, target, model):
loss = nn.MSELoss(reduction='mean')
regularization_loss = 0
for param in model.parameters():
regularization_loss += torch.sum(param ** 2) # L2正则
return loss(pred, target) + 0.00075 * regularization_loss
- MSE损失:均方误差适合回归问题,对离群点敏感但数学性质良好
- L2正则化:
- λ=0.00075控制正则化强度
- 有效防止过拟合,特别是对于这种小型网络
- 实现方式:手动计算所有参数的平方和
注意:正则化系数需要根据具体问题调整,过大可能导致欠拟合,过小则防过拟合效果有限
4. 训练流程详解
4.1 训练-验证循环
python复制def train_val(model, train_loader, val_loader, lr, optimizer, device, epochs, save_path):
plt_train_loss = []
plt_val_loss = []
min_val_loss = float('inf')
for epoch in range(epochs):
# 训练阶段
model.train()
train_loss = 0.0
for x, y in train_loader:
x, y = x.to(device), y.to(device)
optimizer.zero_grad()
y_pred = model(x)
bat_loss = loss(y_pred, y, model)
bat_loss.backward()
optimizer.step()
train_loss += bat_loss.item()
# 验证阶段
model.eval()
val_loss = 0.0
with torch.no_grad():
for val_x, val_y in val_loader:
val_x, val_y = val_x.to(device), val_y.to(device)
val_pred_y = model(val_x)
val_bat_loss = loss(val_pred_y, val_y, model)
val_loss += val_bat_loss.item()
# 保存最佳模型
if val_loss < min_val_loss:
min_val_loss = val_loss
torch.save(model, save_path)
4.1.1 关键训练技巧
-
训练/验证模式切换:
model.train():启用Dropout和BatchNorm的训练行为model.eval():关闭上述层的训练特定行为
-
梯度管理:
zero_grad():每batch前清空梯度,防止梯度累积backward():自动计算梯度step():根据梯度更新参数
-
模型保存策略:
- 基于验证集损失保存最佳模型(而非训练损失)
- 使用
torch.save保存完整模型(包含结构和参数)
4.2 优化器配置
python复制optimizer = optim.SGD(params=model.parameters(), lr=0.001, momentum=0.9)
- SGD with Momentum:
- 学习率lr=0.001:较小的学习率适合配合Momentum使用
- momentum=0.9:加速收敛并帮助跳出局部极小值
- 相比Adam等自适应优化器,SGD+Momentum通常能获得更好的最终性能(但需要更仔细的超参调优)
5. 评估与结果分析
5.1 测试集评估
python复制def evaluate(model_path, test_loader, rel_path, device):
model = torch.load(model_path).to(device)
rel = []
model.eval()
with torch.no_grad():
for x in test_loader:
x = x.to(device)
pred = model(x)
rel.append(pred.cpu().item())
# 结果保存
with open(rel_path, "w", newline="") as f:
csv_writer = csv.writer(f)
csv_writer.writerow(["id", "tested_positive"])
for i, pred in enumerate(rel):
csv_writer.writerow([str(i), str(pred)])
5.1.1 评估注意事项
-
推理模式:
with torch.no_grad():禁用梯度计算,减少内存消耗model.eval():确保BatchNorm等层使用运行统计量而非batch统计量
-
结果保存:
- 按比赛要求的格式保存预测结果
- 保持测试样本顺序不变(shuffle=False)
5.2 训练曲线分析
项目生成的训练曲线展示了训练损失和验证损失的变化趋势:
-
理想情况:
- 两条曲线同步下降并最终收敛
- 验证损失不低于训练损失太多
-
问题诊断:
- 如果验证损失开始上升而训练损失继续下降 → 过拟合
- 如果两条曲线都下降缓慢 → 学习率可能太小或模型容量不足
- 如果损失震荡剧烈 → 学习率可能太大
6. 实战经验与改进建议
6.1 常见问题排查
-
GPU内存不足:
- 减小batch_size
- 使用
torch.cuda.empty_cache()释放缓存 - 检查是否有不必要的张量保留在GPU上
-
训练不收敛:
- 检查数据标准化是否正确
- 尝试更大的学习率或不同的优化器
- 验证模型是否有足够的容量(增加隐藏层大小)
-
过拟合处理:
- 增加L2正则化系数
- 添加Dropout层
- 获取更多训练数据
6.2 进阶改进方向
-
模型架构改进:
- 增加网络深度(更多全连接层)
- 尝试Batch Normalization
- 使用更复杂的激活函数(如LeakyReLU)
-
训练策略优化:
- 实现学习率调度(如ReduceLROnPlateau)
- 添加早停机制(Early Stopping)
- 使用交叉验证替代简单验证集
-
特征工程:
- 分析特征重要性
- 尝试特征选择或降维技术
- 创建更有意义的衍生特征
7. 完整实现建议
对于想要完整复现项目的读者,建议按照以下步骤操作:
-
环境准备:
bash复制
conda create -n covid python=3.8 conda activate covid pip install torch numpy pandas matplotlib -
目录结构:
code复制covid_prediction/ ├── data/ │ ├── covid.train.csv │ └── covid.test.csv ├── model_save/ ├── train.py └── utils.py -
执行训练:
python复制python train.py --lr 0.001 --batch_size 32 --epochs 50 -
参数调优建议:
- 学习率:尝试0.1到0.0001之间的对数尺度值
- batch_size:根据GPU内存选择16/32/64等2的幂次
- 正则化系数:通过验证集性能选择最佳值
