DAY24:模型训练ResNet152

ResNet

  1. 简介

    • 在当时的CNN中,都是较浅层的设计,较深层的训练未必会带来正面效果,容易训练不起来,带来更差的效果。在2015年提出的ResNet改变了CNN,其中residual learning可以让深层网路的训练更加容易,为CNN的带来深层网路的时代。
  2. Residual / Bottleneck Block

    • Block的设计(左图),在残差传入某一层之前,将其残差相加,这方法简单,又能使深层网路训练更为容易。ResNet设计出了Bottleneck Block(右图)将其降低了宽度,减少了运算量。

      图片来源:Deep Residual Learning for Image Recognition
  3. 短路连线(shortcuts)

  4. ResNet解决了甚麽问题?

    • ResNet的出现,解决了因为网路层数加深,而训练效果变差的问题。为何训练不起来,当网路层数越深,梯度爆炸或梯度消失的机率发生就越高,透过Batch normalization的方法,有缓解了这个问题。

    • 但由於上述状况仍无法解决此问题,论文提出了恒等映射(Identity mapping)的方法,增加网路层数,但训练的误差不会增加。详细可以参考这篇文章(传送门)


训练过程

  1. import的套件

    import torch
    import torch.nn as nn
    from torch.autograd import Variable
    from dataset import CaptchaData
    from torch.utils.data import DataLoader
    from torchvision.transforms import Compose, ToTensor,ColorJitter,RandomRotation,RandomAffine,Resize,Normalize,CenterCrop,RandomApply,RandomErasing
    import torchvision.models as models
    import time
    import copy
    
  2. dataset载入以及DataLoader

    train_dataset = CaptchaData('./mask_2/train',
                                 transform=transforms)
     train_data_loader = DataLoader(train_dataset, batch_size=batch_size, num_workers=0,
                                    shuffle=True, drop_last=True,pin_memory=True)
     test_data = CaptchaData('./mask_2/test',
                             transform=transforms_1)
     test_data_loader = DataLoader(test_data, batch_size=batch_size,
                                   num_workers=0, shuffle=True, drop_last=True,pin_memory=True)
    
  3. transforms的设置

    • train资料集设置有旋转、图像变换的transforms,而test我们则是设置只有转换成tensor及标准化。
    transform_set = [ RandomRotation(degrees=10,fill=(255, 255, 255)),
    RandomAffine(degrees=(-10,+10), translate=(0.2, 0.2), fillcolor=(255, 255, 255)),
    RandomAffine(degrees=(-10,+10),scale=(0.8, 0.8),fillcolor=(255, 255, 255)),
    RandomAffine(degrees=(-10,+10),shear=(0, 0, 0, 20),fillcolor=(255, 255, 255))]
    
    transforms = Compose([RandomApply(transform_set, p=0.7),
                           ToTensor(),
                            Normalize((0.5,), (0.5,))
                           ])
    
    transforms_1 = Compose([
                             ToTensor(),
                             Normalize((0.5,), (0.5,))
                             ])
    
  4. 计算准确度

    def calculat_acc(output, target):
     output, target = output.view(-1, 800), target.view(-1, 800)
     output = nn.functional.softmax(output, dim=1)
     output = torch.argmax(output, dim=1)
     target = torch.argmax(target, dim=1)
     output, target = output.view(-1, 1), target.view(-1, 1)
     correct_list = []
     for i, j in zip(target, output):
         if torch.equal(i, j):
             correct_list.append(1)
         else:
             correct_list.append(0)
     acc = sum(correct_list) / len(correct_list)
     return acc
    
  5. 预训练模型

    model = models.resnet152(num_classes=800)
    
  6. 储存best_model(test_score最高的模型)

    if epoch > min_epoch and acc_best <= acc:
        acc_best = acc
        best_model = copy.deepcopy(model)
    
  7. 完整的code

import torch
import torch.nn as nn
from torch.autograd import Variable
from dataset import CaptchaData
from torch.utils.data import DataLoader
from torchvision.transforms import Compose, ToTensor,ColorJitter,RandomRotation,RandomAffine,Resize,Normalize,CenterCrop,RandomApply,RandomErasing
import torchvision.models as models
import time
import copy
import matplotlib.pyplot as plt
batch_size = 32
base_lr = 0.01
max_epoch = 25
model_path = './resnet_mask2.pth'
restor = False



def calculat_acc(output, target):
    output, target = output.view(-1, 800), target.view(-1, 800)
    output = nn.functional.softmax(output, dim=1)
    output = torch.argmax(output, dim=1)
    target = torch.argmax(target, dim=1)
    output, target = output.view(-1, 1), target.view(-1, 1)
    correct_list = []
    for i, j in zip(target, output):
        if torch.equal(i, j):
            correct_list.append(1)
        else:
            correct_list.append(0)
    acc = sum(correct_list) / len(correct_list)
    return acc


