Task4:Pytorch实现模型训练与验证

一、前言

DL中,当构建了一个CNN模型,只是定义了一个Input、Output接口,无论是单张图片还是Batch多张图片,都需要取训练这个模型以达到目的得参数,训练一个模型一般有三个步骤:

  • 分别定义两个数据集trainsets和validsets,分别完成模型的训练与验证
  • 保存最优参数(权重、偏置等)
  • 记录trainsets和validsets的精度,便于调参。

通过以上的步骤,可以得到CNN模型的参数了,利用训练的参数可以对任意输入图像进行测试了。

二、模型训练与验证

首先明确几个概念:

  • 训练集(Trainsets):模型用于训练和调整模型参数
  • 验证集(Validsets):用来验证模型精度和调整模型超参数
  • 测试集(Testsets):验证模型的泛化能力

训练过程用到Trainsets+Validsets,而他两者是分开的,所以模型在验证集上面的精度一定程度上可以反映模型的泛化能力。为了保证训练参数对于验证集的有效性,应该保持两者的数据分布一致。
较好的模型应该能够随着训练Epoch的增加训练和验证误差同时降低,而在实际训练过程中常会发生两种常见泛化误差高的情况:

  • 欠拟合:以字符识别来说,训练样本被提取的特征较少,导致训练出来的模型不能很好在验证集上识别,甚至训练集里面的样本都不能有效识别。这一般是训练样本较少造成的,实际上我们在训练DL模型过程中是需要大量样本的。
  • 过拟合:随着模型复杂度和训练Epoch的增加,CNN模型在训练集上的误差降低,但是在测试集上的误差会降低后升高,如下图所示:
    在这里插入图片描述
    这是由于训练过程过于细致,以至于把样本的特有特征也当做识别特征一起训练了,所以在验证集上会表现得较差。

针对过拟合的情况,可以从两个方面来解决(1)模型训练方式,(2)数据集。
1、模型训练方式

  • 正则化(Regulation)
  • Dropout:随机失活
  • 提前停止训练

2、数据集
合理的从给定的数据集中拆分出训练集和验证集,将大大减低模型过拟合的可能,常用的验证集划分的方法有:

  • 留出法(Hold-out):按一定比例直接将训练集划分为两部分。训练集和验证集一般是7:3或8:2。
  • K折交叉验证(K-flod Cross Validation):将训练集划分为K份,将其中K-1份作为训练集,剩下一份作为验证集,循环K次训练。
  • 自助采样(BootStrap):通过有放回的采样方式得到新的训练集和验证集,这样每次的训练集和验证集都是有区别的。这对小数据量的训练较为适用。

Pytorch中模型训练和验证的一般代码为:

# 构造训练集
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_loss
		torch.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 /= 6
	optimizer.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 /= 6
				val_loss.append(loss.item())
	return np.mean(val_loss)

三、保存模型与调参

在Pytorch中模型的保存于加载实现为:

# 模型保存到 ./model.pt文件下
torch.save(model_object.state_dict(), 'model.pt')
#加载模型 ./model.pt
model.load_state_dict(torch.load(' model.pt'))

DL的调参实践性较强,只有通过不断地训练过程才能确定模型的优劣,通常情况下,首先考虑构建最简单的模型进行训练,跑通train、valid和 test的过程,然后从以下几个方面体高精度:

  • 数据扩充,提高泛化能力
  • 改变Loss function,dropout,BN方式等
  • 提高网络深度和复杂度。
  • 22
    点赞
  • 112
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
Pytorch中,验证集的使用是为了评估训练模型在未见过的数据上的性能。一般来说,我们需要从给定的数据集中划分出一个独立的验证集来进行验证。常用的验证集划分方法有三种:留出法(Hold-out)、K折交叉验证(K-fold Cross Validation)和自助采样(Bootstrap)。 留出法是将训练集按照一定的比例划分成两部分,一部分作为训练集,另一部分作为验证集。常见的划分比例是7:3或8:2。这种方法比较简单,但是可能会导致一部分数据无法用于训练。 K折交叉验证训练集划分为K份,其中K-1份作为训练集,剩下的一份作为验证集,然后循环K次,每次使用不同的验证集进行训练验证。这种方法可以更充分地利用数据,但是会增加计算量。 自助采样是通过有放回地采样方式得到新的训练集验证集,这样每次的训练集验证集都是有区别的。这种方法适用于小数据集,但是会引入一定的重复样本。 在验证的过程中,通常会使用验证函数来评估模型验证集上的性能。这个函数会对每个输入数据进行预测,计算损失,并返回平均损失。在Pytorch中,可以通过设置模型为eval模式和使用torch.no_grad()来关闭梯度计算来进行验证。 最后,为了保存训练得到的最佳模型,可以使用torch.save()函数将模型的参数保存到文件中。这样可以方便后续的模型加载和使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Task4:Pytorch实现模型训练验证](https://blog.csdn.net/m0_37833142/article/details/106447751)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值