# 执行问题
[](https://gitee.com/mindspore/docs/blob/r2.3.q1/docs/mindspore/source_zh_cn/faq/implement_problem.md)
## Q: 请问使用MindSpore如何实现多尺度训练?
A: 在多尺度训练过程中,使用不同`shape`调用`Cell`对象的时候,会自动根据不同`shape`编译并调用不同的图,从而实现多尺度的训练。要注意多尺度训练只支持非数据下沉模式,不能支持数据下沉的训练方式。可以参考[yolov3](https://gitee.com/mindspore/models/tree/r2.3/official/cv/YOLOv3)的多尺度训练实现。
## Q: 如果MindSpore的`requires_grad=False`的`tensor`转化为`numpy`类型进行处理然后再转化会`tensor`,会对计算图和反向传播有影响吗?
A: 在PyNative模式下,如果中间使用`numpy`计算,会导致梯度传递中断,`requires_grad=False`的场景下,如果该`tensor`的反向传播不传给其他参数使用,是没有影响的;如果`requires_grad=True`的场景下,是有影响的。
## Q: 请问怎样实现类似`torch.nn.functional.linear()`那样能够对全连接层`weight`、`bias`进行修改,应该如何操作?
A: MindSpore与`torch.nn.functional.linear()`功能最接近的接口就是`nn.Dense`了。`nn.Dense`能指定`weight`和`bias`的初始值,后续的变化是由优化器自动更新的。训练过程中,用户不需要主动修改这两个参数的值。
## Q: 使用MindSpore在模型保存后生成的`.meta`文件作用是什么,可以用`.meta`文件导入图结构吗?
A: 这里的`.meta`文件是编译好的图结构,但是目前并不支持直接导入这种结构。如果不知道图结构的情况下想要导入网络,还是需要用MindIR格式的文件。
## Q: 请问`yolov4-tiny-3l.weights`模型文件可以直接转换成MindSpore模型吗?
A: 不能的,需要把其他框架训练好的参数转换成MindSpore的格式,才能转成MindSpore的模型。
## Q: 使用MindSpore进行`model.train`的时候进行了如下设置,为什么会报错呢?
```python
model.train(1, dataset, callbacks=ms.train.LossMonitor(1), dataset_sink_mode=True)
model.train(1, dataset, callbacks=ms.train.LossMonitor(1), dataset_sink_mode=False)
```
A: 因为在已经设置为下沉模式的情况下,就不能再设置为非下沉了,是运行机制上的限制。
## Q: 使用MindSpore训练模型在`eval`阶段,需要注意什么?能够直接加载网络和参数吗?需要在Model中使用优化器吗?
A: 在`eval`阶段主要看需要什么,比如图像分类任务`eval`网络的输出是各个类的概率值,与对应标签计算`acc`。
大多数情况是可以直接复用训练的网络和参数的,需要注意的是需要设置推理模式。
```python
net.set_train(False)
```
在eval阶段不需要优化器,但是需要使用MindSpore的`model.eval`接口的话需要配置一下`loss function`,如:
```python
# 定义模型
model = ms.train.Model(net, loss_fn=loss, metrics={'top_1_accuracy', 'top_5_accuracy'})
# 评估模型
res = model.eval(dataset)
```
## Q: 如何使用SGD里的`param_group`来实现学习率的衰减?
A: 如果需要按照`epoch`来变化,可以使用[Dynamic LR](https://mindspore.cn/docs/zh-CN/r2.3.0rc1/api_python/mindspore.nn.html#dynamic-lr函数),把其中的`step_per_epoch`设置成`step_size`,如果需要按照`step`来变化,可以把其中的`step_per_epoch`设置成1,也可以用[LearningRateSchedule](https://mindspore.cn/docs/zh-CN/r2.3.0rc1/api_python/mindspore.nn.html#learningrateschedule类)。
## Q: MindSpore如何进行参数(如dropout值)修改?
A: 在构造网络的时候可以通过 `if self.training: x = dropput(x)`,推理时,执行前设置`network.set_train(False)`,就可以不使用dropout,训练时设置为True就可以使用dropout。
## Q: 如何查看模型参数量?
A: 可以直接加载CheckPoint统计,可能额外统计了动量和optimizer中的变量,需要过滤下相关变量。
您可以参考如下接口统计网络参数量:
```python
def count_params(net):
"""Count number of parameters in the network
Args:
net (mindspore.nn.Cell): Mindspore network instance
Returns:
total_params (int): Total number of trainable params
"""
total_params = 0
for param in net.trainable_params():
total_params += np.prod(param.shape)
return total_params
```
具体[脚本链接](https://gitee.com/mindspore/models/blob/r2.3/research/cv/tinynet/src/utils.py)。
## Q: 如何在训练过程中监控`loss`在最低的时候并保存训练参数?
A: 可以自定义一个`Callback`。参考`ModelCheckpoint`的写法,此外再增加判断`loss`的逻辑:
```python
class EarlyStop(Callback):
def __init__(self, control_loss=1):
super(EarlyStop, self).__init__()
self._control_loss = control_loss
def on_train_step_end(self, run_context):
cb_params = run_context.original_args()
loss = cb_params.net_outputs
if loss.asnumpy() < self._control_loss:
# Stop training
run_context._stop_requested = True
stop_cb = EarlyStop(control_loss=1)
model.train(epoch_size, ds_train, callbacks=[stop_cb])
```
## Q: 使用`nn.Conv2d`时,怎样获取期望大小的`feature map`?
A: `Conv2d shape`推导方法可以[参考这里](https://www.mindspore.cn/docs/zh-CN/r2.3.0rc1/api_python/nn/mindspore.nn.Conv2d.html#mindspore.nn.Conv2d),`Conv2d`的`pad_mode`改成`same`,或者可以根据`Conv2d shape`推导公式自行计算`pad`,想要使得`shape`不变,一般pad为`(kernel_size-1)//2`。
## Q: 使用MindSpore可以自定义一个可以返回多个值的loss函数?
A: 自定义`loss function`后还需自定义`TrainOneStepCell`,实现梯度计算时`sens`的个数和`network`的输出个数相同。具体可参考:
```python
net = Net()
loss_fn = MyLoss()
loss_with_net = MyWithLossCell(net, loss_fn)
train_net = MyTrainOneStepCell(loss_with_net, optim)
model = ms.train.Model(net=train_net, loss_fn=None, optimizer=None)
```
## Q: MindSpore如何实现早停功能?
A:可以使用[EarlyStopping 方法](https://www.mindspore.cn/docs/zh-CN/r2.3.0rc1/api_python/train/mindspore.train.EarlyStopping.html)。
## Q: 模型已经训练好,如何将模型的输出结果保存为文本或者`npy`的格式?
A: 您好,我们网络的输出为`Tensor`,需要使用`asnumpy()`方法将`Tensor`转换为`numpy`,再进行下一步保存。具体可参考:
```python
out = net(x)
np.save("output.npy", out.asnumpy())
```
## Q: 缓存服务器异常关闭如何处理?
A: 缓存服务器使用过程中,会进行IPC共享内存和socket文件等系统资源的分配。若允许溢出,在磁盘空间还会存在溢出的数据文件。一般情况下,如果通过`cache_admin --stop`命令正常关闭服务器,这些资源将会被自动清理。
但如果缓存服务器被异常关闭,例如缓存服务进程被杀等,用户需要首先尝试重新启动服务器,若启动失败,则应该依照以下步骤手动清理系统资源:
- 删除IPC资源。
1. 检查是否有IPC共享内存残留。
一般情况下,系统会为缓存服务分配4GB的共享内存。通过以下命令可以查看系统中的共享内存块使用情况。
```text
$ ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x61020024 15532037 root 666 4294967296 1
```
其中,`shmid`为共享内存块id,`bytes`为共享内存块的大小,`nattch`为链接到该共享内存块的进程数量。`nattch`不为0表示仍有进程使用该共享内存块。在删除共享内存前,需要停止使用该内存块的所有进程。
2. 删除IPC共享内存。
找到对应的共享内存id,并通过以下命令删除。
```text
ipcrm -m {shmid}
```
- 删除socket文件。
一般情况下,socket文件位于`/tmp/mindspore/cache`。进入文件夹,执行以下命令删除socket文件。
```text
rm cache_server_p{port_number}
```
其中`port_number`为用户创建缓存服务器时指定的端口号,默认为50052。
- 删除溢出到磁盘空间的数据文件。
进入启用缓存服务器时指定的溢出数据路径。通常,默认溢出路径为`/tmp/mindspore/cache`。找到路径下对应的数据文件夹并逐一删除。
## Q: 通过Hub可以使用GPU加载`vgg16`模型以及是否可以做迁移模型吗?
A: 请手动修改如下两处参数即可:
```python
# 增加**kwargs参数: 如下
def vgg16(num_classes=1000, args=None, phase="train", **kwargs):
```
```python
# 增加**kwargs参数: 如下
net = Vgg(cfg['16'], num_classes=num_classes, args=args, batch_norm=args.batch_norm, phase=phase, **kwargs)
```
## Q: 如何得到VGG模型中间层特征?
A: 你好,获取网络中间层的特征,其实跟具体框架没有太大关系了。`torchvison`里定义的`vgg`模型,可以通过`features`字段获取"中间层特征",`torchvison`的`vgg`源码如下:
```python
class VGG(nn.Module):
def __init__(self, features, num_classes=1000, init_weights=True):
super(VGG, self).__init__()
self.features = features
self.avgpool = nn.AdaptiveAvgPool2d((7, 7))
```
在MindSpore的ModelZoo里定义的`vgg16`,可以通过`layers`字段获取,如下:
```python
network = vgg16()
print(network.layers)
```
## Q: 使用MindSpore进行模型训练时,`CTCLoss`的输入参数有四个: `inputs`、`labels_indices`、`labels_values`、`sequence_length`,如何使用`CTCLoss`进行训练?
A: 定义的`model.train`接口里接收的`dataset`可以是多个数据组成,形如(`data1`、`data2`、`data3`...),所以`dataset`是可以包含`inputs`、`labels_indices`、`labels_values`、`sequence_length`的信息的。只需要定义好相应形式的`dataset`,传入`model.train`里就可以。具体的可以了解下相应的[数据处理接口](https://www.mindspore.cn/tutorials/zh-CN/r2.3.0rc1/advanced/dataset.html)。
## Q: MindSpore有哪些现成的推荐类或生成类网络或模型可用?
A: 目前正在开发Wide & Deep、DeepFM、NCF等推荐类模型,NLP领域已经支持Bert_NEZHA,正在开发MASS等模型,用户可根据场景需要改造为生成类网络,可以关注[MindSpore ModelZoo](https://gitee.com/mindspore/models/blob/r2.3/README_CN.md#)。
## Q: `mindspore/tests`下怎样执行单个`ut`用例?
A: `ut`用例通常需要基于debug版本的MindSpore包,官网并没有提供。可以基于源码使用`sh build.sh`编译,然后通过`pytest`指令执行,debug模式编包不依赖后端。编译选项`sh build.sh -t on`,用例执行可以参考`tests/runtest.sh`脚本。
## Q: 在Ascend平台上,执行用例有时候会报错`run task error`,如何获取更详细的日志帮助问题定位?
A: 使用msnpureport工具设置device侧日志级别,工具位置在: `/usr/local/Ascend/latest/driver/tools/msnpureport`。
- 全局级别:
```bash
/usr/local/Ascend/latest/driver/tools/msnpureport -g info
```
- 模块级别:
```bash
/usr/local/Ascend/latest/driver/tools/msnpureport -m SLOG:error
```
- Event级别:
```bash
/usr/local/Ascend/latest/driver/tools/msnpureport -e disable/enable
```
- 多device id级别:
```bash
/usr/local/Ascend/latest/driver/tools/msnpureport -d 1 -g warning
```
假设deviceID的取值范围是[0-7],`device0`-`device3`和`device4`-`device7`分别在一个os上。其中`device0`-`device3`共用一个日志配置文件;`device4`-`device7`共用一个配置文件。如果修改了`device0`-`device3`中的任意一个日志级别,其他`device`的日志级别也会被修改。如果修改了`device4`-`device7`中的任意一个日志级别,其他device的日志级别也会被修改。
`Driver`包安装以后(假设安装路径为/usr/local/HiAI,在Windows环境下,`msnpureport.exe`执行文件在C:\ProgramFiles\Huawei\Ascend\Driver\tools\目录下),假设用户在/home/shihangbo/目录下直接执行命令行,则Device侧日志被导出到当前目录下,并以时间戳命名文件夹进行存放。
## Q: 使用Ascend平台执行训练过程,出现报错: `Out of Memory!!! total[3212254720] (dynamic[0] memory poll[524288000]) malloc[32611480064] failed!` 如何解决?
A: 此问题属于内存占用过多导致的内存不够问题,可能原因有两种:
- `batch_size`的值设置过大。解决办法: 将`batch_size`的值设置减小。
- 引入了异常大的`Parameter`,例如单个数据shape为[640,1024,80,81],数据类型为float32,单个数据大小超过15G,这样差不多大小的两个数据相加时,占用内存超过3*15G,容易造成`Out of Memory`。解决办法: 检查参数的`shape`,如果异常过大,减少shape。
- 如果以上操作还是未能解决,可以上[官方论坛](https://www.hiascend.com/forum/forum-0106101385921175002-1.html)发帖提出问题,将会有专门的技术人员帮助解决。
## Q: 如何在训练神经网络过程中对计算损失的超参数进行改变?
A: 您好,很抱歉暂时还未有这样的功能。目前只能通过训练-->重新定义优化器-->训练,这样的过程寻找较优的超参数。
## Q: 运行应用时报错`error while loading shared libraries: libge_compiler.so: cannot open shared object file: No such file or directory`怎么办?
A: 安装MindSpore所依赖的Atlas 200/300/500推理产品配套软件包时,`CANN`包不能安装`nnrt`版本,而是需要安装功能完整的`toolkit`版本。
## Q: MindSpore代码里面的model_zoo/official/cv/ResNet/train.py中set_ps_context(enable_ps=True)为什么一定要在init之前设置?
A: MindSpore Ascend模式下,如果先调用init,那么会为所有的进程都分配卡,但是parameter server训练模式下server是不需要分配卡的,那么worker和server就会去使用同一块卡,导致会报错: Ascend kernel runtime initialization failed。
## Q: 在CPU ARM平台上进行resnet50训练,内存持续增长怎么办?
A: 在CPU ARM上进行resnet50训练时,部分算子的实现是基于oneDNN库,oneDNN库中是基于libgomp库实现多线程并行,当前libgomp存在多个并行域配置的线程数不同时有内存占用持续增长的问题。可通过全局配置统一的线程数来控制内存的持续增长。再综合性能上的考虑,建议统一配置为物理核数的1/4,比如`export OMP_NUM_THREADS=32`。
## Q: 为什么在Ascend平台执行模型时报错`Stream isn't enough`?
A: 流表示一个操作队列,同一条流上的任务按序串行执行,不同流之间可以并行执行。网络中的各种操作会生成Task并被分配到流上,以控制任务执行的并发方式。由于Ascend平台对同一条流上的的任务数存在限制,超限的任务会分配新流,且MindSpore框架的多种并行方式也会分配新流,例如通信算子并行,因此当分配流的数目超过Ascend平台的资源限制就会报流超限的错误。参考解决方案:
- 减小网络模型规模
- 减少网络中通信算子的使用
- 减少网络中的条件控制语句
## Q: 在Ascend平台上,日志中出现报错“Ascend error occurred, error message:”且跟随了一个错误码,如“E40011”,如何查找出现错误码的原因?
A: 当出现“Ascend error occurred, error message:”时,说明昇腾CANN相关模块出现异常,上报了错误日志。
此时错误码后有异常的错误信息。如果需要该异常更详细的可能原因和处理方法,请参考对应昇腾版本文档的《Error Code介绍》部分,如[昇腾CANN商用版(7.0.0) Error Code介绍](https://www.hiascend.com/document/detail/zh/canncommercial/700/troublemanagement/troubleshooting/atlaserrorcode_15_0139.html)。
## Q: 训练nlp类网络,当使用第三方组件gensim时,可能会报错: ValueError,如何解决?
A: 以下为报错信息:
```bash
>>> import gensim
Traceback (most recent call last):
File "", line 1, in
File "/home/miniconda3/envs/ci39_cj/lib/python3.9/site-packages/gensim/__init__.py", line 11, in
from gensim import parsing, corpora, matutils, interfaces, models, similarities, utils # noqa:F401
File "/home/miniconda3/envs/ci39_cj/lib/python3.9/site-packages/gensim/corpora/__init__.py", line 6, in
from .indexedcorpus import IndexedCorpus # noqa:F401 must appear before the other classes
File "/home/miniconda3/envs/ci39_cj/lib/python3.9/site-packages/gensim/corpora/indexedcorpus.py", line 14, in
from gensim import interfaces, utils
File "/home/miniconda3/envs/ci39_cj/lib/python3.9/site-packages/gensim/interfaces.py", line 19, in
from gensim import utils, matutils
File "/home/miniconda3/envs/ci39_cj/lib/python3.9/site-packages/gensim/matutils.py", line 1024, in
from gensim._matutils import logsumexp, mean_absolute_difference, dirichlet_expectation
File "gensim/_matutils.pyx", line 1, in init gensim._matutils
ValueError: numpy.ndarray size changed, may indicate binary incompatibility. Expected 88 from C header, got 80 from PyObject
```
报错原因请参考[gensim](https://github.com/RaRe-Technologies/gensim/issues/3095)官网,或者[numpy](https://github.com/numpy/numpy/issues/18709)官网:
解决方案:
方法一: 重新安装numpy及gensim,执行命令: `pip uninstall gensim numpy -y && pip install numpy gensim` ;
方法二: 如果还是有问题,请删除wheel安装包的缓存文件,然后执行方法一(wheel安装包缓存目录为: `~/.cache/pip/wheels`)。
## Q:运行文档示例代码的过程中,遇到`matplotlib.pyplot.show()`或`plt.show()`无法执行怎么处理?
A: 首先确认是否安装`matplotlib`,如果没有安装,可以在命令行中执行`pip install matplotlib`进行安装。
其次由于`matplotlib.pyplot.show()`的作用是以图形化方式展示,所以需要运行系统支持图形展示功能,如果系统不能支持图形展示,需要将该图形展示的命令行注释后再运行,不影响整体代码的运行结果。
## Q: 使用文档中提供的在线运行时,遇到运行失败该如何处理?
A: 需要确认有做以下准备工作。
- 首先,需要通过华为云账号登录ModelArts。
- 其次,注意教程文档的标签中列举的硬件环境,以及样例代码中配置的硬件环境,是Ascend、GPU还是CPU,由于登录后默认使用的硬件环境是CPU,Ascend环境和GPU环境需要用户手动点击切换。
- 最后,确保当前`Kernel`为MindSpore。
完成上述步骤后,就可以运行文档了。
具体的操作过程可以参考[基于ModelArts在线体验MindSpore](https://www.hiascend.com/forum/thread-0254122007639293043-1-1.html)。
## Q: 静态图下使用除法结果未报错,动态图下使用除法结果却报错?
A: 在静态图模式下,由于使用的是静态编译,对于算子输出结果的数据类型是在图编译阶段确定的。
例如如下代码在静态图模式下执行,输入数据的类型都为int类型,根据静态图编译,其输出结果也是int类型。
```python
import mindspore as ms
from mindspore import nn
ms.set_context(mode=ms.GRAPH_MODE, device_target="CPU")
class MyTest(nn.Cell):
def __init__(self):
super(MyTest, self).__init__()
def construct(self, x, y):
return x / y
x = 16
y = 4
net = MyTest()
output = net(x, y)
print(output, type(output))
```
输出结果:
```text
4
```
修改执行模式,将GRAPH_MODE修改成PYNATIVE_MODE,由于在动态图模式下使用的Python语法执行,Python语法对任意除法输出的类型都是float类型,因此执行结果如下:
```text
4.0
```
因此在后续算子明确需要使用int的场景下,建议使用Python的整除符号`//`。
## Q: 1.8版本首次运行GPU的脚本会卡很久?
A: 由于NVCC编译CUDA算子时为了兼容更多GPU架构,先编译成ptx文件,在首次使用时会进行JIT编译成二进制执行文件,因此会产生编译耗时。
而1.8版本相较于前版本增加了许多CUDA算子,导致这部分编译时间增加(不同设备时间不同,如在V100上首次编译时间为5分钟左右)。
该编译会产生缓存文件(以ubuntu系统为例,缓存文件位于 `~/.nv/ComputeCache` 路径下),在后续执行时会直接加载缓存文件。
因此会产生首次使用时会卡住几分钟,后续使用时间正常的现象。
后续版本会进行预编译优化。
## Q: 算子执行过程中出现报错: `MemoryError: std::bad_alloc` 如何解决?
A: 此问题的原因为:用户未正确配置算子参数,导致算子申请的内存空间超过了系统内存限制,进而系统分配内存失败。下面以算子 mindspore.ops.UniformCandidateSampler 为例进行说明:
- UniformCandidateSampler使用均匀分布对一组类别进行采样,根据用户设定的参数`num_sampled`,其输出Tensor的shape为`(num_sampled,)`。
- 当用户设定的`num_sampled=int64.max`时,其输出Tensor申请的内存空间超过了系统内存限制,并导致`bad_alloc`。
因此,用户需要适当设置算子参数,以避免此类报错。
## Q: 如何理解报错提示中的"Ascend Error Message"?
A: "Ascend Error Message"是MindSpore调用CANN(昇腾异构计算架构)接口时,CANN执行出错后抛出的故障信息,其中包含错误码和错误描述等信息,如下例子:
```text
Traceback (most recent call last):
File "train.py", line 292, in
train_net()
File "/home/resnet_csj2/scripts/train_parallel0/src/model_utils/moxing_adapter.py", line 104, in wrapped_func
run_func(*args, **kwargs)
File "train.py", line 227, in train_net
set_parameter()
File "train.py", line 114, in set_parameter
init()
File "/home/miniconda3/envs/ms/lib/python3.7/site-packages/mindspore/communication/management.py", line 149, in init
init_hccl()
RuntimeError: Ascend kernel runtime initialization failed.
\----------------------------------------------------
\- Ascend Error Message:
\----------------------------------------------------
EJ0001: Failed to initialize the HCCP process. Reason: Maybe the last training process is running. //EJ0001为错误码,之后是错误的描述与原因,本例子的错误原因是多次启动了相同8节点的分布式训练,造成进程冲突
Solution: Wait for 10s after killing the last training process and try again. //此处打印信息给出了问题的解决方案,此例子建议用户清理进程
TraceBack (most recent call last): //此处打印的信息是开发用于定位的堆栈信息,一般情况下用户不需关注
```
```text
tsd client wait response fail, device response code[1]. unknown device error.[FUNC:WaitRsp][FILE:process_mode_manager.cpp][LINE:233]
```
另外在一些情况下,CANN会抛出一些内部错误(Inner Error),例如:错误码为 "EI9999: Inner Error" 此种情况如果在MindSpore官网或者论坛无法搜索到案例说明,可在社区提单求助。
## Q: 如何控制`print`方法打印出的Tensor值?
A: 在PyNative动态图模式下,可以使用numpy原生方法如`set_printoptions`对输出的值进行控制。在Graph静态图模式下,因为`print`方法需要转化成为算子,所以暂时无法对输出的值进行控制。print算子具体用法可[参考](https://www.mindspore.cn/docs/zh-CN/r2.3.0rc1/api_python/ops/mindspore.ops.Print.html)。
## Q: `Tensor.asnumpy()`是怎么和Tensor共享内存地址的?
A: `Tensor.asnumpy()`会将Tensor本身转换为NumPy的ndarray。这个Tensor和`Tensor.asnumpy()`返回的ndarray共享host侧的内存地址,在host侧,对Tensor本身的修改会反映到相应的ndarray上,反之亦然。需要注意的是,host侧的修改无法自动同步到device侧。如:
```text
import mindspore as ms
x = ms.Tensor([1, 2, 3]) + ms.Tensor([4, 5, 6])
y = x.asnumpy()
# x 是 device 侧算子计算的结果,而 y 在 host 侧。host 侧对 y 的修改无法自动同步到 device 侧的 x。
y[0] = 11
print(y)
# 打印 x 会触发数据同步,将 x 的数据同步到 y。
print(x)
print(y)
```
运行结果如下:
```text
[11 7 9]
[5 7 9]
[5 7 9]
```