学习目标
理解验证集,验证集是一个与测试集尽可能分布一致的样本集,在训练过程中不断验证模型在验证集上的精度,并以此控制模型的训练。
学会使用Pytorch环境下的模型读取和加载,并了解调参流程
理解训练集、验证集和测试集。
模型训练与验证
使用Pytorch来完成CNN的训练和验证过程,CNN网络结构与之前的章节中保持一致。我们需要完成的逻辑结构如下:
构造训练集和验证集;
每轮进行训练和验证,并根据最优验证集精度保存模型。
import torch.nn as nn
from torch.utils.data.dataset import Dataset
# class SVHN_Model1(nn.Module):
# def __init__(self):
# super(SVHN_Model1, self).__init__()
# model_conv = models.resnet18(pretrained=True)
# model_conv.avgpool = nn.AdaptiveAvgPool2d(1)
# model_conv = nn.Sequential(*list(model_conv.children())[:-1])
# self.cnn = model_conv
# self.fc1 = nn.Linear(512, 11)
# self.fc2 = nn.Linear(512, 11)
# self.fc3 = nn.Linear(512, 11)
# self.fc4 = nn.Linear(512, 11)
# self.fc5 = nn.Linear(512, 11)
# def forward(self, img):
# feat = self.cnn(img)
# # print(feat.shape)
# feat = feat.view(feat.shape[0], -1)
# c1 = self.fc1(feat)
# c2 = self.fc2(feat)
# c3 = self.fc3(feat)
# c4 = self.fc4(feat)
# c5 = self.fc5(feat)
# return c1, c2, c3, c4, c5
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')
训练模型中的训练代码:
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()
预测模型中的验证代码:
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)
模型的保存和加载:
torch.save(model_object.state_dict(), 'model.pt')
model.load_state_dict(torch.load(' model.pt'))
标题模型调参流程
深度学习原理少但实践性非常强,基本上很多的模型的验证只能通过训练来完成。同时深度学习有众多的网络结构和超参数,因此需要反复尝试。训练深度学习模型需要GPU的硬件支持,也需要较多的训练时间,如何有效的训练深度学习模型逐渐成为了一门学问。
深度学习有众多的训练技巧,比较推荐的阅读链接有:
http://lamda.nju.edu.cn/weixs/project/CNNTricks/CNNTricks.html
http://karpathy.github.io/2019/04/25/recipe/
学习小结
以深度学习模型的训练和验证为基础,讲解了验证集划分方法、模型训练与验证、模型保存和加载以及模型调参流程。
需要注意的是模型复杂度是相对的,并不一定模型越复杂越好。在有限设备和有限时间下,需要选择能够快速迭代训练的模型。
特此感谢 阿水(天池数据大神,CV爱好者。 公众号:Coggle数据科学 知乎:https://www.zhihu.com/people/finlayliu)。