ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

优达学城《DeepLearning》2-2:迁移学习

2021-06-17 21:34:02  阅读:197  来源: 互联网

标签:loss target correct 优达 test DeepLearning data class 学城


目录

加载和预处理数据

转换数据

数据加载器和数据可视化

定义模型

最终分类器层

指定损失函数和优化器

训练

测试

可视化样本测试结果


大多数时候,你不会想自己训练一个完整的卷积网络。像ImageNet这样的大型数据集上的现代卷积网络训练需要在多个gpu上花费数周时间。

作为替代,大多数人使用预先训练好的网络作为固定的特征提取器,或者作为初始网络进行微调。

在本笔记本中,您将使用在ImageNet数据集上训练的VGGNet作为特征提取器。下面是VGGNet体系结构的示意图,有一系列卷积层和最大池层,最后是三个完全连接的层,它们对ImageNet数据库中的1000个类进行了分类。

VGGNet之所以伟大,是因为它简单且性能优异,在ImageNet的竞争中曾名列第二。这里的想法是我们保留所有的卷积层,但是用我们自己的分类器替换最后一个完全连接的层。通过这种方式,我们可以使用VGGNet作为图像的固定特征提取器,然后在此基础上轻松地训练一个简单的分类器。

  • 使用除最后一个全连接层以外的所有层作为固定的特征提取器。
  • 定义一个新的、最终的分类层,并将其应用到我们选择的任务中!

你可以从CS231n斯坦福课程笔记中阅读更多关于迁移学习的内容。

这里我们将使用VGGNet对花的图像进行分类。我们将像往常一样,从导入我们通常的数据集开始。然后检查是否可以在GPU上训练我们的模型。

加载和预处理数据

我们将使用PyTorch的ImageFolder类,这使得从目录加载数据非常容易。例如,训练图像都存储在如下目录路径中:

其中,在本例中,training的根文件夹是flower_photos/train/,类别名是花类型的名称。

转换数据

当我们进行迁移学习时,我们必须将输入数据改造成预先训练好的模型所期望的形状。VGG16需要224维度的正方形图像作为输入,因此,我们调整每个花图像的大小以适应这个模型。

数据加载器和数据可视化

定义模型

为了定义一个训练模型,我们将遵循以下步骤:

  • 1.加载一个预先训练过的VGG16模型
  • 2.冻结所有参数,使网络充当一个固定的特征提取器
  • 3.删除最后一层
  • 4.用我们自己的线性分类器替换最后一层

冻结仅仅意味着预训练模型中的参数在训练过程中不会改变。

打印结果:

Downloading: "https://download.pytorch.org/models/vgg16-397923af.pth" to C:\Users\yinm/.cache\torch\hub\checkpoints\vgg16-397923af.pth
100%|██████████| 528M/528M [03:56<00:00, 2.34MB/s]
VGG(
  (features): Sequential(
    (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): ReLU(inplace=True)
    (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (3): ReLU(inplace=True)
    (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (6): ReLU(inplace=True)
    (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (8): ReLU(inplace=True)
    (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (11): ReLU(inplace=True)
    (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (13): ReLU(inplace=True)
    (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (15): ReLU(inplace=True)
    (16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (18): ReLU(inplace=True)
    (19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (20): ReLU(inplace=True)
    (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (22): ReLU(inplace=True)
    (23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (25): ReLU(inplace=True)
    (26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (27): ReLU(inplace=True)
    (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (29): ReLU(inplace=True)
    (30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
  (classifier): Sequential(
    (0): Linear(in_features=25088, out_features=4096, bias=True)
    (1): ReLU(inplace=True)
    (2): Dropout(p=0.5, inplace=False)
    (3): Linear(in_features=4096, out_features=4096, bias=True)
    (4): ReLU(inplace=True)
    (5): Dropout(p=0.5, inplace=False)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
  )
)

最终分类器层

您可以通过名称和(有时)编号访问预训练网络中的任何层,例如:vgg16.classifier[6]是名为 “classifier” 层组中的第六层。

TODO:将最后一个全连接的层替换为适当数量的类输出层。

指定损失函数和优化器

下面我们将使用交叉熵损失和小学习率的随机梯度下降。注意,优化器只接受可训练参数vgg.classifier.parameters()作为输入。

训练

在这里,我们将训练网络。

练习:到目前为止,我们已经为您提供了训练代码。在这里,我将给你一个更大的挑战,让你写代码来训练网络。当然,如果你需要帮助,你可以看到我的解决方案。

# number of epochs to train the model
n_epochs = 2

## TODO complete epoch and training batch loops
## These loops should update the classifier-weights of this model
## And track (and print out) the training loss over time

for epoch in range(1, n_epochs + 1):
    
    train_loss = 0.0 # 每n个batch的平均损失

    for batch_i, (data, target) in enumerate(train_loader):
        if train_on_gpu:
            data, target = data.cuda(), target.cuda()
        
        optimizer.zero_grad() #清除优化器中梯度

        output = vgg16(data) #前向传播

        loss = criterion(output, target)#计算损失

        loss.backward() #反向传播

        optimizer.step() # 参数更新
 
        train_loss += loss.item() #累计本批次损失

        if batch_i % 20 == 19:
            print('Epoch %d, Batch %d loss: %.16f' % (epoch, batch_i + 1, train_loss/20))
            train_loss = 0.0

结果:

测试

下面是每个flower类的测试精度。

# track test loss 
# over 5 flower classes
test_loss = 0.0
class_correct = list(0. for i in range(5))
class_total = list(0. for i in range(5))

vgg16.eval() # eval mode

# iterate over test data
for data, target in test_loader:
    # move tensors to GPU if CUDA is available
    if train_on_gpu:
        data, target = data.cuda(), target.cuda()
    # forward pass: compute predicted outputs by passing inputs to the model
    output = vgg16(data)
    # calculate the batch loss
    loss = criterion(output, target)
    # update  test loss 
    test_loss += loss.item()*data.size(0)
    # convert output probabilities to predicted class
    _, pred = torch.max(output, 1)    
    # compare predictions to true label
    correct_tensor = pred.eq(target.data.view_as(pred))
    correct = np.squeeze(correct_tensor.numpy()) if not train_on_gpu else np.squeeze(correct_tensor.cpu().numpy())
    # calculate test accuracy for each object class
    for i in range(batch_size):
        if i >= len(target): #防止最后一个batch不够20个。
            continue

        label = target.data[i]
        class_correct[label] += correct[i].item()
        class_total[label] += 1

# calculate avg test loss
test_loss = test_loss/len(test_loader.dataset)
print('Test Loss: {:.6f}\n'.format(test_loss))

for i in range(5):
    if class_total[i] > 0:
        print('Test Accuracy of %5s: %2d%% (%2d/%2d)' % (
            classes[i], 100 * class_correct[i] / class_total[i],
            np.sum(class_correct[i]), np.sum(class_total[i])))
    else:
        print('Test Accuracy of %5s: N/A (no training examples)' % (classes[i]))

print('\nTest Accuracy (Overall): %2d%% (%2d/%2d)' % (
    100. * np.sum(class_correct) / np.sum(class_total),
    np.sum(class_correct), np.sum(class_total)))

结果:

可视化样本测试结果

 

 

 

 

 

 

 

 

标签:loss,target,correct,优达,test,DeepLearning,data,class,学城
来源: https://blog.csdn.net/weixin_42118657/article/details/117981385

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有