本文主要是介绍Datawhale 零基础入门CV-Task04.模型训练与验证,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前言
一个成熟合格的深度学习训练流程至少具备以下功能
- 在训练集上进行训练,并在验证集上进行验证
- 模型可以保存最优的权重,并读取权重
- 记录下训练集和验证集的精度,便于调参
学习目标
- 理解验证集的作用,并使用训练集和验证集完成训练
- 学会使用
Pytorch
环境下的模型读取和加载,并了解调参流程
构造验证集
- 在机器学习模型的训练过程中,模型是非常容易过拟合的深度学习模型在不断的训练过程中训练误差会逐渐降低,但测试误差的走势则不一定。
- 在模型的训练过程中,模型只能利用训练数据来进行训练,模型并不能接触到测试集上的样本。因此模型如果将训练集学的过好,模型就会记住训练样本的细节,导致模型在训练集的泛化效果较差,这种现象称为过拟合。与过拟合相对应的是欠拟合,即模型在训练集上的拟合效果较差
- 如图所示:随着模型复杂度和模型训练轮数的增加,
CNN
模型在训练集上的误差会降低,但在测试集上的误差会逐渐降低,然后逐渐升高,而我们为了追求的是模型在测试集上的精度越高越好。导致模型过拟合的情况有很多种原因,其中最为常见的情况是模型复杂度太高,导致模型学习到了训练数据的方方面面,学习到了一些细节上的规律 - 解决问题最好的办法:构建一个与测试集尽可能分布一致的样本集(可称为验证集),在训练过程中不断验证模型在验证集上的精度,并以此控制模型的训练
- 在一般情况下,可以在本地划分出一个验证机出来,进行本地验证。训练集、验证集和测试集份别有不同的作用
1.训练集:模型用于训练和调整模型参数
2.验证集:用来验证模型精度和调整模型超参数
3.测试集:验证模型的泛化能力 - 因为训练集和验证集是分开的,所以模型在验证集上面的精度在一定程度上可以反映模型的泛化能力。在划分验证集的时候,需要注意验证集的分布应该与测试集尽量保持一致,不然模型在验证集上的精度就失去了指导意义
验证集的划分方式
- 留出法
Hold-Out
:直接将训练集划分成两部分,新的训练集和验证集。这种划分方式的优点最为简单直接;缺点是只得到了一份验证集,有可能导致模型在验证集上过拟合。留出法应用场景是数据量比较大的情况 - 交叉验证法
Cross Validation
:将训练集划分成K
份,将其中的K-1份
作为训练集,剩余的1份作为验证集,循环K
训练。这种划分方式是所有的训练集都是验证集,最终模型验证精度是K
份平均得到。这种方式的优点是验证集精度比较可靠。训练K
次可以得到K
个有多样性差异的模型;CV验证的缺点是需要训练K
次,不适合数据量很大的情况 - 自助采样法
BootStrap
:通过有放回的采样方式得到新的训练集和验证集,每次的训练集和验证集都是有区别的。这种划分方式一般适用于数据量较小的情况
模型训练与验证
- 构造训练集和验证集
- 每轮进行训练和验证,并根据最优验证集精度保存模型
train_loader = torch.utils.data.DataLoader(train_dataset,batch_size=10,shuffle=True,num_workers=10,
)val_loader = torch.utils.data.DataLoader(val_dataset,batch_size=10,shuffle=False,num_workers=10,
)model = SVHN_Model1()
criterion = nn.CrossEntropyLoss (size_average=False)
optimizer = torch.optim.Adam(model.parameters(), 0.001)
best_loss = 1000.0
for epoch in range(20):print('Epoch: ', epoch)train(train_loader, model, criterion, optimizer, epoch)val_loss = validate(val_loader, model, criterion)# 记录下验证集精度if val_loss < best_loss:best_loss = val_losstorch.save(model.state_dict(), './model.pt')
- 其中每个
Epoch
的训练代码如下:
def train(train_loader, model, criterion, optimizer, epoch):# 切换模型为训练模式model.train()for i, (input, target) in enumerate(train_loader):c0, c1, c2, c3, c4, c5 = model(data[0])loss = criterion(c0, data[1][:, 0]) + \criterion(c1, data[1][:, 1]) + \criterion(c2, data[1][:, 2]) + \criterion(c3, data[1][:, 3]) + \criterion(c4, data[1][:, 4]) + \criterion(c5, data[1][:, 5])loss /= 6optimizer.zero_grad()loss.backward()optimizer.step()
- 其中每个
Epoch
的验证代码如下:
def validate(val_loader, model, criterion):# 切换模型为预测模型model.eval()val_loss = []# 不记录模型梯度信息with torch.no_grad():for i, (input, target) in enumerate(val_loader):c0, c1, c2, c3, c4, c5 = model(data[0])loss = criterion(c0, data[1][:, 0]) + \criterion(c1, data[1][:, 1]) + \criterion(c2, data[1][:, 2]) + \criterion(c3, data[1][:, 3]) + \criterion(c4, data[1][:, 4]) + \criterion(c5, data[1][:, 5])loss /= 6val_loss.append(loss.item())return np.mean(val_loss)
模型保存与加载
- 在
Pytorch
种模型的保存和加载非常简单,比较常见的做法是保存和加载模型参数:
torch.save(model_object.state_dict(), 'model.pt')model.load_state_dict(torch.load(' model.pt'))
模型调参流程
- 深度学习原理少但实践性非常强,基本上很多的模型的验证只能通过训练来完成同时深度学习有众多的网络结构和超参数,因此需要反复尝试。训练深度学习模型需要GPU的硬件支持,也需要较多的训练时间。
小结
- 以深度学习模型的训练和验证为基础,讲解了验证集划分方法、模型训练与验证、模型保存和加载以及模型调参流程
- 需要注意的是模型复杂度是相对的,并不一定模型越复杂越好。
这篇关于Datawhale 零基础入门CV-Task04.模型训练与验证的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!