# 调试调优 [](https://gitee.com/mindspore/docs/blob/r2.5.0/docs/mindspore/source_zh_cn/migration_guide/debug_and_tune.md) ## 调优常见问题及解决办法 - 精度调试阶段,可能会遇到以下常见问题: - 第一个loss和标杆对不齐: 说明网络正向和标杆对不齐,可固定网络输入,关闭shuffle等随机性,在网络某些关键节点保存输出为npy,再借助[TroubleShooter比较两组Tensor值(npy文件)是否相等](https://gitee.com/mindspore/toolkits/blob/master/troubleshooter/docs/migrator.md#%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF4%E6%AF%94%E8%BE%83%E4%B8%A4%E7%BB%84tensor%E5%80%BCnpy%E6%96%87%E4%BB%B6%E6%98%AF%E5%90%A6%E7%9B%B8%E7%AD%89),定位到第一个不一致的位置,再进行二分定位,分析正向哪里差异导致loss和标杆对不齐造成精度问题。 - 第一个loss和标杆对齐,后续loss对不齐: 这个大概率是网络反向出现问题。可借助[TroubleShooter比对MindSpore与PyTorch的ckpt/pth](https://gitee.com/mindspore/toolkits/blob/master/troubleshooter/docs/migrator.md#%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF2%E6%AF%94%E5%AF%B9mindspore%E4%B8%8Epytorch%E7%9A%84ckptpth)通过比较ckpt与pth的对应参数的值来检验网络反向更新的结果。 - loss出现NAN/INF: 可以通过[TroubleShooter获取INF/NAN值抛出点](https://gitee.com/mindspore/toolkits/blob/master/troubleshooter/docs/tracker.md#%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF2%E8%8E%B7%E5%8F%96infnan%E5%80%BC%E6%8A%9B%E5%87%BA%E7%82%B9)识别网络中第一个出现NAN或INF的位置。 也可通过[Dump](https://www.mindspore.cn/docs/zh-CN/r2.5.0/model_train/debug/dump.html)工具进行溢出算子检测。 - 显存调试阶段,可能遇到以下常见问题: - Malloc device memory failed: MindSpore申请device侧内存失败,原始是设备被其他进程占用,可通过ps -ef | grep "python"查看正在跑的进程。 - Out of Memory: MindSpore申请动态内存失败,可能的原因有:batch size太大,处理数据太多导致内存占用大;通信算子占用内存太多导致整体内存复用率较低。 ## MindSpore功能调试介绍 ### 功能调试 在网络的迁移过程,建议优先使用PYNATIVE模式进行调试,在PYNATIVE模式下可以进行debug,日志打印也比较友好。在调试ok后转成图模式运行,图模式在执行性能上会更友好,也可以找到一些在编写网络中的问题,比如使用了三方的算子导致梯度截断。 详情请参考[错误分析](https://www.mindspore.cn/docs/zh-CN/r2.5.0/model_train/debug/error_analysis/error_scenario_analysis.html)。 ### 精度调优 精度调试的过程基本可以分为以下过程: #### 1.检查参数 这部分包含检查所有参数和可训练参数的数量,检查所有参数的shape。 - PyTorch可训练的参数用`Parameter`,不可训练的参数`Parameter`的`requires_grad=False`或使用`buffer`。 - MindSpore可训练的参数和不可训练的参数都用`Parameter`。 - MindSpore和PyTorch的参数除了BatchNorm区别大一点,其他都差不多。注意MindSpore里没有`num_batches_tracked`的对应,实际使用时这个参数可以用优化器里的`global_step`替代。 | MindSpore | PyTorch | | --------- | --------| | gamma | weight | | beta | bias | | moving_mean | running_mean | | moving_variance | running_var | | 无 | num_batches_tracked |
PyTorch 获取参数方法 | MindSpore 获取参数方法 |
```python from torch import nn class ptNet(nn.Module): def __init__(self): super(ptNet, self).__init__() self.fc = nn.Linear(1, 1) def construct(self, x): output = self.fc(x) return output ptnet = ptNet() all_parameter = [] trainable_params = [] # 获取网络里的参数 for name, item in ptnet.named_parameters(): if item.requires_grad: trainable_params.append(item) all_parameter.append(item) print(name, item.shape) for name, buffer in ptnet.named_buffers(): all_parameter.append(buffer) print(name, buffer.shape) print(f"all parameter numbers: {len(all_parameter)}") print(f"trainable parameter numbers: {len(trainable_params)}") ``` 打印结果: ```text fc.weight torch.Size([1, 1]) fc.bias torch.Size([1]) all parameter numbers: 2 trainable parameter numbers: 2 ``` |
```python from mindspore import nn class msNet(nn.Cell): def __init__(self): super(msNet, self).__init__() self.fc = nn.Dense(1, 1, weight_init='normal') def construct(self, x): output = self.fc(x) return output msnet = msNet() # 获取所有参数 all_parameter = [] for item in msnet.get_parameters(): all_parameter.append(item) print(item.name, item.data.shape) print(f"all parameter numbers: {len(all_parameter)}") # 获取可训练的参数 trainable_params = msnet.trainable_params() for item in trainable_params: print(item.name, item.data.shape) print(f"trainable parameter numbers: {len(trainable_params)}") ``` 打印结果: ```text fc.weight (1, 1) fc.bias (1,) all parameter numbers: 2 fc.weight (1, 1) fc.bias (1,) trainable parameter numbers: 2 ``` |