李哥深度学习班 预测新冠感染数 回归实战 上
四个部分:数据、模型、超参、训练流程

项目来源:
***************************************ML2021Spring-hw1 | Kaggle**************************************
训练集、验证集、测试集
训练集(Training Set)是模型学习的主要数据来源。通过输入训练数据,模型不断调整内部参数(如权重、偏置)以最小化损失函数。 特点:
-
数据量最大,覆盖数据多样性
-
用于反向传播和优化器迭代更新
-
不直接评估泛化能力 示例:猫狗分类器中成千上万张已标注的猫狗图片。
验证集(Validation Set)用于在训练过程中评估模型性能,帮助选择最佳超参数(如学习率、批大小、网络层数、Dropout比例)。 特点:
-
与训练集独立,不参与参数更新
-
用于早停(Early Stopping)、模型选择
-
过度依赖可能导致对验证集过拟合 示例:每训练若干轮后,用5000张未参与训练的图片评估模型表现。
测试集(Test Set)在模型训练与调参完成后,用于最终性能评估,检验模型在真实场景下的泛化能力。 特点:
-
完全独立于训练与验证过程
-
生成准确率、召回率、F1等指标
-
结果是模型发布前的最终参考 示例:使用全新图片集测试猫狗分类器的准确率。
注意事项
- 避免数据泄露:确保训练集、验证集和测试集之间完全独立,避免信息泄露。
- 随机划分:采用随机抽样方式划分数据集,以减少偏差。
- 分层抽样:对于不平衡的数据集,应考虑分层抽样,以保持各类别在划分后的数据集中的比例。
代码
with语句用法:
with 语句的基本形式如下:
with expression [as variable]:
# 代码块
expression返回一个支持上下文管理协议的对象as variable是可选的,用于将表达式结果赋值给变量- 代码块执行完毕后,自动调用清理方法
最常见的 with 语句应用是文件操作:
with open('example.txt', 'r') as file:
content = file.read()
print(content)
# 文件已自动关闭

数据集合类 定义:
每一行是一组数据,每一列是一项参数
class CovidDataset(Dataset): # 数据集类定义 继承Dataset类
def __init__(self, file_path, mode): # 三个必备方法:__init__, __getitem__, __len__
with open(file_path, "r") as f:
ori_data = list(csv.reader(f))
csv_data = np.array(ori_data)[1:, 1:].astype(float) # 切片 切除第0行和第0列
# 取 训练集 和 验证集,采用逢五取一来取验证集(不推荐这么做,最好随机取)
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)
self.mode = mode
def __getitem__(self, item): # 传入下标,返回下标对应的数据
if self.mode == "test":
return self.X[item].float()
else:
return self.X[item].float(), self.Y[item].float()
def __len__(self): # 返回长度
return len(self.X)
利用csv库打开.csv训练文件,并将其转化为矩阵进行切片,切除掉不需要的字符行、列(即第0行和第0列)
mode属性决定了这个集合是数据集、验证集还是测试集
按照逢五取一的方法取验证集(实际上应该用随机取,这里简化了),即将训练样本按照4:1分为数据集和验证集
将取出的样本转化为tensor张量,并去掉最后一列,因为最后一列存放的是label标签,即目标数值,其余部分是对目标数值产生影响的data输入数据,因而要把它们分开,用x和y分别存放
随后要对x进行数据标准化,消除量纲和数据取值范围影响
Z-score标准化也被称为标准差标准化或者零-均值归一化,是将数据变换为均值为0,标准差为1的分布,变换后依然保留原数据分布。
这种方法给予原始数据的均值(mean)和标准差(standard deviation)进行数据的标准化。
经过处理的数据符合标准正态分布,即均值为0,标准差为1,这里的关键在于复合标准正态分布。

后续的get_item方法和get_len方法分别实现了取数据和取长度的功能
此外,get_item()方法还承担了区分数据data和标签label的工作,注意到它返回的是self.X[item]和self.Y[item],就是在这一步实际上区分了X和Y谁是data谁是label,后续dataloader按批次取数据也是基于此进行的
总结:
Dataset 负责区分:
1、getitem__() 方法决定返回什么
2、通常返回 (data, label) 元组
DataLoader 只是搬运工,拆包是用户的责任:
1、调用 dataset[idx] 获取每个样本
2、使用 collate_fn 将多个样本批处理
3、默认 collate_fn 能正确处理元组
模型类定义:
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)
return x
super(myModel, self).__init__()
super()函数:
是用于调用父类(超类)的一个方法。
super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
Python super() 函数 | 菜鸟教程 中给出的示例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class FooParent(object):
def __init__(self):
self.parent = 'I\'m the parent.'
print ('Parent')
def bar(self,message):
print ("%s from Parent" % message)
class FooChild(FooParent):
def __init__(self):
# super(FooChild,self) 首先找到 FooChild 的父类(就是类 FooParent),
# 然后把类 FooChild 的对象转换为类 FooParent 的对象
super(FooChild,self).__init__()
print ('Child')
def bar(self,message):
super(FooChild, self).bar(message)
print ('Child bar fuction')
print (self.parent)
if __name__ == '__main__':
fooChild = FooChild()
fooChild.bar('HelloWorld')
执行结果:
Parent Child HelloWorld from Parent Child bar fuction I'm the parent.
此处模型类定义中super的用法与示例中相同。
self.fc1 = nn.Linear(inDim, 128)
fc = fully connected 全连接,fc1,意为添加一个全连接层,输入维度为inDim,输出维度为128.
linear会自动创建和管理一批可优化的参数w和b,构建y = xWᵀ + b的全连接层
nn.linear是一个类,此处是对其进行实例化,实例化为一个linear对象self.fc1
由于该类中定义了__call__()方法,故该对象可以像一个函数一样被调用,这也是后续定义forward()方法时可以直接调用对象fc1进行前向传播计算的原因。
python类中的 __call__()方法运用_python 类 def call-CSDN博客
self.relu1 = nn.ReLU()
ReLU类的实例化,同样使用了__call__方法,可被调用,按照ReLU激活函数计算返回值。
forward()方法,前向传播
将输入的x矩阵(n×93)通过输入层,隐层(93,128,带激活函数ReLU),输出层(128,1)得到最终的输出并返回
datadim = 93
model = myModel(datadim)
batch_size = 16
train_set = CovidDataset(train_file, "train")
train_loader = DataLoader(train_set, batch_size=batch_size, shuffle=True)
for x, y in train_loader:
pred_y = model(x)
print(pred_y)
模型实例化,输入维度设置为93,batchsize设置为16,训练集实例化,训练数据生成器实例化。
model由于继承了nn.module类,而module类也使用了__call__,因而也可以作为一个函数调用,调用的内容就是执行forward()方法进行前向传播,如此一来就可以根据输入的x得到一批预测值y_pred.
DataLoader 的核心作用:
1、批处理:batch_size 控制每批样本数
2、数据打乱:shuffle=True 用于把数据打乱实现随机取数
3、并行加载:num_workers 加速数据准备
4、内存优化:pin_memory 加速GPU训练
5、灵活性:collate_fn 处理各种数据格式
更多推荐
所有评论(0)