模型迁移训练
本节提供了一个简单的模型迁移样例,采用了最简单的自动迁移方法,帮助用户快速体验GPU模型脚本迁移到昇腾NPU上的流程。基于CNN模型识别手写数字的脚本,对在GPU上训练的该脚本代码进行修改,使其可以迁移到昇腾NPU上进行训练。
- 新建脚本train.py,写入以下原GPU脚本代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
# 引入模块 import time import torch import torch.nn as nn from torch.utils.data import Dataset, DataLoader import torchvision # 初始化运行device device = torch.device('cuda:0') # 定义模型网络 class CNN(nn.Module): def __init__(self): super(CNN, self).__init__() self.net = nn.Sequential( # 卷积层 nn.Conv2d(in_channels=1, out_channels=16, kernel_size=(3, 3), stride=(1, 1), padding=1), # 池化层 nn.MaxPool2d(kernel_size=2), # 卷积层 nn.Conv2d(16, 32, 3, 1, 1), # 池化层 nn.MaxPool2d(2), # 将多维输入一维化 nn.Flatten(), nn.Linear(32*7*7, 16), # 激活函数 nn.ReLU(), nn.Linear(16, 10) ) def forward(self, x): return self.net(x) # 下载数据集 train_data = torchvision.datasets.MNIST( root='mnist', download=True, train=True, transform=torchvision.transforms.ToTensor() ) # 定义训练相关参数 batch_size = 64 model = CNN().to(device) # 定义模型 train_dataloader = DataLoader(train_data, batch_size=batch_size) # 定义DataLoader loss_func = nn.CrossEntropyLoss().to(device) # 定义损失函数 optimizer = torch.optim.SGD(model.parameters(), lr=0.1) # 定义优化器 epochs = 10 # 设置循环次数 # 设置循环 for epoch in range(epochs): for imgs, labels in train_dataloader: start_time = time.time() # 记录训练开始时间 imgs = imgs.to(device) # 把img数据放到指定NPU上 labels = labels.to(device) # 把label数据放到指定NPU上 outputs = model(imgs) # 前向计算 loss = loss_func(outputs, labels) # 损失函数计算 optimizer.zero_grad() loss.backward() # 损失函数反向计算 optimizer.step() # 更新优化器 # 定义保存模型 torch.save({ 'epoch': 10, 'arch': CNN, 'state_dict': model.state_dict(), 'optimizer' : optimizer.state_dict(), },'checkpoint.pth.tar')
- 在train.py中添加以下加粗部分库代码。
- 若用户使用
Atlas 训练系列产品 ,则在迁移完成、训练开始之前,由于其架构特性需要,用户需要开启混合精度。 - 若用户使用
Atlas A2 训练系列产品 或Atlas A3 训练系列产品 ,则可以自行选择是否开启混合精度。
import time import torch ...... import torch_npu from torch_npu.npu import amp # 导入AMP模块 from torch_npu.contrib import transfer_to_npu # 使能自动迁移
- 若用户使用
- 使能AMP混合精度计算。若用户使用
Atlas A2 训练系列产品 或Atlas A3 训练系列产品 ,则可以选择跳过此步骤。在模型、优化器定义之后,定义AMP功能中的GradScaler。...... loss_func = nn.CrossEntropyLoss().to(device) # 定义损失函数 optimizer = torch.optim.SGD(model.parameters(), lr=0.1) # 定义优化器 scaler = amp.GradScaler() # 在模型、优化器定义之后,定义GradScaler epochs = 10
删除以下加粗部分的原GPU脚本代码。...... for epoch in range(epochs): for imgs, labels in train_dataloader: start_time = time.time() # 记录训练开始时间 imgs = imgs.to(device) # 把img数据放到指定NPU上 labels = labels.to(device) # 把label数据放到指定NPU上 outputs = model(imgs) # 前向计算 loss = loss_func(outputs, labels) # 损失函数计算 optimizer.zero_grad() loss.backward() # 损失函数反向计算 optimizer.step() # 更新优化器
添加以下加粗部分代码开启AMP。
...... for i in range(epochs): for imgs, labels in train_dataloader: imgs = imgs.to(device) labels = labels.to(device) with amp.autocast(): outputs = model(imgs) # 前向计算 loss = loss_func(outputs, labels) # 损失函数计算 optimizer.zero_grad() # 进行反向传播前后的loss缩放、参数更新 scaler.scale(loss).backward() # loss缩放并反向传播 scaler.step(optimizer) # 更新参数(自动unscaling) scaler.update() # 基于动态Loss Scale更新loss_scaling系数
- 执行命令启动训练脚本(命令脚本名称可根据实际修改)。
python3 train.py
训练结束后生成如下图权重文件,则说明迁移训练成功。