当前位置:   article > 正文

【PyTorch][chapter 25][李宏毅深度学习][Transfer Learning-1]

【PyTorch][chapter 25][李宏毅深度学习][Transfer Learning-1]

前言:

       迁移学习是一种机器学习的方法,指的是一个预训练的模型被重新用在另一个任务中。

比如已经有个模型A 实现了猫狗分类

    

模型B 要实现大象和老虎分类,可以利用训练好的模型A 的一些参数特征,简化当前的训练

过程.

目录:

  1.    简介
  2.    Model Fine-Tuning (模型微调)
  3.    multitask learning( 多任务学习)
  4.    Python 例子

一 简介

        Transfer Learning 是一种常用的深度学习方案.

如下图:

           Task A:  通过语音识别台语.   但是 Task Data 中数据集非常少,很难训练出好的模型A,

           TaskB:  通过语音识别中英文.  我们很容易获得大量 Source Data,,我们是否可以先 训练一个模型B,实现中英文文语音识别. 然后再通过模型B 的参数去实现 Task A呢?

        同样在图像识别,文本分类依然存在同样的场景,需要做的Task A 的 Target Data 非常少,是否

可以利用相似的TaskB ,反过来优化任务A。


二  Model Fine-Tuning (模型微调)

     source Data : (x^s,y^s)已经打了标签,有大量的数据集

     Target Data:  (x^t,y^t) 未打标签,极少量的数据集,是Target Task.

      方案:

          1: 先通过 source Data 训练一个模型B,实现Task B

           2:再通过参数微调得到模型A,实现Task A

   下面介绍几个方案

2.1 Conservation Training 1(保守的微调)

 1: 利用source Data 训练出 model B

 2:   利用model B 的模型参数初始化 model A

3:   利用Task Data,  只训练几个epoch ,这样model B 和 model A 的参数尽可能的接近

 如上面实现猫狗分类 到  老虎和大象分类的例子

2.2 Conservation Training 2 (保守的微调)

 1: 利用source Data 训练出 model B

 2:   利用model B 的模型参数初始化 model A

3:    固定部分layer ,利用Target Data 训练剩下来的layer

 在语音识别中:    通常copy最后几层,   通过Target Data 训练接近输入层的layer

 在图像识别中:  通常copy 前面几层,  通过Target Data 训练接近输出层的layer


二  multitask learning( 多任务学习)

2.1 自动驾驶案例

     我们需要实时对图像进行车辆检测、车道线分割、景深估计等 。传统的方式使是基于单任务学习(Single-Task Learning,STL),即每个 任务 使用一个独立的模型。

      多任务使用一个模型实现多任务的预测。输入一张图片,通过不同的Decoder 实现不同任务的检测

2.2 语音识别案例

输入一段语音,使用相同的Encoder,不同的Decoder来训练多任务,实现中文,法文,日文,英文文字识别任务。

2.3 为什么要使用该方案

1: 实验效果
   很多实验效果证明多任务系统相对于当任务有更好的效果。
   比如语音识别例子中,语料库里面 法文标签的数据集非常少,我们可以通过Multi-Task Learning
   比单独训练 法文Model 具有更好的效果.
   每个任务可以选择性的利用其他任务中学习到的隐藏特征,提高自身能力;

2  训练效率更高
  多个任务使用一个共享的Encoder,更少的GPU显存占用,更快的处理性能;
 
3   泛化性更强
     在多个任务的数据集上训练,任务之间有一定相关性,相当于一种隐式的数据增强,可以提高模型泛化能力;

4  防止模型过拟合
    兼顾多个任务,一定程度上避免了模型过拟合到单个任务的训练集;

5  更好的特征表达
   共享的Encoder输出满足多任务的,相比STL可以获得更好的特征表达;


三 Progressive Neural Networks(增量学习)

Step 1:构建 Model 1,   通过task1的数据集训练 Model 1

Step 2:固定Model 1,构建Model 2,把task2 的数据集输入Model 1,其每一层的输出添加进Model2 的输入层, 训练Model 2

                

