-
【功能模块】今天写PPO算法,使用随即策略梯度,然后在进行计算策略网络的梯度时候出现了错误。【操作步骤&问题现象】1、神经网络输出放入到Categorical中使用sample函数进行采样,然后获得index再放入distribution中,在进行计算loss计算梯度报错。【截图信息】【日志信息】(可选,上传日志内容或者附件)Traceback (most recent call last): File "E:/ProgramData/Documents/Pycharm Documents/MindSpore_Learning/MindSpore_Learning/PPO/Main.py", line 42, in <module> Main() File "E:/ProgramData/Documents/Pycharm Documents/MindSpore_Learning/MindSpore_Learning/PPO/Main.py", line 25, in Main agent.train() File "E:\ProgramData\Documents\Pycharm Documents\MindSpore_Learning\MindSpore_Learning\PPO\PPO.py", line 100, in train actor_grad = self.Actor_train(state,advantages_reward,self.epsilon) File "D:\ProgramData\Anaconda3\envs\MindSpore\lib\site-packages\mindspore\nn\cell.py", line 404, in __call__ out = self.compile_and_run(*inputs) File "D:\ProgramData\Anaconda3\envs\MindSpore\lib\site-packages\mindspore\nn\cell.py", line 682, in compile_and_run self.compile(*inputs) File "D:\ProgramData\Anaconda3\envs\MindSpore\lib\site-packages\mindspore\nn\cell.py", line 669, in compile _cell_graph_executor.compile(self, *inputs, phase=self.phase, auto_parallel_mode=self._auto_parallel_mode) File "D:\ProgramData\Anaconda3\envs\MindSpore\lib\site-packages\mindspore\common\api.py", line 548, in compile result = self._graph_executor.compile(obj, args_list, phase, use_vm, self.queue_name)RuntimeError: mindspore\ccsrc\pipeline\jit\static_analysis\prim.cc:954 GetEvaluatedValueForBuiltinTypeAttrOrMethod] Not supported to get attribute item name:'log_prob' of a type[Func]The function call stack (See file 'E:\ProgramData\Documents\Pycharm Documents\MindSpore_Learning\MindSpore_Learning\PPO\rank_0\om/analyze_fail.dat' for more details):# 0 In file E:\ProgramData\Documents\Pycharm Documents\MindSpore_Learning\MindSpore_Learning\PPO\MyTrainOneStepCell.py(59) return self.grad(self.loss_network, weights)(state, advantage_reward, epsilon) ^# 1 In file E:\ProgramData\Documents\Pycharm Documents\MindSpore_Learning\MindSpore_Learning\PPO\MyTrainOneStepCell.py(15) def construct(self, state, advantage_reward, epsilon): ^# 2 In file E:\ProgramData\Documents\Pycharm Documents\MindSpore_Learning\MindSpore_Learning\PPO\MyTrainOneStepCell.py(18) log_probs = ops.exp(cat.log_prob(index)) ^WARNING: Logging before InitGoogleLogging() is written to STDERR[WARNING] CORE(1636,1,?):2021-11-1 17:36:44 [mindspore\core\ir\anf_extends.cc:65] fullname_with_scope] Input 0 of cnode is not a value node, its type is CNode.[EXCEPTION] ANALYZER(1636,1,?):2021-11-1 17:36:46 [mindspore\ccsrc\pipeline\jit\static_analysis\prim.cc:954] GetEvaluatedValueForBuiltinTypeAttrOrMethod] Not supported to get attribute item name:'log_prob' of a type[Func]Process finished with exit code 1
-
【截图信息】color_mapping = {0: sns.xkcd_rgb['bright purple'],1: sns.xkcd_rgb['pale red'], 2: sns.xkcd_rgb['ochre']}colors = list(map(lambda x: color_mapping[x], Y))plt.scatter(pca_data[:, 0].asnumpy(), pca_data[:, 1].asnumpy(), c=colors)plt.show()我是在本地跑的,matplotlib和seaborn都是安装的最新的版本画图的时候一片空白而且卡死【日志信息】报错信息 进程已结束,退出代码为 -1073741819 (0xC0000005)
-
图像分割功能可以定位图片中的物体,识别物体的边界轮廓 大致是:     # 代码标注 训练模型: ```C++ if __name__ == '__main__': rank = 0 device_num = 1 # 调用接口进行数据处理 dataset = create_new_dataset(image_dir=config.coco_root, batch_size=config.batch_size, is_training=True, num_parallel_workers=8) dataset_size = dataset.get_dataset_size() print("total images num: ", dataset_size) # 图像总数 print("Create dataset done!") # 创建数据集完成! # 实例化网络 net = Mask_Rcnn_Resnet50(config=config) net = net.set_train() # 加载预训练模型 load_path = args_opt.pre_trained if load_path != "": param_dict = load_checkpoint(load_path) if config.pretrain_epoch_size == 0: for item in list(param_dict.keys()): if not (item.startswith('backbone') or item.startswith('rcnn_mask')): param_dict.pop(item) load_param_into_net(net, param_dict) # 设定损失函数、学习率、优化器 loss = LossNet() opt = Momentum(params=net.trainable_params(), learning_rate=0.0001, momentum=config.momentum, weight_decay=config.weight_decay, loss_scale=config.loss_scale) # 包装损失函数 net_with_loss = WithLossCell(net, loss) # 通过TrainOneStepCell自定义训练过程 net = TrainOneStepCell(net_with_loss, opt, sens=config.loss_scale) # 监控训练过程 time_cb = TimeMonitor(data_size=dataset_size) loss_cb = LossCallBack(rank_id=rank) cb = [time_cb, loss_cb] # 保存训练后的模型 if config.save_checkpoint: # 设置模型保存参数 ckptconfig = CheckpointConfig(save_checkpoint_steps=config.save_checkpoint_epochs * dataset_size, keep_checkpoint_max=config.keep_checkpoint_max) save_checkpoint_path = os.path.join(config.save_checkpoint_path, 'ckpt_' + str(rank) + '/') # 应用模型保存参数 ckpoint_cb = ModelCheckpoint(prefix='mask_rcnn', directory=save_checkpoint_path, config=ckptconfig) cb += [ckpoint_cb] # 进行训练 model = Model(net) model.train(config.epoch_size, dataset, callbacks=cb, dataset_sink_mode = False) ``` 输出: ```C++ total loss is: 1.3203125 total loss is: 0.88623046875 total loss is: 0.794921875 total loss is: 0.7216796875 total loss is: 0.67138671875 epoch time: 133629.138 ms, per step time: 26725.828 ms total loss is: 0.65625 total loss is: 0.646484375 total loss is: 0.5712890625 total loss is: 0.56982421875 total loss is: 0.5732421875 epoch time: 4547.359 ms, per step time: 909.472 ms total loss is: 0.5595703125 total loss is: 0.5166015625 total loss is: 0.8193359375 total loss is: 0.389892578125 total loss is: 0.44970703125 epoch time: 4639.649 ms, per step time: 927.930 ms total loss is: 0.360107421875 total loss is: 0.25830078125 total loss is: 0.30224609375 total loss is: 0.2236328125 total loss is: 0.1971435546875 epoch time: 4851.436 ms, per step time: 970.287 ms total loss is: 0.2021484375 total loss is: 0.36376953125 total loss is: 0.1787109375 total loss is: 0.56884765625 total loss is: 0.1864013671875 epoch time: 4904.663 ms, per step time: 980.933 ms total loss is: 0.184326171875 total loss is: 0.1395263671875 total loss is: 0.301025390625 total loss is: 0.1458740234375 total loss is: 0.36376953125 epoch time: 4838.346 ms, per step time: 967.669 ms total loss is: 0.1260986328125 total loss is: 0.08843994140625 total loss is: 0.10125732421875 total loss is: 0.09942626953125 total loss is: 0.162109375 epoch time: 5143.703 ms, per step time: 1028.741 ms ```
-
【功能模块】【操作步骤&问题现象】1、使用modelzoo下载的yolo5在gpu训练时,loss出现nan的情况,请问一下一般出现nan的原因是啥,如何排查?下图是训练的打印信息,里面有具体的参数【截图信息】【日志信息】(可选,上传日志内容或者附件)
kindredspirit
发表于2021-11-01 16:38:42
2021-11-01 16:38:42
最后回复
jinxinbesti
2022-03-23 20:44:16
1669 4 -
【功能模块】【操作步骤&问题现象】1、使用modelzoo下载的yolo5在gpu训练时,loss出现nan的情况,请问一下一般出现nan的原因是啥,如何排查?下图是训练的打印信息,里面有具体的参数【截图信息】【日志信息】(可选,上传日志内容或者附件)
-
de_dataset = de.ImageFolderDataset(data_dir, num_parallel_workers=num_parallel_workers, shuffle=shuffle, sampler=sampler, class_indexing=class_indexing, num_shards=group_size, shard_id=rank)上面是导入训练集的代码,class_indexing为Noneclass_indexing默认为None时,class_indexing (dict): A str-to-int mapping from folder name to index (default=None, the folder names will be sorted alphabetically and each class will be given a unique index starting from 0).想要获得类似{0: 'cat' , 1: 'dog'} 的class_index,查阅官网后使用 class_indexing = de_dataset.get_col_names() 获取class index 无法得到结果,请问有什么api可以调用得到?
-
训练集:   --------------------------------------------------  测试集:  -------------------------------------------------- 通过matplotlib可视化部分增强后的训练数据 ```python data = next(train_ds.create_dict_iterator()) images = data["image"] labels = data["label"] print("Tensor of image", images.shape) print("Labels:",labels) class_name = {0:"dogs",1:"wolves"} count = 1 # 输出测试图 plt.figure(figsize=(12,5)) for i in images: plt.subplot(3,8,count) plt.imshow(i.asnumpy().transpose(1,2,0)) plt.title(class_name[int(labels[count-1].asnumpy())]) plt.xticks([]) count += 1 plt.axis("off") plt.show() ```  定义visualize_mode函数,可视化模型预测 ```python def visualize_model(best_ckpt_path,val_ds): # 定义网络并加载参数,对验证集进行预测 net = resnet50(2) param_dict = load_checkpoint(best_ckpt_path) load_param_into_net(net,param_dict) loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True,reduction='mean') model = Model(net, loss,metrics={"Accuracy":nn.Accuracy()}) data = next(val_ds.create_dict_iterator()) images = data["image"].asnumpy() labels = data["label"].asnumpy() class_name = {0:"dogs",1:"wolves"} output = model.predict(Tensor(data['image'])) pred = np.argmax(output.asnumpy(),axis=1) # 可视化模型预测 for i in range(len(labels)): plt.subplot(2,2,i+1) color = 'blue' if pred[i] == labels[i] else 'red' plt.title('pre:{}'.format(class_name[pred[i]]), color=color) plt.imshow(images[i].transpose(1,2,0)) plt.axis('off') ``` 加载预训练的模型并重置最终的全连接层 ```python net = resnet50(2) num_epochs=20 # 加载预训练模型 param_dict = load_checkpoint('resnet50.ckpt') # 获取全连接层的名字 filter_list = [x.name for x in net.end_point.get_parameters()] # 删除预训练模型的全连接层 filter_checkpoint_parameter_by_list(param_dict, filter_list) # 给网络加载参数 load_param_into_net(net,param_dict) # 定义优化器和损失函数 opt = nn.Momentum(params=net.trainable_params(), learning_rate=0.001, momentum=0.9) loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True,reduction='mean') # 实例化模型 model = Model(net, loss,opt,metrics={"Accuracy":nn.Accuracy()}) ```  训练和评估 ```python # 加载训练和验证数据集 train_ds = create_dataset(train_data_path) val_ds = create_dataset(val_data_path) # 实例化回调类 eval_param_dict = {"model":model,"dataset":val_ds,"metrics_name":"Accuracy"} eval_cb = EvalCallBack(apply_eval, eval_param_dict,) # 模型训练 model.train(num_epochs,train_ds, callbacks=[eval_cb, TimeMonitor()], dataset_sink_mode=True) ```  [代码+图片](https://www.mindspore.cn/tutorials/zh-CN/r1.3/intermediate/image_and_video/transfer_learning.html "代码+图片")
-
### 问题描述 1. 训练条件: Linux Euler OS x86; 8 显卡; 物理 CPU 2; 每个物理 CPU 中的核数 26; 逻辑 CPU 104; MindSpore 1.2.0 TensorFlow 1.15.0  2. GPU 训练时长 MindSpore: 1:58 TensorFlow: 1:04 3. 优化目的 在相同条件下,使用 MindSpore 框架训练网络的时长 **小于或等于** 使用 TensorFlow 框架训练的时长 ### 问题分析 1. 该网络为了防止过拟合,会基于同一模型同时训练多个神经网络。通过阅读代码,发现无论是 CPU 训练还是 GPU 训练,在训练多个神经网络时,会给每一个神经网络绑定一个逻辑 CPU 进行训练。 2. 监控 GPU 训练过程,发现训练时,被绑定的逻辑 CPU 资源占用率一直为100%,据此推测是网络训练过程中的一些与 CPU 有关的操作耗资源太大,导致训练总时长增加。  3. 关闭代码中,每个网络绑定一个逻辑 CPU 进行训练的逻辑。再监控 GPU 训练过程,发现训练时,逻辑 CPU 资源占用率为250%左右。  4. 对比 TensorFlow,保留/注释每个网络绑定一个逻辑 CPU 进行训练的部分代码,监控 GPU 训练过程,发现绑定一个逻辑 CPU 时,被绑定的逻辑 CPU 资源占用率为100%;而当不绑定逻辑 CPU 时,逻辑 CPU 资源占用率为150%左右。  --  5. 对比 TensorFlow,MindSpore 框架训练该网络所需要的 CPU 资源更多。据此可以断定,使用 MindSpore 框架训练该网络的性能瓶颈在 CPU 相关的操作部分。 6. 由于在 GPU 上训练,CPU 相关的操作只涉及样本数据的处理、数据处理完后拷贝到 GPU 这些。咨询 MindSpore 框架负责数据处理部分的专家,了解到原因为: 1. 涉及 CPU 的主要操作为,在每一个 step,一个 batch 的数据输入一层网络,计算完成后,都需要做一次类型转换,才能够输入到下一层网络。所以这里存在 把数据从 GPU 拷贝至 CPU -> 数据类型转换 -> 把数据从 CPU 拷贝回 GPU 这三步(不一定准确,具体需要再看代码实现)。 2. 数据处理(数据同步和拷贝),用了 MindDataset 和 Batch 两个模块。在不额外设置线程数的情况下,默认会给每个模块分别分配2个线程(主线程做简单的同步,子线程并行地进行数据拷贝)。另外再加上一个 ctrl+c 线程,总共会分配5个线程。 3. 根据一个逻辑 CPU 处理两个线程的基本原则,不绑定逻辑 CPU 的情况下,5个线程就会占用约2.5个逻辑 CPU(这与之前的测试数据相吻合)。而在绑定逻辑 CPU 的情况下,单个逻辑 CPU 启用5个线程处理数据,会导致线程竞争,这可能是造成训练耗时比较长的主要原因。 ### 优化方案 1. 弃用 MindDataset 和 Batch 两个模块,改用 GeneratorDataset 模块(2个线程)对数据进行预处理以及负责数据的拷贝,这样从 线程数:2(MindDataset) + 2(Batch) + 1(ctrl + c) = 5 CPU数:5 / 2 = 2.5 降为 线程数:2(GeneratorDataset) + 1(ctrl + c)= 3 CPU数:3 / 2 = 1.5 2. 减少了所需要的 CPU 数,减少了线程数以降低线程竞争现象。最终达到的效果为,进行 GPU 训练时,GPU 训练性能基本与 TensorFlow 持平: MindSpore: 0:57 TensorFlow: 1:04 ### 反思 1. 同样是数据同步和拷贝,GeneratorDataset 模块只需要2个线程, 而MindDataset 和 Batch 两个模块需要4个线程。也就是说,2个线程可以做完的事情,分配了4个线程去做。这是不是 CPU 资源分配的不合理呢? 在本次网络训练中,数据样本量较小(7k行,3MB)。但尽管如此,在数据处理过程中,由于 Batch Size = N 是预先设置好的(超参数),每一个 step 中固定读取 N 条样本数据。实践证明,训练该网络,每一个 step 处理的这 N 条样本数据,3个线程也就是1.5个左右的逻辑 CPU 资源就够了。MindDataset 和 Batch 两个模块默认分配至少4个线程处理数据的设计,是值得讨论的。至少在这个网络对应的应用场景下,这两个模块的设计是可以优化的。 2. 其实,单看数据处理(数据同步和拷贝)这部分,GeneratorDataset 模块也需要2个线程,加上 ctrl + c 的1个线程,总共占用了3个线程也就是1.5个 CPU 资源,这是否合理呢? 3. 在不绑定逻辑 CPU 的情况下验证一下。发现使用MindDataset 和 Batch 两个模块时,虽然逻辑 CPU 占用率为250%左右,但是每个 CPU 的用户空间使用率并不高。进一步证实了 CPU 资源分配的不合理   如果是在 GPU 上进行训练,那么网络的计算在 GPU 上,数据处理在 CPU 上,没有问题。但是如果在 CPU 上进行训练,那么网络计算所需要的资源也需要 CPU 提供。光是数据处理就占了1个逻辑 CPU,整个网络的训练性能可以达到什么程度,很难想象。
-
### 问题描述 1. 训练条件: Linux Euler OS x86; 8 显卡; 物理 CPU 2; 每个物理 CPU 中的核数 26; 逻辑 CPU 104; MindSpore 1.2.0 TensorFlow 1.15.0  2. CPU 训练时长 MindSpore(不绑定核): 33:00 TensorFlow(不绑定核): 01:06 MindSpore(绑定一个逻辑 CPU):3小时左右 TensorFlow(绑定一个逻辑 CPU): 01:47 3. 优化目的 在相同条件下,使用 MindSpore 框架训练网络的时长 **小于或等于** 使用 TensorFlow 框架训练的时长 ### 问题分析 1. 不绑定核的情况下,MindSpore 训练会占用几乎所有56个逻辑 CPU。不知道它为什么会需要如此多的 CPU 资源。而绑定一个逻辑 CPU 的情况下,MindSpore 的训练慢到几乎跑不动  --  2. 在绑定一个逻辑 CPU 的情况下,通过 MindSpore 配套的网络分析工具 MindInsight 查看具体算子的执行时间信息:  3. 再用 TensorFlow 训练该神经网络,并通过 TensorFlow 的 profiler 工具分析具体算子的执行信息(耗时最长的5个算子):  4. 对比发现,TensorFlow 算子的执行时间都在 us 级别,而 MindSpore 耗时前5的算子的执行时间在 s 级别。相差一百万倍,这显然是不正常的。 5. 阅读 MindSpore 耗时前5的算子(AddN、Relu、Mul、MatMul、Abs)的源代码,发现它们都是通过第三方库 MKL-DNN 实现的。 6. MKL-DNN 全称 Math Kernel Library for Deep Neural Networks。该库是几年前,由 Intel 官方发布。主要优化了深度学习中一些常用算子在 CPU 上的性能表现。因此不太可能是这个库的实现出了问题。估计是应用这个库的方式出了问题。 7. 咨询负责这部分代码实现的同事,并查阅相关信息,发现在应用该库时,需要设置环境变量: export OMP_NUM_THREADS = num physical cores 8. 设置该环境变量为1(因为该网络绑定一个逻辑 CPU 训练,而一般一个物理 CPU 含有 N 个逻辑 CPU,因此理论上该环境变量应设为 1/N,向上取整为1),测试该神经网络的性能。发现时间性能从原来的3小时提升到了3分13秒,单步执行时间从19260ms左右提升到了6ms左右:  9. 查看算子执行时间的具体信息,发现原先5个耗时最长的算子都有大幅的性能提升,其中 AddN、Relu、Abs、Mul 均达到了 TensorFlow 的性能量级。MatMul 与 TensorFlow的相比仍有差距,但也有不小的提升。  10. 至此,该神经网络的 CPU 训练性能从原来的3小时提升到了3分13秒,训练时间减少了99.97%。但相比 TensorFlow 的 1分47秒,仍有不小差距。 11. 继续分析。从算子时间信息中可以发现,优化 MKL-DNN 后,ReluGrad(Relu 算子的反向) 在算子总耗时中占比最高,为76%。阅读该算子的源代码,发现该算子的实现有很大问题:  12. 该算子在实现多线程时,并没有使用统一的线程池,而是自起了最大线程数的线程。这会导致: 1. 同时起如此多的线程,会造成 CPU 资源浪费; 2. 除此之外,还有可能引起线程竞争; 3. 线程的启用和销毁,也会增加额外的开销; 这些都会大大增加 CPU 的负担,降低神经网络的时间性能。 13. 重构这部分代码,使用统一的线程池管理线程,并删除冗余操作。再测试该神经网络的性能。发现时间性能从原来的3分13秒提升到了1分52秒,单步执行时间从6ms左右提升到了3.5ms左右:  14. 查看算子执行时间的具体信息,发现包括 ReluGrad 在内的所有算子,执行时间都降到了 us 级别,与 TensorFlow 的基本相当。  ### Reference [Accelerating Deep Learning on CPU with Intel MKL-DNN](https://medium.com/apache-mxnet/accelerating-deep-learning-on-cpu-with-intel-mkl-dnn-a9b294fb0b9), Apache MXNet, May 11, 2018 [Maximize TensorFlow* Performance on CPU: Considerations and Recommendations for Inference Workloads](https://software.intel.com/content/www/us/en/develop/articles/maximize-tensorflow-performance-on-cpu-considerations-and-recommendations-for-inference.html), Intel Official [linux top命令查看内存及多核CPU的使用讲述](https://www.cnblogs.com/dragonsuc/p/5512797.html), 长风破浪, 2016-05-20
-
#### 一、整体介绍 从华为的官方文件[MindSpore](https://www.mindspore.cn/mindarmour/docs/zh-CN/r1.5/differential_privacy_design.html)中,我们了解到差分隐私优化器继承了MindSpore优化器的能力,并使用差分隐私的噪声机制对梯度加保护。目前,MindArmour提供三类差分隐私优化器:固定高斯优化器、自适应高斯优化器、自适应裁剪优化器,每类差分隐私优化器从不同的角度为SGD、Momentum等常规优化器增加差分隐私保护的能力。 - 固定高斯优化器,是一种非自适应高斯噪声的差分隐私优化器。其优势在于可以严格控制差分隐私预算ϵ,缺点是在模型训练过程中,每个Step添加的噪声量固定,若迭代次数过大,训练后期的噪声使得模型收敛困难,甚至导致性能大幅下跌,模型可用性差。 - 自适应高斯优化器,通过自适应调整标准差,来调整高斯分布噪声的大小,在模型训练初期,添加的噪声量较大,随着模型逐渐收敛,噪声量逐渐减小,噪声对于模型可用性的影响减小。自适应高斯噪声的缺点是不能严格控制差分隐私预算。 - 自适应裁剪优化器,是一种自适应调整调整裁剪粒度的差分隐私优化器,梯度裁剪是差分隐私训练的一个重要操作,自适应裁剪优化器能够自适应的控制梯度裁剪的比例在给定的范围波动,控制迭代训练过程中梯度裁剪的粒度。 [optimizer.py](https://gitee.com/mindspore/mindarmour/blob/r1.5/mindarmour/privacy/diff_privacy/optimizer/optimizer.py):这个文件实现了使用噪声生成机制在反向传播时添加噪声的根本逻辑。 #### 二、最优化问题 差分隐私添加的噪声是在训练过程中产生的最终参数,通过这样生成的噪声是黑盒的过程。不幸的是,一般来说,人们可能没有一个有用的、严密的表征这些参数对训练数据的依赖性。 在参数中加入过于保守的噪声,噪声是根据最坏情况分析选择的,这将破坏所学习模型的实用性。 因此,我们需要采用更复杂的方式在训练过程中控制数据的影响。所以需要考虑使用优化算法,optimizer模块中使用了三种优化算法。 SGD实际就是min-batch的实现,为最基础的优化算法,当今大部分优化算法都是以SGD为基础实现的。 Momentum引入了动量v,以指数衰减的形式累计历史梯度,以此来解决Hessian矩阵病态问题。 Adam算法可以看做是修正后的Momentum+RMSProp算法。 #### 三、代码分析 模块中重要的是create函数和construct函数。 create函数的作用是创建DP优化器。优化策略可以是 'sgd'、'momentum' 或“Adam”。 construct函数的作用是构建计算流程,即生成噪声、在梯度上添加噪声、更新模型参数,我们分别从源代码分析这两个函数。 ###### (1)create(self, policy) - **源代码** ```python def create(self, policy): policy_ = policy.lower() #随机梯度下降优化算法 if policy_ == 'sgd': dp_opt_class = self._get_dp_optimizer_class(nn.SGD) #动量最优化算法 elif policy_ == 'momentum': dp_opt_class = self._get_dp_optimizer_class(nn.Momentum) #adam最优化算法 elif policy_ == 'adam': dp_opt_class = self._get_dp_optimizer_class(nn.Adam) else: msg = "The policy must be in ('SGD', 'Momentum', 'Adam'), but got {}." \ .format(policy) LOGGER.error(TAG, msg) raise NameError(msg) return dp_opt_class ``` - **参数** | 参数名 | 描述 | | ------ | --------------------------------------- | | policy | 最优化的机制,可以是sgd、momentum和adam | - **返回值** | 参数名 | 描述 | | ------------ | --------------------------- | | dp_opt_class | Optimizer,一个带DP的优化器 | - **具体分析** create(self, policy)的作用是根据用户要求的优化算法,提供对应的优化器。可以是'sgd'、'momentum' 或“Adam”,优化的算法继承于MindSpore优化器的能力,所以这里不再赘述。 ###### (2)def construct(self, gradients) - **源代码** ```python def construct(self, gradients): # 生产噪声 grad_noise_tuple = () for grad_item in gradients: grad_noise = self._mech(grad_item) grad_noise_tuple = grad_noise_tuple + (grad_noise,) # 增加噪声 gradients = self._tuple_add(gradients, grad_noise_tuple) gradients = self._hyper_map(F.partial(_grad_scale, self._micro_batches), gradients) # 更新模型参数 if self._mech_param_updater is not None: multiplier = self._mech_param_updater() gradients = F.depend(gradients, multiplier) gradients = super(DPOptimizer, self).construct(gradients) return gradients ``` - **参数** | 参数名 | 描述 | | --------- | ---------------- | | gradients | 要添加噪声的梯度 | - **返回值** | 参数名 | 描述 | | --------- | ------------------ | | gradients | 要添加噪声后的梯度 | - **具体分析** 差分隐私代码的目标即为计算过程中的梯度加噪,而construc是实现加噪的最后一步,它定义了生产噪声、增加噪声、更新模型的整个过程。 ***部分参考于华为MindSpore开发者社区发布内容:[mindspore](https://www.mindspore.cn/doc/api_python/zh-CN/r1.2/mindarmour/mindarmour.privacy.diff_privacy.html#mindarmour.privacy.diff_privacy.PrivacyMonitorFactory)*。**
-
# MindSpore代码评析(一)从计算图开始,带你看MindIR(上) ### 一、计算图初步 当我们学习深度学习框架的时候,有时会不理解计算图的概念。我就曾经以为计算图是对图形进行的某种操作,但是在查阅相关资料后,发现计算图是一个以算子(Operators)为节点的有向图所表达的计算函数,由计算流转变而来。在AI框架里面,这个计算函数对输入依次调用执行有向图中的算子节点,并得到最终的输出。 > 张量:在深度学习/人工智能领域中,把N维数据都统称为tensor。 如图所示,这个计算图就表示P=X+Y的操作,其中“+”就是一个算子,X、Y为输入。 > 算子:算子本质可以理解为一个计算函数,而大部分算子都是可以拆分为若干更为基本的算子组成的的子图。  计算图看起来比计算流要清晰,但计算图描述运算的优势不仅是让你看起舒服,更重要的原因是方便计算梯度,这一点不再赘述。 ### 二、MindIR概述 IR-Intermediate Representation(中间表示)是程序编译过程中,源代码(如深度神经网络)与设备可以执行的目标代码之间翻译的中介。一般可以分为函数式IR和计算图的IR。函数方式的优点在于更方便的实现自动微分和隐式并行分析,计算图方式则能更方便的实现图的优化。 而MindSpore的图层IR叫做MindIR,MindIR选择的技术路线是采用Functional Graph IR,理论可以同时拥有函数和计算图方式的优点。 MindIR的语法如下,如果你学过编译原理,肯定能很清楚的理解,如果没有也不用担心,我会具体讲解。 ``` ::= | ::= Parameter ::= Scalar | Named | Tensor | Type | Shape | Primitive | MetaFuncGraph | FuncGraph ::= ( …) ::= | ``` > *MIndIR中的节点可以总体表示为AnfNode,它由Cnode(函数调用),Anode(常数)构成,这样就能基本表示一个基本的函数调用* > > *ANode有两个子类分别为ValueNode和ParameterNode。* > > *ValueNode表示常数节点,可承载的意义有Scalar(标量)、 Named (符号)、 Tensor(张量) 、 Type(类型)、 Shape(维度)这类普通的输入,也有Primitive(原语函数)、MetaFuncGraph(原函数)、 FuncGraph(普通函数)这样的函数,因为在函数式编程中函数定义本身也是一个值。* > > *ParameterNode是参数节点,表示函数的形参。* > > *CNode表示一次函数调用。* > > *在MindSpore自动微分时,会计算ParameterNode和CNode的梯度,并返回最终ParameterNode的梯度,而不计算ValueNode的梯度。* 下面用具体的一段简单代码看看MindIR长什么样。 ```python def func(x, y): return x / y ```  在函数func中,形参是x和y,所以ParameterNode中即x、y; x,y作为常数节点,即ValueNode; MultitypeFuncGraph表示div的除法函数; Primitive即原语函数,在本实例中表示return; 两个方框样子的节点CNode即表示函数调用的节点。
-
本代码标注主要涉及\mindspore-master\mindspore\train\loss_scale_manager.py文件,本人本次所有的代码标注前面均以#*开头!#* 损失规模管理器 class LossScaleManager: #* 获得损失规模值 def get_loss_scale(self): #* 更新损失规模值 def update_loss_scale(self, overflow): """ Args: overflow (bool) #* 是否溢出 """ #* 获得更新后的损失规模逻辑单元 def get_update_cell(self): #* 具有固定的损失比例,继承于损失规模管理器 class FixedLossScaleManager(LossScaleManager): """ Args: loss_scale (float) #* 损失规模 drop_overflow_update (bool) #* 溢出时是否使用优化器 """ #* 初始化 def __init__(self, loss_scale=128.0, drop_overflow_update=True): if loss_scale < 1: raise ValueError("The argument 'loss_scale' must be >= 1, " "but got {}".format(loss_scale)) self._loss_scale = loss_scale self._drop_overflow_update = drop_overflow_update #* 获得损失规模 def get_loss_scale(self): """ Returns: bool, `loss_scale` value. """ return self._loss_scale #* 获取溢出时是否放弃优化器更新的标志 def get_drop_overflow_update(self): """ Returns: bool, `drop_overflow_update` value. """ return self._drop_overflow_update #* 更新损失规模 def update_loss_scale(self, overflow): """ Args: overflow (bool) #* 是否溢出 """ #* 更新逻辑单元 def get_update_cell(self): """ Returns: None or Cell. Cell object, used to update `loss_scale`, when `drop_overflow_update` is True. None when `drop_overflow_update` is False. """ if not self._drop_overflow_update: return None return nn.FixedLossScaleUpdateCell(self._loss_scale) #* 动态调整损失规模,继承于损失规模管理器 class DynamicLossScaleManager(LossScaleManager): """ Args: init_loss_scale (float) #* 初始损失规模 scale_factor (int) #* 损失规模变化系数 scale_window (int) #* 无溢出时的最大连续步数 """ #* 初始化 def __init__(self, init_loss_scale=2 ** 24, scale_factor=2, scale_window=2000): if init_loss_scale < 1.0: raise ValueError("The argument 'init_loss_scale' must be > 1, but got {}".format(init_loss_scale)) self.loss_scale = init_loss_scale validator.check_positive_int(scale_window, "scale_window", self.__class__.__name__) self.scale_window = scale_window if scale_factor <= 0: raise ValueError("The argument 'scale_factor' must be > 0, but got {}".format(scale_factor)) self.scale_factor = scale_factor self.increase_ratio = scale_factor self.decrease_ratio = 1 / scale_factor self.cur_iter = 1 self.last_overflow_iter = 0 self.bad_step_max = 1000 self.bad_step = 0 #* 获得损失规模 def get_loss_scale(self): return self.loss_scale #* 更新损失规模 def update_loss_scale(self, overflow): """ Args: overflow (bool) #* 是否溢出 """ if overflow: self.loss_scale = max(self.loss_scale * self.decrease_ratio, 1) self.last_overflow_iter = self.cur_iter self.bad_step += 1 else: if (self.cur_iter - self.last_overflow_iter) % self.scale_window == 0: self.loss_scale *= self.increase_ratio self.bad_step = 0 if self.bad_step > self.bad_step_max: raise RuntimeError("Dynamic loss scale Continuous overflow ", self.bad_step, " times, has exceeded maximum threshold.") self.cur_iter += 1 #* 获取溢出时是否丢弃优化器更新的标志 def get_drop_overflow_update(self): """ Returns: bool, always return True at `DynamicLossScaleManager`. """ return True #* 更新逻辑单元 def get_update_cell(self): """ Returns: Cell, cell object used to update `loss_scale`. """ return nn.DynamicLossScaleUpdateCell(self.loss_scale, self.scale_factor, self.scale_window) Returns:
-
本代码标注主要涉及\mindspore-master\mindspore\train\dataset_helper.py文件,本人本次所有的代码标注前面均以#*开头!#* 数据集助手 class DatasetHelper: """ Args: dataset (Dataset) #* 迭代数据集 dataset_sink_mode (bool) #* 数据集迭代模式 sink_size (int) #* 迭代加深的跨度 epoch_num (int) #* 迭代深度 """ #* 初始化 def __init__(self, dataset, dataset_sink_mode=True, sink_size=-1, epoch_num=1): dataset_sink_mode = Validator.check_bool(dataset_sink_mode) Validator.check_is_int(sink_size) if sink_size < -1 or sink_size == 0: raise ValueError("The 'sink_size' must be -1 or positive, but got sink_size {}.".format(sink_size)) if sink_size == -1: sink_size = dataset.get_dataset_size() if dataset_sink_mode: if context.get_context("enable_ge"): iterclass = _DatasetIterGE else: if context.get_context("mode") == context.GRAPH_MODE: ms_role = os.getenv("MS_ROLE") if ms_role in ("MS_PSERVER", "MS_SCHED"): iterclass = _DatasetIterPSServer elif ms_role == "MS_WORKER": iterclass = _DatasetIterPSWork elif (context.get_context("device_target") == "Ascend") or \ (context.get_context("device_target") == "GPU"): iterclass = _DatasetIterMSLoopSink elif context.get_context("device_target") == "CPU": raise RuntimeError("Currently dataset sink mode is not supported when the device " "target is CPU, please set dataset sink mode to False.") else: iterclass = _DatasetIterPyNative self.iter = iterclass(dataset, sink_size, epoch_num) else: iterclass = _DatasetIterNormal self.iter = iterclass(dataset, epoch_num=epoch_num) #* 返回自身的迭代对象 def __iter__(self): return self.iter.__iter__() # A temp solution for loop sink. Delete later #* 从当前配置的数据集中获取类型和形状 def types_shapes(self): return self.iter.types_shapes() #* 获得每次迭代的迭代加深的跨度 def sink_size(self): return self.iter.get_sink_size() #* 停止发送数据 def stop_send(self): self.iter.stop_send() #* 释放数据资源 def release(self): self.iter.release() #* 继续发送数据 def continue_send(self): self.iter.continue_send() #* 获取数据信息 def get_data_info(self): return self.iter.get_data_info() #* 返回动态数据集的最大以及最小的数据长度 def dynamic_min_max_shapes(self): return self.iter.dynamic_min_max_shapes() #* 数据集迭代器 class _DatasetIter: #* 初始化 def __init__(self, dataset, sink_size, epoch_num): self.dataset = dataset self.sink_size = sink_size self.sink_count = self.get_sink_count(dataset) if not hasattr(dataset, '__transfer_dataset__'): if hasattr(dataset, '__loop_size__'): ms_role = os.getenv("MS_ROLE") # PS mode does not support loop sink and need get the real sink size. if ms_role != "MS_WORKER": self.sink_size = dataset.__loop_size__ create_data_info_queue = (sink_size == 1 and self.sink_count == 1 and context.get_context( "device_target") == "Ascend") dataset.__transfer_dataset__ = _exec_datagraph(dataset, self.sink_size, create_data_info_queue=create_data_info_queue) if not hasattr(dataset, '__no_send__'): _send_data(dataset, epoch_num) else: _send_data_no_flag(dataset, epoch_num) self.stop_send = dataset.__transfer_dataset__.stop_send self.release = dataset.__transfer_dataset__.release self.continue_send = dataset.__transfer_dataset__.continue_send self.get_data_info = dataset.__transfer_dataset__.get_data_info self.dynamic_min_max_shapes = dataset.dynamic_min_max_shapes self.dataset_types, self.dataset_shapes = _get_types_and_shapes(dataset) #* 返回自身的迭代对象 def __iter__(self): self.index = 0 return self #* 获取下一个对象 def __next__(self): if self.index >= self.sink_count: raise StopIteration() self.index += 1 return self.op() #* 返回数据集的类型和形状 def types_shapes(self): return self.dataset_types, self.dataset_shapes #* 获取迭代次数 def get_sink_count(self, dataset): sink_count = 1 if hasattr(dataset, '__loop_size__'): loop_size = dataset.__loop_size__ if loop_size <= dataset.get_dataset_size() and dataset.get_dataset_size() % loop_size != 0: raise ValueError(f"Dataset size {dataset.get_dataset_size()} and 'sink_size' {loop_size} " f"are not matched, dataset size should be divisible by 'sink_size'.") sink_count = math.ceil(dataset.get_dataset_size() / loop_size) return sink_count #* 获取迭代加深的跨度 def get_sink_size(self): sink_size = 1 ms_role = os.getenv("MS_ROLE") if hasattr(self.dataset, '__loop_size__'): sink_size = self.dataset.__loop_size__ elif ms_role == "MS_WORKER": # PS mode does not support loop sink. sink_size = 1 else: if context.get_context("enable_ge") or context.get_context("device_target") == "Ascend" \ or context.get_context("device_target") == "GPU": if self.sink_size > 0: sink_size = self.sink_size else: sink_size = self.dataset.get_dataset_size() return sink_size #* GE数据集迭代器 class _DatasetIterGE(_DatasetIter): #* 初始化 def __init__(self, dataset, sink_size, epoch_num): super().__init__(dataset, sink_size, epoch_num) self.sink_count = self.get_sink_count(dataset) batch_expand_num = 1 if _need_to_full(): batch_expand_num = _get_device_num() // _get_pipeline_stages() tensor_list_run = _construct_tensor_list(self.dataset_types, self.dataset_shapes, batch_expand_num) def op(): return tensor_list_run self.op = op #* 适用于mode=PYNATIVE_MODE内容的数据集迭代器 class _DatasetIterPyNative(_DatasetIter): def __init__(self, dataset, sink_size, epoch_num): super().__init__(dataset, sink_size, epoch_num) if sink_size > 0: self.sink_count = sink_size else: self.sink_count = dataset.get_dataset_size() def op(): return tuple() self.op = op #* 适用于device_target=Ascend内容的数据集迭代器 class _DatasetIterMSLoopSink(_DatasetIter): def __init__(self, dataset, sink_size, epoch_num): super().__init__(dataset, sink_size, epoch_num) self.sink_count = self.get_sink_count(dataset) # for self._parallel_mode equal to semi_auto_parallel or auto_parallel, and not using full_batch, # use a complete tensor to compile, and slice tensor to run. The batch dimension of tensors for # compile is device_number times the batch dimension of tensors for run. Now only support LoopSink. if _need_to_full(): device_num = _get_device_num() // _get_pipeline_stages() self.dataset_shapes = _to_full_shapes(self.dataset_shapes, device_num) def op(): return tuple() self.op = op #* 适用于MS_PSERVER或者MS_SCHED内容的数据集迭代器 class _DatasetIterPSServer(_DatasetIter): def __init__(self, dataset, sink_size, epoch_num): super().__init__(dataset, sink_size, epoch_num) self.sink_count = 1 self.sink_size = 1 self.op = None def op(): return _construct_tensor_list(self.dataset_types, self.dataset_shapes, batch_expand_num=1) self.op = op #* 适用于MS_WORKER内容的数据集迭代器 class _DatasetIterPSWork(_DatasetIter): def __init__(self, dataset, sink_size, epoch_num): super().__init__(dataset, sink_size, epoch_num) if sink_size > 0: self.sink_count = sink_size else: self.sink_count = dataset.get_dataset_size() def op(): return tuple() self.op = op #* 适用于平常(非迭代)内容的数据集迭代器 class _DatasetIterNormal: def __init__(self, dataset, epoch_num=-1): self.dataset = dataset self.device_num = _get_device_num() self.global_rank = _get_global_rank() self.iter = self.dataset.create_tuple_iterator(num_epochs=epoch_num, do_copy=True) def __iter__(self): return self def __next__(self): data = self.iter.__next__() return data __all__ = ["DatasetHelper", "connect_network_with_dataset"]
-
本代码标注主要涉及\mindspore-master\mindspore\train\dataset_helper.py文件,本人本次所有的代码标注前面均以#*开头!#* 传输数据但需要进行判断验证 def _send_data(dataset, epoch_num): if not hasattr(dataset, '__has_sent__'): exec_dataset = dataset.__transfer_dataset__ exec_dataset.send(epoch_num) dataset.__has_sent__ = True #* 直接传输数据不做任何判断 def _send_data_no_flag(dataset, epoch_num): exec_dataset = dataset.__transfer_dataset__ exec_dataset.send(epoch_num) #* 动态迭代加深场景 def _dynamic_sink_scenario(dataset, dataset_iter): flag = False ms_role = os.getenv("MS_ROLE") if hasattr(dataset_iter, "sink_size") and \ dataset_iter.sink_size == 1 and \ dataset.get_dataset_size() != 1 and \ hasattr(dataset_iter, "sink_count") and \ dataset_iter.sink_count == 1 and \ context.get_context("device_target") == "Ascend" and \ context.get_context("mode") == context.GRAPH_MODE and \ ms_role != "MS_WORKER": flag = True return flag #* 数据包装 class _DataWrapper(nn.Cell): #* 初始化 def __init__(self, network, dataset_types, dataset_shapes, queue_name, min_shapes=None, max_shapes=None): super(_DataWrapper, self).__init__(auto_prefix=False, flags=network.get_flags()) flags = getattr(network.__class__.construct, "_mindspore_flags", {}) self.info = (dataset_types, dataset_shapes) self.add_flags(**flags) self.get_next = P.GetNext(dataset_types, dataset_shapes, len(dataset_types), queue_name) if min_shapes is not None and max_shapes is not None: Validator.check_value_type("min_shapes", min_shapes, [list, tuple]) Validator.check_value_type("max_shapes", max_shapes, [list, tuple]) self.get_next.add_prim_attr("min_shapes", min_shapes) self.get_next.add_prim_attr("max_shapes", max_shapes) self.network = network #* 该数据集使用GetNext函数从数据集通道输入数据并执行前向计算。 def construct(self): outputs = self.get_next() return self.network(*outputs) #* 生成数据集迭代加深模型网络 def _generate_dataset_sink_mode_net(network, dataset_shapes, dataset_types, queue_name, min_shapes=None, max_shapes=None): if not isinstance(network, _DataWrapper): network = _DataWrapper(network, dataset_types, dataset_shapes, queue_name, min_shapes, max_shapes) return network #* 是否具有动态形状 def has_dynamic_shape(dataset_shapes): for shape in dataset_shapes: if -1 in shape: return True return False #* 生成带有数据集的网络 def _generate_network_with_dataset(network, dataset_helper, queue_name): dataset_types, dataset_shapes = dataset_helper.types_shapes() (min_shapes, max_shapes) = (None, None) if not has_dynamic_shape(dataset_shapes) \ else dataset_helper.dynamic_min_max_shapes() network = _generate_dataset_sink_mode_net(network, dataset_shapes, dataset_types, queue_name, min_shapes, max_shapes) return network #* 连接数据集与网络 def connect_network_with_dataset(network, dataset_helper): """ Args: network (Cell) #* 训练网络的数据集 dataset_helper (DatasetHelper) #* 数据集助手 Returns: Cell, a new network wrapped with 'GetNext' in the case of running the task on Ascend in graph mode, otherwise it is the input network. Raises: RuntimeError: If the API was not called in dataset sink mode. Supported Platforms: ``Ascend`` ``GPU`` """ dataset_iter = dataset_helper.iter dataset = dataset_iter.dataset if isinstance(dataset_iter, _DatasetIterNormal): raise RuntimeError("The API 'connect_network_with_dataset' should be called in dataset sink mode.") ms_role = os.getenv("MS_ROLE") if ms_role in ("MS_PSERVER", "MS_SCHED"): return network queue_name = dataset.__transfer_dataset__.queue_name if _dynamic_sink_scenario(dataset, dataset_iter): if not hasattr(dataset_iter, '__network__'): dataset_iter.__network__ = network network = dataset_iter.__network__ dataset_types, dataset_shapes = dataset_helper.get_data_info() dataset_types = [pytype_to_dtype(x) for x in dataset_types] key = str(dataset_types) + str(dataset_shapes) if hasattr(dataset_iter, '__network_manage__') and key in dataset_iter.__network_manage__: network = dataset_iter.__network_manage__[key] else: if _need_to_full(): device_num = _get_device_num() // _get_pipeline_stages() dataset_shapes = _to_full_shapes(dataset_shapes, device_num) network = _generate_dataset_sink_mode_net(network, dataset_shapes, dataset_types, queue_name) dataset_iter.__network_manage__ = dataset_iter.__network_manage__ if hasattr( dataset_iter, '__network_manage__') else dict() dataset_iter.__network_manage__[key] = network return network if not hasattr(dataset, '__me_inited__') and \ not context.get_context("enable_ge") and \ context.get_context("device_target") in ("Ascend", "GPU"): dataset.__me_inited__ = True network = _generate_network_with_dataset(network, dataset_helper, queue_name) if hasattr(dataset_iter, "sink_size") and \ dataset_iter.sink_size == 1 and \ dataset.get_dataset_size() != 1 and \ hasattr(dataset_iter, "sink_count") and \ dataset_iter.sink_count == 1 and \ context.get_context("device_target") == "Ascend" and \ context.get_context("mode") == context.PYNATIVE_MODE: dataset_helper.get_data_info() return network
-
本代码标注主要涉及\mindspore-master\mindspore\train\amp.py文件,本人本次所有的代码标注前面均以#*开头!#* 将网络输出投射回float16 class _OutputTo16(nn.Cell): def __init__(self, op): super(_OutputTo16, self).__init__(auto_prefix=False) self._op = op def construct(self, x): return F.cast(self._op(x), mstype.float16) #* 确保批处理规范fp32 def _do_keep_batchnorm_fp32(network): cells = network.name_cells() change = False for name in cells: subcell = cells[name] if subcell == network: continue elif isinstance(subcell, (nn.BatchNorm2d, nn.BatchNorm1d)): network._cells[name] = _OutputTo16(subcell.to_float(mstype.float32)) change = True else: _do_keep_batchnorm_fp32(subcell) if isinstance(network, nn.SequentialCell) and change: network.cell_list = list(network.cells()) #* 配置选项 _config_level = { "O0": { "keep_batchnorm_fp32": False, "cast_model_type": mstype.float32, "loss_scale_manager": None}, "O2": { "keep_batchnorm_fp32": True, "cast_model_type": mstype.float16, "loss_scale_manager": DynamicLossScaleManager()}, "O3": { "keep_batchnorm_fp32": False, "cast_model_type": mstype.float16, "loss_scale_manager": None}} #* 关键字的合法性检查 def _check_kwargs(key_words): for arg in key_words: if arg not in ['cast_model_type', 'keep_batchnorm_fp32', 'loss_scale_manager']: raise ValueError(f"Unsupported arg '{arg}'") if 'cast_model_type' in key_words: validator.check_type_name('cast_model_type', key_words['cast_model_type'], [mstype.float16, mstype.float32], None) if 'keep_batchnorm_fp32' in key_words: validator.check_value_type('keep_batchnorm_fp32', key_words['keep_batchnorm_fp32'], bool) if 'loss_scale_manager' in key_words: loss_scale_manager = key_words['loss_scale_manager'] if loss_scale_manager: validator.check_value_type('loss_scale_manager', loss_scale_manager, LossScaleManager) #* 添加代价(损失)网络 def _add_loss_network(network, loss_fn, cast_model_type): class WithLossCell(nn.Cell): "Wrap loss for amp. Cast network output back to float32" def __init__(self, backbone, loss_fn): super(WithLossCell, self).__init__(auto_prefix=False) self._backbone = backbone self._loss_fn = loss_fn def construct(self, data, label): out = self._backbone(data) label = F.mixed_precision_cast(mstype.float32, label) return self._loss_fn(F.mixed_precision_cast(mstype.float32, out), label) validator.check_value_type('loss_fn', loss_fn, nn.Cell) if cast_model_type == mstype.float16: network = WithLossCell(network, loss_fn) else: network = nn.WithLossCell(network, loss_fn) return network #* 构建自动化混合精度训练网络 def build_train_network(network, optimizer, loss_fn=None, level='O0', boost_level='O0', **kwargs): """ Args: network (Cell) #* 网络的定义 loss_fn (Union[None, Cell]) #* 代价(损失)函数 optimizer (Optimizer) #* 更新参数的优化器 level (str) #* 训练等级 boost_level (str) #* boost等级 cast_model_type (:class:`mindspore.dtype`) #* 投射模型类型 keep_batchnorm_fp32 (bool) #* 是否保持批处理规范fp32 loss_scale_manager (Union[None, LossScaleManager]) #* 损失规模管理器 Raises: ValueError: Auto mixed precision only supported on device GPU and Ascend. If device is CPU, a `ValueError` exception will be raised. ValueError: If device is CPU, property `loss_scale_manager` only can be set as `None` or `FixedLossScaleManager` (with property `drop_overflow_update=False` ), or a `ValueError` exception will be raised. """ validator.check_value_type('network', network, nn.Cell) validator.check_value_type('optimizer', optimizer, (nn.Optimizer, boost.FreezeOpt)) if not isinstance(level, str): raise TypeError(f"The argument `level` must be a string in ['O0', 'O2', 'O3', 'auto'], " f"but got type {str(type(level))}.") validator.check('level', level, "", ['O0', 'O2', 'O3', 'auto'], Rel.IN) validator.check('boost_level', boost_level, "", ['O0', 'O1', 'O2'], Rel.IN) if level == "auto": device_target = context.get_context('device_target') if device_target == "GPU": level = "O2" elif device_target == "Ascend": level = "O3" else: raise ValueError("Level `auto` only support when `device_target` is GPU or Ascend.") _check_kwargs(kwargs) config = dict(_config_level[level], **kwargs) if config["cast_model_type"] == mstype.float16: network.to_float(mstype.float16) if config["keep_batchnorm_fp32"]: _do_keep_batchnorm_fp32(network) if loss_fn: network = _add_loss_network(network, loss_fn, config["cast_model_type"]) if _get_parallel_mode() in (ParallelMode.SEMI_AUTO_PARALLEL, ParallelMode.AUTO_PARALLEL): network = _VirtualDatasetCell(network) enable_boost = False if boost_level in ["O1", "O2"]: enable_boost = True loss_scale = 1.0 if config["loss_scale_manager"] is not None: loss_scale_manager = config["loss_scale_manager"] loss_scale = loss_scale_manager.get_loss_scale() update_cell = loss_scale_manager.get_update_cell() if update_cell is not None: # only cpu not support `TrainOneStepWithLossScaleCell` for control flow. if not context.get_context("enable_ge") and context.get_context("device_target") == "CPU": raise ValueError("Only `loss_scale_manager=None` or " "`loss_scale_manager=FixedLossScaleManager(drop_overflow_update=False)`" "are supported on device `CPU`. ") if _get_pipeline_stages() > 1: network = _TrainPipelineWithLossScaleCell(network, optimizer, scale_sense=update_cell).set_train() elif enable_boost: network = boost.BoostTrainOneStepWithLossScaleCell(network, optimizer, scale_sense=update_cell).set_train() else: network = nn.TrainOneStepWithLossScaleCell(network, optimizer, scale_sense=update_cell).set_train() return network if _get_pipeline_stages() > 1: network = _TrainPipelineAccuStepCell(network, optimizer).set_train() elif enable_boost: network = boost.BoostTrainOneStepCell(network, optimizer, loss_scale).set_train() else: network = nn.TrainOneStepCell(network, optimizer, loss_scale).set_train() return network
推荐直播
-
HDC深度解读系列 - Serverless与MCP融合创新,构建AI应用全新智能中枢2025/08/20 周三 16:30-18:00
张昆鹏 HCDG北京核心组代表
HDC2025期间,华为云展示了Serverless与MCP融合创新的解决方案,本期访谈直播,由华为云开发者专家(HCDE)兼华为云开发者社区组织HCDG北京核心组代表张鹏先生主持,华为云PaaS服务产品部 Serverless总监Ewen为大家深度解读华为云Serverless与MCP如何融合构建AI应用全新智能中枢
回顾中 -
关于RISC-V生态发展的思考2025/09/02 周二 17:00-18:00
中国科学院计算技术研究所副所长包云岗教授
中科院包云岗老师将在本次直播中,探讨处理器生态的关键要素及其联系,分享过去几年推动RISC-V生态建设实践过程中的经验与教训。
回顾中 -
一键搞定华为云万级资源,3步轻松管理企业成本2025/09/09 周二 15:00-16:00
阿言 华为云交易产品经理
本直播重点介绍如何一键续费万级资源,3步轻松管理成本,帮助提升日常管理效率!
回顾中
热门标签