1. 项目概述
1.1 核心需求解析
2020年之后,公共卫生领域对疫情数据的量化分析需求急剧上升,大家开始意识到,如果能在早期就对感染人数走势做出相对可靠的预判,相关部门在医疗资源调度、防控措施制定上就会从容很多。这个深度学习入门项目“新冠感染人数预测”,就是从这个痛点切入的。
项目本质上属于时间序列预测问题,也就是根据过去一段时间的感染人数序列,预测未来若干天的数值。时间序列预测并不是深度学习的专属领域,传统的ARIMA、指数平滑等统计模型也一直在用,但这类方法对非线性关系的拟合能力偏弱,面对疫情传播中大量非线性因素(人员流动、变异毒株、防控强度变化)时,预测效果很容易崩。深度学习的优势在于,它能从历史数据中自适应地学习到这些复杂模式,不需要手写规则,也不需要人为指定函数形式。
我用LSTM(长短期记忆网络)来作为这个项目的核心模型。为什么要选LSTM而不是普通的全连接网络或者CNN?因为感染人数是带时间顺序的序列数据,今天的感染人数和昨天、前天甚至前两周的人数都有依赖关系。普通神经网络把每一条样本当作独立个体处理,会丢掉这个顺序信息。LSTM天生就是为序列数据设计的,它的门控机制可以决定该记住什么、该遗忘什么,在处理这种时间依赖问题时表现稳定。拿生活里的例子来类比:普通RNN像是只有短期记忆的人,说一句忘一句;而LSTM像是带着笔记本工作的人,重要的信息会记在本子上,不重要的信息过目即忘。
这个项目适合谁来上手?我觉得有Python基础、了解一点深度学习基本概念但还没完整跑通过一个项目的人是最合适的群体。如果你已经会写Python但没装过深度学习环境、没训练过模型、对PyTorch只是一知半解,那跟着这个项目走一遍,脑子里那些零碎的概念就能串起来了。项目的完整链路覆盖了环境搭建、数据获取、数据清洗、序列化处理、模型构建、训练调参、结果评估和可视化,基本上把深度学习做项目的标准流程都走了一遍。
1.2 项目技术栈与工具选择
我选用的技术栈如下:
- Python 3.9+:深度学习生态最成熟的语言,没有之一
- PyTorch 2.x:动态计算图机制对初学者友好,调试时能直观看到每步的张量状态,写起来灵活
- Pandas + NumPy:数据处理阶段的主力工具,加载CSV、缺失值处理、滑动窗口构建都靠它们
- Matplotlib:预测结果可视化,训练损失曲线和预测对比图的绘制
- Scikit-learn:计算RMSE、MAE等评估指标,也可以用来做数据归一化
为什么不选TensorFlow?不是说TensorFlow不好,它的生态同样强大,但PyTorch的调试体验对入门者来说确实更友好。想象一下你排错的时候,PyTorch的报错信息会精确告诉你哪个张量的形状在哪个操作上对不上,TensorFlow的静态图机制查起错来就麻烦一些。而且现在学术圈和工业界的新模型大部分都先出PyTorch版本,跟着生态走能少踩很多坑。
项目的运行环境,我先后在Windows 11和Ubuntu 20.04上验证过,Windows下建议用Anaconda管理Python环境,NVIDIA显卡用户可以启用CUDA加速。没独显也不用慌,这个模型的规模用CPU跑也就几分钟到十几分钟的事,完全能接受。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据获取与预处理
2.1 数据源选择与加载方式
做预测类项目,数据质量直接决定模型的上限。这个项目我用的是约翰斯·霍普金斯大学发布的公开疫情数据集,它在GitHub上有仓库,整理得很规范,按国家、省份、日期三个维度记录了确诊、死亡、康复三类数据。对入门项目来说,这种结构化程度高的数据能省去大量清洗功夫,把精力留在模型本身。
数据加载的步骤我用代码说明,其实就三步:下载CSV文件、用Pandas读入、过滤出目标地区的列。
python复制import pandas as pd
# 读取全球疫情数据,文件路径根据自己实际下载位置修改
df = pd.read_csv("time_series_covid19_confirmed_global.csv")
# 查看前几行,确认数据结构
print(df.head())
这个数据集是宽表结构,每一行是一个地区,每一列是一个日期,列名就是日期字符串,比如“2020-01-22”“2020-03-15”这样的格式。我第一次拿到这个数据的时候愣了一下,因为平时见惯了长表,这个宽表的日期都在列名里,处理起来要顺手转换一下才是我们熟悉的“日期+数值”两列结构。
具体转换思路是:先选一个我们关注的国家或地区(我这里以中国为例,你也可以换成美国、印度等国来做对比实验),把该行数据取出来,再用 melt 函数把日期列从宽表转成长表。转换后的数据就是标准的时序数据了:一列日期,一列累计确诊人数。
python复制# 以中国为例,提取中国的数据行
china_data = df[df["Country/Region"] == "China"].iloc[:, 4:]
# 转置并重置索引,形成“日期-人数”两列数据
china_series = china_data.T.reset_index()
china_series.columns = ["date", "confirmed"]
# 将日期字符串转为datetime类型
china_series["date"] = pd.to_datetime(china_series["date"])
china_series = china_series.sort_values("date")
print(china_series.head())
print(china_series.tail())
这里有个细节值得说明:数据源里记录的是累计确诊人数,不是每日新增。累计序列的单调递增特性会让模型退化成“照着昨天的数加一点”,学习不到真正的增长规律。所以必须做一步差分,把累计值转成每日新增值,这才是有起伏、能学到传播规律的信号。
python复制# 计算每日新增确诊人数
china_series["new_cases"] = china_series["confirmed"].diff().fillna(0)
做差分的目的,是让模型预测的对象从单调序列变成波动序列。累计确诊数必然递增,模型只要学会“今天的值略大于昨天”就能得到不错的损失,但这没有意义。每日新增是一个波动序列,有涨有落,模型必须学到真实的变化模式才有预测能力。这个思路不仅适用于疫情数据,任何累计型指标做预测前都应该先考虑是否要转成增量。比如股票累计成交额、网站累计访问量,直接预测累计值基本就是“昨天加噪声”,没有信息量。
2.2 缺失值与异常值处理
真实世界的数据永远没有教科书里那么干净。我下载的数据里就碰到了两个典型问题:一个是部分日期的数据为空值,另一个是某些日期的新增病例数出现了负数。
空值的出现,通常是因为数据源在某些日期没有更新某个地区的统计。处理方案比较直接,用前向填充即可,拿前一天的值来补:
python复制# 将空值用前向填充方式处理
china_series["new_cases"] = china_series["new_cases"].fillna(method="ffill")
新增病例为负数的情况则更有意思。这不是数据源出错,而是某
