PyTorch实战:基于新冠数据的阳性病例占比预测
大家好,今天给大家带来一个超实用的PyTorch实战项目------利用美国新冠调查数据预测阳性病例占比。整个流程从数据加载、预处理,到模型搭建、训练,全程代码+详细解析,新手也能轻松上手,话不多说,开整!
一、任务背景与数据集解析
1. 任务目标
本次任务是一个典型的回归预测问题:使用美国特定州过去5天的新冠调查数据,预测未来5天的新增新冠检测阳性病例占比。
2. 数据集详情
先给大家看一下我整理的数据集核心信息,这是后续代码的基础:
数据格式:CSV文件存储,每行对应一个样本
特征维度:共117维有效特征,包含37个州的独热编码、16类特征的5天数据
标签信息:每行最后一列是预测目标------阳性病例占比
样本规模:训练集共2699个样本,特征维度 (2699, 117),标签维度 (2699,)
二、完整代码实现与逐行精讲
1. 环境与库导入
第一步先导入需要的库,都是深度学习的老朋友了,注释里给大家讲清楚用途:
python
# 数据处理三剑客之两剑客:Pandas加载CSV,NumPy处理数值计算
import pandas as pd
import numpy as np
# PyTorch核心库:构建模型、处理张量
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
# 优化器与可视化:Adam优化模型参数,Matplotlib画训练曲线
from torch.optim import Adam
import matplotlib.pyplot as plt
2. 数据加载与预处理
数据是模型的血液,这一步的核心是加载数据→分离特征标签→转换为张量,直接上代码:
python
def load_and_preprocess_data(csv_path):
# 1. 加载CSV数据,删除全为NaN的无效列
train_data = pd.read_csv(csv_path).dropna(axis=1, how='all')
# 2. 分离特征和标签:特征取前117列,标签取最后1列
X_train = train_data.iloc[:, :-1].values # 特征数组 (2699, 117)
y_train = train_data.iloc[:, -1].values # 标签数组 (2699,)
# 3. 转换为PyTorch浮点型张量,标签升维适配模型输出
X_train = torch.tensor(X_train, dtype=torch.float32)
y_train = torch.tensor(y_train, dtype=torch.float32).unsqueeze(1) # 升维为(2699,1)
return X_train, y_train
# 调用函数(记得替换成你的数据集路径!)
X_train, y_train = load_and_preprocess_data("covid-train.csv")
# 打印维度验证:确保数据处理正确
print("特征维度:", X_train.shape) # 预期输出 (2699, 117)
print("标签维度:", y_train.shape) # 预期输出 (2699, 1)
关键解析:
dropna(axis=1, how='all'):清理无效列,避免脏数据干扰模型训练
iloc[:, :-1]:按列索引切片,精准分离特征和标签
unsqueeze(1):给标签升维,因为模型输出是二维张量 (batch_size, 1),维度匹配才能计算损失
3. 自定义Dataset类
PyTorch加载数据的标准操作是自定义Dataset,必须实现三个核心方法,代码如下:
python
class CovidDataset(Dataset):
def _init_(self,features,labels=None):
if y in None:
self.labels = labels
else:
self = torch.FloatTensor(labels)
self.features = torch.FloatTensor(features)
def __getitem__(self, idx):
# 按索引取样本:返回单个样本的特征和标签
return self.features[idx], self.labels[idx]
def __len__(self):
# 返回数据集总长度:供DataLoader计算批次
return len(self.features)
# 实例化数据集
train_dataset = CovidDataset(X_train, y_train)
关键解析:
init :接收特征和标签张量,完成初始化
getitem :DataLoader加载数据时会调用这个方法,按索引获取样本
len:告诉DataLoader数据集有多少个样本,是批量加载的基础
4. 构建DataLoader
有了Dataset,下一步就是用DataLoader实现批量加载+数据打乱,提升训练效率:
python
# 超参数:批次大小,可根据显存调整,常用32/64/128
batch_size = 32
train_loader = DataLoader(
dataset=train_dataset,
batch_size=batch_size,
shuffle=True # 训练时打乱数据,避免模型学顺序
)
# 验证DataLoader是否正常工作
for batch_X, batch_y in train_loader:
print("批次特征维度:", batch_X.shape) # 预期输出 (32, 117)
print("批次标签维度:", batch_y.shape) # 预期输出 (32, 1)
break # 只看第一个批次就够了
关键解析:
batch_size=32:每次训练喂给模型32个样本,平衡训练速度和显存占用
shuffle=True:训练集必须打乱,否则模型会学习到数据的顺序规律,泛化能力变差
5. 定义神经网络模型
本次任务是回归预测,我们搭建一个简单的全连接神经网络,代码如下:
python
class CovidPredictor(nn.Module):
def __init__(self, input_dim=117, hidden_dim=64, output_dim=1):
super(CovidPredictor, self).__init__()
# 定义三层全连接层
self.fc1 = nn.Linear(input_dim, hidden_dim) # 输入层→隐藏层
self.fc2 = nn.Linear(hidden_dim, hidden_dim//2) # 隐藏层→次隐藏层
self.fc3 = nn.Linear(hidden_dim//2, output_dim) # 次隐藏层→输出层
# 激活函数:ReLU解决线性模型表达能力不足的问题
self.relu = nn.ReLU()
def forward(self, x):
# 前向传播:数据流过网络的路径
x = self.relu(self.fc1(x)) # 第一层+激活
x = self.relu(self.fc2(x)) # 第二层+激活
x = self.fc3(x) # 输出层无激活!回归任务直接输出数值
return x
# 实例化模型
model = CovidPredictor()
print("模型结构:")
print(model)
关键解析:
输入维度input_dim=117:对应我们的特征维度
隐藏层设计:64→32,逐层压缩特征,提取核心信息
输出层output_dim=1:对应预测的阳性病例占比,回归任务输出层不加激活函数
6. 模型训练与可视化
万事俱备,最后一步就是训练模型了!核心步骤是定义损失函数+优化器+训练循环:
python
# 1. 定义损失函数:回归任务用均方误差MSE
criterion = nn.MSELoss()
# 2. 定义优化器:Adam优化器,学习率1e-3是常用值
optimizer = Adam(model.parameters(), lr=1e-3)
# 3. 训练超参数
epochs = 50 # 训练轮数
train_losses = [] # 存储每轮损失,用于可视化
# 训练循环
for epoch in range(epochs):
model.train() # 切换到训练模式
epoch_loss = 0.0 # 累计本轮损失
for batch_X, batch_y in train_loader:
# 梯度清零:必须操作,否则梯度会累加
optimizer.zero_grad()
# 前向传播:模型预测结果
outputs = model(batch_X)
# 计算损失:预测值和真实值的差距
loss = criterion(outputs, batch_y)
# 反向传播:计算梯度
loss.backward()
# 优化器更新参数:梯度下降
optimizer.step()
# 累计损失:乘以批次大小,避免批次影响
epoch_loss += loss.item() * batch_X.size(0)
# 计算本轮平均损失
avg_loss = epoch_loss / len(train_dataset)
train_losses.append(avg_loss)
# 每5轮打印一次损失,方便观察训练进度
if (epoch+1) % 5 == 0:
print(f"Epoch [{epoch+1}/{epochs}], Loss: {avg_loss:.4f}")
# 可视化训练损失曲线
plt.figure(figsize=(10, 6))
plt.plot(train_losses, label="Training Loss", color="#1f77b4")
plt.xlabel("Epochs", fontsize=12)
plt.ylabel("MSE Loss", fontsize=12)
plt.title("Training Loss Curve", fontsize=14)
plt.legend()
plt.grid(True, linestyle="--", alpha=0.7)
plt.show()
关键解析:
损失函数nn.MSELoss():回归任务的标配,计算预测值和真实值的均方误差
优化器Adam:比传统SGD收敛更快,学习率lr=1e-3是经验值
训练循环四步走:梯度清零→前向传播→反向传播→参数更新,这是PyTorch训练的固定流程
损失可视化:通过损失曲线可以判断模型是否收敛,曲线下降并趋于平稳就是训练有效的标志。
三、总结
本文完整实现了基于PyTorch的新冠阳性病例占比预测任务,从数据预处理到模型训练的每一步都有详细解析。这个项目不仅适合新手入门PyTorch,还可以在此基础上拓展优化,形成更深入的技术博客。
四、数据集
