单精度和半精度混合训练
概述
混合精度训练方法,通过混合使用单精度和半精度数据格式,加速深度神经网络训练的过程,同时保持了单精度训练所能达到的网络精度。混合精度训练能够加速计算过程,同时减少内存使用和存取,并使得在特定的硬件上可以训练更大的模型或batch size。
对于FP16的算子,若给定的数据类型是FP32,MindSpore框架的后端会进行降精度处理。用户可以开启INFO日志,并通过搜索关键字“Reduce precision”查看降精度处理的算子。
计算流程
MindSpore混合精度典型的计算流程如下图所示:

  1. 参数以FP32存储;
  2. 正向计算过程中,遇到FP16算子,需要把算子输入和参数从FP32 cast成FP16进行计算;
  3. 将Loss层设置为FP32进行计算;
  4. 反向计算过程中,首先乘以Loss Scale值,避免反向梯度过小而产生下溢;
  5. FP16参数参与梯度计算,其结果将被cast回FP32;
  6. 除以Loss scale值,还原被放大的梯度;
  7. 判断梯度是否存在溢出,如果溢出则跳过更新,否则优化器以FP32对原始参数进行更新。
    本文通过自动混合精度和手动混合精度的样例来讲解计算流程。
    自动混合精度
    使用自动混合精度,需要调用相应的接口,将待训练网络和优化器作为输入传进去;该接口会将整张网络的算子转换成FP16算子(除BatchNorm算子和Loss涉及到的算子外)。可以使用amp接口和Model接口两种方式实现混合精度。
    使用amp接口具体的实现步骤为:
  8. 引入MindSpore的混合精度的接口amp;
  9. 定义网络:该步骤和普通的网络定义没有区别(无需手动配置某个算子的精度);
  10. 使用amp.build_train_network接口封装网络模型、优化器和损失函数,设置level参数,参考https://www.mindspore.cn/doc/api_python/zh-CN/r1.1/mindspore/mindspore.html#mindspore.build_train_network。在该步骤中,MindSpore会将有需要的算子自动进行类型转换。
    代码样例如下:
    import numpy as np

import mindspore.nn as nn
from mindspore import Tensor, context
import mindspore.ops as ops
from mindspore.nn import Momentum

The interface of Auto_mixed precision

from mindspore import amp

context.set_context(mode=context.GRAPH_MODE)
context.set_context(device_target=“Ascend”)

Define network

class Net(nn.Cell):
def init(self, input_channel, out_channel):
super(Net, self).init()
self.dense = nn.Dense(input_channel, out_channel)
self.relu = ops.ReLU()

def construct(self, x):x = self.dense(x)x = self.relu(x)return x

Initialize network

net = Net(512, 128)

Define training data, label

predict = Tensor(np.ones([64, 512]).astype(np.float32) * 0.01)
label = Tensor(np.zeros([64, 128]).astype(np.float32))

Define Loss and Optimizer

loss = nn.SoftmaxCrossEntropyWithLogits()
optimizer = Momentum(params=net.trainable_params(), learning_rate=0.1, momentum=0.9)
train_network = amp.build_train_network(net, optimizer, loss, level=“O3”, loss_scale_manager=None)

Run training

output = train_network(predict, label)
使用Model接口具体的实现步骤为:

  1. 引入MindSpore的模型训练接口Model;
  2. 定义网络:该步骤和普通的网络定义没有区别(无需手动配置某个算子的精度);
  3. 创建数据集。该步骤可参考 https://www.mindspore.cn/tutorial/training/zh-CN/r1.1/use/data_preparation.html;
  4. 使用Model接口封装网络模型、优化器和损失函数,设置amp_level参数,参考https://www.mindspore.cn/doc/api_python/zh-CN/r1.1/mindspore/mindspore.html#mindspore.Model。在该步骤中,MindSpore会将有需要的算子自动进行类型转换。
    代码样例如下:
    import numpy as np
    import mindspore.nn as nn
    from mindspore.nn.metrics import Accuracy
    from mindspore import context, Model
    from mindspore.common.initializer import Normal
    from src.dataset import create_dataset

context.set_context(mode=context.GRAPH_MODE)
context.set_context(device_target=“Ascend”)

