Datawhale 零基础入门CV赛事-Task4-模型训练与验证

本次的学习目标则与以下两点:

  • 理解验证集的作用,并使用训练集和验证集完成训练
  • 学会使用pytorch环境下的模型读取和加载,并理解调参的流程

样本集

训练集(Train Set):模型用于训练和调整模型参数
测试集(Test Set):验证模型的泛化能力
验证集(Validation Set):用来验证模型精度和调整模型超参数

验证集划分方法

留出法(Hold-Out)

直接将训练集划分成两部分,新的训练集和验证集。
优点:简单
缺点:有可能导致模型在验证集上过拟合
应用:数据量比较大的情况

交叉验证法(Cross Validation,CV)

将训练集划分成K份,将其中的K-1份作为训练集,剩余的1份作为验证集,循环K训练。这种划分方式是所有的训练集都是验证集,最终模型验证精度是K份平均得到。
优点:验证集精度比较可靠,训练K次可以得到K个有多样性差异的模型
缺点:需要训练K次,不适合数据量很大的情况

自助采样法(BootStrap)

通过有放回的采样方式得到新的训练集和验证集,每次的训练集和验证集都是有区别的。
应用:数据量较小的情况

使用Pytorch来完成CNN的训练和验证

构建测试集和验证集

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"))

 

你可能感兴趣的:(天池竞赛)