新冠疫情数据回归预测
什么是张量?(零基础形象大白话 + 生活例子 + 项目例子)
我完全不用专业公式,用你天天见的东西打比方,保证秒懂,面试还能直接说!
一、一句话核心定义
张量(Tensor) = PyTorch专用的「数据容器」
你可以把它理解成:装数字的盒子,只是这个盒子是深度学习框架专门定制的,能用来训练模型、算梯度、用GPU加速。
普通的列表、数组 = 家用塑料盒(只能存数据,不能训练模型)
张量 = 深度学习专用工具箱(既能存数据,又能跑模型)
二、形象举例(从简单到复杂,一看就会)
我们按维度举例子,维度就是盒子的层数/形状:
1. 0维张量(标量)→ 一个单独的数字
就是一个数,没有行列
✅ 生活例子:你今天的体温 36.5
✅ 项目例子:预测出来的1个新冠阳性人数 120
2. 1维张量(向量)→ 一排数字 / 一串珠子
一行/一列数字,像糖葫芦
✅ 生活例子:购物清单 [苹果, 香蕉, 梨]
✅ 项目例子:1个患者的93个特征 [特征1, 特征2, ..., 特征93]
👉 这就是你代码里单条数据的形状!
3. 2维张量(矩阵)→ 一张表格 / Excel
行和列都有,最常用!
✅ 生活例子:班级成绩表(行=学生,列=科目)
✅ 项目例子:16个患者的特征数据(16行93列)
👉 这就是你代码里 DataLoader 喂给模型的一批数据!
4. 高维张量(3维/4维)→ 立体的、批量的表格
比如图片(长×宽×颜色)、视频,咱们这个项目用不到,不用记!
三、结合咱们的新冠预测项目(面试必说!)
在你的代码里:
-
原始CSV数据 → 普通表格(家用盒子)
-
torch.tensor(x)→ 把表格装进张量盒子 -
模型只认这个张量盒子,不认家用盒子
我们项目里用到的就是:
1维张量(单个样本) + 2维张量(批量样本)
四、极简总结(刻在脑子里)
-
张量 = 装数字的专用盒子(PyTorch定制)
-
维度越低越简单:1个数(0维) → 1排数(1维) → 1张表(2维)
-
我们的项目就是用1维、2维张量存疫情特征数据
五、考研复试满分背诵版
张量是PyTorch框架中用于存储和运算数据的基本单位,可以理解为多维数组。在我们的疫情预测项目中,单个样本的特征是1维张量,批量输入模型的训练数据是2维张量,它支持梯度计算和GPU加速,是深度学习的核心数据格式。
什么是前向传播,在myModel中定义的 反向传播
forward函数:模型的核心,输入数据x(特征),自动走一遍网络,输出预测值;
反向传播
定义损失函数(批改试卷的标准)
loss = nn.MSELoss()
-
MSELoss:均方误差,回归任务最常用
-
作用:计算预测值和真实值的误差(错得有多离谱)
-
✅ 比喻:老师的批改标准,算错题分数
整个项目完整流程(终极总结,刻在脑子里)
-
准备数据:加载疫情数据集,打包成批量
-
搭建模型:两层全连接网络,输入93特征输出1个预测值
-
配置工具:老师(优化器)、批改标准(损失函数)、学习计划
-
训练模型:学20遍,改错参数,保存最优模型
-
预测结果:用最优模型做测试,输出CSV答案文件
考研复试 满分背诵版(直接背)
该段代码是项目的主执行逻辑:首先定义学习率、训练轮数等超参数;创建自定义回归模型,定义MSE损失函数和SGD优化器;调用训练验证函数完成模型训练与最优模型保存;最后调用评估函数加载最优模型完成测试集预测,并将结果保存为CSV文件,完整实现了数据训练到模型预测的全流程。
小白3句话终极总结
-
这是程序的总入口,一键运行全流程
-
先训练模型学习数据规律,再用最优模型做预测
-
最终输出一个CSV文件,包含每一行测试数据对应的阳性人数预测值
MSE损失韩式
我用最直白的大白话+你的新冠预测项目,告诉你回归任务必须用MSE的5个核心原因,全程不绕弯、不搞晦涩公式!
先定前提
你的项目是回归任务:预测具体的阳性人数(连续数字)
我们需要一个损失函数,能告诉模型:你预测的数字,和真实数字差了多少?
MSE 就是为这个场景量身定做的!
一、为什么回归必须用MSE?(核心理由)
1. 它是唯一能「计算数值误差」的损失函数
回归任务的目标是预测准确的数字
MSE 直接计算:
预测值 - 真实值
精准衡量模型错了多少
而分类任务的损失函数(如交叉熵),只能判断「对/错」,根本算不了数值差,完全用不了。
2. 平方运算:让正负误差不会互相抵消(最关键!)
举个例子:
-
真实人数:100
-
模型A预测:110(多了10)
-
模型B预测:90(少了10)
如果不用平方,直接算平均误差:(+10) + (-10) = 0
→ 模型会误以为自己预测全对!
用MSE平方后:误差都变成正数,错多错少一目了然,绝不会出错。
3. 自动「惩罚大错误」,让模型优先改大错
误差平方后:
-
小错(差5)→ 平方=25
-
大错(差50)→ 平方=2500
MSE会放大大误差,逼迫模型优先修正离谱的预测
比如把阳性人数100预测成200,这种大错会被模型立刻改掉。
4. 数学性质完美,模型能轻松学习
MSE 曲线光滑、好计算,优化器(SGD)可以轻松算出梯度
也就是能轻松告诉模型:哪里错了、该怎么改参数
让训练稳定、不崩溃、学得快。
5. 计算简单、通用性极强
几乎所有回归问题(房价、气温、销量、人数预测)
都能用MSE,稳定又好用,是工业界最标准的选择。
二、结合你的项目一句话总结
你在预测新冠阳性人数,是连续的数值:
-
要算准数字 → 必须用MSE
-
不能让正负误差抵消 → 必须用平方
-
要修正大错误 → MSE自动惩罚
-
要让模型能学习 → MSE数学最适配
所以回归任务,首选MSE!
三、考研复试 满分背诵版
MSE是回归任务的标准损失函数,原因如下:第一,它能够直接计算预测值与真实连续数值的误差,适配回归任务的预测目标;第二,通过平方运算消除正负误差抵消的问题,真实反映模型误差;第三,可放大并惩罚大的预测错误,引导模型快速修正;第四,数学特性优良,便于反向传播更新参数,训练稳定高效。因此是数值预测类回归任务的最佳选择。
3句话终极小白总结
-
回归预测数字,MSE专门算数字的误差
-
平方让误差不会抵消,还能惩罚大错
-
好计算、好训练、通用强,是回归的标配!
SGD 优化器:模型参数的专属辅导老师
我延续你最熟悉的「学生改错题」比喻,结合你的新冠回归项目代码,把 SGD 优化器 讲得透透的!
全程大白话、无晦涩公式,面试直接背!
核心一句话(先刻死)
SGD(随机梯度下降)= 模型的专属辅导老师
MSE 告诉老师「错了多少分」,SGD 负责手把手教模型改参数,让预测的阳性人数越来越准!
一、SGD 是干嘛的?(对应你的代码)
你的代码:
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
它的唯一使命:
根据反向传播算出的错误(梯度),微调模型里的参数,缩小MSE损失!
二、超形象比喻(延续之前的场景)
-
模型 = 学生
-
预测阳性人数 = 做题
-
MSE损失 = 错题分数
-
SGD = 辅导老师
-
model.parameters()= 学生脑子里的解题公式(参数) -
optimizer.step()= 老师帮学生改公式
完整流程:
-
学生做题(模型预测)→ 错了
-
MSE 算错题分(损失)
-
反向传播告诉老师错在哪(梯度)
-
SGD 老师动手改参数 → 下次做对
三、SGD 两个关键参数(你的代码里都有!)
1. lr 学习率(最重要!)
lr=0.001
-
比喻:老师改题的步子大小
-
太大:乱改,学生越学越错
-
太小:改得太慢,半天学不会
-
0.001 是回归任务最稳妥的默认值
2. momentum 动量
momentum=0.9
-
比喻:给学生加惯性,顺着正确方向一直学
-
作用:防止模型走弯路,加速收敛,让训练更快更稳
四、SGD 具体怎么工作?(极简流程)
-
拿一批数据(16行)
-
模型预测 → 算MSE损失
-
反向传播找错误方向
-
SGD 按学习率,轻轻修改模型参数
-
清零梯度,下一批继续学
→ 循环20轮,参数越改越准,MSE越来越小!
五、为什么你的回归项目要用 SGD?
-
简单稳定:最基础的优化器,适合数值预测(回归任务)
-
适配MSE:和MSE损失完美配合,改参数效率极高
-
内存小:批量训练,不占电脑资源
-
效果好:能让你的阳性人数预测精准收敛
六、考研复试 满分背诵版
SGD即随机梯度下降,是深度学习最常用的优化器。它根据损失函数计算的梯度,按照设定的学习率更新模型参数,引导模型不断减小误差。搭配动量参数可加速训练、提升稳定性,是回归任务中高效、稳定的优化选择。
3句话终极小白总结
-
SGD = 帮模型改参数的老师
-
跟着MSE的错误走,一点点修正模型
-
学习率控节奏,动量加速度,让模型学得又快又准!
鲁棒性 = 系统的 “抗造能力”就是你的程序在不完美、复杂、有干扰的场景下,依然能稳定运行、准确识别、不崩溃、不出错的能力。
简单说:
- 环境正常 → 能运行,这不叫鲁棒;
- 光线暗、人脸歪、画面糊、角度偏 → 还能正常识别、不报错,这才叫鲁棒性强。
创新点 1:多模态识别适配,支持全场景签到(核心亮点)
背诵答案
系统突破了传统单一摄像头实时签到的限制,同时支持摄像头实时识别、本地图片识别、本地视频识别三种签到模式。老师既可以现场实时签到,也可以用课堂录像、抓拍图片完成补签,完美适配课堂灵活的签到需求,实用性远超传统单一模式系统。
项目对应
你的代码专门实现了三个识别按钮 / 功能,不是只有摄像头签到,这是绝大多数同类毕设没有的设计。
import matplotlib.pyplot as plt
import torch
from torch.utils.data import DataLoader, Dataset
import csv
import pandas as pd
import numpy as np
import torch.nn as nn
from torch import optim
import time
class Covid_dataset(Dataset):
def __init__(self, file_path, mode): # mode说明数据集是什么类型 训练集还是测试集
with open(file_path, "r") as f:
csv_data = list(csv.reader(f))
data = np.array(csv_data[1:])
if mode == "train":
indices = [i for i in range(len(data)) if i % 5 != 0]
elif mode == "val":
indices = [i for i in range(len(data)) if i % 5 == 0]
if mode == "test":
x = data[:, 1:].astype(float)
x = torch.tensor(x)
else:
x = data[indices, 1:-1].astype(float)
x = torch.tensor(x)
y = data[indices, -1].astype(float)
self.y = torch.tensor(y)
self.x = x - x.mean(dim=0, keepdim=True) / x.std(dim=0, keepdim=True)
self.mode = mode
def __getitem__(self, item):
if self.mode == "test":
return self.x[item].float() # 测试集没标签。 注意data要转为模型需要的float32型
else: # 否则要返回带标签数据
return self.x[item].float(), self.y[item].float()
def __len__(self):
return len(self.x)
class myModel(nn.Module):
def __init__(self, dim):
super(myModel, self).__init__()
self.fc1 = nn.Linear(dim, 100)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(100, 1)
def forward(self, x):
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
if len(x.size()) > 1:#16个行预测一个y
return x.squeeze(1)
else:
return x
def train_val(model, train_loader, val_loader, device, epochs, optimizer, loss, save_path):
model = model.to(device)
plt_train_loss = []
plt_val_loss = []
min_val_loss = 9999999999
for epoch in range(epochs):
train_loss = 0.0
val_loss = 0.0
start_time = time.time()
model.train()
for batch_x, batch_y in train_loader:
x, target = batch_x.to(device), batch_y.to(device)
pred = model(x)
train_bat_loss = loss(pred, target)
train_bat_loss.backward()
optimizer.step() # 更新参数 之后要梯度清零否则会累积梯度
optimizer.zero_grad()
train_loss += train_bat_loss.cpu().item()
plt_train_loss.append(train_loss / train_loader.dataset.__len__())
model.eval()
with torch.no_grad():
for batch_x, batch_y in val_loader:
x, target = batch_x.to(device), batch_y.to(device)
pred = model(x)
val_bat_loss = loss(pred, target)
val_loss += val_bat_loss.cpu().item()
plt_val_loss.append(val_loss / val_loader.dataset.__len__())
if val_loss < min_val_loss:
torch.save(model, save_path)
min_val_loss = val_loss
print('[%03d/%03d] %2.2f sec(s) TrainLoss : %.6f | valLoss: %.6f' % \
(epoch, epochs, time.time() - start_time, plt_train_loss[-1], plt_val_loss[-1])
) # 打印训练结果。 注意python语法, %2.2f 表示小数位为2的浮点数, 后面可以对应。
plt.plot(plt_train_loss)
plt.plot(plt_val_loss)
plt.title("loss")
plt.legend(["train", "val"])
plt.show()
def evaluate(save_path, device, test_loader, rel_path):
model = torch.load(save_path).to(device)
rel = []
with torch.no_grad():
for x in test_loader:
pred = model(x.to(device))
rel.append(pred.cpu().item())
print(rel)
with open(rel_path, "w") as f:
csv_writer = csv.writer(f)
csv_writer.writerow(["id", "test_positive"])
for i in range(len(rel)):
csv_writer.writerow([str(i), str(rel[i])])
print("文件已经保存到" + rel_path)
device = "cuda" if torch.cuda.is_available() else "cpu"
train_file = "covid.train.csv"
test_file = "covid.test.csv"
train_data = Covid_dataset(train_file, "train")
val_data = Covid_dataset(train_file, "val")
test_data = Covid_dataset(train_file, "test")
train_loader = DataLoader(train_data, batch_size=16, shuffle=True)
val_loader = DataLoader(val_data, batch_size=16, shuffle=True)
test_loader = DataLoader(test_data, batch_size=1, shuffle=False) # 测试集的batchsize一般为1 且不可以打乱
dim = 93
config = {
"lr": 0.001,
"momentum": 0.9,
"epochs": 20,
"save_path": "model_save/model.pth",
"rel_path": "pred.csv"
}
model = myModel(dim)
loss = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=config["lr"], momentum=config["momentum"]) # 优化器
train_val(model, train_loader, val_loader, device, config["epochs"], optimizer, loss, config["save_path"])
evaluate(config["save_path"], device, test_loader, config["rel_path"])
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)