Step 3: 固定Model1,Model2, 构建Model 3,然后同上一样的方法连接到第三个神经网络中,

训练Model 3

下面给出两个简单的例子

  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Sun Apr 7 14:53:19 2024
  4. @author: chengxf2
  5. """
  6. from torch import nn
  7. from torchvision import models
  8. import torchvision
  9. import torch.optim as optim
  10. from torch.optim import lr_scheduler
  11. import torch
  12. device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
  13. def net():
  14. # 加载预训练模型
  15. model = models.vgg16(pretrained=True)
  16. print(model)
  17. for parameter in model.parameters():
  18. # 冻结了所有层(参数不会更新)
  19. parameter.requires_grad = False
  20. #查看model.parameters()的参数
  21. model.classifier[6] = nn.Linear(in_features=4096, out_features=2, bias=True)
  22. for name,param in model.named_parameters():
  23. print(name, param.requires_grad)
  24. return model
  25. def netFin():
  26. # 加载预训练模型
  27. model_conv = torchvision.models.resnet18(pretrained=True)
  28. for param in model_conv.parameters():
  29. param.requires_grad = False
  30. # Parameters of newly constructed modules have requires_grad=True by default
  31. num_ftrs = model_conv.fc.in_features
  32. model_conv.fc = nn.Linear(num_ftrs, 2)
  33. for name,param in model_conv.named_parameters():
  34. print(name, param.requires_grad)
  35. model_conv = model_conv.to(device)
  36. criterion = nn.CrossEntropyLoss()
  37. # Observe that only parameters of final layer are being optimized as
  38. # opposed to before.
  39. optimizer_conv = optim.SGD(model_conv.fc.parameters(), lr=0.001, momentum=0.9)
  40. # Decay LR by a factor of 0.1 every 7 epochs
  41. exp_lr_scheduler = lr_scheduler.StepLR(optimizer_conv, step_size=7, gamma=0.1)
  42. netFin()


四  Python 例子

利用resnet18 来进行昆虫分类,默认是实现1000种分类。

现在把全连接层改成二分类:分类蚂蚁和蜜蜂,只要训练1-2轮

精确度可以达到90%以上。

项目分为三个部分

1: data.py 加载数据集

2: train.py  训练模型

3: model.py 模型部分

数据集

 https://download.csdn.net/download/weixin_46233323/12182815

1: train.py 

  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Sun Apr 7 15:28:16 2024
  4. @author: chengxf2
  5. """
  6. import torch
  7. from model import netFin
  8. import time
  9. from tempfile import TemporaryDirectory
  10. import os
  11. from data import create_dataset
  12. import matplotlib.pyplot as plt
  13. from data import imshow
  14. device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
  15. def visualize_model(model, dataloaders,class_names, num_images,device):
  16. was_training = model.training
  17. model.eval()
  18. images_so_far = 0
  19. fig = plt.figure()
  20. with torch.no_grad():
  21. for i, (inputs, labels) in enumerate(dataloaders['val']):
  22. inputs = inputs.to(device)
  23. labels = labels.to(device)
  24. outputs = model(inputs)
  25. _, preds = torch.max(outputs, 1)
  26. for j in range(inputs.size()[0]):
  27. images_so_far += 1
  28. ax = plt.subplot(num_images//2, 2, images_so_far)
  29. ax.axis('off')
  30. ax.set_title(f'predicted: {class_names[preds[j]]}')
  31. imshow(inputs.cpu().data[j])
  32. if images_so_far == num_images:
  33. model.train(mode=was_training)
  34. return
  35. model.train(mode=was_training)
  36. def train_model(model, criterion, optimizer, scheduler, num_epochs,dataloaders,dataset_sizes):
  37. # Create a temporary directory to save training checkpoints
  38. with TemporaryDirectory() as tempdir:
  39. best_model_params_path = os.path.join(tempdir, 'best_model_params.pt')
  40. torch.save(model.state_dict(), best_model_params_path)
  41. best_acc = 0.0
  42. print("\n --train---")
  43. start_time = time.time()
  44. for epoch in range(num_epochs):
  45. epoch_start_time = time.time()
  46. #print(f'Epoch {epoch}/{num_epochs - 1}')
  47. #print('-' * 10)
  48. # Each epoch has a training and validation phase
  49. for phase in ['train', 'val']:
  50. if phase == 'train':
  51. model.train() # Set model to training mode
  52. else:
  53. model.eval() # Set model to evaluate mode
  54. running_loss = 0.0
  55. running_corrects = 0
  56. # Iterate over data.
  57. for inputs, labels in dataloaders[phase]:
  58. inputs = inputs.to(device)
  59. labels = labels.to(device)
  60. # zero the parameter gradients
  61. optimizer.zero_grad()
  62. # forward
  63. # track history if only in train
  64. with torch.set_grad_enabled(phase == 'train'):
  65. outputs = model(inputs)
  66. _, preds = torch.max(outputs, 1)
  67. loss = criterion(outputs, labels)
  68. # backward + optimize only if in training phase
  69. if phase == 'train':
  70. loss.backward()
  71. optimizer.step()
  72. # statistics
  73. running_loss += loss.item() * inputs.size(0)
  74. running_corrects += torch.sum(preds == labels.data)
  75. if phase == 'train':
  76. scheduler.step()
  77. epoch_loss = running_loss / dataset_sizes[phase]
  78. epoch_acc = running_corrects.double() / dataset_sizes[phase]
  79. #print(f'{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}')
  80. # deep copy the model
  81. if phase == 'val' and epoch_acc > best_acc:
  82. best_acc = epoch_acc
  83. torch.save(model.state_dict(), best_model_params_path)
  84. print('End of epoch %d Time Taken: %d sec' % (epoch, time.time() - epoch_start_time),f'{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}')
  85. time_elapsed = time.time() - start_time
  86. print(f'Training complete in {time_elapsed // 60:.0f}m {time_elapsed % 60:.0f}s')
  87. print(f'Best val Acc: {best_acc:4f}')
  88. # load best model weights
  89. model.load_state_dict(torch.load(best_model_params_path))
  90. return model
  91. if __name__ == '__main__':
  92. num_epochs = 20
  93. num_images = 6
  94. dataloaders,dataset_sizes,class_names = create_dataset()
  95. model, criterion, optimizer, scheduler = netFin()
  96. train_model(model, criterion, optimizer, scheduler, num_epochs,dataloaders,dataset_sizes)
  97. visualize_model(model, dataloaders,class_names, num_images,device)

2: data.py

  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Sun Apr 7 15:37:38 2024
  4. @author: chengxf2
  5. """
  6. import os
  7. import torch
  8. from torchvision import datasets, models, transforms
  9. import numpy as np
  10. from PIL import Image
  11. import matplotlib.pyplot as plt
  12. import torchvision
  13. def visualize_model_predictions(model,data_transforms,img_path,device,class_names):
  14. was_training = model.training
  15. model.eval()
  16. img = Image.open(img_path)
  17. img = data_transforms['val'](img)
  18. img = img.unsqueeze(0)
  19. img = img.to(device)
  20. with torch.no_grad():
  21. outputs = model(img)
  22. _, preds = torch.max(outputs, 1)
  23. ax = plt.subplot(2,2,1)
  24. ax.axis('off')
  25. ax.set_title(f'Predicted: {class_names[preds[0]]}')
  26. imshow(img.cpu().data[0])
  27. model.train(mode=was_training)
  28. def imshow(inp, title=None):
  29. """Display image for Tensor."""
  30. #[channel=3, 228, 228*batch_size]
  31. inp = inp.numpy().transpose((1, 2, 0))
  32. #[228, 228*batch_size, channel=3]
  33. mean = np.array([0.485, 0.456, 0.406])
  34. std = np.array([0.229, 0.224, 0.225])
  35. inp = std * inp + mean
  36. inp = np.clip(inp, 0, 1)
  37. #(行, 列, channel):具有RGB值(0-1浮点数或0-255整数)的图像。
  38. plt.imshow(inp)
  39. if title is not None:
  40. plt.title(title)
  41. plt.pause(0.001) # pause a bit so that plots are updated
  42. def create_dataset():
  43. # Data augmentation and normalization for training
  44. # Just normalization for validation
  45. image_datasets={}
  46. dataloaders={}
  47. dataSize ={}
  48. data_transforms = {
  49. 'train': transforms.Compose([
  50. transforms.RandomResizedCrop(224),
  51. transforms.RandomHorizontalFlip(),
  52. transforms.ToTensor(),
  53. transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
  54. ]),
  55. 'val': transforms.Compose([
  56. transforms.Resize(256),
  57. transforms.CenterCrop(224),
  58. transforms.ToTensor(),
  59. transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
  60. ]),
  61. }
  62. data_dir = 'hymenoptera_data'
  63. for x in ['train', 'val']:
  64. image_datasets[x]= datasets.ImageFolder(os.path.join(data_dir, x),data_transforms[x])
  65. for x in ['train', 'val']:
  66. dataloaders[x] = torch.utils.data.DataLoader(image_datasets[x], batch_size=2,shuffle=True)
  67. for x in ['train', 'val']:
  68. dataSize[x]= len(image_datasets[x])
  69. #device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
  70. #print(type(dataloaders))
  71. class_names = image_datasets['train'].classes
  72. return dataloaders, dataSize,class_names
  73. '''
  74. # Get a batch of training data
  75. dataloaders, class_names= create_dataset(None)
  76. inputs, classes = next(iter(dataloaders['train']))
  77. #[batch, channel, width, hight]
  78. #print(inputs.shape)
  79. #torch.Size([4, 3, 224, 224])
  80. # Make a grid from batchdataloaders
  81. out = torchvision.utils.make_grid(inputs)
  82. imshow(out, title=[class_names[x] for x in classes])
  83. '''

3:model.py

  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Sun Apr 7 14:53:19 2024
  4. @author: chengxf2
  5. """
  6. from torch import nn
  7. from torchvision import models
  8. import torchvision
  9. import torch.optim as optim
  10. from torch.optim import lr_scheduler
  11. import torch
  12. from torchsummary import summary
  13. device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
  14. def net():
  15. # 加载预训练模型
  16. model = models.vgg16(pretrained=True)
  17. print(model)
  18. for parameter in model.parameters():
  19. # 冻结了所有层(参数不会更新)
  20. parameter.requires_grad = False
  21. #查看model.parameters()的参数
  22. model.classifier[6] = nn.Linear(in_features=4096, out_features=2, bias=True)
  23. for name,param in model.named_parameters():
  24. print(name, param.requires_grad)
  25. return model
  26. def netFin():
  27. # 加载预训练模型
  28. model_conv = torchvision.models.resnet18(pretrained=True)
  29. for param in model_conv.parameters():
  30. param.requires_grad = False
  31. # Parameters of newly constructed modules have requires_grad=True by default
  32. num_ftrs = model_conv.fc.in_features
  33. #打印出默认的网络结构
  34. summary(model_conv, (3, 512, 512)) # 输出网络结构
  35. #model_conv.fc = nn.Linear(num_ftrs, 2)
  36. '''
  37. # Debug info
  38. for name,param in model_conv.named_parameters():
  39. print(name, param.requires_grad)
  40. '''
  41. model_conv = model_conv.to(device)
  42. criterion = nn.CrossEntropyLoss()
  43. # Observe that only parameters of final layer are being optimized as
  44. # opposed to before.
  45. optimizer = optim.SGD(model_conv.fc.parameters(), lr=0.001, momentum=0.9)
  46. # Decay LR by a factor of 0.1 every 7 epochs
  47. exp_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=7, gamma=0.1)
  48. return model_conv, criterion, optimizer, exp_lr_scheduler


Multi-Task Learning 多任务学习 - 知乎

Transfer Learning for Computer Vision Tutorial — PyTorch Tutorials 2.2.1+cu121 documentation

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/392002
推荐阅读
相关标签
  

闽ICP备14008679号