• [其他] 浅谈强化学习基本模型和原理
    强化学习是从动物学习、参数扰动自适应控制等理论发展而来,其基本原理是:如果Agent的某个行为策略导致环境正的奖赏(强化信号),那么Agent以后产生这个行为策略的趋势便会加强。Agent的目标是在每个离散状态发现最优策略以使期望的折扣奖赏和最大。强化学习强化学习把学习看作试探评价过程,Agent选择一个动作用于环境,环境接受该动作后状态发生变化,同时产生一个强化信号(奖或惩)反馈给Agent,Agent根据强化信号和环境当前状态再选择下一个动作,选择的原则是使受到正强化(奖)的概率增大。选择的动作不仅影响立即强化值,而且影响环境下一时刻的状态及最终的强化值。强化学习不同于连接主义学习中的监督学习,主要表现在强化信号上,强化学习中由环境提供的强化信号是Agent对所产生动作的好坏作一种评价(通常为标量信号),而不是告诉Agent如何去产生正确的动作。由于外部环境提供了很少的信息,Agent必须靠自身的经历进行学习。通过这种方式,Agent在行动一一评价的环境中获得知识,改进行动方案以适应环境。强化学习系统学习的目标是动态地调整参数,以达到强化信号最大。若已知r/A梯度信息,则可直接可以使用监督学习算法。因为强化信号r与Agent产生的动作A没有明确的函数形式描述,所以梯度信息r/A无法得到。因此,在强化学习系统中,需要某种随机单元,使用这种随机单元,Agent在可能动作空间中进行搜索并发现正确的动作。
  • [其他] 浅谈深度学习模型压缩
    常见的模型压缩方法有以下几种:    模型蒸馏 Distillation,使用大模型的学到的知识训练小模型,从而让小模型具有大模型的泛化能力    量化 Quantization,降低大模型的精度,减小模型    剪枝 Pruning,去掉模型中作用比较小的连接    参数共享,共享网络中部分参数,降低模型参数数量    teacher-student模型    teacher-student模型是迁移学习的一种,迁移学习也就是将一个模型的性能迁移到另一个模型上,对于教师网络往往是一个更加复杂的网络,具有非常好的性能和泛化能力,可以用这个网络来作为一个soft target来指导另外一个更加简单的学生网络来学习,使得更加简单、参数运算量更少的学生模型也能够具有和教师网络相近的性能   知识蒸馏作为前端压缩比较热门的一种压缩技术,其核心思想是通过学习的方法,将庞大复杂的模型迁移到一个精简的小模型上,尽量保持原有模型的特征和精度。这两个模型就类似于老师和学生两个角色,大的模型是老师,精简的模型是学生,通过一定的学习方法尽量继承大模型的特征,而这些学习方法就是研究人员正在研究的蒸馏算法。2014 年,Jimmy 等人认为 Softmax 层含有更为丰富的监督信息,可以作为网络中知识的有效概括。2016 年,Luo 等人提出可以使用Softmax 前一层的输出来指导小模型的训练,可以取得很好的分类效果,其精度甚至超过大模型。但蒸馏因为指导训练的方法较难确定,一直没有得到广泛应用。后端压缩中常用的模型压缩方法是参数量化,其核心思想是从权重中归纳出若干“代表”,由这些“代表”来表示某一类权重,将这些代表储存在码本(Codebook)当中,原始权重矩阵只需在码本中索引所需要的代表就可以,这样会大大降低储存的开销。2014 年,Gong 等人提出将 K 均值聚类算法(K-Means clustering algorithm,K-Means)应用于模型量化,可以使模型大小和准确率之间得到很好的平衡,在比较先进的卷积神经网络(Convolutional Neural Networks, CNN)上可以实现 16-24倍的网路压缩,精度只有 1%的损失。同样基于 K-Means 的思想,Han 等人采用了标量量化的方法,令 K 值等于 4,对所有的权重进行聚类,并储存在码本当中,原始权重只记录码本的索引,这样可以使模型储存空间降低,同时针对精度损失的问题,他们借鉴了剪枝的微调思想,最后对量化后的模型进行微调,使精度有所回升。目前还有一种比较主流且集成好的量化方案就是 TensorRT,TensorRT 是由NVIDIA 公司开发的一个高性能加速工具包,它可以实现将原来 32 位浮点类型的卷积操作替换成 16 位浮点类型的卷积操作或 8 位整数类型的卷积操作,使计算量大大减小,从而降低模型大小,提升推理速度。 后端压缩还有一项重要技术就是模型剪枝,被广泛的应用于神经网络算法的后处理当中,可以有效降低模型大小,减少参数冗余。早在 1990 年,Yann 等人就提出采用二阶导数对网络复杂性和测试误差之间做过一个平衡,通过删除不重要的权重,使模型测试效果达到最优。之后,Babak 等人的剪枝算法也证明了其思想的正确性,但是此类方法多是基于二阶梯度来判断权重的重要程度,所以压缩的程度比较小,无法实现大数量级别的压缩。
  • [其他问题] notebook训练模型,关闭终端(没关闭botebook)后,如何再次打开原终端,查看训练输出进度?
    如题,notebook训练模型,关闭终端后(没关闭botebook),如何再次打开原终端界面,查看训练输出进度?
  • [问题求助] 在Atlas200DK上运行强化学习算法
    想在Atlas200DK上运行强化学习算法,但之前没这么用过,请问有什么技术支持或者开发案例可供入门吗?
  • [其他] 浅谈生成对抗网络
    生成对抗网络深度学习在很多领域的都取得了突破性进展,但大家似乎发现了这样的一个现实,即深度学习取得突破性进展的工作基本都是判别模型相关的。2014 年 Goodfellow 等人启发自博弈论中的二人零和博 弈 ,开创性地提出了生成对抗网络 (GAN)。生成对抗网络包含一个生成模型和一个判别模型。其中,生成模型负责捕捉样本数据的分布,而判别模型一般情况下是一个二分类器,判别输入是真实数据还是生成的样本。这个模型的优化过程是一个“二元极小极大博弈”问题 ,训练时固定其中一方(判别网络或生成网络),更新另一个模型的参数,交替迭代,最终,生成模型能够估测出样本数据的分布。生成对抗网络的出现对无监督学习,图片生成的研究起到极大的促进作用。生成对抗网络已经从最初的图片生成,被拓展到计算机视觉的各个领域,如图像分割、视频预测、风格迁移等。深度卷积生成对抗网络深度卷积生成网络(DCGAN)将卷积神经网络(CNN) [4]  引入到了生成模型和判别模型当中,使得生成性能有了质的提升,以至于后来很多工作都在该网络的基础上进行改进。该网络结构的几个设计要点为:1)将卷积网络中的池化层用相应步长的卷积层代替;2)在生成模型和判别模型中都使用了批归一化层;3)去掉了网络中的全连接层;4)在生成模型中采用Re LU激活函数;5)在判别模型中采用Leaky Re LU激活函数。其生成模型结构图如图3所示。深度卷积生成网络相对于一般的生成对抗网络而言具有更强大的生成能力,同时训练起来更加稳定、容易,生成样本更加多样化等优点。深度卷积生成网络生成的图片足以以假乱真,但缺点是生成图像分辨率比较低(64 * 64),这也是现阶段各种生成对抗网络及其变体所具有的共同问题,因此,如何生成高质量、高分辨率图像将会是一个热门研究方向。半监督生成对抗网络半监督生成对抗网络(SGAN)的判别模型不仅仅判断图像的来源(由 G 生成或者来自训练数据)同时判断图像的类别,这样使得判别模型具有更强的判别能力,其网络结构图。另一方面,输入网络的类别信息也在一定程度上提高了生成模型生成图片的质量,因此半监督生成抗网络的性能要比普通的生成对抗网络的性能略好一些。生成对抗网络的应用图像分割图像分割是指将图像的中的内容根据不同的语义分割开来。绝大多数分割的方法是将图像的每个像素进行分类,这样就忽略了空间一致性这个重要信息。生成对抗网络做图像分割时,生成模型被图像像素分类的网络替换,判别模型用于判断是网络的分类产生的分割图(Class predictions)还是标准的分分割图(Ground truth)。视频预测视频预测是根据当前的几帧视频预测接下来的一帧或者多帧视频。一般常用的做法是用最小二乘回归视频帧的逐个像素值,这样做的一个问题就是生成视频帧存在动作模糊(Motion blur)。一种采用生成对抗网络的做法是,将现有视频帧改变不同尺寸 输入生成模型 G ,让 其 输 出 接 下 来 的 真 值 帧(Ground truth frame)。图6给出了生成对抗网络应用于视频预测时生成网络部分示意图。判别模型和一般生成对抗网络相同,即判断视频帧是生成的还是训练数据原有的风格迁移风格迁移是指将目标图像的风格迁移到源图像当中,使得源图像保留内容的同时具有目标图像的风格,比如将卡通人物的风格迁移到真实人脸图像使其成为卡通头像。生成对抗网络用于图像风格迁移时其特点有3个:1)将源图像输入生成网络后,生成网络输出目标图像风格的图片;2)生成图像和源图像特征相同(或者说保持内容);3)当把目标图像输入生成网络后,生成网络仍然输出目标图像(相当于单位映射)。
  • [其他] 浅学R-CNN目标检测上的算法
    R-CNN的全称是Region-CNN,是第一个成功将深度学习应用到目标检测上的算法。R-CNN基于卷积神经网络(CNN),线性回归,和支持向量机(SVM)等算法,实现目标检测技术。R-CNN的全称是Region-CNN,它可以说是第一个成功将深度学习应用到目标检测上的算法。传统的目标检测方法大多以图像识别为基础。 一般可以在图片上使用穷举法选出所有物体可能出现的区域框,对这些区域框提取特征并使用图像识别方法分类, 得到所有分类成功的区域后,通过非极大值抑制(Non-maximumsuppression)输出结果。R-CNN遵循传统目标检测的思路,同样采用提取框,对每个框提取特征、图像分类、 非极大值抑制四个步骤进行目标检测。只不过在提取特征这一步,将传统的特征(如 SIFT、HOG 特征等)换成了深度卷积网络提取的特征。R-CNN 体框架如图1所示。对于一张图片,R-CNN基于selective search方法大约生成2000个候选区域,然后每个候选区域被resize成固定大小,并送入一个CNN模型中,最后得到一个特征向量。然后这个特征向量被送入一个多类别SVM分类器中,预测出候选区域中所含物体的属于每个类的概率值。每个类别训练一个SVM分类器,从特征向量中推断其属于该类别的概率大小。为了提升定位准确性,R-CNN最后又训练了一个边界框回归模型,通过边框回归模型对框的准确位置进行修正。
  • [MindX SDK] Overlap-Recovery重叠文本还原设计案例
    MindX SDK-Overlap-Recovery重叠文本还原参考设计1 介绍本开发样例使用自研算法完成重叠文本的还原任务,供用户参考。 本系统基于昇腾Ascend310卡。本仓库是重叠文本识别任务(Overlap-CRNN)的上游任务,即完成对重叠文本还原并输出文本实例的mask。1.1 支持的产品本系统采用Ascend 310作为实验验证的推理硬件平台,训练硬件平台支持Ascend和GPU。1.2 支持的版本推理代码支持的版本为MindX SDK 3.0RC3,Ascend-CANN-toolkit 6.0.RC1。1.3 软件方案介绍软件方案主要为文本还原的系统,子系统功能具体描述请参考 表1.1 系统方案各子系统功能描述。重叠文本还原子系统可以实现还原重叠文本并得到各个文本实例的mask,本方案选择使用基于分割的算法并提出一种重叠区域感知的模块来恢复出重叠文本实例。系统方案中各模块功能如表1.2 所示。表1.1 系统方案各子系统功能描述:序号子系统功能描述1重叠文本还原子系统重叠文本还原子系统将得到重叠文本实例的mask的结果,之后将结果送入到下游的文字识别模型进行文字识别。表1.2 系统方案中各模块功能:序号子系统功能描述1输入图像将图像(JPG/PNG格式)通过Pillow库读入。2图像解码通过Pillow第三方库对图像解码。3图像放缩模型的输入为固定尺寸,所以需要对输入图片进行等比例放缩。4文字还原在图像放缩后,将缓存区数据送入文字还原模型。本方案选用自研算法进行文本还原5结果可视化通过Pillow库可视化单张图像的预测的文本实例mask。1.4 代码目录结构与说明eg:本sample工程名称为Overlap-Recovery,工程根目录如下图所示:├── train #训练代码的文件夹 ├── inference #推理代码的文件夹其中,Overlap-Recovery/train工程目录如下图所示,训练部分代码下载链接。├── eval.py #精度测试 ├── train.py #模型训练主函数 ├── export.py #将ckpt模型导出为onnx格式的模型 ├── __init__.py ├── src #模型源码及相关辅助函数 │ ├── __init__.py │ ├── dataset #数据集加载、预处理等相关函数 │ │ ├── __init__.py │ │ ├── base_dataset.py #dataset类的基类 │ │ ├── build_dataset.py #提供接口构造dataset对象 │ │ ├── data_process.py #数据预处理相关函数 │ │ ├── real_dataset.py #用于测试数据的dataset类 │ │ ├── synth_dataset.py #用于训练数据的dataset类 │ │ ├── utils.py #dataset构造所需的辅助函数 │ ├── deoccluder #去重叠算法相关代码 │ │ ├── __init__.py │ │ ├── deoccluder_r50.py #模型主结构代码 │ │ ├── fpn_neck.py # FPN模块代码 │ │ ├── resnet.py # resnet-50 backbone代码 │ │ ├── utils.py # 辅助函数 │ │ ├── rpn # kernel初始化相关 │ │ │ ├── __init__.py │ │ │ ├── kernel_head.py # kernel初始化相关函数 │ │ │ ├── positional_encoding.py # 位置编码函数 │ │ │ ├── semantic_fpn_warpper.py # 语义fpn编码 │ │ ├── roi # kernel更新相关 │ │ │ ├── __init__.py │ │ │ ├── custom_kernel_iter_head.py # kernel迭代函数 │ │ │ ├── custom_kernel_update_head.py # kernel更新函数 │ │ │ ├── kernel_update_head.py # kernel更新函数基类 │ │ │ ├── kernel_updator.py # kernel更新辅助函数 │ │ ├── custom_cells # 算法组件 │ │ │ ├── __init__.py │ │ │ ├── custom_assigner.py # 标签分配函数 │ │ │ ├── custom_blocks.py # 自定义模块 │ │ │ ├── custom_losses.py # 自定义损失函数 │ │ │ ├── custom_match_cost.py # 自定义匹配代价评估函数 │ │ │ ├── custom_operations.py # 自定义算子 │ │ │ ├── custom_samplers.py # 自定义采样函数 │ ├── model_utils # 模型训练相关代码 │ │ ├── __init__.py │ │ ├── device_adapter.py │ │ ├── local_adapter.py │ │ ├── moxing_adapter.py │ │ ├── configs # 配置文件函数 │ │ │ ├── __init__.py │ │ │ ├── config_base.py │ │ │ ├── config_model.py │ ├── utils # 将pytorch权重转为mindspore权重 │ │ └── pth2ckpt.py ├── scripts # scripts文件 │ ├── convert_resnet.sh # 将pytorch的resnet权重转为mindspore权重 │ └── train.sh # 训练指令 ├── resource_utils # 转换pytorch权重所需的相关材料 │ └──resnet50_dict.json其中,Overlap-Recovery/inference工程目录如下图所示:├── eval.py #精度测试 ├── eval_utils.py #指标计算的辅助函数 ├── load_ann.py #加载测试集 ├── load_img_data.py #加载图片数据 ├── ominfer.py #单张图片推理 ├── preprocess_utils.py #加载图片做预处理的辅助函数 ├── README.md ├── models #不同类型的模型文件 │ ├── best_iou.onnx │ └── best_iou.ckpt │ └── best_iou.om ├── dataset #测试数据集 │ ├── img │ └── annotation.json1.5 技术实现流程图实现流程图如下图所示:1.6 特性及适用场景本案例中的还原模型适用于常规图像的文本,并可以返回测试图像的文本区域的IOU指标。本模型在以下几种情况还原效果良好:图像中文字清晰可见、排版工整、字符大小适中等。在以下几种情况去噪效果不太好:图像中文字模糊、排版随意、字符较小等。1.7 代码地址本项目的代码地址为:cid:link_22 环境依赖下面列出环境依赖软件和版本。推荐系统为ubuntu 18.04或centos 7.6。2.1 训练环境训练支持Ascend和GPU硬件。其中GPU环境下依赖的软件和版本如下表:软件名称版本CUDA11.1ubuntu18.04.1 LTSpython3.9.2MindSpore1.9.0opencv-python4.6.0.66numpy1.23.1pillow9.1.0mmcv0.2.14loguru0.2.14tqdm4.64.1imagesize1.4.1terminaltables3.1.10其中Ascend环境下依赖的软件和版本如下表:软件名称版本Ascend-CANN-toolkit6.0.RC1ubuntu18.04.1 LTSpython3.9.2MindSpore1.9.0opencv-python4.6.0.66numpy1.23.1pillow9.1.0mmcv0.2.14loguru0.2.14tqdm4.64.1imagesize1.4.1terminaltables3.1.102.2 推理环境推理环境依赖软件和版本如下表:软件名称版本MindX SDK3.0RC3Ascend-CANN-toolkit6.0.RC1ubuntu18.04.1 LTSpython3.9.2cv24.5.5.64numpy1.23.1pillow9.1.0mmcv-full1.7.0在运行推理项目前,需要设置环境变量:环境变量介绍. ${sdk_path}/set_env.sh . ${ascend_toolkit_path}/set_env.sh3 模型训练步骤0 下载训练部分的源码放置到Overlap-Recovery/train文件夹下。步骤1 从pytorch官方下载resnet-50预训练权重 ,并利用脚本转换成mindspore支持的格式# 准备好logs保存路径 mkdir train/logs # 运行转换脚本 sh train/scripts/convert_resnet.sh PATH-TO-PYTORCH-WEIGHT PATH-TO-MINDSPORE-WEIGHT步骤2 修改训练相关的配置参数在train/src/model_utils/config_base.py中,完成下述参数的修改:a) 设置训练设备类型:设置103行的device_target选择在GPU或者Ascend设备上训练。b) 修改105行mindrecord_dir为预期的log输出和模型保存路径。c) 修改预训练backbone路径:将107行的pretrained_r50改为步骤1中转换后的backbone权重路径。# 用于训练的设备 ['GPU', 'Ascend'] device_target='GPU', # 训练时的log文件和权重的保存路径 mindrecord_dir='path-for-saving-logs-and-files', # 预训练backbone的权重路径 pretrained_r50='path-to-pretrained-model',d) 修改数据集路径:参考测试数据的格式准备好训练数据,修改synth_data_root和real_data_root参数为训练集、测试集的根目录。# 39行的训练集的根目录 SYNTH_DATA_ROOT = "root-directory-to-train-data" # 41行的测试集的根目录 REAL_DATA_ROOT = "root-directory-to-test-data"e) 修改训练的epoch数量: 将94行的total_epoch根据训练集数据量调整为合适的数值。在本案例中total_epoch设置为了60,但训练数据量较大,所以在训练到第2个epoch时性能就满足要求,也可以提前终止训练。步骤3 按照2.1节环境依赖要求配置好训练所需运行环境后,执行如下命令启动模型训练。python train/train.py注:在Ascend上如需指定特定设备序号,可在训练命令前加上DEVICE_ID=X。在GPU上如需指定特定设备序号,可在训练命令前加上CUDA_VISIBLE_DEVICES=X。步骤4 使用训练好的mindspore模型直接推理修改train/src/model_utils/config_base.py中112行checkpoint_path参数为要测评的checkpoint的路径,执行如下命令推理。python train/eval.py4 模型转换通过第三节的训练后得到ckpt模型文件,在项目运行前需要先将ckpt文件通过 export.py 转换成ONNX模型文件,然后在本代码仓下通过ATC将ONNX转换成om模型,其中ckpt->onnx的转换在训练环境下进行(参考第2.1节所述),onnx->om的转换在推理环境下进行(参考第2.2节所述)。模型转换工具(ATC)相关介绍如下:ATC介绍具体步骤如下:准备好训练得到的ckpt模型文件,放至服务器上Overlap-Recovery/train/models文件夹下,环境同训练环境相同(硬件包含CPU,参考第2.1节所述)。进入Overlap-Recovery/train文件夹下,修改export.py文件中ckpt_file_path和file_name参数为自己的路径,执行如下命令完成ckpt->onnx的模型转换:cd train python export.py将生成的ONNX模型转移到推理服务器,放至在Overlap-Recovery/inference/models路径下,环境同推理环境相同(硬件为Ascend 310,参考第2.2节述所)。进入推理服务器执行如下命令(修改onnx_model_path和output_model_path参数为自己的路径)完成onnx->om的模型转换:cd inference/models atc --model=[onnx_model_path] --framework=5 --output=[output_model_path] --soc_version=Ascend310 --input_shape="img:1,3,768,768" --precision_mode=force_fp32执行该命令会在当前目录下生成项目需要的模型文件[output_model].om。执行后终端输出为:ATC start working now, please wait for a moment. ATC run success, welcome to the next use.表示命令执行成功。相关模型的下载链接如下:models.zip。 将模型按照提供的文件夹目录放至即可。5 模型推理当已有模型的om文件,保存在Overlap-Recovery/inference/models/下,推理所需环境如第2.2节所述。示例步骤如下:步骤1 将任意一张待预测的图片存到当前目录下(./Overlap-Recovery/inference),文件名修改为test。步骤2 按照第4节模型转换获取om模型,放置在Overlap-Recovery/inference/models/路径下。若未自行转换模型,使用的是仓库提供的模型,则无需修改相关文件,否则修改ominfer.py中相关配置,将model_path对象的路径改成实际的om模型的路径;img_prefix和img_name对象的路径改成实际的测试图片的路径;save_path对象设置成需要保存可视化图像的路径。步骤3 在命令行输入 如下命令运行单张图片模型推理:cd inference python ominfer.py步骤4 运行结束输出test文件夹,预测的mask可视化结果保存在test文件夹下。6 测试精度步骤1 在Overlap-Recovery/inference/dataset/路径下准备相同格式的数据集(已提供测试用的数据集,按照文件目录放至即可:dataset.zip)步骤2 在命令行输入 如下命令运行精度测试:cd inference python eval.py模型在测试集上的精度达标,最终模型的的精度为87.0%,满足精度要求(≥80%)。
  • [应用开发] 如何升级CANN
    我用的硬件是MDC300,用的CANN版本是Ascend-cann-toolkit_5.0.mdc300_linux-x86_64.run,在onnx转om过程中出现算子不支持的情况,是否升级在最新版本,算子就可以支持,如何升级最新版本呢?
  • [问题求助] 如何升级CANN
    现在用的是MDC300平台,安装的cann版本是Ascend-cann-toolkit_5.0.mdc300_linux-x86_64.run,但是在onnnx转om文件时,用到了不支持的算子,如何解决不支持的算子呢?如果升级cann,需要卸载原来的cann吗?如何升级cann呢?
  • [技术干货] 如何全面掌握图机器学习?最新《图学习》全面综述
    图学习旨在学习现实世界中常见的复杂节点关系和图的拓扑结构,如社交网络、学术网络和电子商务网络等。这些关系使得图数据与传统的表格数据不同,其中节点依赖于非欧氏空间,包含了丰富的信息。图学习从图论发展到图数据挖掘,现在被赋予表示学习的能力,使其在各种场景中取得了出色的性能,甚至包括文本、图像、化学和生物。由于在现实世界中的广泛应用前景,图学习已经成为机器学习中一个热门且有前景的领域。近年来,已有成千上万的研究成果被提出用于解决图学习中的各种问题,引起了学术界越来越多的关注,因此对已有的有价值的研究成果进行综述变得至关重要。尽管一些研究人员已经注意到这种现象,并完成了关于图学习的令人印象深刻的调研。然而,由于图学习的快速扩展,它们未能以更合乎逻辑的方式将相关目标、方法和应用联系起来,并涵盖当前丰富的场景和具有挑战性的问题。1. 引言图学习旨在对图进行建模,图是一种广泛存在于真实场景中的非欧氏数据,与以往机器学习中的数据结构有很大不同,如社交网络[1]、[2]、[3],学术网络[4]、[5]、[6],电子商务网络[7]、[8]、[9],企业知识图谱[10]、[11]、[12]等。挖掘图中节点间复杂连接关系和拓扑结构中蕴含的丰富信息,对于图上的许多任务和应用具有重要意义。此外,传统应用也可以转换为图数据(如计算机视觉[13]、[14]、[15]、语言模型[16]、[17]、[18]、物理[19]、[20]和化学[21]、[22])。重点假设不同实体之间存在许多未直接观察到的潜在联系。这使得图学习不仅是一种处理自然图结构的方法,而且是一种思考各种问题的方式。由于图学习具有广阔的应用前景,因此在国内外引起了广泛的关注。尽管之前关于图的理论工作帮助人们理解图上的各种字符,并提供了基本的分析框架。这些工作通常集中在较小的模拟图上,这限制了它们在真实场景中的应用,特别是当图上存在复杂的关系和结构时。尽管在这一领域已经有了一些显著而详细的调查。目前还缺乏一个综合的、将相关的目标、方法和应用联系起来,形成一个有机的、逻辑的综述。此外,每年在顶级会议上都有数百篇关于图学习的研究,并且数量还在高速增长。由于其发展迅速,缺乏涵盖最新趋势和挑战的全面调研。图2按时间顺序展示了有影响力的图学习方法。这些方法主要分为3类(图挖掘方法、图表示方法和深度图学习方法)。在图学习早期,大多数方法集中于图的字符[1]或利用图的结构信息在小图[25]、[26]上完成一些下游任务。图表示学习目前占据主流地位,可归纳为图嵌入方法和图神经网络方法两大类。这两类方法都旨在学习节点、边或图的语义表示。前者直接优化嵌入,可以减少图结构信息的损失;后者利用深度神经网络,在图上建模信息传递过程。如图3所示,在本综述中,我们从图学习目标的角度提供了一个直观的分类法。根据图的元素(即节点、边和图结构)对以前对图的工作进行排序。基于这种逻辑,综述了图上的相关方法和任务。展示了图学习在现实世界中的各种应用上的出色性能。最后,提出了图学习的发展趋势和挑战,以期进一步推动该领域的研究。本综述的主要贡献总结如下。提供了一个新的分类法,以调查以前关于数据、模型和任务的研究。总结了当前图学习在现实世界中的应用。提出了图学习的当前趋势和挑战。本文的其余部分组织如下。第2节从数据、模型和任务3个角度,基于节点、边和图结构对已有工作进行了直观的分类。第3节展示了用于图学习的主要方法和当前的研究趋势。第四部分总结了该方法在实际中的应用。第5节提出了当今图学习面临的挑战。2 方法在本节中,我们将当前的模型分为两大类(即传统模型和图神经网络)。传统模型可以进一步分为3类(即矩阵分解模型、基于随机游走的模型和基于自编码器的模型)。首先回顾了传统模型,其中一些仍然活跃或与GNN相结合,并给出了当前模型的许多启示。在大多数场景下,与传统模型相比,GNN表现出更高的表达能力和出色的性能。本文将GNN归纳为两个方面。3 应用介绍当前图学习在现实世界中的主要应用,包括传统的机器学习场景,如推荐系统、自然语言处理、计算机视觉和金融科技,以及科学场景中的新兴应用,如化学、生物、物理和数学。最后,总结了图学习中流行的数据集。
  • [经验分享] 使用MindStudio进行MindX SDK 财务票据OCR 开发
    一、任务介绍1.1任务描述在本系统中,目的是基于MindX SDK,在昇腾平台上,开发端到端财务票据OCR识别的参考设计,实现对财务票据中的文本信息进行OCR识别的功能,达到功能要求。视频演示过程:【使用MindStudio进行MindX SDK 财务票据OCR 开发】https://www.bilibili.com/video/BV1644y1m7Qe/?share_source=copy_web&vd_source=2a40c54eb5f208ef5b1c3cb38321c4121.2 任务目标样例输入:财务票据jpg图片样例输出:框出主要文本信息并标记文本内容以及票据类型的jpg图片1.3 环境信息开发环境:Windows 10 + MindStudio 5.0.RC2昇腾芯片:Ascend 310服务器环境依赖软件和版本如下表:软件名称版本Ubantu18.04.1 LTSMindX SDK2.0.4Python3.9.2CANN5.1RC2二、模型介绍本文开发选用了ResNet-50模型实现财务数据分类,通过DB模型实现端到端文本框识别、采用CRNN模型进行抠图以及框内文本内容识别。财务数据识别流程图如下图所示: 票据识别的SDK流程图如下图所示:2.1 票据分类本文开发选用了ResNet-50模型对图片进行分类。ResNet-50模型相关文件可在此处下载: cid:link_2ResNet是ImageNet竞赛中分类问题效果比较好的网络,它引入了残差学习的概念,通过增加直连通道来保护信息的完整性,解决信息丢失、梯度消失、梯度爆炸等问题,让很深的网络也得以训练。ResNet有不同的网络层数,常用的有18-layer、34-layer、50-layer、101-layer、152-layer。支持的特性包括:1、分布式并行训练;2、混合精度训练。2.2 文本框识别本文开发选用db模型对图片进行文本框识别。论文连接:cid:link_11模型相关文件链接:cid:link_3DBNet是基于分割的文本检测算法,算法将可微分二值化模块引入了分割模型,使得分割模型能够通过自适应的阈值进行二值化。经过验证,该方案不仅简化了后处理过程而且提升了文本检测的效果。相较于其他文本检测模型,DBNet在效果和性能上都有比较大的优势,是当前常用的文本检测算法。DB文本检测模型可以分为三个部分:Backbone网络,负责提取图像的特征;FPN网络,特征金子塔结构增强特征;Head网络,计算文本区域概率图。其模型结构如下图所示:2.3 文本内容识别本文使用CRNN模型对文本内容进行识别。CRNN模型相关文件可在此处下载:cid:link_4CRNN是一种基于图像序列识别的神经网络及其在场景文本识别中的应用,本文研究了场景文本识别问题,这是基于图像序列识别中最重要和最具挑战性的任务之一。提出了一种新的神经网络体系结构,将特征提取、序列建模和转录集成到一个统一的框架中。与以前的场景文本识别系统相比,所提出的体系结构具有四个独特的特性:它是端到端可训练的,与大多数现有算法相比,这些算法的组件是单独训练和调整的。它自然地处理任意长度的序列,不涉及字符分割或水平尺度归一化。它不局限于任何预定义的词典,在无词典和基于词典的场景文本识别任务中都取得了显著的性能。它生成了一个有效但小得多的模型,这对于现实世界的应用场景更实用。三、MindStuido介绍与安装MindStudio的具体安装步骤以及详细功能介绍可参考用户手册。3.1 MindStudio简介可提供再AI开发所需的一站式开发环境,支持模型开发、算子开发以及应用开发三个主流程中的开发任务。依靠模型可视化、算力测试、IDE本地仿真调试等功能。MindStudio可以单独安装在Windows上。在安装MindStudio前需要在Linux服务器上安装部署好Ascend-cann-toolkit开发套件包,之后在Windows上安装MindStudio,安装完成后通过配置远程连接的方式建立MindStudio所在的Windows服务器与Ascend-cann-toolkit开发套件包所在的Linux服务器的连接,实现全流程开发功。本文开发采用的就是将MindStudio安装在Windows服务器上时,Windows服务器为本地环境,Linux服务器为远端环境。3.2 MindStudio安装步骤1 : 通过MindStudio下载链接,下载Windows系统的安装包,下载完成后点击下载的安装包安装MindStudio。双击下载好的软件安装包进行安装。步骤2:双击安装包,进入安装界面,单击“Next”。步骤3:在下图安装界面,用户根据需要勾选安装选项后,单击“Next”。其中Create Desktop Shortcut:勾选“MindStudio”,创建桌面快捷方式。Update PATH Variable(restart needed):将MindStudio的启动文件路径加入环境变量PATH中,可从系统命令行直接启动MindStudio。如果勾选此项,MindStudio安装配置完成后会重启操作系统。Update Context Menu:勾选“Add "Open Folder as Project"”后,右键单击文件夹,可以作为MindStudio工程打开。Create Associations:默认不勾选。步骤4:选择MindStudio默认安装路径下的启动菜单文件夹,单击“Install”步骤5:开始安装MindStudio,完成后单击“Next”。步骤6:完成MindStudio安装配置,单击“Finish”。以上安装完成后,启动MindStudio,进入导入设置界面,这里选择的是Do not import settings不导入设置。选择该选项,则创建新的配置文件,默认为该选项。如果没有报错信息且能正常进入欢迎界面,则表示MindStudio安装成功。3.3 MindStudio环境搭建进入欢迎界面后,从欢迎界面打开Remote CANN Setting窗口的图文内容:Customize-》All Settings-》Appearance & Behavior-》System Settings-》CANN点击Remote Connection后面的添加图标点击左上角的“➕”,然后填写服务器连接的相关信息,测试成功后点击OK。点击Remote CANN location后面的文件图标,打开远端服务器目录树,选择CANN安装路径,点击OK,点击Finish开始同步。在欢迎界面点击Plugins,在插件市场搜索并安装如下插件工具。Grep ConsolePylintPython Community Edition在欢迎界面依次点击Customize-》All Settings-》Appearance & Behavior-》System Settings-》MindX SDK打开管理界面。点击“Install SDK”,导入远程MindX SDK。以上步骤全部完成且没有报错信息,表示MindStudio开发环境已成功搭建。3.4 MindStudio新建工程在 Projects 标签下点击“New Project”创建一个新的工程。选择 MindX SDK Project (Python),点击“Finish”。点击File->Project Structure点击“SDKs”,点击加号,点击“Add Python SDK”点击Interpreter后的按钮选择python版本(一般系统会自动检索,如果有多个python版本请手动选择正确的)。填好后点击OK。点击“Project”,选择创建的 SDK。点击 “Modules”->“Dependence”,选择创建的 SDK,点击“OK”。File ->Settings ->Tools ->Deployment,点击Mappings,根据下图操作顺序设置远程映射路径。点击“Tools”-> “Deployment”->“Automatic Upload”。进入远程服务器项目所在目录,两端文件已同步完成开发完成后完整的工程结构如下所示:四、模型转换MindStudio模型转换工具的详细使用和参数说明可参考MindStudio用户手册--模型转换。4.1 Resnet模型转换可以通过在菜单栏选择“Ascend > Model Converter” 进入模型转换界面。​打开模型转换页面,在“Model Information”页签中配置Model File,可以选择远端或本地的模型文件,点击“OK”以后会自动解析模型并自动填充如图相关信息。添加input Node, 参数值为“1,3,224,224”,TYPE选择UINT8。设置模型名称、om 模型生成目录、点击“Next”。进入“Data Preprocessing”数据预处理的配置页,开启Load Aipp Configuration,选择对应的配置文件。配置文件如下所示:最终的数据预处理参数如下,点击“Next”。检查生成的atc命令,确认无误后点击“Finish”。模型转换成功后,如下图所示:4.2 DB模型转换可以通过在菜单栏选择“Ascend > Model Converter” 进入模型转换界面。打开模型转换页面,在“Model Information”页签中配置Model File,可以选择远端或本地的模型文件,点击“OK”以后会自动解析模型并自动填充如图相关信息。添加input Node, --input_shape="x:1,3,-1,-1",TYPE选择FP32。dynamic_image_size="1216,1280;1280,1216;1120,1280;1280,1120;1024,1280;1280,1024;928,1280;1280,928;832,1280;1280,832;736,1280;1280,736;704,1280;1280,704;672,1280;1280,672;640,1280;1280,640;608,1280;1280,608;576,1280;1280,576;544,1280;1280,544;512,1280;1280,512;480,1280;1280,480;448,1280;1280,448"。点击Next。 点击“Next”。进入“Advanced Options Preview”高级选项配置页,在Additional Arguments添加转换参数。Command Preview展示了模型转换使用的atc参数预览数。配置文件如下所示:模型转换成功后,如下图所示:4.3 CRNN模型转换可以通过在菜单栏选择“Ascend > Model Converter” 进入模型转换界面。打开模型转换页面,在“Model Information”页签中配置Model File,可以选择远端或本地的模型文件,点击“OK”以后会自动解析模型并自动填充如图相关信息。input Node参数值为input_shape="x:1,3,48,320",Type选择UINT8。点击“Next”。进入“Data Preprocessing”数据预处理的配置页,开启Load Aipp Configuration,选择对应的配置文件。配置文件如下所示:最终的数据预处理参数如下,点击“Next”。进入“Advanced Options Preview”高级选项配置页, 其中Command Preview展示了模型转换使用的atc参数预览数。确认无误后点击“Finish”。模型转换成功后,如下图所示五、项目开发5.1 pipeline流程编排MindX SDK实现功能的最小粒度是插件,每一个插件实现特定的功能,如图片解码、图片缩放等。将这些插件按照合理的顺序编排,实现相应的功能。这个配置文件叫做pipeline,以JSON格式编写,用户必须指定业务流名称、元件名称和插件名称,并根据需要,补充元件属性和下游元件名称信息。本文实现所使用的插件和工作流程如下:(1)输入类型可以是图片数据(jpg图片序列)(2)调用MindX SDK提供的图像解码接口mxpi_imagedecoder,解码后获取图像数据(3)进行图像尺寸大小变换,调用MindX SDK提供的图像尺寸大小变换接口mxpi_imageresize插件(4)首先进行票据类别识别,调用MindX_SDK的mxpi_tensorinfer接口,将尺寸变换后的图像数据输入Resnet训练模型,完成图片所属票据类别的识别(5)根据所属票据类别,结合DBNet模型方法进行文本框识别,并进行文本框缺失判断(6)检测后处理,调用MindX SDK提供的模型推理插件mxpi_tensorinfer,然后调用MindX SDK提供的插件mxpi_objectpostprocessor,将结果组装成json字符串传给下一个插件(7)抠图,调用MindX_SDK的mxpi_imagecrop插件,将各个文本框分别抠出并标记(8)对框内文本进行识别,然后将结构化信息写入文本文件中。文本文件与图片名保持一致。序号插件功能描述图像解码调用MindX SDK的 mxpi_imagedecoder图像缩放调用MindX SDK的mxpi_imageresize分类识别使用已经训练好的Resnet模型,对图像进行票据分类。插件:mxpi_tensorinfer分类后处理mxpi_classpostprocessor文本框识别使用已经训练好的DBNet模型,对检测出图像中的所有文本框信息。插件:mxpi_tensorinfer检测后处理mxpi_textobjectpostprocessor抠图调用MindX SDK的抠图插件mxpi_imagecrop文字识别使用已经训练好的CRNN模型,对单个文本框进行文字识别。插件:mxpi_tensorinfer文本生成后处理mxpi_textgenerationpostprocessor结构化输出进行后处理插件的开发,将票据类别、文本框分类及文字信息结构化输出到图片同名的文本文件中MindStudio中可以进行可视化流程编排。在顶部菜单栏中选择“Ascend-》MindX SDK Pipeline”,打开空白的pipeline绘制界面,可以在左方插件库中选中所需的插件,并进行插入插件、修改参数等操作。点击Save As进行保存。保存之后可以通过代码进行修改。可在test.pipeline文件中配置所需的模型路径与模型后处理插件路径。next和dataSource制定了各个元件之间的连接关系,om模型地址需要放在推理插件里面,推理插件输出结果不一定可以可视化,所以需要后处理元件对推理插件进行处理输出。最终pipeline可视化如下:5.2 主程序开发由于目前MindStudio连接远程python服务器的功能正在开发中,目前仅支持使用MindStudio实现python项目两端代码同步,项目运行依然需要在服务器上实现。pipeline在脚本main.py内部。获取输入图片文件名与路径将识别的文本内容添加到方框左上方。创建并初始化流管理对象;读取pipeline文件。创建流以及输入对象,输入类型为图片数据(jpg图片序列)。获取输出,并打印结果。判断并标记输入票据的类型保存框出票据的主要文本信息并标记文本内容以及票据类型的jpg图片在./ouput文件夹下。以及最后销毁流。将测试图片放在inputs文件夹中,运行main.py等待运行成功后,MindStudio会自动同步远程项目,但是若是自动同步失败或者没有运行,可以点击菜单栏中的Tools>Deployment>Download,下载服务器里的项目,应当包含模型的输出。待执行完毕可在./outputs目录下查看结果六、模型精度验证测试数据可在此处下载,将下载的数据解压到eval_data目录下。定义获取测试数据的文件名、标签如下:定义计算iou函数以及字符串计数函数如下定义精度函数如下:创建并初始化流管理对象, 读取pipeline。创建流。其中type_acc为分类精度,acc为识别端到端精度。在远程项目目录下执行python3 eval.py可得精度结果如下所示,其中acc为db+crnn端到端精度,type_acc为resnet50精度。七、总结本文主要介绍使用 MindStudio 全流程开发工具链,在昇腾平台上,开发端到端财务票据OCR识别的参考设计,实现对财务票据中的文本信息进行OCR识别的功能,达到功能要求。在开发过程中碰到了很多问题,除了参考 MindStudio用户手册,社区帖子也提供了很多解决问题的思路。建议在开发过程中遇到问题可查看社区相关经验分享。社区地址如下:cid:link_9实现参考链接cid:link_10。参考文档:cid:link_7八、FAQCANN配置失败:Permission denied报错原因与解决方法:原先的CANN安装再root权限的用户下,普通用户没有权限。我们需要重新下载普通用户下,然后导入普通用户的路径。模型转换时,无法导入python module报错原因与解决方法:未配置python的环境变量。打开~/.bashrc文件,添加环境变量。
  • [技术干货] 目标检测算法套件使用Demo
    目标检测算法套件使用指导本Notebook通过引导用户导入数据集、选择模型、训练并可视化推理,快速完成COCO数据集目标检测任务。Step0 安装依赖包!pip install ipywidgets==7.7.1 !pip install pillow==9.1.1 !pip install pandas==1.3.4Step1 加载算法、样例数据集与预训练模型完成模型的微调和探索经典的目标检测方法主要包括单阶段(YOLO、RetinaNet等)和多阶段算法(Faster RCNN、Cascade RCNN等),本案例以fcos算法模型为例,fcos算法属于anchor free的一阶段目标检测算法,具有训练速度快、超参数少等特点。本小节以"mmdetection:fcos/fcos_r50_caffe_fpn_gn-head_1x_coco"模型为例,演示如何下载预训练模型。1. 选择预训练模型#@title Install pretrained model from ma_cau.apis import EnvManager env = EnvManager() env.init_env() # initialize environment algo_name = "mmdetection" #@param {type:"string", dropdown} model_name = "mmdetection:fcos/fcos_r50_caffe_fpn_gn-head_1x_coco" #@param {type:"string", dropdown} dataset_name = "coco2017_sample" #@param {type:"string"}# 安装算法套件,首次安装时可能需要restart kernel用以使用更新后的依赖包 env.install(mode="algorithm", asset_name=algo_name, version="2.17.0")首次安装完套件需要restart kernel,重启后重新执行第一个cell,然后就可以直接执行下面一个cell,不需要再执行安装算法套件步骤def restart_kernel(): import os status = input("Restart Kernel【只需要在第一次安装算法套件时才需要重启kernel,重启后重新执行第一个cell】[y/n(default)]: ") or "n" if status.lower() == "y": os._exit(00) restart_kernel() # 安装样例数据集,数据集会下载到./{project_dir}/data/raw/ env.install(mode="dataset", asset_name=dataset_name) # 从AI Gallery下载 coco2017_sample 数据集 # 安装预训练模型,模型会下载到./{project_dir}/model_zoo/ env.install(mode="model", asset_name=model_name) # 从openmmlab网站下载预训练模型2. 构建数据集DataBlock对象DataBlock支持自动统计数据集信息,比如目标、尺寸等信息,帮助用户更好的理解数据集,同时还可以动态查看每一个batch经过pipeline之后的输入图像,确保数据增强的正确性。detblock.plot_dataset_stats() 可以绘制数据集的统计信息,图像的显示大小可以由figsize参数控制; detblock.print_dataset_stats() 能够打印出具体的统计信息数值; datablock.show_batch() 可以动态展示内存中的经过增强后的图片信息,可以通过rows(显示行数)和figsize(显示大小)来控制输出。DetDataBlock主要接收如下入参:env: EnvManager对象batch_size: 批处理大小 data_type: 数据集类型,目前只支持“coco”,其他数据集格式可以通过CocoConverter进行转换 data_root: 数据集路径 seed:随机数种子,和数据集batch加载顺序相关 num_classes:类别数 categories:类别信息列表,默认为None表示使用所有类别,否则只加载对应类别 train_img_prefix:训练集图片路径,相对于data_root train_ann_file:训练集标注文件路径,相对于data_root val_img_prefix:验证集集图片路径,相对于data_root,可缺省 val_ann_file:验证集标注文件路径,相对于data_root,可缺省 test_img_prefix:测试集图片路径,相对于data_root,可缺省 test_ann_file:测试集标注文件路径,相对于data_root,可缺省 model_name:模型名称#@title Build DataBlock from ma_cau.apis import DetDataBlock num_classes = 80 #@param {type:"integer"} data_root = "./data/raw/coco2017_sample" #@param {type:"string"} train_img_prefix = "val2017" #@param {type:"string"} train_ann_file = "annotations/instances_val2017.json" #@param {type:"string"} val_img_prefix = "val2017" #@param {type:"string"} val_ann_file = "annotations/instances_val2017.json" #@param {type:"string"} batch_size = 4 #@param {type:"slider", min:1, max:10, step:1} db = DetDataBlock(env, batch_size=batch_size, data_root=data_root, seed=0, num_classes=num_classes, train_img_prefix=train_img_prefix, train_ann_file=train_ann_file, val_img_prefix=val_img_prefix, val_ann_file=val_ann_file, model_name=model_name ) 2.1 可视化数据集plotter = db.show_batch(rows=2, figsize=(14, 8))next(plotter)2.2 绘制数据集分布图db.plot_dataset_stats(figsize=(14, 8))2.3 打印数据集分布结果db.print_dataset_stats()3. 构建模型Model对象Model主要接收如下入参:env: EnvManager对象 model_name:模型名称 num_classes:类别数 checkpoint:预训练模型文件路径,默认为None(随机初始化网络权重) load_default_backbone: 是否加载预训练backbone,默认为False。当指定checkpoint参数后,该参数可设置为False请手动选择一个路径,加载预训练模型,如"model_zoo/mmdetection/2.17.0/fcos/fcos_r50_caffe_fpn_gn-head_1x_coco-821213aa.pth"import os from ipyfilechooser import FileChooser from ipywidgets import Layout fc = FileChooser(path=os.getcwd(), layout=Layout(width="1000px")) display(fc)# Build Model from ma_cau.apis import Model ckpt_path = os.path.join(fc.selected_path, fc.selected_filename) fcos_model = Model(env, model_name=model_name, num_classes=num_classes, checkpoint=ckpt_path)4. 构建学习器Learner对象Learner主要接收如下入参model: model对象 datablock: datablock对象 work_dir: 训练输出路径 optimizer: 训练优化器,默认为SGD momentum: 动量 pretrained_model: 预训练模型路径,当构建Model时指定该参数后,此参数可忽略 warmup_policy: warm up策略,如cosine warmup_iters: warm up 步数, 默认为500 epoch_based_eval_interval: 每完成n个epoch训练后进行一次模型评估,用于检测等任务 iter_based_eval_interval: 每完成n个iteration训练后进行一次模型评估,用于分割等任务 save_ckpt_interval: 保存模型的间隔 no_validate: 训练中不进行评估操作,默认为False log_params: 字典类型参数,训练日志类型,默认以表格形式输出训练和评估日志,具体参数如下 log_type: 输出日志类型,默认为table table_highlight_method: 当log_type为table时,对训练结果的高亮方法,默认为best,即高亮最好的训练结果 log_interval: 训练输出间隔,每完成n个训练迭代输出日志 launcher: 分布式作业启动类型,当前暂不支持执行代码如下:from ma_cau.apis import Learner output_path = 'output' log_interval = 11 epoch_based_eval_interval = 1 log_params = { 'log_type': ['graph', 'table'], 'table_highlight_method':'best', 'log_interval':log_interval } learner = Learner(fcos_model, db, output_path, log_params=log_params, epoch_based_eval_interval=epoch_based_eval_interval)learner.fit:model: model对象 datablock: datablock对象 work_dir: 训练输出路径 optimizer: 训练优化器,默认为SGD momentum: 动量 pretrained_model: 预训练模型路径,当构建Model时指定该参数后,此参数可忽略 warmup_policy: warm up策略,如cosine warmup_iters: warm up 步数, 默认为500 epoch_based_eval_interval: 每完成n个epoch训练后进行一次模型评估,用于检测等任务 iter_based_eval_interval: 每完成n个iteration训练后进行一次模型评估,用于分割等任务 save_ckpt_interval: 保存模型的间隔 no_validate: 训练中不进行评估操作,默认为False log_params: 字典类型参数,训练日志类型,默认以表格形式输出训练和评估日志,具体参数如下 log_type: 输出日志类型,默认为table table_highlight_method: 当log_type为table时,对训练结果的高亮方法,默认为best,即高亮最好的训练结果 log_interval: 训练输出间隔,每完成n个训练迭代输出日志 launcher: 分布式作业启动类型,当前暂不支持本步骤主要演示训练过程的loss值可视化功能,1 epoch 训练耗时约12分钟,训练1分钟后即可提前手动停止#@title Fit parameters weight_decay = 0.0005 #@param {type:"number"} max_epochs = 1 #@param {type:"slider", min:0, max:20, step:1} lr = 0.001 #@param {type:"slider", min:0.001, max:0.1, step:0.001} learner.fit(lr=lr, max_epochs=max_epochs, weight_decay=weight_decay, gpu_ids=[0])Step3 模型评估1. 评估验证集learner.validate: 用于模型评估,具体参数如下data: 指定评估的数据集,只接受datablock类型的对象, 默认为None, 如果使用默认值则会使用已经定义好并传入Model中的datablock中的验证数据集进行评估 gpu_collect: 是否使用GPU进行评估,默认为True checkpoint: 评估时使用的模型权重路径, 默认为None。当传入有效路径时,该处优先级最高。没有传入参数时,会按完成训练后的模型权重高于Model中指定的checpoint的优先级加载模型权重。如果均未指定checpoint且没有进行训练,则默认使用随机初始化的权重进行评估# learner.validate() # 这步耗时较长,可跳过2. 图片推理learner.predict: 用于模型推理,具体参数如下img_path: 指定需要推理的图片路径 model: 指定用于推理的模型,默认为None, 不填写该参数则默认使用Learner中的Model进行推理 checkpoint: 推理时使用的模型权重路径, 默认为None。当传入有效路径时,该处优先级最高。没有传入参数时,会按完成训练后的模型权重高于Model中指定的checpoint的优先级加载模型权重。如果均未指定checpoint且没有进行训练,则默认使用随机初始化的权重进行推理 device: 推理时的设备类型,默认为'cpu',即使用cpu进行推理 score_thr: 模型logits判别阈值,默认为0.3 save_dir: 推理后的文件保存路径,默认为None手动选择一张图片进行推理,比如"./data/raw/coco2017_sample/val2017/000000000139.jpg"img_fc = FileChooser(path=os.getcwd(), layout=Layout(width="1000px")) display(img_fc)# 模型推理 result = learner.predict(os.path.join(img_fc.selected_path, img_fc.selected_filename))Step4 交互式推理本算法套件支持动态交互式推理方式,您可以通过鼠标勾选需要推理的图片、视频,并且可以选择不同的iou和score参数进行动态比较。测试图片路径:default_ma_cau_project/data/raw/coco2017_sample/val2017/测试视频路径:default_ma_cau_project/algorithms/mmdetection/algorithm/demo/demo.mp4VisDetPlatform主要接收如下几个参数: learner: Learner对象,主要用于在线实时推理; stage:推理图片所属的数据集类别,"train"、"val"、"test"; ann_json: 标注文件路径,主要用于离线展示 det_file: 验证输出的检测结果文件路径,主要用于离线展示 det_box_color:实际检测框颜色 gt_box_color:GT检测框颜色 without_gt:是否只查看数据集标注 classes:关注的类别列表 mask_palette:mask蒙版颜色列表,如果不设置,则使用随机颜色 infer_param: 推理相关参数,如不指定则使用配置文件默认参数,与推理速度相关,主要包含 1. nms_pre:nms操作前生成的bbox数量 2. max_per_img:每张图片最大目标数 3. img_scale:图像resize尺寸from ma_cau.apis import VisDetPlatform infer_param = {"nms_pre": 200, "max_per_img": 20, "img_scale": (800, 600)} VisDetPlatform(learner, infer_param=infer_param, stage="val", det_box_color=(0, 0, 255))如果您不清楚交互式推理的用法,请查看下方视频
  • 使用MindStudio进行基于双目视觉的目标定位
       对应的视频教程,可参考:【使用MindStudio进行基于双目视觉的目标定位】一、基于双目视觉的目标定位介绍基于计算机视觉的目标定位有单目视觉和双目视觉两种定位方式。单目视觉使用一台相机获取场景图像。由于图像透视投影过程丢失深度信息,因此单目视觉深度恢复得到物体的相对位置。双目视觉感知原理基于哺乳动物视觉机制,获取物体在左右两个相机的图像,并从获取图像恢复物体的三维几何信息。双目视觉从场景获取一组图像,利用这组图像标定相机参数,恢复物体三维几何信息。双目视觉的通用流程是特征点提取、特征点匹配、相机标定、三维重建等处理过程,恢复场景物体的三维几何信息,实现从二维图像重建三维场景。本案例输入的是用自制双目相机同时获取场景物体的图像,案例介绍利用MindX SDK对两幅图像进行相机标定、图像畸变矫正、视差求解、用MindX SDK模型检测目标、计算相物体的三维坐标。项目所用硬件平台:Ascend 310服务器,Atlas 200DK板卡,支持的SDK版本为mxVision 3.0.RC3。双目视觉目标定位流程,如图1-1所示。图1-1 双目视觉目标定位流程双目视觉目标定位流程主要步骤如下:(1)输入一组图像数据标定相机参数,标定的参数包括内参和外参。(2)利用标定的相机参数,用OpenCV函数stereoRectify和remap进行图像校正处理。(3)调用OpenCV函数StereoSGBM_create计算两张图像的视差。(4)通过调用MindX SDK 提供的图像处理插件ImageProcessor的成员函数decode解码并获取校正后图像。(5)对图像进行尺寸变换,调用MindX SDK提供的图像处理插件ImageProcessor的图像尺寸大小改变函数resize改变图像尺寸。(6)调用MindX SDK的Model的infer函数,调用YoloV3模型对尺寸变换后的图像进行推理,定位出目标物体。(7)模型后处理,调用MindX SDK函数post.Yolov3PostProces得到模型推理结果。(8)使用 BTensor函数对后处理结果进行处理,得到标注检测到物体包围盒的左上角和右下角坐标。(9)取右下角坐标,用项目方法把物体检测结果转化为三维坐标。二、MindStudio介绍与安装2.1 MindStudio简介      MindStudio是华为自研昇腾AI处理器开发的AI全栈开发工具平台,该IDE(Integrated Development Environment,集成开发环境)上功能很多,可以进行包括网络模型训练、移植、应用开发、推理运行及自定义算子开发等多类型任务。MindStudio具有工程项目管理、编译、调试、运行等常用功能,还具有性能分析、算子比对等功能,可有效提高开发人员的工作效率。此外,MindStudio具有远程操控功能,可执行远端任务。       MindStudio提供AI开发所需的一站式开发环境,支持模型开发、算子开发以及应用开发三个主流程的开发任务。通过模型可视化、算力测试、IDE本地仿真调试等功能,MindStudio能够在一个IDE中高效便捷地完成AI应用开发。MindStudio采用插件扩展机制,开发者可以通过开发插件来扩展已有功能。2.2 MindStudio安装MindStudio下载地址为MindStudio下载-昇腾社区。点击MindStudio_{version}_win.exe后的“软件包下载”,将其下载到本地指定的目录。双击该软件包,即可开始安装MindStudio。MindStudio安装具体步骤包括 。进入MindStudio Setup安装界面,如图2-1所示,单击“Next”。图2-1 MindStudio 安装开始界面2. 非首次安装MindStudio时,可选择是否卸载已安装MindStudio版本。若不卸载已有版本,直接点击“Next”,进入步骤4;若要卸载则勾选相应版本,点击“Next”,进入步骤3,若同时勾选静默卸载,则会保留之前安装的MindStudio版本的一些配置。图2-2 卸载之前安装的MindStudio版本选取3. 选择需要卸载的项,单击“Uninstall”进行卸载。图2-3 卸载MindStudio4. 输入或选择MindStudio的安装路径,单击“Next”进入下一步骤。图2-4 输入或选取确定MindStudio安装路径5. 根据需要勾选安装选项,选项给出是/否在桌面产生MindStudio快捷启动、是/否把MindStudio可执行文件目录加入到系统路径变量PATH、是/否在右键弹出Context菜单出现“Open Folder as Project”选项、MindStudio缺省关联的文件扩展名,图2-5给出.java、.groovy、.kt及.kts扩展名文件。点击“Next”进入下一步骤。图2-5 选取设定安装配置选项       6. 选择或创建MindStudio安装路径下的启动菜单文件夹,默认即可,单击“Install”。图2-6 Start Menu Folder7. 开始安装MindStudio,完成后单击“Next”。8. 安装完成后,单击“Finish”。9. 双击桌面的MindStudio图标启动MindStudio,或者进入MindStudio安装目录的bin文件夹,双击MindStudio应用程序启动MindStudio。进入设置界面,如图2-7所示。图2-7 首次启动环境设置       默认选择“Do not import settings”,即不导入设置。选择该选项会创建新的配置文件。10. 如果没有报错信息则进入欢迎界面,表示MindStudio安装成功,如图2-8所示。图2-8 MindStudio启动初始界面2.3安装项目运行依赖环境2.3.1安装Python1. 进入Python官网,点击Downloads选项,选择下载Python版本。MindStudio目前支持的Python版本为3.7~3.9。2. 将下载Python压缩包解压、运行,进入图2-9所示的安装选项选取界面。3. 此页面中的选项全部勾选即可,然后点击“Next”。图2-9 安装选项设定4. 在Advanced Options 窗口中,点击“Customize install location”更改安装路径;选取“Create shortcuts for installed applications”在桌面创建Python启动快捷图标;选取“Add Python to environment variables”把Python安装目录加入到系统环境变量。点击“Install”进入安装。图2-10 设定Python安装选项5. 安装完成后,打开Command命令提示符窗口,输入“python”,显示如图2-11所示Python版本信息,表明Python成功安装。图2-11 检查python是否成功安装6. 在MindStudio中配置Python解释器(1) 在菜单栏中选择 File → Project Structure,在 Project Structure窗口中,点击 Platform Settings → SDKs,点击上方的“+”添加 Python SDK,如图2-12。图2-12 添加 Python SDK目录       在弹出窗口中选取“Existing environment”,选择python.exe的安装目录,点击“OK”完成在MindStudio配置Python解释器。若选取“New environment”,则会将“Base interpreter”的python 环境复制到工程目录下,该选项设置表示项目所有类库依赖都脱离系统安装python而运行。图2-13 设置Python解释器目录(2) 在Project Structure窗口中点击 Project Settings → Project,选择添加的 Python SDK,如图2-14所示。图2-14 选择Python SDK(3) 在Project Structure窗口中点击 Project Settings → Modules,右键工程名称,选择“Add”菜单项的“Python”,为 Python Interpreter 添加 Python SDK。点击“Apply”后再点击“OK”,如图2-15所示。图2-15 设定 Python解释器       Python SDK已配置完成。注意:上面各项配置好后,先点击“Apply”后再点击“OK”。2.3.2安装MinGW       MinGW下载地址:cid:link_7       选择下图中红框内的版本进行下载。图2-16 MinGW版本选择       下载后直接将其解压至自定义目录。把MinGW的bin文件路径添加到环境变量中,则安装完成。打开Command命令提示符窗口,输入“g++ --version”,显示如图2-17所示信息,则表示安装成功。图2-17 检查MinGW是否成功安装2.3.3安装CMake       CMake下载地址:https://cmake.org/download/       下载图2-18红框所示版本。图2-18 CMake版本选择       下载完成后,双击安装包进入安装。安装时选择“Add CMake to the system PATH for all users”把CMake路径加入到环境变量。安装完成后打开CMD命令提示符窗口,输入“cmake –version”,若显示如图2-19所示窗口,表明CMake安装成功。图2-19 检查CMake是否成功安装2.3.4安装CANN工具包       从菜单栏中点击File → Settings,并在弹出的窗口中选择Appearance & Behavior → System Settings → CANN进入CANN管理界面,如图2-20所示。图2-20 CANN管理界面       上图所示为CANN工具包安装完成界面。CANN工具包未安装时,蓝框中内容为空,点击图中的Change CANN,进入图2-21所示界面。图2-21 CANN安装       单击“Remote Connection”后的“+”号, 配置MindStudio连接远程开发环境Ascend-cann-toolkit开发套件包;单击“Remote CANN location”后的文件夹图标,在弹出界面中选择Ascend-cann-toolkit开发套件包的安装路径(需要选择到版本号一级)。选择完成后点击Finish开始安装。2.3.5安装MindX SDKMindX SDK提供昇腾AI处理器加速的各类AI软件开发套件(SDK),提供极简易用的API,加速AI应用开发。MindX SDK安装过程如下:1. 从菜单栏中点击File → Settings,并在弹出的窗口中选择Appearance & Behavior → System Settings → MindX SDK进入MindX SDK管理界面,如图2-22所示。图2-22 MindX SDK管理界面2. 界面中“MindX SDK Location”为软件包的默认安装路径,默认安装路径为 “C:\Users\用户名\Ascend\mindx_sdk”。单击Install SDK进入Installation settings界面,如图2-23所示。图2-23 MindX SDK安装3. 上图中前两个参数“Remote Connection”与“Remote CANN location”,跟图2-21中的选择保持一致;第三个参数“Remote SDK location”为远端环境SDK的路径,需配置到版本号一级;第四个参数“Local SDK location”为SDK的本地安装路径,图2-24所示为默认安装路径。选择完成后点击OK开始安装。4. 安装完成后的结果如下,点击OK即可。图2-24 成功安装MindX SDK三、基于双目视觉的目标定位开发3.1创建项目3.1.1创建初始项目1. 首先通过SecoClient连接VPN,以确保MindStudio能够连接远程服务器。启动MindStudio进入图2-8所示窗口,点击New Project,弹出图3-1所示新建项目窗口。2. 命名项目,图文案例把项目命名为BinocularStereoDepthRecovery,选择CANN版本及新建项目位置,点击Next。图3-1 新建昇腾项目3. 在打开的窗口左侧选择Ascend App(如图3-1所示),然后选择MindX SDK Projet(Python)(如图3-2所示),点击Finish。图3-2 选择MindX SDK Projet(Python)类型4. 项目创建完成后的初始界面如图3-3所示。图3-3 新建昇腾项目初始界面3.1.2项目文件介绍为新建昇腾项目创建“基于双目视觉的目标定位”所需文件。创建完毕后,BinocularStereoDepthRecovery项目目录树在MindStudio的显示如图3-4所示。图3-4 所需文件创建完毕的昇腾项目其中,image目录存放测试图片,每两个为一组,是我们用自制双目相机同时获取场景物体的图像。model目录存放模型文件,模型下载地址为:YOLOv3-昇腾社区。本案例所下载模型可直接使用,无需模型转换过程。若需要模型转换,可点击图3-5中任意一个红框位置,进入图3-6所示界面进行设置,具体过程可参考:模型转换-用户指南。图3-5 进入模型转换图3-6 模型转换设置界面camera_configs.py文件主要代码介绍如图3-7所示。执行该函数会从camera.xml文件中有序地导入相机参数,并计算校正变化。该函数在yolo_deep.py文件中被调用。图3-7 相机配置文件代码介绍camera.xml文件中含有相机预标定的数据,包括相机内参、外参和畸变参数,如图3-8与图3-9所示。图3-8 camera.xml文件中的相机参数信息图3-9 camera.xml文件中的相机参数信息yolo_deep.py文件计算物体坐标,主要代码介绍如图3-10与图3-11所示。图3-10 物体坐标计算文件代码介绍图3-11 物体坐标计算文件代码介绍yolov3_infer.py为模型推理文件,主要代码介绍如图3-12与图3-13所示。图3-12 模型推理文件代码介绍图3-13 模型推理文件代码介绍3.1.3接口调用介绍本模型采用API接口实现流程编排,对API的调用可参见第一章中“双目视觉目标定位流程的主要步骤”,代码中调用API的地方如下图所示。图3-14 yolo_deep.py文件中对API的调用图3-15 模型推理文件中对API的调用图3-16 模型推理文件中对API的调用如果需要进行pipeline编排,可在MindStudio顶部菜单栏中选择Ascend下的MindX SDK Pipeline,如图3-17所示,进入pipeline绘制界面,详细的pipeline绘制过程可参考可视化流程编排-用户指南。图3-17 打开pipeline绘制界面3.1.4连接远程终端       1. 选择MindStudio Tools菜单的Start SSH session菜单项,如图3-18所示。图3-18 打开Tools菜单选择“Start SSH session…”       在弹出的对话框中选择要连接的远程终端服务器,如图3-19所示。图3-19 选择远程终端连接的服务器       远程终端开启后,点击MindStudio底部状态栏目的Remote Terminal图标,如图3-20所示。图3-20 打开远程终端2. 激活远程终端mxVision的环境变量在远程终端窗口输入指令“vim ~/.bashrc”,在打开的文件末尾添加图3-21红框中内容(该内容从mxVision目录下的set_env.sh文件中复制得到),添加完成后在末行输入“wq!”保存并退出。最后,输入指令“source ~/.bashrc”使环境变量生效。图3-21 设置远程终端mxVision环境变量3. Deployment配置从顶部菜单栏中选择Tools → Deployment → Configuration,如图3-22所示。图3-22 打开Deployment Configuration新弹出的界面如图3-23所示。图3-23 Deployment Configuration界面点击上图中红框位置处的加号,在弹出的对话框中输入new server name。点击OK后Deployment Configuration界面如图3-24。在Connection模块下,Type项选择SFTP,SSH configuration项选择要连接的远程服务器。图3-24 Deployment界面的Connection模块在Mappings模块下,Local path已给出,保持不变;点击Deployment path后的文件夹图标,会弹出一个指定的目录,选择该默认路径即可。图3-25 Deployment界面的Mappings模块返回Connection模块,点击Test Connection,出现图3-26所示界面则代表连接成功,点击OK。然后依次点击Deployment Configuration界面的Apply与OK,完成配置。图3-26 成功连接服务器4. 如图3-27所示,把鼠标放在项目名上,单击鼠标右键,在弹出的菜单项中选择Deployment下的Upload to,在新弹出的对话框中选择所连接的服务器。执行该操作会把MindStudio本地客户端的项目文件会同步到服务器端。图3-27 同步项目文件到服务器端执行完毕后,会看到MindStudio界面下方的File Transfer窗口中显示如下。图3-28 同步成功提示信息进入服务器端,可以看到新生成了一个MindStudio-WorkSpace目录,如下图所示。图3-29 MindX服务器生成工作目录       进入MindStudio-WorkSpace目录,含有BinocularStereoDepthRecovery项目所在目录,如图3-30中红框所示。图3-30 服务器端创建的项目目录       进入到BinocularStereoDepthRecovery项目目录,可以看到从MindStudio本地客户端同步至服务器端的项目文件,目录信息如图3-31所示。图3-31 服务器端项目目录情况3.2运行项目       选择顶部菜单栏Run下的Edit Configurations菜单项,如图3-32所示。图3-32 打开Edit Configurations弹出的窗口如图3-33所示。在窗口左侧,我们选择Ascend App下的项目名;在窗口右侧,Deployment项是前面已经设置过的,Executable项选择此次要执行函数yolo_deep.py的路径。选择完成后点击OK。图3-33 Run Configurations界面设定完要运行的函数后,点击MindStudio界面的程序运行按钮,即下图中红框内的蓝色三角号,便可执行yolo_deep.py程序。图3-34 程序运行按钮 基于双目视觉的目标定位运行结果如图3-35所示。对于输入的两张(用双目相机拍摄的)图像,输出检测到的物体像素坐标,并且输出物体的世界坐标以及物体与相机的距离。图3-35 深度推理结果图3-36为输入图像中的其中一幅,图3-35中输出的距离便是红色汽车模型与相机之间的距离。此外,我们生成了相对应的深度图,如图3-37所示。深度图中越亮的部分表示与相机的距离越近,越暗的部分与相机的距离越远。图3-36 输入图像图3-37 输入图像对应的深度图四、FAQ1. No Python interpreter configured for the module答:未配置Python解释器,可参考2.3.1节中的步骤6配置Python解释器。2. Get MindX SDK version failed!答:选择远程服务器中SDK路径时,没有选择到版本号一级,选择父路径时会提示SDK版本获取失败。可参考2.3.5节完成MindX SDK的安装。3. CANN 连接错误(连接服务器 SSH 成功,但是连接 CANN 失败)答:有可能是没有选择到版本号一级,选择父路径时会报错,也有可能是因为当前用户非 root 用户,还有可能是服务器端内存不足。查看同步 CANN 运行日志可判断缘由,可在服务器端的log目录下查看日志文件。       开发者在使用 MindStudio 或进行算子开发过程中遇到任何问题,都可以在昇腾社区进行互动,提出问题,获得更多的帮助。 昇腾官网:cid:link_8 昇腾博客:cid:link_5 昇腾论坛:cid:link_6   
  • [经验分享] MindStudio模型推理场景精度比对全流程和结果分析
    视频案例,可以查看Bilibili MindStudio模型推理场景精度比对全流程和结果分析:【经验分享】MindStudio模型推理场景精度比对全流程和结果分析1、MindStudio介绍MindStudio提供在AI开发所需的一站式开发环境,支持模型开发、算子开发以及应用开发三个主流程中的开发任务,依靠模型可视化、算力测试、IDE本地仿真调试等功能,MindStudio能够帮助您在一个工具上就能高效便捷地完成AI应用开发,MindStudio采用了插件化扩展机制,开发者可以通过开发插件来扩展已有功能。本实验使用的MindStudio版本为5.0.RC3,安装请参考MindStudio安装教程。2、交付件介绍(1)精度对比简介​ 在下面两种情况下,自有实现的算子在昇腾AI处理器上的运算结果与业界标准算子(如Caffe、ONNX、TensorFlow、PyTorch)的运算结果可能存在差异。在模型转换过程中对模型进行了优化,包括算子消除、算子融合、算子拆分,这些动作可能会造成自有实现的算子运算结果与业界标准算子(如Caffe、TensorFlow、ONNX)运算结果存在偏差。用户原始网络可以迁移到昇腾910 AI处理器上执行训练,网络迁移可能会造成自有实现的算子运算结果与用业界标准算子(如TensorFlow)运算结果存在偏差。(2)实现流程​ 为了帮助开发人员快速解决算子精度问题,需要提供自有实现的算子运算结果与业界标准算子运算结果之间进行精度差异对比的工具。​ MindStudio精度比对工具提供Tensor比对能力,包含余弦相似度、欧氏相对距离、绝对误差(最大绝对误差、平均绝对误差、均方根误差)、相对误差(最大相对误差、平均相对误差、累积相对误差)、KL散度、标准差算法比对维度。精度比对总体流程如下:(3)代码工程本实验基于MindStudio的代码工程结构如下所示。本实验基于MindStudio的代码工程结构如下所示。 ├── caffeResnet50_49048f18 │ ├── acl_net.py //离线模型推理脚本代码 │ ├── caffe_dump.py //原始模型推理脚本代码 │ ├── caffe_model //原始模型文件存储目录 │ │ ├── resnet50.caffemodel │ │ └── resnet50.prototxt │ ├── caffeResnet50.iml │ ├── constant.py //离线模型推理脚本工具脚本 │ ├── data //数据文件夹 │ │ └── img.png │ ├── dump //离线模型dump数据文件夹 │ ├── model //离线模型文件夹 │ │ └── resnet50.om │ ├── npy_dump //原始模型dump数据文件夹 │ ├── output //精度比对输出文件夹 │ │ └── 20221111205145 │ └── src │ └── acl.json //离线模型dump构造文件 (4)文章介绍​ 文章详细记录了如何使用MindStudio中的精度比对功能去进行推理场景下的模型的精度比对操作,包括原始第三方框架下模型的npy数据准备,离线模型的dump数据准备,精度比对以及分析。第三节介绍了MindStudio的昇腾App工程的创建。第四节介绍了推理场景下的数据准备。第五节介绍了精度比对和分析。第六节介绍了整个流程中遇到的问题和解决方案。第七节介绍MindStudio的更多的内容。3、App工程创建打开MindStudio进入算子工程创建界面首次登录MindStudio:在MindStudio欢迎界面中单击“New Project”,进入创建工程界面。非首次登录MindStudio:在顶部菜单栏中选择“File > New > Project...”,进入创建工程界面。创建App工程左侧导航栏选择“Ascend App”,如图所示,在右侧点击选择ACL Project(Python)工程。单击“Next”,在弹出的页面中,Project name那一行输入项目名称,然后点击Finish,既可完成工程的创建。单击“Finish”,完成应用工程的创建若工作窗口已打开其他工程,会出现如图所示提示。选择“This Window”,则直接在当前工作窗口打开新创建的工程。选择“New Window”,则新建一个工作窗口打开新创建的工程。 4、推理场景数据准备(1)准备Caffe模型npy数据文件MindStudio当前版本不提供Caffe模型numpy数据生成功能,请自行安装Caffe环境并提前准备Caffe原始数据“*.npy”文件。本文仅提供生成符合精度比对要求的numpy格式Caffe原始数据“*.npy”文件的样例参考。下面给出Resnet50原始模型dump数据的推理脚本代码。请参考表1的参数说明进行使用。​ 表1 原始模型推理脚本参数说明-wCaffe 权重文件路径,如'resnet50.caffemodel'-i, --input_bins模型推理输入bin文件或者图片文件路径,多个以;分隔,如'./a.bin;./img.png'-n, --input_names模型推理输入节点名称,多个以;分隔,如'graph_input_0:0; graph_input_1:0'-mCaffe 模型文件路径,如'resnet50.prototxt'-odump输出文件路径,如'./output_dir', 该路径需要用户自己创建脚本代码:# coding=utf-8 import caffe import sys import argparse import os import caffe.proto.caffe_pb2 as caffe_pb2 import google.protobuf.text_format import json import numpy as np import time TIME_LENGTH = 1000 FILE_PERMISSION_FLAG = 0o600 class CaffeProcess: def __init__(self): parse = argparse.ArgumentParser() parse.add_argument("-w", dest="weight_file_path", help="<Required> the caffe weight file path", required=False,default="caffe_model/resnet50.caffemodel") parse.add_argument("-m", dest="model_file_path", help="<Required> the caffe model file path", required=False,default="caffe_model/resnet50.prototxt") parse.add_argument("-o", dest="output_path", help="<Required> the output path", required=False,default="npy_dump") parse.add_argument("-i", "--input_bins", dest="input_bins", help="input_bins bins. e.g. './a.bin;./c.bin'", required=False,default="./data/img.png") parse.add_argument("-n", "--input_names", dest="input_names", help="input nodes name. e.g. 'graph_input_0:0;graph_input_0:1'", required=False,default="data:0") args, _ = parse.parse_known_args(sys.argv[1:]) self.weight_file_path = os.path.realpath(args.weight_file_path) self.model_file_path = os.path.realpath(args.model_file_path) self.input_bins = args.input_bins.split(";") self.input_names = args.input_names.split(";") self.output_path = os.path.realpath(args.output_path) self.net_param = None self.cur_layer_idx = -1 @staticmethod def _check_file_valid(path, is_file): if not os.path.exists(path): print('Error: The path "' + path + '" does not exist.') exit(-1) if is_file: if not os.path.isfile(path): print('Error: The path "' + path + '" is not a file.') exit(-1) else: if not os.path.isdir(path): print('Error: The path "' + path + '" is not a directory.') exit(-1) def _check_arguments_valid(self): self._check_file_valid(self.model_file_path, True) self._check_file_valid(self.weight_file_path, True) self._check_file_valid(self.output_path, False) for input_file in self.input_bins: self._check_file_valid(input_file, True) @staticmethod def calDataSize(shape): dataSize = 1 for dim in shape: dataSize *= dim return dataSize def _load_inputs(self, net): inputs_map = {} for layer_name, blob in net.blobs.items(): if layer_name in self.input_names: input_bin = np.fromfile( self.input_bins[self.input_names.index(layer_name)], np.float32) input_bin_shape = blob.data.shape if self.calDataSize(input_bin_shape) == self.calDataSize(input_bin.shape): input_bin = input_bin.reshape(input_bin_shape) else: print("Error: input node data size %d not match with input bin data size %d.", self.calDataSize( input_bin_shape), self.calDataSize(input_bin.shape)) exit(-1) inputs_map[layer_name] = input_bin return inputs_map def process(self): """ Function Description: process the caffe net, save result as dump data """ # check path valid self._check_arguments_valid() # load model and weight file net = caffe.Net(self.model_file_path, self.weight_file_path, caffe.TEST) inputs_map = self._load_inputs(net) for key, value in inputs_map.items(): net.blobs[key].data[...] = value # process net.forward() # read prototxt file net_param = caffe_pb2.NetParameter() with open(self.model_file_path, 'rb') as model_file: google.protobuf.text_format.Parse(model_file.read(), net_param) for layer in net_param.layer: name = layer.name.replace("/", "_").replace(".", "_") index = 0 for top in layer.top: data = net.blobs[top].data[...] file_name = name + "." + str(index) + "." + str( round(time.time() * 1000000)) + ".npy" output_dump_path = os.path.join(self.output_path, file_name) np.save(output_dump_path, data) os.chmod(output_dump_path, FILE_PERMISSION_FLAG) print('The dump data of "' + layer.name + '" has been saved to "' + output_dump_path + '".') index += 1 if __name__ == "__main__": caffe_process = CaffeProcess() caffe_process.process()说明:运行之前需要提前准备数据文件和模型文件,原始模型下载地址为:cid:link_3​ 数据图片下载地址为:https://gitee.com/link?target=https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/models/aclsample/dog1_1024_683.jpg远程安装好caffe的python3环境,在本地配置好安装的caffe的SDK。将上述代码拷贝到新建的python脚本中,右键点击运行该脚本,即可以在参数-o指定的路径下生成npy数据文件。生成的文件是以{op_name}.{output_index}.{timestamp}.npy形式命名。其中{op_name}为算子名称,{output_index}是算子的编号索引,{timestamp}是时间戳;设置numpy数据文件名包括output_index字段且值为0,确保转换生成的dump数据的output_index为0,否则无比对结果,原因是精度比对时默认从第一个output_index为0的数据开始。(2)准备离线模型dump数据通过MindStudio提供的dump功能,生成离线模型的dump数据,需要提前完成以下操作:完成Caffe、TensorFlow或ONNX模型的ATC模型转换,将原始模型转换为OM离线模型。详细介绍请参见模型转换。完成应用工程的开发、编译和运行,确保具备可执行的应用工程。详细介绍请参见应用开发。操作步骤如下:准备好离线模型,离线模型下载地址为:cid:link_3; 或者参考如下模型转换步骤进行模型转换(1) 在菜单栏选择“Ascend > Model Converter”。出现如下配置界面,参数配置参考MindStudio官网>用户指南>模型转换>操作步骤。(2) 单击“Next”,进入“Data Pre-Processing”配置数据预处理页签,界面参考如图所示。说明:数据预处理是昇腾AI处理器提供的硬件图像预处理模块,包括色域转换,图像归一化(减均值/乘系数)和抠图(指定抠图起始点,抠出神经网络需要大小的图片)等功能。只有当“Model Information”页签,“Input Nodes”参数中,输入节点的“Type”有配置为“Uint8”类型,“Data Pre-Processing”页签才可以配置该节点的数据预处理功能。如果模型有多个输入,每个输入节点都可以获取shape信息中的宽和高,并且“Input Nodes”参数中每个输入节点的“Type”都配置为“Uint8”,则“Data Pre-Processing”页签可以配置多个节点的数据预处理功能。(3) 单击“Next”,进入“Advanced Options Preview”高级选项配置页签,界面参考如图所示。(4) 单击Finish完成模型转换。在MindStudio界面下方,“Output”窗口会显示模型转换过程中的日志信息,如果提示“Model converted successfully”,则表示模型转换成功。准备好离线模型的推理代码。推理代码可以从cid:link_0中获取,或者直接拷贝下面代码。构造dump的.json配置,选择“Ascend > Dump Configuration”菜单,弹出“Select Offline Model”窗口,如图所示。注意:如果不知道自己本地同步到远程哪个路径下,可以点击Tools>Development>Configuration下查看。选择.om模型文件,单击“OK”,展示模型文件结构,设置dump开关。如图所示。它会在src目录下生成acl.json配置文件,通过修改窗口最右侧配置项,设置.om模型文件的dump配置项,会自动更新到acl.json文件中。(1) Dump Option:配置dump范围。ALL:所有算子开启dump。Several:自定义部分算子开启dump。选择该项后,需要右键单击待dump数据的算子并选择“Enable Dump”。None:所有算子不开启dump。(2) Dump Mode:dump数据模式。ALL:同时dump算子的输入、输出数据。Input:dump算子的输入数据。Output:dump算子的输出数据。(3) Dump Path:配置保存dump数据文件的路径,默认为:{project_path}/dump。如果Dump Path设置为其他路径,需要确保MindStudio安装用户对该路径具有读写权限。注意:该选项要选择远程的dump目录,当前版本mindstudio只支持选择本地的dump目录,如果不能选择远程dump目录,请自行在acl.json中配置。(4) AclConfig File:Acl配置文件,在dump操作中该文件保存算子的dump配置信息。一般路径为{project_path}/src/acl.json。请参考表2中的参数说明使用该脚本​ 表2 离线模型推理脚本参数说明--devicenpu设备编号。--model_path离线模型文件路径,到文件名层次。--images_path数据文件路径,到数据文件的文件夹层次。import argparse import numpy as np import acl import os from PIL import Image from constant import ACL_MEM_MALLOC_HUGE_FIRST, \ ACL_MEMCPY_HOST_TO_DEVICE, ACL_MEMCPY_DEVICE_TO_HOST, \ ACL_SUCCESS, IMG_EXT, NPY_FLOAT32 buffer_method = { "in": acl.mdl.get_input_size_by_index, "out": acl.mdl.get_output_size_by_index } def check_ret(message, ret): if ret != ACL_SUCCESS: raise Exception("{} failed ret={}" .format(message, ret)) class Net(object): def __init__(self, device_id, model_path): self.device_id = device_id # int self.model_path = model_path # string self.model_id = None # pointer self.context = None # pointer self.input_data = [] self.output_data = [] self.model_desc = None # pointer when using self.load_input_dataset = None self.load_output_dataset = None self.init_resource() def release_resource(self): print("Releasing resources stage:") ret = acl.mdl.unload(self.model_id) check_ret("acl.mdl.unload", ret) if self.model_desc: acl.mdl.destroy_desc(self.model_desc) self.model_desc = None while self.input_data: item = self.input_data.pop() ret = acl.rt.free(item["buffer"]) check_ret("acl.rt.free", ret) while self.output_data: item = self.output_data.pop() ret = acl.rt.free(item["buffer"]) check_ret("acl.rt.free", ret) if self.context: ret = acl.rt.destroy_context(self.context) check_ret("acl.rt.destroy_context", ret) self.context = None ret = acl.rt.reset_device(self.device_id) check_ret("acl.rt.reset_device", ret) ret = acl.finalize() check_ret("acl.finalize", ret) print('Resources released successfully.') def init_resource(self): print("init resource stage:") current_dir=os.path.dirname(os.path.abspath(__file__)) ret = acl.init(os.path.join(current_dir,"./src/acl.json")) check_ret("acl.init", ret) # ret = acl.mdl.init_dump() # check_ret("acl.init", ret) # ret = acl.mdl.set_dump(os.path.join(current_dir,"./src/acl.json")) # check_ret("acl.init", ret) ret = acl.rt.set_device(self.device_id) check_ret("acl.rt.set_device", ret) self.context, ret = acl.rt.create_context(self.device_id) check_ret("acl.rt.create_context", ret) # load_model self.model_id, ret = acl.mdl.load_from_file(self.model_path) check_ret("acl.mdl.load_from_file", ret) print("model_id:{}".format(self.model_id)) self.model_desc = acl.mdl.create_desc() self._get_model_info() print("init resource success") def _get_model_info(self,): ret = acl.mdl.get_desc(self.model_desc, self.model_id) check_ret("acl.mdl.get_desc", ret) input_size = acl.mdl.get_num_inputs(self.model_desc) output_size = acl.mdl.get_num_outputs(self.model_desc) self._gen_data_buffer(input_size, des="in") self._gen_data_buffer(output_size, des="out") def _gen_data_buffer(self, size, des): func = buffer_method[des] for i in range(size): # check temp_buffer dtype temp_buffer_size = func(self.model_desc, i) temp_buffer, ret = acl.rt.malloc(temp_buffer_size, ACL_MEM_MALLOC_HUGE_FIRST) check_ret("acl.rt.malloc", ret) if des == "in": self.input_data.append({"buffer": temp_buffer, "size": temp_buffer_size}) elif des == "out": self.output_data.append({"buffer": temp_buffer, "size": temp_buffer_size}) def _data_interaction(self, dataset, policy=ACL_MEMCPY_HOST_TO_DEVICE): temp_data_buffer = self.input_data \ if policy == ACL_MEMCPY_HOST_TO_DEVICE \ else self.output_data if len(dataset) == 0 and policy == ACL_MEMCPY_DEVICE_TO_HOST: for item in self.output_data: temp, ret = acl.rt.malloc_host(item["size"]) if ret != 0: raise Exception("can't malloc_host ret={}".format(ret)) dataset.append({"size": item["size"], "buffer": temp}) for i, item in enumerate(temp_data_buffer): if policy == ACL_MEMCPY_HOST_TO_DEVICE: if "bytes_to_ptr" in dir(acl.util): bytes_data = dataset[i].tobytes() ptr = acl.util.bytes_to_ptr(bytes_data) else: ptr = acl.util.numpy_to_ptr(dataset[i]) ret = acl.rt.memcpy(item["buffer"], item["size"], ptr, item["size"], policy) check_ret("acl.rt.memcpy", ret) else: ptr = dataset[i]["buffer"] ret = acl.rt.memcpy(ptr, item["size"], item["buffer"], item["size"], policy) check_ret("acl.rt.memcpy", ret) def _gen_dataset(self, type_str="input"): dataset = acl.mdl.create_dataset() temp_dataset = None if type_str == "in": self.load_input_dataset = dataset temp_dataset = self.input_data else: self.load_output_dataset = dataset temp_dataset = self.output_data for item in temp_dataset: data = acl.create_data_buffer(item["buffer"], item["size"]) _, ret = acl.mdl.add_dataset_buffer(dataset, data) if ret != ACL_SUCCESS: ret = acl.destroy_data_buffer(data) check_ret("acl.destroy_data_buffer", ret) def _data_from_host_to_device(self, images): print("data interaction from host to device") # copy images to device self._data_interaction(images, ACL_MEMCPY_HOST_TO_DEVICE) # load input data into model self._gen_dataset("in") # load output data into model self._gen_dataset("out") print("data interaction from host to device success") def _data_from_device_to_host(self): print("data interaction from device to host") res = [] # copy device to host self._data_interaction(res, ACL_MEMCPY_DEVICE_TO_HOST) print("data interaction from device to host success") result = self.get_result(res) self._print_result(result) # free host memory for item in res: ptr = item['buffer'] ret = acl.rt.free_host(ptr) check_ret('acl.rt.free_host', ret) def run(self, images): self._data_from_host_to_device(images) self.forward() self._data_from_device_to_host() def forward(self): print('execute stage:') ret = acl.mdl.execute(self.model_id, self.load_input_dataset, self.load_output_dataset) check_ret("acl.mdl.execute", ret) self._destroy_databuffer() print('execute stage success') def _print_result(self, result): vals = np.array(result).flatten() top_k = vals.argsort()[-1:-6:-1] print("======== top5 inference results: =============") for j in top_k: print("[%d]: %f" % (j, vals[j])) def _destroy_databuffer(self): for dataset in [self.load_input_dataset, self.load_output_dataset]: if not dataset: continue number = acl.mdl.get_dataset_num_buffers(dataset) for i in range(number): data_buf = acl.mdl.get_dataset_buffer(dataset, i) if data_buf: ret = acl.destroy_data_buffer(data_buf) check_ret("acl.destroy_data_buffer", ret) ret = acl.mdl.destroy_dataset(dataset) check_ret("acl.mdl.destroy_dataset", ret) def get_result(self, output_data): result = [] dims, ret = acl.mdl.get_cur_output_dims(self.model_desc, 0) check_ret("acl.mdl.get_cur_output_dims", ret) out_dim = dims['dims'] for temp in output_data: ptr = temp["buffer"] # 转化为float32类型的数据 if "ptr_to_bytes" in dir(acl.util): bytes_data = acl.util.ptr_to_bytes(ptr, temp["size"]) data = np.frombuffer(bytes_data, dtype=np.float32).reshape(tuple(out_dim)) else: data = acl.util.ptr_to_numpy(ptr, tuple(out_dim), NPY_FLOAT32) result.append(data) return result def transfer_pic(input_path): input_path = os.path.abspath(input_path) with Image.open(input_path) as image_file: image_file = image_file.resize((256, 256)) img = np.array(image_file) height = img.shape[0] width = img.shape[1] # 对图片进行切分,取中间区域 h_off = (height - 224) // 2 w_off = (width - 224) // 2 crop_img = img[h_off:height - h_off, w_off:width - w_off, :] # rgb to bgr,改变通道顺序 img = crop_img[:, :, ::-1] shape = img.shape img = img.astype("float16") img[:, :, 0] -= 104 img[:, :, 1] -= 117 img[:, :, 2] -= 123 img = img.reshape([1] + list(shape)) img = img.transpose([0, 3, 1, 2]) result = np.frombuffer(img.tobytes(), np.float16) return result if __name__ == '__main__': current_dir = os.path.dirname(os.path.abspath(__file__)) parser = argparse.ArgumentParser() parser.add_argument('--device', type=int, default=0) parser.add_argument('--model_path', type=str, default=os.path.join(current_dir, "./model/resnet50.om")) parser.add_argument('--images_path', type=str, default=os.path.join(current_dir, "./data")) args = parser.parse_args() print("Using device id:{}\nmodel path:{}\nimages path:{}" .format(args.device, args.model_path, args.images_path)) images_list = [os.path.join(args.images_path, img) for img in os.listdir(args.images_path) if os.path.splitext(img)[1] in IMG_EXT] net = Net(args.device, args.model_path) for image in images_list: print("images:{}".format(image)) img = transfer_pic(image) net.run([img]) # acl.mdl.finalize_dump() # net.run([img]) print("*****run finish******") net.release_resource() 说明:(1) 数据文件应该是与原始模型生成npy数据文件保持一致。(2) 如果是从gitee上下载的代码,需要修改acl.init()这行代码,在里面传入dump的配置参数.json文件。6.设置dump完成后,单击MindStudio界面“Run”菜单,重新编译和运行应用工程。工程运行完毕后,可以在{project_path}/dump路径下查看到生成的dump数据文件。生成的路径及格式说明:time/device_id/model_name/model_id/data_index/dump文件time:dump数据回传落盘时间。格式为:YYYYMMDDhhmmss。device_id:Device设备ID号。model_name:模型名称。model_id:模型ID号。data_index:针对每个Task ID执行的次数维护一个序号,从0开始计数,该Task每dump一次数据,序号递增1。dump文件:命名规则如{op_type}.{op_name}.{taskid}.{timestamp}。如果model_name、op_type、op_name出现了“.”、“/”、“\”、空格时,转换为下划线表示。5、精度比对及分析(1)全网精度比对操作步骤在MindStudio界面菜单栏选择“Ascend > Model Accuracy Analyzer > New Task”菜单,进入比对界面,如下图所示。参考表3配置好参数后点击Next下一步。进入到数据和模型的配置界面。 ​ 表3 精度比对New Task参数说明参数说明Run ModeRemote Run:远程运行。Local Run:本地运行。Windows使用场景下仅支持Remote Run,该参数不展示。Deployment运行配置,选择Remote Run模式时可见,必选配置。通过Deployment功能,详细请参见Deployment,可以将指定项目中的文件、文件夹同步到远程指定机器的指定目录。Remote Toolkit Path远端运行环境toolkit软件包安装路径,选择Remote Run模式时可见,必选配置。例如配置为${HOME}/Ascend/ascend-toolkit/xxx/toolkit。与Deployment参数为绑定关系,单击“Start”后参数值将被保存。再次配置时,如连接已配置过的Deployment,则参数自动填充,可手动修改。Environment Variables环境变量配置,选择Remote Run模式时可见,可以直接在框中输入,也可以单击后在弹窗内单击填写。可选配置,当Model File指定文件为离线模型文件(*.om)时,需要配置环境变量,否则工具将无法为离线模型文件(*.om)进行ATC转换导致比对失败。与Deployment参数为绑定关系,单击“Start”后参数值将被保存。再次配置时,如连接已配置过的Deployment,则参数自动填充,可手动修改。Output Path比对数据结果存放路径,必选配置。无论选择Remote Run模式还是Local Run模式,均需要指定为本端路径。默认路径为当前系统的用户目录。Analysis Mode精度比对分析模式,必选配置。可选择模式为:NPU vs NPU:表示两个比对文件均为昇腾AI处理器上运行生成的dump数据文件。此时Model File参数可选。一般用于分析开启和关闭融合规则时进行模型转换后的dump数据文件之间的精度差。模型转换开启和关闭融合规则的详细介绍请参见模型转换。NPU vs GPU/CPU:表示昇腾AI处理器上运行生成的dump数据文件与原始模型的npy文件进行比对。此时展示Framework必选参数。Framework比对数据所属的框架类型,必选配置。Analysis Mode为NPU vs GPU/CPU时可见。可选类型为:- TensorFlow:TensorFlow框架模型dump数据的精度比对,支持推理、训练场景,Model File参数必选。- ONNX:ONNX框架模型dump数据的精度比对,支持推理场景,Model File参数必选。- Caffe:Caffe框架模型dump数据的精度比对,支持推理场景,Model File参数必选。NPU Dump昇腾AI处理器上运行生成的dump数据文件目录,必选配置。在远端执行比对时(Remote Run),须指定远端设备上的dump数据文件目录。Model File模型文件或融合规则文件。Analysis Mode为NPU vs NPU时,进行离线模型转换开启算子融合功能前后的dump数据精度比对,需要指定开融合的算子映射文件(.json)或离线模型文件(*.om)和关融合的算子映射文件(.json)或离线模型文件(*.om)。Analysis Mode为NPU vs GPU/CPU时,根据Framework选择的框架类型选择不同的文件:l TensorFlow:推理场景选择昇腾模型压缩后的量化融合规则文件(json文件)或离线模型文件(*.om);训练场景选择计算图文件(*.txt)。l ONNX:选择昇腾模型压缩后的量化融合规则文件(json文件)或离线模型文件(*.om)。l Caffe:选择昇腾模型压缩后的量化融合规则文件(json文件)或离线模型文件(*.om)。l 具体选择文件请参见比对场景。Quantization Rule File(.json)量化算子映射关系文件(昇腾模型压缩输出的json文件),可选配置。仅Framework为Caffe时展示。Ground Truth原始模型的npy文件目录,必选配置。在远端执行比对时(Remote Run),须指定远端设备上的原始模型的npy文件目录。Algorithm比对算法维度。取值为:l Cosine Similarity:余弦相似度算法,默认勾选。l Relative Euclidean Distance:欧氏相对距离算法,默认勾选。l Absolute Error,绝对误差,默认勾选,此项执行的比对算法为:l Max Absolute Error:最大绝对误差。l Mean Absolute Error:平均绝对误差。l Root Mean Square Error:均方根误差。l Relative Error,相对误差,默认勾选,此项执行的比对算法为:l Max Relative Error:最大相对误差。l Mean Relative Error:平均相对误差。l Accumulated Relative Error:累积相对误差。l Kullback Leibler Divergence:KL散度算法,默认不勾选。l Standard Deviation:标准差算法,默认不勾选。l 与Customized Algorithm自定义算法之间至少勾选一种算法。Advance Options扩展选项。包括Customized Algorithm、Advisor和Operator Range。Customized Algorithm自定义算法文件路径。与Algorithm内置算法之间至少勾选一种算法。需用户自行准备自定义算法.py文件,所在目录格式为“algorithm”,指定该目录下的自定义算法.py文件,生成自定义算法。自定义算法.py文件相关要求参见《精度比对工具使用指南》附录中的“准备自定义算法.py文件”章节。Advisor专家系统分析开关,默认关闭。开启后会在完成整网比对后对比对结果进行专家系统分析并输出问题节点、问题类型和优化建议。详细介绍请参见比对结果专家建议。使用本功能前需要先执行*pip3* *install* ****pandas****命令安装pandas 1.3或更高版本依赖。与Operator Range无法同时开启。Operator Range设定算子比对范围。有两种设置方式:方式一:单击“Select”按钮,在弹出框内勾选需要比对的算子。方式二:根据Start、End、Step参数配置比对算子的范围。l start:第一个比对的算子,取值范围为[1, 参与计算的算子个数],默认值为1。l end:最后一个比对的算子,取值范围为-1或[start, 参与计算的算子个数],默认值为-1(动态获取网络模型中最后一个参与计算的算子)。l step:第start+stepn个比对的算子,step取值范围为[1, 参与计算的算子个数),默认值为1,n为从1开始的正整数。配置格式为:“start,end,step”。比如:-r 1,101,20,表示算子1,21,41,61,81,101的Tensor参与比对。不配置本参数时,比对网络模型中的所有参与计算的算子。配置本参数且Analysis Mode参数配置为NPU vs NPU时,需同时指定NPU Dump和Ground Truth的Model File分别指定开融合的算子映射文件(.json)或离线模型文件(.om)和关融合的算子映射文件(.json)或离线模型文件(*.om)。与Advisor无法同时开启。(2)全网比对结果分析上面步骤配置好参数后点击start即可以出现对比的结果界面。如下所示。图一 图二 图三 所示将Tensor比对结果界面分为四个区域分别进行介绍。其中1~4区域为整网比对结果。表4 整网比对结果说明区域区域名称说明1菜单栏从左到右分别为Open…、New Task、Refresh、Help四项功能。Open…为打开并展示比对结果csv文件;New Task为创建新的比对任务;Refresh用于读取并刷新File Manager中管理的文件;单击Help弹出小窗,可展示精度比对工具的使用限制(Restrictions)、使用建议、在线教程链接等。2File Manager,历史数据管理显示用户指定文件夹以及文件夹下生成的整网比对的csv文件以及显示通过Open…单独打开的csv文件;对文件夹和csv,提供历史数据管理功能,包括打开、删除、另存为;在文件夹处右键删除;在空白处右键创建新比对任务(New Task)、刷新(Refresh)和Open…(打开并展示比对结果csv文件)。3Model Accuracy Analysis,精度比对分析界面默认仅显示有结果的算子。可单击列名,进行排序;单击Show Invalid Data,可展示无法比对的数据,各列字段含义请参见表2。4Scatter Diagram,各项算法指标的散点分布图Show Model,比对模型可视化展示Scatter Diagram:横坐标表示算子的执行顺序,纵坐标为算法指标在对应Tensor上的实际取值。各字段含义请参见表3。Show Model:分别展示NPU和Ground Truth的模型图。详细介绍请参见表4。表5 比对结果字段说明字段说明Index网络模型中算子的ID。OpSequence算子运行的序列。全网层信息文件中算子的ID。仅配置“Operator Range”时展示。OpType算子类型。NPUDump表示NPU Dump模型的算子名。光标悬浮时,可显示具体算子所在的文件路径。DataType表示NPU Dump侧数据算子的数据类型。Addressdump tensor的虚拟内存地址。用于判断算子的内存问题。仅基于昇腾AI处理器运行生成的dump数据文件在整网比对时可提取该数据。GroundTruth表示Ground Truth模型的算子名。光标悬浮时,可显示具体算子所在的文件路径。DataType表示Ground Truth侧数据算子的数据类型。TensorIndex表示NPU Dump模型算子的input ID和output ID。Shape比对的Tensor的Shape。OverFlow溢出算子。显示YES表示该算子存在溢出;显示NO表示算子无溢出;显示NaN表示不做溢出检测。开启Advisor功能时展示,为比对结果专家建议的FP16溢出检测专家建议提供数据。CosineSimilarity进行余弦相似度算法比对出来的结果。取值范围为[-1,1],比对的结果如果越接近1,表示两者的值越相近,越接近-1意味着两者的值越相反。MaxAbsoluteError进行最大绝对误差算法比对出来的结果。取值范围为0到无穷大,值越接近于0,表明越相近,值越大,表明差距越大。KullbackLeiblerDivergence进行KL散度算法比对出来的结果。取值范围为0到无穷大。KL散度越小,真实分布与近似分布之间的匹配越好。RootMeanSquareError表示均方根误差。取值范围为0到无穷大,MeanAbsoluteError趋于0,RootMeanSquareError趋于0,说明测量值与真实值越近似;MeanAbsoluteError趋于0,RootMeanSquareError越大,说明存在局部过大的异常值;MeanAbsoluteError越大,RootMeanSquareError等于或近似MeanAbsoluteError,说明整体偏差越集中;MeanAbsoluteError越大,RootMeanSquareError越大于MeanAbsoluteError,说明存在整体偏差,且整体偏差分布分散;不存在以上情况的例外情况,因为RMSE ≥ MAE恒成立。MaxRelativeError表示最大相对误差。取值范围为0到无穷大,值越接近于0,表明越相近,值越大,表明差距越大。RelativeEuclideanDistance进行欧氏相对距离算法比对出来的结果。取值范围为0到无穷大,值越接近于0,表明越相近,值越大,表明差距越大。StandardDeviation进行标准差算法比对出来的结果。取值范围为0到无穷大。标准差越小,离散度越小,表明越接近平均值。该列显示NPU Dump和Ground Truth两组数据的均值和标准差,第一组展示NPU Dump模型dump数据的数值(均值;标准差),第二组展示Ground Truth模型dump数据的数值(均值;标准差)。AccumulatedRelativeError进行累积相对误差算法比对出来的结果。取值范围为0到无穷大,值越接近于0,表明越相近,值越大,表明差距越大。MeanAbsoluteError表示平均绝对误差。取值范围为0到无穷大,MeanAbsoluteError趋于0,RootMeanSquareError趋于0,说明测量值与真实值越近似;MeanAbsoluteError趋于0,RootMeanSquareError越大,说明存在局部过大的异常值;MeanAbsoluteError越大,RootMeanSquareError等于或近似MeanAbsoluteError,说明整体偏差越集中;MeanAbsoluteError越大,RootMeanSquareError越大于MeanAbsoluteError,说明存在整体偏差,且整体偏差分布分散;不存在以上情况的例外情况,因为RMSE ≥ MAE恒成立。MeanRelativeError表示平均相对误差。取值范围为0到无穷大,值越接近于0,表明越相近,值越大,表明差距越大。CompareFailReason算子无法比对的原因。若余弦相似度为1,则查看该算子的输入或输出shape是否为空或全部为1,若为空或全部为1则算子的输入或输出为标量,提示:this tensor is scalar。注1:余弦相似度和KL散度比较结果为NaN,其他算法有比较数据,则表明左侧或右侧数据为0;KL散度比较结果为inf,表明右侧数据有一个为0;比对结果为nan,表示dump数据有nan。 注2:光标悬浮在表头可以看到对应的参数详细解释。 注3:若配置了自定义算法比对,则在比对结果的内置算法后增加对应自定义算法列。表6 散点分布图字段说明字段说明Algorithm选择展示对应比对算法结果的散点分布图,不支持展示StandardDeviation、KullbackLeiblerDivergence和AccumulatedRelativeError。Tensor过滤显示Input、Output结果散点分布图。Highlight对算子Tensor散点进行高亮。通过拖拉游标在对应算法指标的[min,max]间滑动来设置算法指标(纵坐标)的阈值,高于或等于阈值的点显示为蓝色,低于阈值的点显示为红色。如针对余弦相似度,图中设置阈值为0.98,小于0.98的算子Tensor被标记为红色。注1:光标移动到对应Tensor点上时,浮窗显示Tensor信息。信息包括:Index(Tensor对应算子的Index)、Op Name(算子名称)、Tensor Index(Tensor类型(input/output))以及Value(在当前算法维度下的Tensor数值)。注2:支持对散点图进行缩放。注3:指定区域3中的Tensor时,高亮对应Tensor点。表7 比对模型可视化展示字段说明字段说明NPU Model离线模型可视化。指定算子映射文件(.json)或离线模型文件(*.om)展示。训练场景下,若整网比对使用的Model File为计算图文件(*.txt),此处不支持展示模型图。Ground Truth Model原始模型可视化。指定原始模型文件展示。Input Model指定算子映射文件(.json)、离线模型文件(*.om)或原始模型文件。注:指定区域3中的Tensor时,高亮对应模型网络中的节点。在第一部分我们可以选择菜单,精度对比、历史等选项。我们可以从第二部分选择我们经过精度对比操作之后得到的不同的答案,并选择我们想要的内容来进行第三部分和第四部分的展示,在本次的实例当中我们只生成了一个模型的整网对比,所以只有一个对应的结果的文件,打开相应的文件夹,双击里面的csv文件,就可以呈现出我们本次模型的精度对比。精度对比页面第三部分看出我们的原模型和转换模型之间每个算子之间的结果的差距,并且也可以得到输入和输出的shape。在后面几栏的算子的精度的对比,我们可以根据不同的评判方法得出原算子和转化的算子之间经过运算之后得出的结果的相似程度来判断算子转化的优劣,我们根据后面几项的精度对比,从数据上可以看出精度正在下降,也意味着误差正在增加。随后也可观察4部分的散点图来观察从最开始的输入到最后的输出,经过每一个算子的计算,两模型之间的精度差距,我们可以看到余弦相似度的值有下降的趋势,且最后的结果接近于零,所以说两模型之间的误差在慢慢的增大。并且在第四部分还可以根据Algorithm选项选择不同的精度比较方法,比如说图1和图3选择的是余弦相似度和均方根误差来来展示精度的对比。在Tensor选项当中,我们可以选择input或者output选项来展示输入或者输出之间的精度对比。我们还可以选择第四部分的show model选项,即可以展示网络模型结构中算子之间的关系,也可以配合精度比对结果来定位具体算子的精度问题。(3)单算子精度比对操作步骤在刚刚的整网络分析界面下,点击下面的Operator Detail,出现如下界面。 对比操作。 (1)基于已经读取到的Tensor信息,通过Operator下拉框选择要比对的算子和对应Tensor(output/input)。 (2)通过Metric选择比对算子的Absolute Error(绝对误差)或Relative Error(相对误差)。 (3)配置输出该指标的TopN个Tensor元素(取值范围为[1,10000])。 (4)单击“Compare”按钮进行单算子比对。 (5)TopN结果显示请参见比对结果。 单算子比对界面说明。算子比对功能是在比对结果的基础上选择具体算子并根据需要指定参数进行比对的。界面展示为图5的6区域、7区域和8区域,如图5。详细介绍请参见表7表7 单算子比对结果说明区域说明5Operator Detail,单算子比对功能。下发单算子比对命令。具体操作请参见比对操作。6单算子比对TopN结果。各列字段解释请参见表8。7Cumulative Error,对于TopN Tensor元素,绘制的误差累积分布折线图。详细介绍请参见表8。比对结果。单算子比对结果界面展示为图5的7区域和8区域。详细介绍请参见表8。表8 比对结果字段说明字段说明6区域Index算子比对的条数。N C H W数据格式。NPUDumpNPU Dump侧算子的dump值。GroundTruthGround Truth侧算子的dump值。Absolute Error绝对误差,NPU Dump侧算子的dump值减Ground Truth侧算子的dump值取绝对值比对出来的结果。小数点后最多6位。Relative Error相对误差,Absolute Error值除以Ground Truth侧算子的dump值比对出来的结果。当Ground Truth侧算子的dump值为0时,该处显示为“-”。小数点后最多6位。7区域A % of tensor elements (B elements) have an absolute error greater than C.当前算子比对的所有tensor元素的绝对误差结果中有A %的tensor也就是B个元素的绝对误差超过了C。其中absolute error根据5区域配置的Metric取值变化可以为relative error;右侧滑块控制C的取值,范围由6区域AbsoluteError或RelativeError的最大最小值决定。误差累积分布折线图横坐标为6区域的AbsoluteError或RelativeError,取值范围由AbsoluteError或RelativeError的最大最小值决定;纵坐标为累积百分占比,含义为AbsoluteError或RelativeError到达某个阈值时,小于等于该阈值的所有tensor元素在整体tensor元素中的占比。注:光标移动到对应Tensor点上时,浮窗显示Tensor信息。信息包括:Index(算子比对的条数)、Absolute Error/Relative Error(绝对/相对误差)、Cumulative Percentage(累积百分占比)(4)对比结果专家建议FP16溢出检测 针对比对数据中数据类型为FP16的数据,进行溢出检测。如果存在溢出数据,输出专家建议。专家系统分析结果:Detection Type: FP16 overflowOperator Index: 228Expert Advice: Float16 data overflow occurs. Rectify the fault and perform comparison again.检测类型:FP16溢出检测Operator Index:228 专家建议:存在Float16数据溢出,请修正溢出问题,再进行比对。输入不一致检测 针对整网的输入数据进行检测,主要判断整网两批待比对数据的输入data是否一致。如果存在不一致问题(余弦相似度<0.99),输出专家建议。专家系统分析结果:Detection Type: Input inconsistentOperator Index: 0Expert Advice: The input data of NPUDump is inconsistent with that of GroundTruth. Use the same data or check the data preprocessing process.检测类型:输入不一致检测Operator Index:0 专家建议:NPUDump和GroundTruth间的输入数据不一致,请使用相同数据或者检查数据预处理流程。整网一致性检测(问题节点检测) 判断整网比对结果中,是否某层小于阈值,该层后续数据均小于阈值或最后一层小于阈值(余弦相似度<0.99),输出量化误差修正建议。专家系统分析结果:Detection Type: global consistencyOperator Index: 1174Expert Advice: The accuracy of some tensors is low, resulting in an unqualified final accuracy. This may be caused by quantization. Calibrate the data or contact Huawei for further diagnosis.检测类型:整网一致性检测Operator Index:1174专家建议:部分张量精度较低,且导致最终结果精度不达标;很可能由量化造成,请进行数据校准或者反馈给华为做进一步定位。整网一致性检测(单点误差检测) 判断整网比对结果中,是否某层小于阈值(余弦相似度<0.99),但最终结果符合精度要求,输出专家建议。专家系统分析结果:Detection Type: global consistencyOperator Index: 195Expert Advice: The accuracy of some tensors is low, while the final accuracy is qualified. This may be caused by Ascend internal optimization. Ignore or contact Huawei for further diagnosis.检测类型:整网一致性检测Operator Index:195专家建议:部分张量精度较低,但最终结果精度达标,可能由内部优化导致,请忽略或反馈给华为做进一步定位。整网一致性检测(一致性检测) 比对结果中的所有数据均符合精度要求,输出专家建议。专家系统分析结果:Detection Type: global consistencyOperator Index: NAExpert Advice: All data in the comparison result meets the accuracy requirements.If data accuracy of the model is still not up to standard in practical application, please check the post-processing process of model outputs.检测类型:整网一致性检测Operator Index:NA专家建议:比对结果中的所有数据均符合精度要求。如果模型实际应用中,精度依旧不达标,请排查输出数据的后处理流程。6、经验总结运行代码的时候,显示同步文件出现问题,如下。解决方法:远程python3运行环境中缺少google模块和protobuf==3.19.0模块,使用pip安装后再运行即可。 2. 单算子分析的时候,点击下面栏框显示不出来单算子分析的窗口。解决方法:确认没有报错信息的情况下,点击自己电脑的设置,调整显示屏分辨率或者缩放比例即可。Windows端的MindStudio中使用离线模型dump数据时,路径配置只能选择本地的路径,没有可选的远程路径。 解决方法:找到自己项目目录下的src/acl.json文件,手动修改JSON文件导出路径配置为远程目录的路径。配置好路径,但是运行的时候有时候会报错路径不存在。 解决方法:所有文件路径,请先确保本地存在相应路径,再同步到远程服务器中,有时候MindStudio不会自动生成路径,导致报错。7、关于MindStudio更多的内容 如果需要了解关于MindStudio更多的信息,请查阅昇腾社区中MindStudio的用户手册cid:link_4,里面有算子开发、模型开发等各种使用操作的详细介绍。 如果在使用MindStudio过程中遇到任何问题,也可以在昇腾社区中的昇腾论坛cid:link_12里进行提问,会有华为内部技术人员对其进行解答,如下图。
  • [经验分享] MindStudio模型推理场景精度比对全流程和结果分析
    视频案例,可以查看Bilibili MindStudio模型推理场景精度比对全流程和结果分析:【经验分享】MindStudio模型推理场景精度比对全流程和结果分析1、MindStudio介绍MindStudio提供在AI开发所需的一站式开发环境,支持模型开发、算子开发以及应用开发三个主流程中的开发任务,依靠模型可视化、算力测试、IDE本地仿真调试等功能,MindStudio能够帮助您在一个工具上就能高效便捷地完成AI应用开发,MindStudio采用了插件化扩展机制,开发者可以通过开发插件来扩展已有功能。本实验使用的MindStudio版本为5.0.RC3,安装请参考MindStudio安装教程。2、交付件介绍(1)精度对比简介​ 在下面两种情况下,自有实现的算子在昇腾AI处理器上的运算结果与业界标准算子(如Caffe、ONNX、TensorFlow、PyTorch)的运算结果可能存在差异。在模型转换过程中对模型进行了优化,包括算子消除、算子融合、算子拆分,这些动作可能会造成自有实现的算子运算结果与业界标准算子(如Caffe、TensorFlow、ONNX)运算结果存在偏差。用户原始网络可以迁移到昇腾910 AI处理器上执行训练,网络迁移可能会造成自有实现的算子运算结果与用业界标准算子(如TensorFlow)运算结果存在偏差。(2)实现流程​ 为了帮助开发人员快速解决算子精度问题,需要提供自有实现的算子运算结果与业界标准算子运算结果之间进行精度差异对比的工具。​ MindStudio精度比对工具提供Tensor比对能力,包含余弦相似度、欧氏相对距离、绝对误差(最大绝对误差、平均绝对误差、均方根误差)、相对误差(最大相对误差、平均相对误差、累积相对误差)、KL散度、标准差算法比对维度。精度比对总体流程如下:(3)代码工程本实验基于MindStudio的代码工程结构如下所示。本实验基于MindStudio的代码工程结构如下所示。 ├── caffeResnet50_49048f18 │ ├── acl_net.py //离线模型推理脚本代码 │ ├── caffe_dump.py //原始模型推理脚本代码 │ ├── caffe_model //原始模型文件存储目录 │ │ ├── resnet50.caffemodel │ │ └── resnet50.prototxt │ ├── caffeResnet50.iml │ ├── constant.py //离线模型推理脚本工具脚本 │ ├── data //数据文件夹 │ │ └── img.png │ ├── dump //离线模型dump数据文件夹 │ ├── model //离线模型文件夹 │ │ └── resnet50.om │ ├── npy_dump //原始模型dump数据文件夹 │ ├── output //精度比对输出文件夹 │ │ └── 20221111205145 │ └── src │ └── acl.json //离线模型dump构造文件 (4)文章介绍​ 文章详细记录了如何使用MindStudio中的精度比对功能去进行推理场景下的模型的精度比对操作,包括原始第三方框架下模型的npy数据准备,离线模型的dump数据准备,精度比对以及分析。第三节介绍了MindStudio的昇腾App工程的创建。第四节介绍了推理场景下的数据准备。第五节介绍了精度比对和分析。第六节介绍了整个流程中遇到的问题和解决方案。第七节介绍MindStudio的更多的内容。3、App工程创建打开MindStudio进入算子工程创建界面首次登录MindStudio:在MindStudio欢迎界面中单击“New Project”,进入创建工程界面。非首次登录MindStudio:在顶部菜单栏中选择“File > New > Project...”,进入创建工程界面。创建App工程左侧导航栏选择“Ascend App”,如图所示,在右侧点击选择ACL Project(Python)工程。单击“Next”,在弹出的页面中,Project name那一行输入项目名称,然后点击Finish,既可完成工程的创建。单击“Finish”,完成应用工程的创建若工作窗口已打开其他工程,会出现如图所示提示。选择“This Window”,则直接在当前工作窗口打开新创建的工程。选择“New Window”,则新建一个工作窗口打开新创建的工程。4、推理场景数据准备(1)准备Caffe模型npy数据文件MindStudio当前版本不提供Caffe模型numpy数据生成功能,请自行安装Caffe环境并提前准备Caffe原始数据“*.npy”文件。本文仅提供生成符合精度比对要求的numpy格式Caffe原始数据“*.npy”文件的样例参考。下面给出Resnet50原始模型dump数据的推理脚本代码。请参考表1的参数说明进行使用。​ 表1 原始模型推理脚本参数说明-wCaffe 权重文件路径,如'resnet50.caffemodel'-i, --input_bins模型推理输入bin文件或者图片文件路径,多个以;分隔,如'./a.bin;./img.png'-n, --input_names模型推理输入节点名称,多个以;分隔,如'graph_input_0:0; graph_input_1:0'-mCaffe 模型文件路径,如'resnet50.prototxt'-odump输出文件路径,如'./output_dir', 该路径需要用户自己创建脚本代码:# coding=utf-8 import caffe import sys import argparse import os import caffe.proto.caffe_pb2 as caffe_pb2 import google.protobuf.text_format import json import numpy as np import time TIME_LENGTH = 1000 FILE_PERMISSION_FLAG = 0o600 class CaffeProcess: def __init__(self): parse = argparse.ArgumentParser() parse.add_argument("-w", dest="weight_file_path", help="<Required> the caffe weight file path", required=False,default="caffe_model/resnet50.caffemodel") parse.add_argument("-m", dest="model_file_path", help="<Required> the caffe model file path", required=False,default="caffe_model/resnet50.prototxt") parse.add_argument("-o", dest="output_path", help="<Required> the output path", required=False,default="npy_dump") parse.add_argument("-i", "--input_bins", dest="input_bins", help="input_bins bins. e.g. './a.bin;./c.bin'", required=False,default="./data/img.png") parse.add_argument("-n", "--input_names", dest="input_names", help="input nodes name. e.g. 'graph_input_0:0;graph_input_0:1'", required=False,default="data:0") args, _ = parse.parse_known_args(sys.argv[1:]) self.weight_file_path = os.path.realpath(args.weight_file_path) self.model_file_path = os.path.realpath(args.model_file_path) self.input_bins = args.input_bins.split(";") self.input_names = args.input_names.split(";") self.output_path = os.path.realpath(args.output_path) self.net_param = None self.cur_layer_idx = -1 @staticmethod def _check_file_valid(path, is_file): if not os.path.exists(path): print('Error: The path "' + path + '" does not exist.') exit(-1) if is_file: if not os.path.isfile(path): print('Error: The path "' + path + '" is not a file.') exit(-1) else: if not os.path.isdir(path): print('Error: The path "' + path + '" is not a directory.') exit(-1) def _check_arguments_valid(self): self._check_file_valid(self.model_file_path, True) self._check_file_valid(self.weight_file_path, True) self._check_file_valid(self.output_path, False) for input_file in self.input_bins: self._check_file_valid(input_file, True) @staticmethod def calDataSize(shape): dataSize = 1 for dim in shape: dataSize *= dim return dataSize def _load_inputs(self, net): inputs_map = {} for layer_name, blob in net.blobs.items(): if layer_name in self.input_names: input_bin = np.fromfile( self.input_bins[self.input_names.index(layer_name)], np.float32) input_bin_shape = blob.data.shape if self.calDataSize(input_bin_shape) == self.calDataSize(input_bin.shape): input_bin = input_bin.reshape(input_bin_shape) else: print("Error: input node data size %d not match with input bin data size %d.", self.calDataSize( input_bin_shape), self.calDataSize(input_bin.shape)) exit(-1) inputs_map[layer_name] = input_bin return inputs_map def process(self): """ Function Description: process the caffe net, save result as dump data """ # check path valid self._check_arguments_valid() # load model and weight file net = caffe.Net(self.model_file_path, self.weight_file_path, caffe.TEST) inputs_map = self._load_inputs(net) for key, value in inputs_map.items(): net.blobs[key].data[...] = value # process net.forward() # read prototxt file net_param = caffe_pb2.NetParameter() with open(self.model_file_path, 'rb') as model_file: google.protobuf.text_format.Parse(model_file.read(), net_param) for layer in net_param.layer: name = layer.name.replace("/", "_").replace(".", "_") index = 0 for top in layer.top: data = net.blobs[top].data[...] file_name = name + "." + str(index) + "." + str( round(time.time() * 1000000)) + ".npy" output_dump_path = os.path.join(self.output_path, file_name) np.save(output_dump_path, data) os.chmod(output_dump_path, FILE_PERMISSION_FLAG) print('The dump data of "' + layer.name + '" has been saved to "' + output_dump_path + '".') index += 1 if __name__ == "__main__": caffe_process = CaffeProcess() caffe_process.process()说明:运行之前需要提前准备数据文件和模型文件,原始模型下载地址为:cid:link_3​ 数据图片下载地址为:https://gitee.com/link?target=https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/models/aclsample/dog1_1024_683.jpg远程安装好caffe的python3环境,在本地配置好安装的caffe的SDK。将上述代码拷贝到新建的python脚本中,右键点击运行该脚本,即可以在参数-o指定的路径下生成npy数据文件。生成的文件是以{op_name}.{output_index}.{timestamp}.npy形式命名。其中{op_name}为算子名称,{output_index}是算子的编号索引,{timestamp}是时间戳;设置numpy数据文件名包括output_index字段且值为0,确保转换生成的dump数据的output_index为0,否则无比对结果,原因是精度比对时默认从第一个output_index为0的数据开始。(2)准备离线模型dump数据通过MindStudio提供的dump功能,生成离线模型的dump数据,需要提前完成以下操作:完成Caffe、TensorFlow或ONNX模型的ATC模型转换,将原始模型转换为OM离线模型。详细介绍请参见模型转换。完成应用工程的开发、编译和运行,确保具备可执行的应用工程。详细介绍请参见应用开发。操作步骤如下:准备好离线模型,离线模型下载地址为:cid:link_3;或者参考如下模型转换步骤进行模型转换(1) 在菜单栏选择“Ascend > Model Converter”。出现如下配置界面,参数配置参考MindStudio官网>用户指南>模型转换>操作步骤。(2) 单击“Next”,进入“Data Pre-Processing”配置数据预处理页签,界面参考如图所示。说明:数据预处理是昇腾AI处理器提供的硬件图像预处理模块,包括色域转换,图像归一化(减均值/乘系数)和抠图(指定抠图起始点,抠出神经网络需要大小的图片)等功能。只有当“Model Information”页签,“Input Nodes”参数中,输入节点的“Type”有配置为“Uint8”类型,“Data Pre-Processing”页签才可以配置该节点的数据预处理功能。如果模型有多个输入,每个输入节点都可以获取shape信息中的宽和高,并且“Input Nodes”参数中每个输入节点的“Type”都配置为“Uint8”,则“Data Pre-Processing”页签可以配置多个节点的数据预处理功能。(3) 单击“Next”,进入“Advanced Options Preview”高级选项配置页签,界面参考如图所示。(4) 单击Finish完成模型转换。在MindStudio界面下方,“Output”窗口会显示模型转换过程中的日志信息,如果提示“Model converted successfully”,则表示模型转换成功。准备好离线模型的推理代码。推理代码可以从cid:link_0中获取,或者直接拷贝下面代码。构造dump的.json配置,选择“Ascend > Dump Configuration”菜单,弹出“Select Offline Model”窗口,如图所示。注意:如果不知道自己本地同步到远程哪个路径下,可以点击Tools>Development>Configuration下查看。选择.om模型文件,单击“OK”,展示模型文件结构,设置dump开关。如图所示。它会在src目录下生成acl.json配置文件,通过修改窗口最右侧配置项,设置.om模型文件的dump配置项,会自动更新到acl.json文件中。(1) Dump Option:配置dump范围。ALL:所有算子开启dump。Several:自定义部分算子开启dump。选择该项后,需要右键单击待dump数据的算子并选择“Enable Dump”。None:所有算子不开启dump。(2) Dump Mode:dump数据模式。ALL:同时dump算子的输入、输出数据。Input:dump算子的输入数据。Output:dump算子的输出数据。(3) Dump Path:配置保存dump数据文件的路径,默认为:{project_path}/dump。如果Dump Path设置为其他路径,需要确保MindStudio安装用户对该路径具有读写权限。注意:该选项要选择远程的dump目录,当前版本mindstudio只支持选择本地的dump目录,如果不能选择远程dump目录,请自行在acl.json中配置。(4) AclConfig File:Acl配置文件,在dump操作中该文件保存算子的dump配置信息。一般路径为{project_path}/src/acl.json。请参考表2中的参数说明使用该脚本​ 表2 离线模型推理脚本参数说明--devicenpu设备编号。--model_path离线模型文件路径,到文件名层次。--images_path数据文件路径,到数据文件的文件夹层次。import argparse import numpy as np import acl import os from PIL import Image from constant import ACL_MEM_MALLOC_HUGE_FIRST, \ ACL_MEMCPY_HOST_TO_DEVICE, ACL_MEMCPY_DEVICE_TO_HOST, \ ACL_SUCCESS, IMG_EXT, NPY_FLOAT32 buffer_method = { "in": acl.mdl.get_input_size_by_index, "out": acl.mdl.get_output_size_by_index } def check_ret(message, ret): if ret != ACL_SUCCESS: raise Exception("{} failed ret={}" .format(message, ret)) class Net(object): def __init__(self, device_id, model_path): self.device_id = device_id # int self.model_path = model_path # string self.model_id = None # pointer self.context = None # pointer self.input_data = [] self.output_data = [] self.model_desc = None # pointer when using self.load_input_dataset = None self.load_output_dataset = None self.init_resource() def release_resource(self): print("Releasing resources stage:") ret = acl.mdl.unload(self.model_id) check_ret("acl.mdl.unload", ret) if self.model_desc: acl.mdl.destroy_desc(self.model_desc) self.model_desc = None while self.input_data: item = self.input_data.pop() ret = acl.rt.free(item["buffer"]) check_ret("acl.rt.free", ret) while self.output_data: item = self.output_data.pop() ret = acl.rt.free(item["buffer"]) check_ret("acl.rt.free", ret) if self.context: ret = acl.rt.destroy_context(self.context) check_ret("acl.rt.destroy_context", ret) self.context = None ret = acl.rt.reset_device(self.device_id) check_ret("acl.rt.reset_device", ret) ret = acl.finalize() check_ret("acl.finalize", ret) print('Resources released successfully.') def init_resource(self): print("init resource stage:") current_dir=os.path.dirname(os.path.abspath(__file__)) ret = acl.init(os.path.join(current_dir,"./src/acl.json")) check_ret("acl.init", ret) # ret = acl.mdl.init_dump() # check_ret("acl.init", ret) # ret = acl.mdl.set_dump(os.path.join(current_dir,"./src/acl.json")) # check_ret("acl.init", ret) ret = acl.rt.set_device(self.device_id) check_ret("acl.rt.set_device", ret) self.context, ret = acl.rt.create_context(self.device_id) check_ret("acl.rt.create_context", ret) # load_model self.model_id, ret = acl.mdl.load_from_file(self.model_path) check_ret("acl.mdl.load_from_file", ret) print("model_id:{}".format(self.model_id)) self.model_desc = acl.mdl.create_desc() self._get_model_info() print("init resource success") def _get_model_info(self,): ret = acl.mdl.get_desc(self.model_desc, self.model_id) check_ret("acl.mdl.get_desc", ret) input_size = acl.mdl.get_num_inputs(self.model_desc) output_size = acl.mdl.get_num_outputs(self.model_desc) self._gen_data_buffer(input_size, des="in") self._gen_data_buffer(output_size, des="out") def _gen_data_buffer(self, size, des): func = buffer_method[des] for i in range(size): # check temp_buffer dtype temp_buffer_size = func(self.model_desc, i) temp_buffer, ret = acl.rt.malloc(temp_buffer_size, ACL_MEM_MALLOC_HUGE_FIRST) check_ret("acl.rt.malloc", ret) if des == "in": self.input_data.append({"buffer": temp_buffer, "size": temp_buffer_size}) elif des == "out": self.output_data.append({"buffer": temp_buffer, "size": temp_buffer_size}) def _data_interaction(self, dataset, policy=ACL_MEMCPY_HOST_TO_DEVICE): temp_data_buffer = self.input_data \ if policy == ACL_MEMCPY_HOST_TO_DEVICE \ else self.output_data if len(dataset) == 0 and policy == ACL_MEMCPY_DEVICE_TO_HOST: for item in self.output_data: temp, ret = acl.rt.malloc_host(item["size"]) if ret != 0: raise Exception("can't malloc_host ret={}".format(ret)) dataset.append({"size": item["size"], "buffer": temp}) for i, item in enumerate(temp_data_buffer): if policy == ACL_MEMCPY_HOST_TO_DEVICE: if "bytes_to_ptr" in dir(acl.util): bytes_data = dataset[i].tobytes() ptr = acl.util.bytes_to_ptr(bytes_data) else: ptr = acl.util.numpy_to_ptr(dataset[i]) ret = acl.rt.memcpy(item["buffer"], item["size"], ptr, item["size"], policy) check_ret("acl.rt.memcpy", ret) else: ptr = dataset[i]["buffer"] ret = acl.rt.memcpy(ptr, item["size"], item["buffer"], item["size"], policy) check_ret("acl.rt.memcpy", ret) def _gen_dataset(self, type_str="input"): dataset = acl.mdl.create_dataset() temp_dataset = None if type_str == "in": self.load_input_dataset = dataset temp_dataset = self.input_data else: self.load_output_dataset = dataset temp_dataset = self.output_data for item in temp_dataset: data = acl.create_data_buffer(item["buffer"], item["size"]) _, ret = acl.mdl.add_dataset_buffer(dataset, data) if ret != ACL_SUCCESS: ret = acl.destroy_data_buffer(data) check_ret("acl.destroy_data_buffer", ret) def _data_from_host_to_device(self, images): print("data interaction from host to device") # copy images to device self._data_interaction(images, ACL_MEMCPY_HOST_TO_DEVICE) # load input data into model self._gen_dataset("in") # load output data into model self._gen_dataset("out") print("data interaction from host to device success") def _data_from_device_to_host(self): print("data interaction from device to host") res = [] # copy device to host self._data_interaction(res, ACL_MEMCPY_DEVICE_TO_HOST) print("data interaction from device to host success") result = self.get_result(res) self._print_result(result) # free host memory for item in res: ptr = item['buffer'] ret = acl.rt.free_host(ptr) check_ret('acl.rt.free_host', ret) def run(self, images): self._data_from_host_to_device(images) self.forward() self._data_from_device_to_host() def forward(self): print('execute stage:') ret = acl.mdl.execute(self.model_id, self.load_input_dataset, self.load_output_dataset) check_ret("acl.mdl.execute", ret) self._destroy_databuffer() print('execute stage success') def _print_result(self, result): vals = np.array(result).flatten() top_k = vals.argsort()[-1:-6:-1] print("======== top5 inference results: =============") for j in top_k: print("[%d]: %f" % (j, vals[j])) def _destroy_databuffer(self): for dataset in [self.load_input_dataset, self.load_output_dataset]: if not dataset: continue number = acl.mdl.get_dataset_num_buffers(dataset) for i in range(number): data_buf = acl.mdl.get_dataset_buffer(dataset, i) if data_buf: ret = acl.destroy_data_buffer(data_buf) check_ret("acl.destroy_data_buffer", ret) ret = acl.mdl.destroy_dataset(dataset) check_ret("acl.mdl.destroy_dataset", ret) def get_result(self, output_data): result = [] dims, ret = acl.mdl.get_cur_output_dims(self.model_desc, 0) check_ret("acl.mdl.get_cur_output_dims", ret) out_dim = dims['dims'] for temp in output_data: ptr = temp["buffer"] # 转化为float32类型的数据 if "ptr_to_bytes" in dir(acl.util): bytes_data = acl.util.ptr_to_bytes(ptr, temp["size"]) data = np.frombuffer(bytes_data, dtype=np.float32).reshape(tuple(out_dim)) else: data = acl.util.ptr_to_numpy(ptr, tuple(out_dim), NPY_FLOAT32) result.append(data) return result def transfer_pic(input_path): input_path = os.path.abspath(input_path) with Image.open(input_path) as image_file: image_file = image_file.resize((256, 256)) img = np.array(image_file) height = img.shape[0] width = img.shape[1] # 对图片进行切分,取中间区域 h_off = (height - 224) // 2 w_off = (width - 224) // 2 crop_img = img[h_off:height - h_off, w_off:width - w_off, :] # rgb to bgr,改变通道顺序 img = crop_img[:, :, ::-1] shape = img.shape img = img.astype("float16") img[:, :, 0] -= 104 img[:, :, 1] -= 117 img[:, :, 2] -= 123 img = img.reshape([1] + list(shape)) img = img.transpose([0, 3, 1, 2]) result = np.frombuffer(img.tobytes(), np.float16) return result if __name__ == '__main__': current_dir = os.path.dirname(os.path.abspath(__file__)) parser = argparse.ArgumentParser() parser.add_argument('--device', type=int, default=0) parser.add_argument('--model_path', type=str, default=os.path.join(current_dir, "./model/resnet50.om")) parser.add_argument('--images_path', type=str, default=os.path.join(current_dir, "./data")) args = parser.parse_args() print("Using device id:{}\nmodel path:{}\nimages path:{}" .format(args.device, args.model_path, args.images_path)) images_list = [os.path.join(args.images_path, img) for img in os.listdir(args.images_path) if os.path.splitext(img)[1] in IMG_EXT] net = Net(args.device, args.model_path) for image in images_list: print("images:{}".format(image)) img = transfer_pic(image) net.run([img]) # acl.mdl.finalize_dump() # net.run([img]) print("*****run finish******") net.release_resource() 说明:(1) 数据文件应该是与原始模型生成npy数据文件保持一致。(2) 如果是从gitee上下载的代码,需要修改acl.init()这行代码,在里面传入dump的配置参数.json文件。6.设置dump完成后,单击MindStudio界面“Run”菜单,重新编译和运行应用工程。工程运行完毕后,可以在{project_path}/dump路径下查看到生成的dump数据文件。生成的路径及格式说明:time/device_id/model_name/model_id/data_index/dump文件time:dump数据回传落盘时间。格式为:YYYYMMDDhhmmss。device_id:Device设备ID号。model_name:模型名称。model_id:模型ID号。data_index:针对每个Task ID执行的次数维护一个序号,从0开始计数,该Task每dump一次数据,序号递增1。dump文件:命名规则如{op_type}.{op_name}.{taskid}.{timestamp}。如果model_name、op_type、op_name出现了“.”、“/”、“\”、空格时,转换为下划线表示。5、精度比对及分析(1)全网精度比对操作步骤在MindStudio界面菜单栏选择“Ascend > Model Accuracy Analyzer > New Task”菜单,进入比对界面,如下图所示。参考表3配置好参数后点击Next下一步。进入到数据和模型的配置界面。​ 表3 精度比对New Task参数说明参数说明Run ModeRemote Run:远程运行。Local Run:本地运行。Windows使用场景下仅支持Remote Run,该参数不展示。Deployment运行配置,选择Remote Run模式时可见,必选配置。通过Deployment功能,详细请参见Deployment,可以将指定项目中的文件、文件夹同步到远程指定机器的指定目录。Remote Toolkit Path远端运行环境toolkit软件包安装路径,选择Remote Run模式时可见,必选配置。例如配置为${HOME}/Ascend/ascend-toolkit/xxx/toolkit。与Deployment参数为绑定关系,单击“Start”后参数值将被保存。再次配置时,如连接已配置过的Deployment,则参数自动填充,可手动修改。Environment Variables环境变量配置,选择Remote Run模式时可见,可以直接在框中输入,也可以单击后在弹窗内单击填写。可选配置,当Model File指定文件为离线模型文件(*.om)时,需要配置环境变量,否则工具将无法为离线模型文件(*.om)进行ATC转换导致比对失败。与Deployment参数为绑定关系,单击“Start”后参数值将被保存。再次配置时,如连接已配置过的Deployment,则参数自动填充,可手动修改。Output Path比对数据结果存放路径,必选配置。无论选择Remote Run模式还是Local Run模式,均需要指定为本端路径。默认路径为当前系统的用户目录。Analysis Mode精度比对分析模式,必选配置。可选择模式为:NPU vs NPU:表示两个比对文件均为昇腾AI处理器上运行生成的dump数据文件。此时Model File参数可选。一般用于分析开启和关闭融合规则时进行模型转换后的dump数据文件之间的精度差。模型转换开启和关闭融合规则的详细介绍请参见模型转换。NPU vs GPU/CPU:表示昇腾AI处理器上运行生成的dump数据文件与原始模型的npy文件进行比对。此时展示Framework必选参数。Framework比对数据所属的框架类型,必选配置。Analysis Mode为NPU vs GPU/CPU时可见。可选类型为:- TensorFlow:TensorFlow框架模型dump数据的精度比对,支持推理、训练场景,Model File参数必选。- ONNX:ONNX框架模型dump数据的精度比对,支持推理场景,Model File参数必选。- Caffe:Caffe框架模型dump数据的精度比对,支持推理场景,Model File参数必选。NPU Dump昇腾AI处理器上运行生成的dump数据文件目录,必选配置。在远端执行比对时(Remote Run),须指定远端设备上的dump数据文件目录。Model File模型文件或融合规则文件。Analysis Mode为NPU vs NPU时,进行离线模型转换开启算子融合功能前后的dump数据精度比对,需要指定开融合的算子映射文件(.json)或离线模型文件(*.om)和关融合的算子映射文件(.json)或离线模型文件(*.om)。Analysis Mode为NPU vs GPU/CPU时,根据Framework选择的框架类型选择不同的文件:l TensorFlow:推理场景选择昇腾模型压缩后的量化融合规则文件(json文件)或离线模型文件(*.om);训练场景选择计算图文件(*.txt)。l ONNX:选择昇腾模型压缩后的量化融合规则文件(json文件)或离线模型文件(*.om)。l Caffe:选择昇腾模型压缩后的量化融合规则文件(json文件)或离线模型文件(*.om)。l 具体选择文件请参见比对场景。Quantization Rule File(.json)量化算子映射关系文件(昇腾模型压缩输出的json文件),可选配置。仅Framework为Caffe时展示。Ground Truth原始模型的npy文件目录,必选配置。在远端执行比对时(Remote Run),须指定远端设备上的原始模型的npy文件目录。Algorithm比对算法维度。取值为:l Cosine Similarity:余弦相似度算法,默认勾选。l Relative Euclidean Distance:欧氏相对距离算法,默认勾选。l Absolute Error,绝对误差,默认勾选,此项执行的比对算法为:l Max Absolute Error:最大绝对误差。l Mean Absolute Error:平均绝对误差。l Root Mean Square Error:均方根误差。l Relative Error,相对误差,默认勾选,此项执行的比对算法为:l Max Relative Error:最大相对误差。l Mean Relative Error:平均相对误差。l Accumulated Relative Error:累积相对误差。l Kullback Leibler Divergence:KL散度算法,默认不勾选。l Standard Deviation:标准差算法,默认不勾选。l 与Customized Algorithm自定义算法之间至少勾选一种算法。Advance Options扩展选项。包括Customized Algorithm、Advisor和Operator Range。Customized Algorithm自定义算法文件路径。与Algorithm内置算法之间至少勾选一种算法。需用户自行准备自定义算法.py文件,所在目录格式为“algorithm”,指定该目录下的自定义算法.py文件,生成自定义算法。自定义算法.py文件相关要求参见《精度比对工具使用指南》附录中的“准备自定义算法.py文件”章节。Advisor专家系统分析开关,默认关闭。开启后会在完成整网比对后对比对结果进行专家系统分析并输出问题节点、问题类型和优化建议。详细介绍请参见比对结果专家建议。使用本功能前需要先执行*pip3* *install* ****pandas****命令安装pandas 1.3或更高版本依赖。与Operator Range无法同时开启。Operator Range设定算子比对范围。有两种设置方式:方式一:单击“Select”按钮,在弹出框内勾选需要比对的算子。方式二:根据Start、End、Step参数配置比对算子的范围。l start:第一个比对的算子,取值范围为[1, 参与计算的算子个数],默认值为1。l end:最后一个比对的算子,取值范围为-1或[start, 参与计算的算子个数],默认值为-1(动态获取网络模型中最后一个参与计算的算子)。l step:第start+stepn个比对的算子,step取值范围为[1, 参与计算的算子个数),默认值为1,n为从1开始的正整数。配置格式为:“start,end,step”。比如:-r 1,101,20,表示算子1,21,41,61,81,101的Tensor参与比对。不配置本参数时,比对网络模型中的所有参与计算的算子。配置本参数且Analysis Mode参数配置为NPU vs NPU时,需同时指定NPU Dump和Ground Truth的Model File分别指定开融合的算子映射文件(.json)或离线模型文件(.om)和关融合的算子映射文件(.json)或离线模型文件(*.om)。与Advisor无法同时开启。(2)全网比对结果分析上面步骤配置好参数后点击start即可以出现对比的结果界面。如下所示。图一图二图三所示将Tensor比对结果界面分为四个区域分别进行介绍。其中1~4区域为整网比对结果。表4 整网比对结果说明区域区域名称说明1菜单栏从左到右分别为Open…、New Task、Refresh、Help四项功能。Open…为打开并展示比对结果csv文件;New Task为创建新的比对任务;Refresh用于读取并刷新File Manager中管理的文件;单击Help弹出小窗,可展示精度比对工具的使用限制(Restrictions)、使用建议、在线教程链接等。2File Manager,历史数据管理显示用户指定文件夹以及文件夹下生成的整网比对的csv文件以及显示通过Open…单独打开的csv文件;对文件夹和csv,提供历史数据管理功能,包括打开、删除、另存为;在文件夹处右键删除;在空白处右键创建新比对任务(New Task)、刷新(Refresh)和Open…(打开并展示比对结果csv文件)。3Model Accuracy Analysis,精度比对分析界面默认仅显示有结果的算子。可单击列名,进行排序;单击Show Invalid Data,可展示无法比对的数据,各列字段含义请参见表2。4Scatter Diagram,各项算法指标的散点分布图Show Model,比对模型可视化展示Scatter Diagram:横坐标表示算子的执行顺序,纵坐标为算法指标在对应Tensor上的实际取值。各字段含义请参见表3。Show Model:分别展示NPU和Ground Truth的模型图。详细介绍请参见表4。表5 比对结果字段说明字段说明Index网络模型中算子的ID。OpSequence算子运行的序列。全网层信息文件中算子的ID。仅配置“Operator Range”时展示。OpType算子类型。NPUDump表示NPU Dump模型的算子名。光标悬浮时,可显示具体算子所在的文件路径。DataType表示NPU Dump侧数据算子的数据类型。Addressdump tensor的虚拟内存地址。用于判断算子的内存问题。仅基于昇腾AI处理器运行生成的dump数据文件在整网比对时可提取该数据。GroundTruth表示Ground Truth模型的算子名。光标悬浮时,可显示具体算子所在的文件路径。DataType表示Ground Truth侧数据算子的数据类型。TensorIndex表示NPU Dump模型算子的input ID和output ID。Shape比对的Tensor的Shape。OverFlow溢出算子。显示YES表示该算子存在溢出;显示NO表示算子无溢出;显示NaN表示不做溢出检测。开启Advisor功能时展示,为比对结果专家建议的FP16溢出检测专家建议提供数据。CosineSimilarity进行余弦相似度算法比对出来的结果。取值范围为[-1,1],比对的结果如果越接近1,表示两者的值越相近,越接近-1意味着两者的值越相反。MaxAbsoluteError进行最大绝对误差算法比对出来的结果。取值范围为0到无穷大,值越接近于0,表明越相近,值越大,表明差距越大。KullbackLeiblerDivergence进行KL散度算法比对出来的结果。取值范围为0到无穷大。KL散度越小,真实分布与近似分布之间的匹配越好。RootMeanSquareError表示均方根误差。取值范围为0到无穷大,MeanAbsoluteError趋于0,RootMeanSquareError趋于0,说明测量值与真实值越近似;MeanAbsoluteError趋于0,RootMeanSquareError越大,说明存在局部过大的异常值;MeanAbsoluteError越大,RootMeanSquareError等于或近似MeanAbsoluteError,说明整体偏差越集中;MeanAbsoluteError越大,RootMeanSquareError越大于MeanAbsoluteError,说明存在整体偏差,且整体偏差分布分散;不存在以上情况的例外情况,因为RMSE ≥ MAE恒成立。MaxRelativeError表示最大相对误差。取值范围为0到无穷大,值越接近于0,表明越相近,值越大,表明差距越大。RelativeEuclideanDistance进行欧氏相对距离算法比对出来的结果。取值范围为0到无穷大,值越接近于0,表明越相近,值越大,表明差距越大。StandardDeviation进行标准差算法比对出来的结果。取值范围为0到无穷大。标准差越小,离散度越小,表明越接近平均值。该列显示NPU Dump和Ground Truth两组数据的均值和标准差,第一组展示NPU Dump模型dump数据的数值(均值;标准差),第二组展示Ground Truth模型dump数据的数值(均值;标准差)。AccumulatedRelativeError进行累积相对误差算法比对出来的结果。取值范围为0到无穷大,值越接近于0,表明越相近,值越大,表明差距越大。MeanAbsoluteError表示平均绝对误差。取值范围为0到无穷大,MeanAbsoluteError趋于0,RootMeanSquareError趋于0,说明测量值与真实值越近似;MeanAbsoluteError趋于0,RootMeanSquareError越大,说明存在局部过大的异常值;MeanAbsoluteError越大,RootMeanSquareError等于或近似MeanAbsoluteError,说明整体偏差越集中;MeanAbsoluteError越大,RootMeanSquareError越大于MeanAbsoluteError,说明存在整体偏差,且整体偏差分布分散;不存在以上情况的例外情况,因为RMSE ≥ MAE恒成立。MeanRelativeError表示平均相对误差。取值范围为0到无穷大,值越接近于0,表明越相近,值越大,表明差距越大。CompareFailReason算子无法比对的原因。若余弦相似度为1,则查看该算子的输入或输出shape是否为空或全部为1,若为空或全部为1则算子的输入或输出为标量,提示:this tensor is scalar。注1:余弦相似度和KL散度比较结果为NaN,其他算法有比较数据,则表明左侧或右侧数据为0;KL散度比较结果为inf,表明右侧数据有一个为0;比对结果为nan,表示dump数据有nan。 注2:光标悬浮在表头可以看到对应的参数详细解释。 注3:若配置了自定义算法比对,则在比对结果的内置算法后增加对应自定义算法列。表6 散点分布图字段说明字段说明Algorithm选择展示对应比对算法结果的散点分布图,不支持展示StandardDeviation、KullbackLeiblerDivergence和AccumulatedRelativeError。Tensor过滤显示Input、Output结果散点分布图。Highlight对算子Tensor散点进行高亮。通过拖拉游标在对应算法指标的[min,max]间滑动来设置算法指标(纵坐标)的阈值,高于或等于阈值的点显示为蓝色,低于阈值的点显示为红色。如针对余弦相似度,图中设置阈值为0.98,小于0.98的算子Tensor被标记为红色。注1:光标移动到对应Tensor点上时,浮窗显示Tensor信息。信息包括:Index(Tensor对应算子的Index)、Op Name(算子名称)、Tensor Index(Tensor类型(input/output))以及Value(在当前算法维度下的Tensor数值)。注2:支持对散点图进行缩放。注3:指定区域3中的Tensor时,高亮对应Tensor点。表7 比对模型可视化展示字段说明字段说明NPU Model离线模型可视化。指定算子映射文件(.json)或离线模型文件(*.om)展示。训练场景下,若整网比对使用的Model File为计算图文件(*.txt),此处不支持展示模型图。Ground Truth Model原始模型可视化。指定原始模型文件展示。Input Model指定算子映射文件(.json)、离线模型文件(*.om)或原始模型文件。注:指定区域3中的Tensor时,高亮对应模型网络中的节点。在第一部分我们可以选择菜单,精度对比、历史等选项。我们可以从第二部分选择我们经过精度对比操作之后得到的不同的答案,并选择我们想要的内容来进行第三部分和第四部分的展示,在本次的实例当中我们只生成了一个模型的整网对比,所以只有一个对应的结果的文件,打开相应的文件夹,双击里面的csv文件,就可以呈现出我们本次模型的精度对比。精度对比页面第三部分看出我们的原模型和转换模型之间每个算子之间的结果的差距,并且也可以得到输入和输出的shape。在后面几栏的算子的精度的对比,我们可以根据不同的评判方法得出原算子和转化的算子之间经过运算之后得出的结果的相似程度来判断算子转化的优劣,我们根据后面几项的精度对比,从数据上可以看出精度正在下降,也意味着误差正在增加。随后也可观察4部分的散点图来观察从最开始的输入到最后的输出,经过每一个算子的计算,两模型之间的精度差距,我们可以看到余弦相似度的值有下降的趋势,且最后的结果接近于零,所以说两模型之间的误差在慢慢的增大。并且在第四部分还可以根据Algorithm选项选择不同的精度比较方法,比如说图1和图3选择的是余弦相似度和均方根误差来来展示精度的对比。在Tensor选项当中,我们可以选择input或者output选项来展示输入或者输出之间的精度对比。我们还可以选择第四部分的show model选项,即可以展示网络模型结构中算子之间的关系,也可以配合精度比对结果来定位具体算子的精度问题。(3)单算子精度比对操作步骤在刚刚的整网络分析界面下,点击下面的Operator Detail,出现如下界面。对比操作。 (1)基于已经读取到的Tensor信息,通过Operator下拉框选择要比对的算子和对应Tensor(output/input)。 (2)通过Metric选择比对算子的Absolute Error(绝对误差)或Relative Error(相对误差)。 (3)配置输出该指标的TopN个Tensor元素(取值范围为[1,10000])。 (4)单击“Compare”按钮进行单算子比对。 TopN结果显示请参见比对结果。单算子比对界面说明。算子比对功能是在比对结果的基础上选择具体算子并根据需要指定参数进行比对的。界面展示为图5的6区域、7区域和8区域,如图5。详细介绍请参见表7表7 单算子比对结果说明区域说明5Operator Detail,单算子比对功能。下发单算子比对命令。具体操作请参见比对操作。6单算子比对TopN结果。各列字段解释请参见表8。7Cumulative Error,对于TopN Tensor元素,绘制的误差累积分布折线图。详细介绍请参见表8。比对结果。单算子比对结果界面展示为图5的7区域和8区域。详细介绍请参见表8。表8 比对结果字段说明字段说明6区域Index算子比对的条数。N C H W数据格式。NPUDumpNPU Dump侧算子的dump值。GroundTruthGround Truth侧算子的dump值。Absolute Error绝对误差,NPU Dump侧算子的dump值减Ground Truth侧算子的dump值取绝对值比对出来的结果。小数点后最多6位。Relative Error相对误差,Absolute Error值除以Ground Truth侧算子的dump值比对出来的结果。当Ground Truth侧算子的dump值为0时,该处显示为“-”。小数点后最多6位。7区域A % of tensor elements (B elements) have an absolute error greater than C.当前算子比对的所有tensor元素的绝对误差结果中有A %的tensor也就是B个元素的绝对误差超过了C。其中absolute error根据5区域配置的Metric取值变化可以为relative error;右侧滑块控制C的取值,范围由6区域AbsoluteError或RelativeError的最大最小值决定。误差累积分布折线图横坐标为6区域的AbsoluteError或RelativeError,取值范围由AbsoluteError或RelativeError的最大最小值决定;纵坐标为累积百分占比,含义为AbsoluteError或RelativeError到达某个阈值时,小于等于该阈值的所有tensor元素在整体tensor元素中的占比。注:光标移动到对应Tensor点上时,浮窗显示Tensor信息。信息包括:Index(算子比对的条数)、Absolute Error/Relative Error(绝对/相对误差)、Cumulative Percentage(累积百分占比)(4)对比结果专家建议FP16溢出检测 针对比对数据中数据类型为FP16的数据,进行溢出检测。如果存在溢出数据,输出专家建议。专家系统分析结果:Detection Type: FP16 overflowOperator Index: 228Expert Advice: Float16 data overflow occurs. Rectify the fault and perform comparison again.检测类型:FP16溢出检测Operator Index:228 专家建议:存在Float16数据溢出,请修正溢出问题,再进行比对。输入不一致检测 针对整网的输入数据进行检测,主要判断整网两批待比对数据的输入data是否一致。如果存在不一致问题(余弦相似度<0.99),输出专家建议。专家系统分析结果:Detection Type: Input inconsistentOperator Index: 0Expert Advice: The input data of NPUDump is inconsistent with that of GroundTruth. Use the same data or check the data preprocessing process.检测类型:输入不一致检测Operator Index:0 专家建议:NPUDump和GroundTruth间的输入数据不一致,请使用相同数据或者检查数据预处理流程。整网一致性检测(问题节点检测) 判断整网比对结果中,是否某层小于阈值,该层后续数据均小于阈值或最后一层小于阈值(余弦相似度<0.99),输出量化误差修正建议。专家系统分析结果:Detection Type: global consistencyOperator Index: 1174Expert Advice: The accuracy of some tensors is low, resulting in an unqualified final accuracy. This may be caused by quantization. Calibrate the data or contact Huawei for further diagnosis.检测类型:整网一致性检测Operator Index:1174专家建议:部分张量精度较低,且导致最终结果精度不达标;很可能由量化造成,请进行数据校准或者反馈给华为做进一步定位。整网一致性检测(单点误差检测) 判断整网比对结果中,是否某层小于阈值(余弦相似度<0.99),但最终结果符合精度要求,输出专家建议。专家系统分析结果:Detection Type: global consistencyOperator Index: 195Expert Advice: The accuracy of some tensors is low, while the final accuracy is qualified. This may be caused by Ascend internal optimization. Ignore or contact Huawei for further diagnosis.检测类型:整网一致性检测Operator Index:195专家建议:部分张量精度较低,但最终结果精度达标,可能由内部优化导致,请忽略或反馈给华为做进一步定位。整网一致性检测(一致性检测) 比对结果中的所有数据均符合精度要求,输出专家建议。专家系统分析结果:Detection Type: global consistencyOperator Index: NAExpert Advice: All data in the comparison result meets the accuracy requirements.If data accuracy of the model is still not up to standard in practical application, please check the post-processing process of model outputs.检测类型:整网一致性检测Operator Index:NA专家建议:比对结果中的所有数据均符合精度要求。如果模型实际应用中,精度依旧不达标,请排查输出数据的后处理流程。6、经验总结运行代码的时候,显示同步文件出现问题,如下。解决方法:远程python3运行环境中缺少google模块和protobuf==3.19.0模块,使用pip安装后再运行即可。 2. 单算子分析的时候,点击下面栏框显示不出来单算子分析的窗口。解决方法:确认没有报错信息的情况下,点击自己电脑的设置,调整显示屏分辨率或者缩放比例即可。Windows端的MindStudio中使用离线模型dump数据时,路径配置只能选择本地的路径,没有可选的远程路径。 解决方法:找到自己项目目录下的src/acl.json文件,手动修改JSON文件导出路径配置为远程目录的路径。配置好路径,但是运行的时候有时候会报错路径不存在。 解决方法:所有文件路径,请先确保本地存在相应路径,再同步到远程服务器中,有时候MindStudio不会自动生成路径,导致报错。7、关于MindStudio更多的内容 如果需要了解关于MindStudio更多的信息,请查阅昇腾社区中MindStudio的用户手册cid:link_4,里面有算子开发、模型开发等各种使用操作的详细介绍。 如果在使用MindStudio过程中遇到任何问题,也可以在昇腾社区中的昇腾论坛cid:link_12里进行提问,会有华为内部技术人员对其进行解答,如下图。