本次的学习目标则与以下两点:
训练集(Train Set):模型用于训练和调整模型参数
测试集(Test Set):验证模型的泛化能力
验证集(Validation Set):用来验证模型精度和调整模型超参数
留出法(Hold-Out)
直接将训练集划分成两部分,新的训练集和验证集。
优点:简单
缺点:有可能导致模型在验证集上过拟合
应用:数据量比较大的情况
交叉验证法(Cross Validation,CV)
将训练集划分成K份,将其中的K-1份作为训练集,剩余的1份作为验证集,循环K训练。这种划分方式是所有的训练集都是验证集,最终模型验证精度是K份平均得到。
优点:验证集精度比较可靠,训练K次可以得到K个有多样性差异的模型
缺点:需要训练K次,不适合数据量很大的情况
自助采样法(BootStrap)
通过有放回的采样方式得到新的训练集和验证集,每次的训练集和验证集都是有区别的。
应用:数据量较小的情况
构建测试集和验证集
train_loader = torch.utils.data.DataLoader(
train_dataset,
batch_size=10,
shuffle=True,
num_workers=0,
)
val_loader = torch.utils.data.DataLoader(
val_dataset,
batch_size=10,
shuffle=False,
num_workers=0,
)
每轮进行训练和验证,并根据最优验证集精度保存模型
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(2):
train_loss = train(train_loader, model, criterion, optimizer, epoch)
val_loss = validate(val_loader, model, criterion)
val_label = [''.join(map(str, x)) for x in val_loader.dataset.img_label]
val_predict_label = predict(val_loader, model, 1)
val_predict_label = np.vstack([
val_predict_label[:, :11].argmax(1),
val_predict_label[:, 11:22].argmax(1),
val_predict_label[:, 22:33].argmax(1),
val_predict_label[:, 33:44].argmax(1),
val_predict_label[:, 44:55].argmax(1),
]).T
val_label_pred = []
for x in val_predict_label:
val_label_pred.append(''.join(map(str, x[x!=10])))
val_char_acc = np.mean(np.array(val_label_pred) == np.array(val_label))
print('Epoch: {0}, Train loss: {1} \t Val loss: {2}'.format(epoch, train_loss, val_loss))
print(val_char_acc)
# 记录下验证集精度
if val_loss < best_loss:
best_loss = val_loss
torch.save(model.state_dict(), 'D:\jiejing\model.pt')
每个Epoch的训练代码:
def train(train_loader, model, criterion, optimizer, epoch):
# 切换模型为训练模式
model.train()
train_loss = []
for i, (input, target) in enumerate(train_loader):
c0, c1, c2, c3, c4 = model(input)
target = target.long()
loss = criterion(c0, target[:, 0]) + \
criterion(c1, target[:, 1]) + \
criterion(c2, target[:, 2]) + \
criterion(c3, target[:, 3]) + \
criterion(c4, target[:, 4])
# loss /= 6
optimizer.zero_grad()
loss.backward()
optimizer.step()
if i % 100 == 0:
print('loss:',loss.item())
train_loss.append(loss.item())
return np.mean(train_loss)
每个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 = model(input)
target = target.long()
loss = criterion(c0, target[:, 0]) + \
criterion(c1, target[:, 1]) + \
criterion(c2, target[:, 2]) + \
criterion(c3, target[:, 3]) + \
criterion(c4, target[:, 4])
# loss /= 6
val_loss.append(loss.item())
return np.mean(val_loss)
结果:
Epoch: 0, Train loss: 3.3967208220163982 Val loss: 3.4839807691574096
acc:0.352
Epoch: 1, Train loss: 2.0795531896750132 Val loss: 3.0064294548034667
acc:0.4306
在Pytorch中模型的保存和加载非常简单,比较常见的做法是保存和加载模型参数:
torch.save(model_object.state_dict(), "model_save_0529.pt")
model.load_state_dict(torch.load("model_save_0529.pt"))