Define network

class LeNet5(nn.Cell):
“”"
Lenet network

Args:num_class (int): Number of classes. Default: 10.num_channel (int): Number of channels. Default: 1.Returns:Tensor, output tensor
Examples:>>> LeNet(num_class=10)"""
def __init__(self, num_class=10, num_channel=1):super(LeNet5, self).__init__()self.conv1 = nn.Conv2d(num_channel, 6, 5, pad_mode='valid')self.conv2 = nn.Conv2d(6, 16, 5, pad_mode='valid')self.fc1 = nn.Dense(16 * 5 * 5, 120, weight_init=Normal(0.02))self.fc2 = nn.Dense(120, 84, weight_init=Normal(0.02))self.fc3 = nn.Dense(84, num_class, weight_init=Normal(0.02))self.relu = nn.ReLU()self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)self.flatten = nn.Flatten()def construct(self, x):x = self.max_pool2d(self.relu(self.conv1(x)))x = self.max_pool2d(self.relu(self.conv2(x)))x = self.flatten(x)x = self.relu(self.fc1(x))x = self.relu(self.fc2(x))x = self.fc3(x)return x

create dataset

ds_train = create_dataset("/dataset/MNIST/train", 32)

Initialize network

network = LeNet5(10)

Define Loss and Optimizer

net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction=“mean”)
net_opt = nn.Momentum(network.trainable_params(),learning_rate=0.01, momentum=0.9)
model = Model(network, net_loss, net_opt, metrics={“Accuracy”: Accuracy()}, amp_level=“O3”)

Run training

model.train(epoch=10, train_dataset=ds_train)
手动混合精度
MindSpore还支持手动混合精度。假定在网络中只有一个Dense Layer要用FP32计算,其他Layer都用FP16计算。混合精度配置以Cell为粒度,Cell默认是FP32类型。
以下是一个手动混合精度的实现步骤:

  1. 定义网络:该步骤与自动混合精度中的步骤2类似;
  2. 配置混合精度:通过net.to_float(mstype.float16),把该Cell及其子Cell中所有的算子都配置成FP16;然后,将模型中的dense算子手动配置成FP32;
  3. 使用TrainOneStepCell封装网络模型和优化器。
    代码样例如下:
    import numpy as np

import mindspore.nn as nn
from mindspore import dtype as mstype
from mindspore import Tensor, context
import mindspore.ops as ops
from mindspore.nn import WithLossCell, TrainOneStepCell
from mindspore.nn import Momentum

context.set_context(mode=context.GRAPH_MODE)
context.set_context(device_target=“Ascend”)

Define network

class Net(nn.Cell):
def init(self, input_channel, out_channel):
super(Net, self).init()
self.dense = nn.Dense(input_channel, out_channel)
self.relu = ops.ReLU()

def construct(self, x):x = self.dense(x)x = self.relu(x)return x

Initialize network

net = Net(512, 128)

Set mixing precision

net.to_float(mstype.float16)
net.dense.to_float(mstype.float32)

Define training data, label

predict = Tensor(np.ones([64, 512]).astype(np.float32) * 0.01)
label = Tensor(np.zeros([64, 128]).astype(np.float32))

Define Loss and Optimizer

loss = nn.SoftmaxCrossEntropyWithLogits()
optimizer = Momentum(params=net.trainable_params(), learning_rate=0.1, momentum=0.9)
net_with_loss = WithLossCell(net, loss)
train_network = TrainOneStepCell(net_with_loss, optimizer)
train_network.set_train()

Run training

output = train_network(predict, label)
约束
使用混合精度时,只能由自动微分功能生成反向网络,不能由用户自定义生成反向网络,否则可能会导致MindSpore产生数据格式不匹配的异常信息。

单精度和半精度混合训练相关推荐

  1. 解决pytorch半精度amp训练nan问题

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 作者 | 可可哒@知乎(已授权) 来源 | https://zhua ...

  2. 浮点数双精度,单精度以及半精度知识总结

    最近工作中遇到一个16位半精度浮点数的问题,纠结了很久,特此研究了一下,总结在此: 1.单精度(32位)浮点数的结构: 名称  长度 比特 位置 符号位 Sign(S):  1bit     (b31 ...

  3. 如何使用 PyTorch 进行半精度训练

    原文链接(可以直接运行代码). 实验: 混合精度训练对比 (GTX 3090 VS TESLA V100-SXM2) 经常有小伙伴问我 TESLA V100 显存 16GB 比 GTX 3090 的 ...

  4. Pytorch自动混合精度(AMP)训练

    相关问题:解决pytorch半精度amp训练nan问题 - 知乎 pytorch模型训练之fp16.apm.多GPU模型.梯度检查点(gradient checkpointing)显存优化等 - 知乎 ...

  5. 在计算机领域,半精度、单精度、双精度的定义,以及多精度计算和混合精度计算的区别。

    在计算机系统的内存中,半精度是16bit,单精度是32bit,双精度是64bit. signed bit符号位,有效数字的符号位 Exponent 阶码或者叫指数,以10^Exponent表示 Sig ...

  6. python单精度和双精度的区别_单精度、双精度和半精度浮点格式之间的区别

    我们学过数学,都知道有理数和无理数,然后在有理数中有一类叫浮点数的数字,不知道大家对这些还有没有印象? 在软件编程的时候,我们也会用到浮点数,一种既包含小数又包含整数的数据类型. 下面就来讲讲关于浮点 ...

  7. 单精度、双精度和半精度浮点格式之间的区别

    源自公众号strongerHuang 单精度.双精度和半精度浮点格式之间的区别 IEEE 浮点算术标准是用来衡量计算机上以二进制所表示数字精度的通用约定.在双精度格式中,每个数字占用64位,单精度格式 ...

  8. 浮点运算/半精度,单精度,双精度/浮点和定点

    目录 1.实数数的表示 1.1定点数 1.2浮点数 2.精度说明 2.1半精度FP16 3.浮点运算加法和乘法 3.1加法 3.2乘法 1.实数数的表示 参考深入理解C语言-03-有符号数,定点数,浮 ...

  9. 单精度 半精度 双精度_单精度与双精度

    单精度 半精度 双精度 Here you will learn about Single Precision vs Double Precision. 在这里,您将了解单精度与双精度. When ta ...

最新文章

  1. Spring 事务用法示例与实现原理
  2. 关于浮点数在计算机内存中的存储
  3. lambda也是python_Python lambda介绍
  4. Linux下test命令使用
  5. Linux的性能故障的含义,Linux排查性能故障的方法
  6. Linux perf tools
  7. 华为鸿蒙os内测,华为“鸿蒙OS”内测信息曝光:界面与EMUI有6个明显不同
  8. 如何提高WEB程序的效率
  9. java 如何反编译文件
  10. 分立元器件——电感器
  11. 【5G系列】MAC (Medium Access Control)协议详解
  12. python 加密文本_Python文件或文本加密(4种方法)
  13. 群体智能优化算法之总结
  14. python数据分析项目经验简历-Python开发工程师岗位项目经历怎么写
  15. CentOS7 中查看进程端口号
  16. 计算机作业实验报告dw感想,微机实验报告
  17. 【历史上的今天】12 月 10 日:世界上第一位程序员诞生;Ada 语言发布;第一人称射击游戏的开拓者
  18. 像素是什么,一个像素有多大,像素和分辨率的关系
  19. linux中默认文件666和目录777的权限关系
  20. Opencv-python 色相饱和度(HLS)

热门文章

  1. 伦理困境:人工智能浪潮与“AI威胁论”之争
  2. 2022-2028年中国汽车工业行业研究及前瞻分析报告
  3. 2022-2028年中国钢材市场投资分析及前景预测报告(全卷)
  4. 2022-2028年中国塑料合成革的制造行业市场全景评估及发展趋势研究报告
  5. GCC 连接器、链接标准库 gcc -l、链接手动创建库(指定目录的库 gcc -L)
  6. Python 标准库之 subprocesss
  7. Python 标准库之 commands
  8. mysql engine innodb myisam 区别
  9. 芯片初创公司一亿融资可以烧多久
  10. 可视化反投射:坍塌尺寸的概率恢复:ICCV9论文解读