def train():
    acc_best = 0
    best_model = None
    min_epoch = 1

    transform_set = [ RandomRotation(degrees=10,fill=(255, 255, 255)),
                      RandomAffine(degrees=(-10,+10), translate=(0.2, 0.2), fillcolor=(255, 255, 255)),
                      RandomAffine(degrees=(-10,+10),scale=(0.8, 0.8),fillcolor=(255, 255, 255)),
                      RandomAffine(degrees=(-10,+10),shear=(0, 0, 0, 20),fillcolor=(255, 255, 255))
]
    transforms = Compose([ ToTensor(),
                           RandomApply(transform_set, p=0.7),
                           Normalize((0.5,), (0.5,))
                          ])

    transforms_1 = Compose([
                            ToTensor(),
                            Normalize((0.5,), (0.5,))
                            ])

    train_dataset = CaptchaData(r'C:\Users\Frank\PycharmProjects\practice\mountain\清洗标签final\train_nomask',
                                transform=transforms)
    train_data_loader = DataLoader(train_dataset, batch_size=batch_size, num_workers=0,
                                   shuffle=True, drop_last=True,pin_memory=True)
    test_data = CaptchaData(r'C:\Users\Frank\PycharmProjects\practice\mountain\清洗标签final\test_nomask',
                            transform=transforms_1)
    test_data_loader = DataLoader(test_data, batch_size=batch_size,
                                  num_workers=0, shuffle=True, drop_last=True,pin_memory=True)
    print('load.........................')

    model = models.resnet152(num_classes=800)

    if torch.cuda.is_available():
        model.cuda()
    if restor:
        model.load_state_dict(torch.load(model_path))

    optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.8)
    scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max =10 , eta_min=0, last_epoch=-1, verbose=False)
    criterion = nn.CrossEntropyLoss()
    acc_history_train = []
    loss_history_train = []
    loss_history_test = []
    acc_history_test = []
    for epoch in range(max_epoch):
        start_ = time.time()

        loss_history = []
        acc_history = []
        model.train()

        for img, target in train_data_loader:
            img = Variable(img)
            target = Variable(target)
            if torch.cuda.is_available():
                img = img.cuda()
                target = target.cuda()
            target = torch.tensor(target, dtype=torch.long)
            output = model(img)

            loss = criterion(output, torch.max(target,1)[1])
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            acc = calculat_acc(output, target)
            acc_history.append(float(acc))
            loss_history.append(float(loss))
        scheduler.step()
        print('train_loss: {:.4}|train_acc: {:.4}'.format(
            torch.mean(torch.Tensor(loss_history)),
            torch.mean(torch.Tensor(acc_history)),
        ))
        acc_history_train.append((torch.mean(torch.Tensor(acc_history))).float())
        loss_history_train.append((torch.mean(torch.Tensor(loss_history))).float())
        loss_history = []
        acc_history = []
        model.eval()
        for img, target in test_data_loader:
            img = Variable(img)
            target = Variable(target)
            if torch.cuda.is_available():
                img = img.cuda()
                target = target.cuda()
            output = model(img)



            acc = calculat_acc(output, target)
            if epoch > min_epoch and acc_best <= acc:
                acc_best = acc
                best_model = copy.deepcopy(model)
            acc_history.append(float(acc))
            loss_history.append(float(loss))
        print('test_loss: {:.4}|test_acc: {:.4}'.format(
            torch.mean(torch.Tensor(loss_history)),
            torch.mean(torch.Tensor(acc_history)),
        ))
        acc_history_test.append((torch.mean(torch.Tensor(acc_history))).float())
        loss_history_test.append((torch.mean(torch.Tensor(loss_history))).float())
        print('epoch: {}|time: {:.4f}'.format(epoch, time.time() - start_))
        print("==============================================")
        torch.save(model.state_dict(), model_path)
        modelbest = best_model
        torch.save(modelbest, './resnet152_mask2.pth')
    # 画出acc学习曲线
    acc = acc_history_train
    epoches = range(1, len(acc) + 1)
    val_acc = acc_history_test
    plt.plot(epoches, acc, 'b', label='Training acc')
    plt.plot(epoches, val_acc, 'r', label='Validation acc')
    plt.title('Training and validation accuracy')
    plt.legend(loc='lower right')
    plt.grid()
    # 储存acc学习曲线
    plt.savefig('./acc_ResNet152.png')
    plt.show()

    # 画出loss学习曲线
    loss = loss_history_train
    val_loss = loss_history_test
    plt.plot(epoches, loss, 'b', label='Training loss')
    plt.plot(epoches, val_loss, 'r', label='Validation loss')
    plt.title('Training and validation loss')
    plt.legend(loc='upper right')
    plt.grid()
    # 储存loss学习曲线
    plt.savefig('./loss_ResNet152.png')
    plt.show()
if __name__ == "__main__":
    train()
    pass

模型训练结果

  1. 学习曲线

  2. 准确度

  3. 总结

    • 训练epoch:40 epoches
    • 训练总时数:3小时52分钟
    • callback采纪录最高test_score
    • test_score:86.16 %

今日小结

  • ResNet152对於我们要的准确度来说,还有一节落差。
  • 明日用DenseNet201去训练模型,看效果如何!

<<:  Day24 Create Image Gallery in React

>>:  Day 24 Password Attacks - 密码生成器 (Wordlists, CeWL, Crunch)

Day 4 - 资料绑定与模板语法

在 Vue 中,使用了基於HMTL的模板,这种模板与允许开发者声明式地将 DOM 绑定至底层 Vue...

〖WordPress主题〗ASTRA释出「AGENCY BUNDLE」头500名购买只要$149的超级优惠

ASTRA 这个热门的WordPress主题,付费版一共有3种方案+2种付费模式;最引以为傲的是☞一...

【心得】你今天种菜了吗? grid之路-grid的使用(2)

前言 昨天介绍了用grid-template-areas 来填格子 grid-template-ar...

【图解演算法教学】【Tree】二元树遍历 vs LeetCode 501 找众数

Youtube连结:https://bit.ly/3m1VQWV 在我们了解Binary Tree...

【Day 3】Git x GitHub x 版本控制的基础:吴宝春的成功秘诀

tags: 铁人赛 Git GitHub 版本控制 概述 碎念时间 为什麽我们需要 版本控制 ? 每...