• AI人脸编辑-代码参数化
    高保真图像编辑注意:本案例必须使用GPU运行,请查看《ModelArts JupyterLab 硬件规格使用指南》了解切换硬件规格的方法High-Fidelity GAN Inversion for Image Attribute Editing (CVPR 2022) cid:link_81 下载代码和数据import os import moxing as mox if not os.path.exists("/home/ma-user/work/ma_share/HFGI/HFGI"): mox.file.copy_parallel('obs://modelarts-labs-bj4-v2/case_zoo/HFGI/HFGI.zip',"/home/ma-user/work/ma_share/HFGI/HFGI.zip") os.system("cd /home/ma-user/work/ma_share/HFGI;unzip HFGI.zip;rm HFGI.zip") if os.path.exists("/home/ma-user/work/ma_share/HFGI/HFGI"): print('Download success') else: raise Exception('Download Failed') else: print("Project already exists")2 安装依赖环境!pip install ninja !pip install dlib !pip uninstall -y torch !pip uninstall -y torchvision !pip install torch==1.6.0 !pip install torchvision==0.7.0安装完后,需要重启一下kernel,点击上方Restart the kernelÍ HFGI3 开始运行代码#@title Setup Repository import os from argparse import Namespace import time import os import sys import numpy as np from PIL import Image import torch import torchvision.transforms as transforms # from utils.common import tensor2im from models.psp import pSp # we use the pSp framework to load the e4e encoder. %load_ext autoreload %autoreload 2def tensor2im(var): # var shape: (3, H, W) var = var.cpu().detach().transpose(0, 2).transpose(0, 1).numpy() var = ((var + 1) / 2) var[var < 0] = 0 var[var > 1] = 1 var = var * 255 return Image.fromarray(var.astype('uint8'))Step 1: 加载预训练模型model_path = "checkpoint/ckpt.pt" ckpt = torch.load(model_path, map_location='cpu') opts = ckpt['opts'] opts['is_train'] = False opts['checkpoint_path'] = model_path opts= Namespace(**opts) net = pSp(opts) net.eval() net.cuda() print('Model successfully loaded!')Step 2: 设置输入图像#@title 设置输入图像 # Setup required image transformations input_img_path = "test_imgs/1919116757.jpg" #@param {type:"string", dropdown} EXPERIMENT_ARGS = {"image_path": input_img_path} EXPERIMENT_ARGS['transform'] = transforms.Compose([ transforms.Resize((256, 256)), transforms.ToTensor(), transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])]) resize_dims = (256, 256)image_path = EXPERIMENT_ARGS["image_path"] original_image = Image.open(image_path) original_image = original_image.convert("RGB") run_align = True图像对齐import numpy as np import PIL import PIL.Image import scipy import scipy.ndimage import dlib def get_landmark(filepath, predictor): """get landmark with dlib :return: np.array shape=(68, 2) """ detector = dlib.get_frontal_face_detector() img = dlib.load_rgb_image(filepath) dets = detector(img, 1) for k, d in enumerate(dets): shape = predictor(img, d) t = list(shape.parts()) a = [] for tt in t: a.append([tt.x, tt.y]) lm = np.array(a) return lm def align_face(filepath, predictor): """ :param filepath: str :return: PIL Image """ lm = get_landmark(filepath, predictor) lm_chin = lm[0: 17] # left-right lm_eyebrow_left = lm[17: 22] # left-right lm_eyebrow_right = lm[22: 27] # left-right lm_nose = lm[27: 31] # top-down lm_nostrils = lm[31: 36] # top-down lm_eye_left = lm[36: 42] # left-clockwise lm_eye_right = lm[42: 48] # left-clockwise lm_mouth_outer = lm[48: 60] # left-clockwise lm_mouth_inner = lm[60: 68] # left-clockwise # Calculate auxiliary vectors. eye_left = np.mean(lm_eye_left, axis=0) eye_right = np.mean(lm_eye_right, axis=0) eye_avg = (eye_left + eye_right) * 0.5 eye_to_eye = eye_right - eye_left mouth_left = lm_mouth_outer[0] mouth_right = lm_mouth_outer[6] mouth_avg = (mouth_left + mouth_right) * 0.5 eye_to_mouth = mouth_avg - eye_avg # Choose oriented crop rectangle. x = eye_to_eye - np.flipud(eye_to_mouth) * [-1, 1] x /= np.hypot(*x) x *= max(np.hypot(*eye_to_eye) * 2.0, np.hypot(*eye_to_mouth) * 1.8) y = np.flipud(x) * [-1, 1] c = eye_avg + eye_to_mouth * 0.1 quad = np.stack([c - x - y, c - x + y, c + x + y, c + x - y]) qsize = np.hypot(*x) * 2 # read image img = PIL.Image.open(filepath) output_size = 256 transform_size = 256 enable_padding = True # Shrink. shrink = int(np.floor(qsize / output_size * 0.5)) if shrink > 1: rsize = (int(np.rint(float(img.size[0]) / shrink)), int(np.rint(float(img.size[1]) / shrink))) img = img.resize(rsize, PIL.Image.ANTIALIAS) quad /= shrink qsize /= shrink # Crop. border = max(int(np.rint(qsize * 0.1)), 3) crop = (int(np.floor(min(quad[:, 0]))), int(np.floor(min(quad[:, 1]))), int(np.ceil(max(quad[:, 0]))), int(np.ceil(max(quad[:, 1])))) crop = (max(crop[0] - border, 0), max(crop[1] - border, 0), min(crop[2] + border, img.size[0]), min(crop[3] + border, img.size[1])) if crop[2] - crop[0] < img.size[0] or crop[3] - crop[1] < img.size[1]: img = img.crop(crop) quad -= crop[0:2] # Pad. pad = (int(np.floor(min(quad[:, 0]))), int(np.floor(min(quad[:, 1]))), int(np.ceil(max(quad[:, 0]))), int(np.ceil(max(quad[:, 1])))) pad = (max(-pad[0] + border, 0), max(-pad[1] + border, 0), max(pad[2] - img.size[0] + border, 0), max(pad[3] - img.size[1] + border, 0)) if enable_padding and max(pad) > border - 4: pad = np.maximum(pad, int(np.rint(qsize * 0.3))) img = np.pad(np.float32(img), ((pad[1], pad[3]), (pad[0], pad[2]), (0, 0)), 'reflect') h, w, _ = img.shape y, x, _ = np.ogrid[:h, :w, :1] mask = np.maximum(1.0 - np.minimum(np.float32(x) / pad[0], np.float32(w - 1 - x) / pad[2]), 1.0 - np.minimum(np.float32(y) / pad[1], np.float32(h - 1 - y) / pad[3])) blur = qsize * 0.02 img += (scipy.ndimage.gaussian_filter(img, [blur, blur, 0]) - img) * np.clip(mask * 3.0 + 1.0, 0.0, 1.0) img += (np.median(img, axis=(0, 1)) - img) * np.clip(mask, 0.0, 1.0) img = PIL.Image.fromarray(np.uint8(np.clip(np.rint(img), 0, 255)), 'RGB') quad += pad[:2] # Transform. img = img.transform((transform_size, transform_size), PIL.Image.QUAD, (quad + 0.5).flatten(), PIL.Image.BILINEAR) if output_size < transform_size: img = img.resize((output_size, output_size), PIL.Image.ANTIALIAS) # Return aligned image. return imgif 'shape_predictor_68_face_landmarks.dat' not in os.listdir(): # !wget http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2 !bzip2 -dk shape_predictor_68_face_landmarks.dat.bz2 def run_alignment(image_path): import dlib predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat") aligned_image = align_face(filepath=image_path, predictor=predictor) print("Aligned image has shape: {}".format(aligned_image.size)) return aligned_image if run_align: input_image = run_alignment(image_path) else: input_image = original_image input_image.resize(resize_dims)Aligned image has shape: (256, 256)img_transforms = EXPERIMENT_ARGS['transform'] transformed_image = img_transforms(input_image)Step 3: 高保真逆向映射(inversion)def display_alongside_source_image(result_image, source_image): res = np.concatenate([np.array(source_image.resize(resize_dims)), np.array(result_image.resize(resize_dims))], axis=1) return Image.fromarray(res) def get_latents(net, x, is_cars=False): codes = net.encoder(x) if net.opts.start_from_latent_avg: if codes.ndim == 2: codes = codes + net.latent_avg.repeat(codes.shape[0], 1, 1)[:, 0, :] else: codes = codes + net.latent_avg.repeat(codes.shape[0], 1, 1) if codes.shape[1] == 18 and is_cars: codes = codes[:, :16, :] return codes#@title 设置上采样模式 mode = "bilinear" #@param {type:"string", dropdown} with torch.no_grad(): x = transformed_image.unsqueeze(0).cuda() tic = time.time() latent_codes = get_latents(net, x) # calculate the distortion map imgs, _ = net.decoder([latent_codes[0].unsqueeze(0).cuda()],None, input_is_latent=True, randomize_noise=False, return_latents=True) res = x - torch.nn.functional.interpolate(torch.clamp(imgs, -1., 1.), size=(256,256) , mode=mode) # ADA img_edit = torch.nn.functional.interpolate(torch.clamp(imgs, -1., 1.), size=(256,256) , mode=mode) res_align = net.grid_align(torch.cat((res, img_edit ), 1)) # consultation fusion conditions = net.residue(res_align) result_image, _ = net.decoder([latent_codes],conditions, input_is_latent=True, randomize_noise=False, return_latents=True) toc = time.time() print('Inference took {:.4f} seconds.'.format(toc - tic)) # Display inversion: display_alongside_source_image(tensor2im(result_image[0]), input_image)Step 4: 高保真图像编辑可以编辑的内容如下:--edit_attribute 编辑属性(inversion', 'age', 'smile', 'eyes', 'lip' ,'beard' )--edit_degree 控制编辑程度(适用于“age”和“smile”)。from editings import latent_editor editor = latent_editor.LatentEditor(net.decoder)#@title 图像编辑设置 # interface-GAN age_model = "./editings/interfacegan_directions/age.pt" #@param {type:"string", dropdown} smile_model = "./editings/interfacegan_directions/smile.pt" #@param {type:"string", dropdown} interfacegan_directions = { 'age': age_model, 'smile': smile_model } edit_status = "smile" #@param {type:"string", dropdown} edit_direction = torch.load(interfacegan_directions[edit_status]).cuda() # 微笑程度 edit_degree = 0.6 #@param {type:"slider", min:-5, max:5, step:0.1}#@title 上采样模型设置 img_edit, edit_latents = editor.apply_interfacegan(latent_codes[0].unsqueeze(0).cuda(), edit_direction, factor=edit_degree) # 设置微笑 # align the distortion map mode = "bilinear" #@param {type:"string", dropdown} img_edit = torch.nn.functional.interpolate(torch.clamp(img_edit, -1., 1.), size=(256,256) , mode=mode) res_align = net.grid_align(torch.cat((res, img_edit ), 1)) # fusion conditions = net.residue(res_align) result, _ = net.decoder([edit_latents],conditions, input_is_latent=True, randomize_noise=False, return_latents=True) result = torch.nn.functional.interpolate(result, size=(256,256) , mode=mode) display_alongside_source_image(tensor2im(result[0]), input_image)#@title ganspace设置 # GANSpace model = "./editings/ganspace_pca/ffhq_pca.pt" #@param {type:"string", dropdown} ganspace_pca = torch.load(model) eyes_param = (54, 7, 8, 20) #@param {type:"raw"} beard_param = (58, 7, 9, -20) #@param {type:"raw"} lip_param = (34, 10, 11, 20) #@param {type:"raw"} ganspace_directions = { 'eyes': eyes_param, # 眼睛 'beard': beard_param, # 胡子 'lip': lip_param } # 嘴唇 edit_option = "lip" #@param {type:"string", dropdown} edit_direction = ganspace_directions[edit_option]#@title 上采样模式设置 img_edit, edit_latents = editor.apply_ganspace(latent_codes[0].unsqueeze(0).cuda(), ganspace_pca, [edit_direction]) # align the distortion map mode = "bilinear" #@param {type:"string", dropdown} img_edit = torch.nn.functional.interpolate(torch.clamp(img_edit, -1., 1.), size=(256,256) , mode=mode) res_align = net.grid_align(torch.cat((res, img_edit ), 1)) conditions = net.residue(res_align) result, _ = net.decoder([edit_latents],conditions, input_is_latent=True, randomize_noise=False, return_latents=True) result = torch.nn.functional.interpolate(result, size=(256,256) , mode=mode) display_alongside_source_image(tensor2im(result[0]), input_image)训练如果需要训练,可以按以下描述进行:准备下载数据集并相应地修改数据集路径./configs/paths_config.py .下载一些预训练模型并将它们放入 ./pretrained.ModelDescriptionStyleGAN2 (FFHQ)Pretrained face generator on FFHQ from rosinality.e4e (FFHQ)Pretrained initial encoder on FFHQ from omertov.Feature extractor (for face)Pretrained IR-SE50 model taken from TreB1eN for ID loss calculation.Feature extractor (for car)Pretrained ResNet-50 model taken from omertov for ID loss calculation.开始训练修改 option 和 training.sh ,开始运行:bash train.sh
  • [经验分享] 使用MindStudio开发铝材表面缺陷检测
    BiliBili视频链接:使用MindStudio完成铝材表面缺陷检测_哔哩哔哩_bilibili使用MindStudio开发铝材表面缺陷检测目 录使用MindStudio开发铝材表面缺陷检测 1. MindStudio介绍 2. 案例模型 3. 环境搭建 3.1 安装MindX SDK和CANN包并配置环境变量 3.2 在windows开发环境同步CANN 3.3 在windows开发环境同步MindX SDK 4. 开发过程 4.1 创建工程 4.2 配置python解释器 4.3 开发步骤 4.4 项目下载连接以及项目结构 5. 运行 5.1 配置远程映射 5.2 精度测试 6. FAQ 1 尺寸不匹配 2 模型路径未进行正确配置 3 未修改pipeline中后处理插件的postProcessLibPath属性 4 同步远端CANN开发包失败 7. 一些个人经验总结 8. Mindstuido下载连接 9. 开发过程中用到的链接 1. MindStudio介绍MindStudio提供AI开发所需的一站式开发环境,支持模型开发、算子开发以及应用开发三个主流程中的开发任务。依靠模型可视化、算力测试、IDE本地仿真调试等功能,MindStudio能够使开发者在一个工具上就能高效便捷地完成AI应用开发 ·MindStudio采用了插件化扩展机制,开发者可以通过开发插件来扩展已有功能。MindStudio-昇腾社区 (hiascend.com)2. 案例模型在本案例中,目的是基于MindX SDK,在华为云昇腾平台上,使用MindStudio开发端到端铝材缺陷检测的参考设计,实现对图像中的铝材进行缺陷类型分类和定位的功能,达到功能要求,并对精度进行测试。3. 环境搭建开发环境为windows版本的MindStudio,运行环境在远端linux上。3.1 安装MindX SDK和CANN包并配置环境变量请先确保远端环境上MindX SDK软件包已安装完成,安装方式请参见安装MindX SDK开发套件。确保远端环境上CANN包已安装完成,安装方式请参见该链接在远端服务器上配置环境变量执行如下命令,打开.bashrc文件vim ~/.bashrc# 在.bashrc文件中添加以下环境变量. ${MX_SDK_HOME}/set_env.sh. ${HOME}/Ascend/ascend-toolkit/set_env.sh# 其中${MX_SDK_HOME}为MindX SDK安装目录,${HOME}为用户目录(如果CANN 开发包装在用户目录,否则为/usr/local/),配置的时候请自行替换成相应目录# 保存退出.bashrc文件# 执行如下命令使环境变量生效source ~/.bashrc#查看环境变量env3.2 在windows开发环境同步CANN工具栏点击“File > Settings > Appearance & Behavior > System Settings > CANN”进入CANN管理界面。点击Change CANN配置CANN包。配置远程连接以及远端CANN包路径(配置到版本号一级)3.3 在windows开发环境同步MindX SDK工具栏点击“File > Settings > Appearance & Behavior > System Settings > MindX SDK”或依次点击“Ascend>MindX SDK Manager”进入MindX SDK管理界面。界面中“MindX SDK Location”为软件包的默认安装路径,默认安装路径为“C:\Users*用户名*\Ascend\mindx_sdk”。单击“Install SDK”进入“Installation settings”界面。在“Installation settings”界面“Remote Connection”:远程连接的用户及IP。“Remote CANN Location”:远端环境上CANN开发套件包的路径,请配置到版本号一级。“Remote SDK Location”:远端环境上SDK的路径,请配置到版本号一级。IDE将同步该层级下的“include”、“opensource”、“python”、“samples”文件夹到本地Windows环境,层级选择错误将导致安装失败。“Local SDK Location”:同步远端环境上SDK文件夹到本地的路径。默认安装路径为“C:\Users*用户名*\Ascend\mindx_sdk”。安装完成之后,界面如图所示:4. 开发过程4.1 创建工程工具栏点击“File > New > Project选择左侧Ascend APP,创建Ascend APP应用工程,,创建MindX SDK空白工程(提供MindX SDK开发框架,不包含代码逻辑),点击finish完成创建。创建完成之后目录结构如下图所示删除config文件夹,创建models和pipeline里的文件,以备后续开发自己的业务流程,目录结构如图所示。4.2 配置python解释器依次点击File->Project Structure,选择SDKs,添加Python SDK如下图所示:选择SSH interpreter,配置远程服务器,MindStudio会自动侦测远程python环境(如果PATH环境变量已正确配置python的路径),点击OKProject中选择配置好的远程SDK,点击Apply点击OK。完成python解释器的配置。4.3 开发步骤4.3.1 确定业务流程根据铝材表面缺陷检测SDK推理的具体需求,这里将流程依次划分为图片获取、图片解码、图像缩放、目标检测、序列化、结果发送。4.3.2 寻找合适的插件首先根据已有SDK插件的功能描述和规格限制来匹配业务功能(SDK插件列表详见已有插件介绍)。当SDK提供的插件无法满足功能需求时,用户可以参考插件开发介绍开发自定义插件,该部分为SDK高阶特性。在本案例中,已有SDK插件已经满足业务需求。铝材表面缺陷检测流程图以及pipeline编排流程图如下所示:1 铝材表面缺陷检测流程图2 铝材表面缺陷检测pipeline示意图4.3.3 准备模型推理文件和数据步骤1 训练铝材缺陷检测对应的yolov5模型,输出pt模型文件。pt模型文件链接:cid:link_2步骤2 将pt模型文件转换成onnx,也可直接通过以下链接下载onnx模型。onnx模型文件链接:cid:link_1下载yolov5官方源码6.1版本Releases · ultralytics/yolov5 (github.com),进入项目根目录,将best.pt模型文件复制到项目目录,执行命令python export.py --weights best.pt –simplify模型转换成功之后,显示的日志信息如下图所示,在项目根目录会生成best.onnx模型文件步骤3 将转化后的YOLOv5模型onnx文件存放至./models/yolov5/。步骤4 AIPP配置由于yolov5模型的输入为rgb格式,pipeline中的图像解码为yuv格式,且数据类型不同,需要在atc转换模型时使用aipp预处理,该案例所需进行的aipp预处理包括色域转化以及归一化操作,aipp配置步骤如下:在./models/yolov5文件夹创建insert_op.cfg配置文件,所需添加的配置内容的属性:参数参数说明aipp_mode每次模型推理过程采用固定的AIPP预处理参数进行处理Related_input_rankrelated_input_rank参数为可选,标识对模型的第几个输入做AIPP处理,从0开始,默认为0。例如模型有两个输入,需要对第2个输入做AIPP,则配置related_input_rank为1。# 类型: 整型Input_format输入图像格式,必选。取值范围:YUV420SP_U8、XRGB8888_U8、RGB888_U8、YUV400_U8src_image_size_wsrc_image_size_h原始图像的宽度、高度宽度取值范围为[2,4096]或0;高度取值范围为[1,4096]或0,对于YUV420SP_U8类型的图像,要求原始图像的宽和高取值是偶数cropAIPP处理图片时是否支持抠图类型:bool取值范围:true/false,true表示支持,false表示不支持Csc_switch色域转换开关,静态AIPP配置类型:bool取值范围:true/false,true表示开启色域转换,false表示关闭rbuv_swap_switch R通道与B通道交换开关/U通道与V通道交换开关类型:bool取值范围:true/false,true表示开启通道交换,false表示关闭matrix_rxcyX和y代表矩阵的行和列一旦确认了AIPP处理前与AIPP处理后的图片格式,即可确定色域转换相关的参数值(matrix_r*c*配置项的值是固定的,不需要调整)var_reci_chn归一化配置参数把需要处理的数据经过处理后限制在一定范围内,方便后面数据的处理。pixel_out_chx(i)=[pixel_in_chx(i)-mean_chn_i-min_chn_i]*var_reci_chn最终配置参数如下图所示:配置文件的教程请参考如下链接:配置文件模板 - CANN 5.0.4 ATC工具使用指南 01 - 华为 (huawei.com)5 模型转换模型转换有两种方式,一种是通过MindStudio可视化操作,另一种是通过命令行的方式,使用MindStudio进行模型转换参考该链接。使用命令方式进行模型转换步骤如下:首先开启一个SSH会话切换到项目根目录,运行如下命令:atc --input_shape="images:1,3,640,640" --out_nodes="Transpose_286:0;Transpose_336:0;Transpose_386:0" --output_type=FP32 --input_format=NCHW --output="./models/yolov5/yolov5_add_bs1_fp16" --soc_version=Ascend310 --framework=5 --model="./models/yolov5/best.onnx" --insert_op_conf=./models/yolov5/insert_op.cfg模型转换成功,模型保存在--output定义的路径下,输出结果如图所示:Atc中各个参数代表的含义请参考这个链接:参数说明 - CANN 5.0.4 ATC工具使用指南 01 - 华为 (huawei.com)。常见的报错请参考这个链接:FAQ - CANN 5.0.4 ATC工具使用指南 01 - 华为 (huawei.com)4.3.4 编写后处理配置文件在./models/yolov5创建模型后处理配置文件yolov5addbs1_fp16.cfg,对后处理参数进行配置:表1 配置文件中各个参数的意义参数名称参数介绍修改方法默认值CLASS_NUM铝材缺陷检测的类别数目。在models/yolov5/yolov5_add_bs1_fp16.cfg文件中修改CLASS_NUM的大小即可10BIASES_NUM铝材缺陷检测锚点框数量在models/yolov5/yolov5_add_bs1_fp16.cfg文件中修改BIASES_NUM的大小即可18BIASES铝材缺陷检测锚点框,用kmeans计算最合适的锚点框在models/yolov5/yolov5_add_bs1_fp16.cfg文件中修改BIASES即可17,14,161,31,113,69,649,17,637,32,636,73,625,132,640,202,626,365YOLO_TYPEYOLO输出特征向量的维度数,YOLOv5使用的是3在models/yolov5/yolov5_add_bs1_fp16.cfg文件中修改YOLO_TYPE即可3SCORE_THRESH是否为框的阈值,大于此值才认定为框在models/yolov5/yolov5_add_bs1_fp16.cfg文件中修改SCORE_THRESH的大小即可0.25IOU_THRESH两个框的IOU阈值,超过此值则被认定为同一个框,用于nms算法在models/yolov5/yolov5_add_bs1_fp16.cfg文件中修改IOU_THRESH的大小即可0.5OBJECTNESS_THRESH识别目标置信度的阈值,大于阈值才会认定为目标在models/yolov5/yolov5_add_bs1_fp16.cfg文件中修改OBJECTNESS_THRESH的大小即可0.0YOLO_VERSIONYOLO版本号,本项目使用的YOLOv5,故取值为5在models/yolov5/yolov5_add_bs1_fp16.cfg文件中修改YOLO_VERSION的大小即可54.3.5 配置names文件在./models/yolov5文件夹下创建aldefectdetection.names文件,按顺序配置相应类名,该文件为数据集中所有类别,后处理插件通过读取改文件,返回准确的类别名称,达到缺陷识别的目的:4.3.6 可视化流程编排根据已经确定的业务流程和合适的插件,利用MindStudio进行可视化插件编排,需要用到的为以下六个插件。1. appsrc # 输入2. mxpi_imagedecoder # 图像解码3. mxpi_imageresize # 图像缩放4. mxpi_tensorinfer # 模型推理(铝材缺陷检测)5. mxpi_objectpostprocessor # 模型后处理(yolov5)6. appsink # 输出用MindStudio进行可视化流程编排,工具栏依次点击“Ascend > MindX SDK Pipeline :搜索流程编排中需要用到的插件:将插件依次拖动到如下界面并连接起来,Format选项可以整理插件连接的排列,让界面更加美观。点击需要配置参数的插件,在如下区域设置合适的参数:点击save,生成相应的pipeline代码,该代码会将可视化pipeline中设置的参数也加载到对应的插件中去:{"classification+detection": {"stream_config": {"deviceId": "0"},"appsrc0": {"props": {"blocksize": "409600"},"factory": "appsrc","next": "mxpi_imagedecoder0"},"mxpi_imagedecoder0": {"factory": "mxpi_imagedecoder","next": "mxpi_imageresize0"},"mxpi_imageresize0": {"props": {"dataSource": "mxpi_imagedecoder0","resizeType": "Resizer_KeepAspectRatio_Fit","resizeWidth":"640","resizeHeight":"640","paddingType":"Padding_NO","interpolation":"2"},"factory": "mxpi_imageresize","next": "mxpi_tensorinfer0"},"mxpi_tensorinfer0": {"props": {"dataSource": "mxpi_imageresize0","modelPath": "./models/yolov5/yolov5_add_bs1_fp16.om"},"factory": "mxpi_tensorinfer","next": "mxpi_objectpostprocessor0"},"mxpi_objectpostprocessor0": {"props": {"dataSource": "mxpi_tensorinfer0","postProcessConfigPath": "./models/yolov5/yolov5_add_bs1_fp16.cfg","labelPath": "./models/yolov5/aldefectdetection.names","postProcessLibPath": "${HOME}/MindX_SDK/mxVision-2.0.4/lib/modelpostprocessors/libyolov3postprocess.so"},"factory": "mxpi_objectpostprocessor","next": "mxpi_dataserialize0"},"mxpi_dataserialize0": {"props": {"outputDataKeys": "mxpi_objectpostprocessor0"},"factory": "mxpi_dataserialize","next": "appsink0"},"appsink0": {"props": {"blocksize": "4096000"},"factory": "appsink"}}}可视化流程编排极大地提升了开发效率,通过这种方式用户可以很快的完成pipeline的编排。4.3.7 编写main.py文件main文件的编写逻辑如下图所示:按照上述流程图,完成代码开发,其中,通过SendDataWithUniqueId将数据送入流里,GetResultWithUniqueId从流里获取数据,最终用opencv将位置信息和类别信息标记在图片上并保存。主函数main.py:初始化流管理器,如果初始化失败,则提示用户并退出程序:2.通过streamManagerApi创建流,导入pipeline文件,如果失败,则提示用户并退出程序3. 构建输入数据,并对输入数据进行检查,确保输入的图片存在且不为空,否则提示用户并退出程序。4. 对输入数据进行预处理,对齐YOLOv5数据预处理操作。5. 将输入数据传入到指定流中,并通过uniqueId获取指定流的输出结果:6. 读取流中的结果,并将位置信息和类别信息输出到图片上,保存图片7. 销毁流4.4 项目下载连接以及项目结构完整项目请在此处下载:cid:link_14项目目录结构如下所示:├── models│ ├── yolov5│ │ ├── aldefectdetection.names # 铝材缺陷检测类别│ │ ├── insert_op.cfg # yolov5 aipp转换配置│ │ ├── yolov5_add_bs1_fp16.cfg # yolov5后处理配置│ │ ├── yolov5_add_bs1_fp16.om # 铝材缺陷检测模型│ │ ├── best.onnx # 用于模型转换├── pipeline│ └── AlDefectDetection.pipeline # pipeline文件├── main.py├── eval.py├── eval_pre.py # letterbox预处理├── plots.py # 绘图工具类├── utils.py # 工具类└── test.jpg5. 运行5.1 配置远程映射在工具栏"Tools > Deployment> Configuration"在Connection选项中配置远程连接。在Mappings选项中配置远程映射,同步远端和本地代码。配置远端路径之后点击OK完成映射。在工具栏点击"Tools > Deployment> Upload to"上传本地代码到远端服务器在精度测试下载的数据集中任意选择一张图片放在项目的根目录下,并命名为test.jpg在main.py文件点击右键,Modify Run Configuration,配置python解释器,选择远端python解释器,配置完成之后点击apply,点击OK。配置完成之后即可右键运行main.py文件得到结果,在程序中,通过输出流里取得的数据,我们可以看到图片的位置和类别信息。通过这些位置信息,我们进一步作出结果图:5.2 精度测试准备测试数据https://mindx.sdk.obs.cn-north-4.myhuaweicloud.com/ascend_community_projects/Aluminum_surface_defect_detection/testDatas.zip和om模型文件:https://mindx.sdk.obs.cn-north-4.myhuaweicloud.com/ascend_community_projects/Aluminum_surface_defect_detection/yolov5_add_bs1_fp16.om运行项目根目录下的eval.py,该文件是在main.py的基础上循环输入测试数据集图片得到结果。生成的位置信息和类别信息会以txt文件的形式保存在项目目录下的test/testouttxt/。在map.py界面右键,修改运行配置,添加路径参数配置命令行参数:其中--gt为测试集数据的标签路径,--testpath为模型输出结果的路径(即上述test/testpre_post/),包括分类结果、位置信息和置信度参数。结果如下图所示:mAP0.5为0.8135478,mAP0.5:0.95为0.5587293358。其中mAP是目标检测模型中常用的评价指标,它的英文全称是(Mean Average Precision),翻译过来就是平均精确率的平均。mAP0.5是指计算标准为IOU阈值大于0.5,也就是预测框和标签IOU>0.5为正样本。mAP0.5:0.95是指取IOU阈值为以0.05为步长,0.5为起始数据,一直到IOU阈值为0.95的十组数据的平均精度。6. FAQ1 尺寸不匹配问题描述:提示mxpi_tensorinfer0The input of the model does not match] The datasize of concated inputTensors0 does not match model inputTensors0. Tensor Dtype: TENSORDTYPEUINT8, model Dtype: TENSORDTYPEUINT8.解决方案:模型经过插件处理后的图像与模型输入不匹配,检查模型经过pipeline之后的尺寸大小是否和模型输入匹配。2 模型路径未进行正确配置问题描述:提示 Failed to get model, the model path is invalidate.解决方案:检查模型存放路径,正确配置模型路径。3 未修改pipeline中后处理插件的postProcessLibPath属性问题描述:提示[Object, file or other resource doesn't exist] The postprocessing DLL does not exist解决方案:修改pipeline文件中mxpi_objectpostprocessor0插件的postProcessLibPath属性,修改为{SDK安装路径}/lib/modelpostprocessors/libyolov3postprocess.so4 同步远端CANN开发包失败问题描述:提示[PermissionError: [Errno 13] Permission denied: '/usr/local/Ascend/ascend-toolkit/5.0.4/pyACL/scene.info' Command execute fail, exitStatus = 1]解决方案:将CANN开发包安装到用户目录下。7. 一些个人经验总结在编写pipeline的时候,MindStudio提供的可视化流程编排极大地提高了开发效率,在MindStudio可以通过拖动的方式完成pipeline的编写,参数也可以很方便的在可视化流程编排中配置;在开发中我们难免会遇到各种各样奇奇怪怪的问题,昇腾论坛是个不错的选择,有问必答,从大四开始已经陆陆续续问了挺多问题,答复速度比较快,开发中受阻,不妨在论坛里请求大佬寻求帮助,链接:华为云论坛云计算论坛开发者论坛_技术论坛-华为云 (huaweicloud.com)。在做模型转换前,最好用netron确定一下输出节点,找到正确输出节点,才能让om模型正确输出,netron下载链接:lutzroeder/netron: Visualizer for neural network, deep learning, and machine learning models (github.com)8. Mindstuido下载连接链接:(MindStudio下载-昇腾社区 (hiascend.com)9. 开发过程中用到的链接MindX SDK 2.0.4 mxVision 用户指南:MindX SDK 2.0.4 mxVision 用户指南 01 - 华为 (huawei.com)CANN安装指南(在用MindStudio可能会由于权限问题,导致远端CANN开发包同步不到本地,可以安装该包到用户目录下) :在昇腾设备上安装 - CANN 5.0.4 软件安装指南 01 - 华为 (huawei.com)基于MindStudio的MindX SDK应用开发全流程:基于MindStudio的MindX SDK应用开发全流程哔哩哔哩bilibili
  • [技术干货] 深度学习——VGG16模型详解-转载
     1、网络结构  VGG16模型很好的适用于分类和定位任务,其名称来自牛津大学几何组(Visual Geometry Group)的缩写。  根据卷积核的大小核卷积层数,VGG共有6种配置,分别为A、A-LRN、B、C、D、E,其中D和E两种是最为常用的VGG16和VGG19。  介绍结构图:  conv3-64 :是指第三层卷积后维度变成64,同样地,conv3-128指的是第三层卷积后维度变成128; input(224x224 RGB image) :指的是输入图片大小为224244的彩色图像,通道为3,即224224*3; maxpool :是指最大池化,在vgg16中,pooling采用的是2*2的最大池化方法(如果不懂最大池化,下面有解释); FC-4096 :指的是全连接层中有4096个节点,同样地,FC-1000为该层全连接层有1000个节点; padding:指的是对矩阵在外边填充n圈,padding=1即填充1圈,5X5大小的矩阵,填充一圈后变成7X7大小; 最后补充,vgg16每层卷积的滑动步长stride=1,padding=1,卷积核大小为333;    如上图VGG16的网络结构为,VGG由5层卷积层、3层全连接层、softmax输出层构成,层与层之间使用max-pooling(最大化池)分开,所有隐层的激活单元都采用ReLU函数。具体信息如下:  卷积-卷积-池化-卷积-卷积-池化-卷积-卷积-卷积-池化-卷积-卷积-卷积-池化-卷积-卷积-卷积-池化-全连接-全连接-全连接  通道数分别为64,128,512,512,512,4096,4096,1000。卷积层通道数翻倍,直到512时不再增加。通道数的增加,使更多的信息被提取出来。全连接的4096是经验值,当然也可以是别的数,但是不要小于最后的类别。1000表示要分类的类别数。 用池化层作为分界,VGG16共有6个块结构,每个块结构中的通道数相同。因为卷积层和全连接层都有权重系数,也被称为权重层,其中卷积层13层,全连接3层,池化层不涉及权重。所以共有13+3=16层。 对于VGG16卷积神经网络而言,其13层卷积层和5层池化层负责进行特征的提取,最后的3层全连接层负责完成分类任务。 2、VGG16的卷积核  VGG使用多个较小卷积核(3x3)的卷积层代替一个卷积核较大的卷积层,一方面可以减少参数,另一方面相当于进行了更多的非线性映射,可以增加网络的拟合/表达能力。 卷积层全部都是3*3的卷积核,用上图中conv3-xxx表示,xxx表示通道数。其步长为1,用padding=same填充。 池化层的池化核为2*2 3、卷积计算   具体的过程:  输入图像尺寸为224x224x3,经64个通道为3的3x3的卷积核,步长为1,padding=same填充,卷积两次,再经ReLU激活,输出的尺寸大小为224x224x64 经max pooling(最大化池化),滤波器为2x2,步长为2,图像尺寸减半,池化后的尺寸变为112x112x64 经128个3x3的卷积核,两次卷积,ReLU激活,尺寸变为112x112x128 max pooling池化,尺寸变为56x56x128 经256个3x3的卷积核,三次卷积,ReLU激活,尺寸变为56x56x256 max pooling池化,尺寸变为28x28x256 经512个3x3的卷积核,三次卷积,ReLU激活,尺寸变为28x28x512 max pooling池化,尺寸变为14x14x512 经512个3x3的卷积核,三次卷积,ReLU,尺寸变为14x14x512 max pooling池化,尺寸变为7x7x512 然后Flatten(),将数据拉平成向量,变成一维51277=25088。 再经过两层1x1x4096,一层1x1x1000的全连接层(共三层),经ReLU激活 最后通过softmax输出1000个预测结果 从上面的过程可以看出VGG网络结构还是挺简洁的,都是由小卷积核、小池化核、ReLU组合而成。其简化图如下(以VGG16为例):    4、权重参数(不考虑偏置)  1)输入层有0个参数,所需存储容量为224x224x3=150k 2)对于第一层卷积,由于输入图的通道数是3,网络必须要有通道数为3的的卷积核,这样的卷积核有64个,因此总共有(3x3x3)x64 = 1728个参数。 所需存储容量为224x224x64=3.2M 计算量为:输入图像224×224×3,输出224×224×64,卷积核大小3×3。  所以Times=224×224×3x3×3×64=8.7×107  3)池化层有0个参数,所需存储容量为 图像尺寸x图像尺寸x通道数=xxx k 4)全连接层的权重参数数目的计算方法为:前一层节点数×本层的节点数。因此,全连接层的参数分别为: 7x7x512x4096 = 1027,645,444 4096x4096 = 16,781,321 4096x1000 = 4096000 按上述步骤计算的VGG16整个网络总共所占的存储容量为24M*4bytes=96MB/image 。  所有参数为138M VGG16具有如此之大的参数数目,可以预期它具有很高的拟合能力;  但同时缺点也很明显: 即训练时间过长,调参难度大。 需要的存储容量大,不利于部署。 5、VGG模型所需要的内存容量  借鉴一下大佬的图:    6、总结  通过增加深度能有效地提升性能; VGG16是最佳的模型,从头到尾只有3x3卷积与2x2池化,简洁优美; 卷积可代替全连接,可适应各种尺寸的图片。 ———————————————— 版权声明:本文为CSDN博主「橙子吖21」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_42012782/article/details/123222042 
  • [经验分享] 使用MindStudio利用TSM模型完成视频分类任务
    3733图4-↵目录1. 写在前面... 22. MindStudio环境搭建... 22.1本地Windows服务器环境搭建... 32.1.1 MindStudio的下载... 42.1.2 MindStudio的安装... 52.2集成MindStudio开发环境搭建... 72.2.1新建项目... 72.2.2 配置远程服务器... 112.2.3 配置项目SDK.. 142.2.4 配置MindX SDK.. 183. 模型介绍... 213.1介绍... 213.2代码目录结构与说明... 213.3环境依赖... 214. 离线推理... 224.1数据集下载... 224.2数据集预处理... 264.3模型转换... 284.4 Pipeline流程编排... 334.4.1 创建Pipeline文件... 334.4.2 设置插件... 344.4.3 配置插件参数... 354.4.4 Pipeline文件保存... 394.5离线推理和精度检测... 404.6 SDK性能测试... 425. 在线推理... 435.1安装视频流工具... 435.2生成视频流... 455.3模型转换... 475.4Pipeline流程编排5.5 程序测试... 506. FAQ.. 511. 写在前面本文进行的项目以昇腾Atlas310卡为主要的硬件平台,使用TSM模型,基于Kinetics-400数据集,在MindX SDK环境下实现视频分类功能。将测试视频传入脚本进行前处理,模型推理,后处理等功能,最终得到模型推理的精度和性能。项目主要由离线精度测试文件,在线功能测试文件,离线单视频推理性能测试文件,模型文件,测试数据集预处理文件组成。如在实践过程中遇到任何的问题,可以前往华为MindStudio论坛华为云论坛_云计算论坛_开发者论坛_技术论坛-华为云 (huaweicloud.com)寻求帮助,本文在实践过程中遇到的诸多问题均从论坛上获得答案最终解决。本项目视频案例链接如下:使用MindStudio利用TSM模型完成视频分类任务_哔哩哔哩_bilibili2. MindStudio环境搭建本项目所处的场景为纯开发场景(分部署形态),详情请参见安装方案(Windows)-安装方案-安装指南-5.0.RC3-MindStudio-文档首页-昇腾社区 (hiascend.com),该场景下在Windows服务器上安装MindStudio,在纯开发环境需要安装Ascend-cann-toolkit,两者建立连接之后,形成了集成的MindStudio的纯开发环境。昇腾AI设备上运行环境的安装部署操作请参见《CANN 软件安装指南》,此场景运行环境多为端侧、边侧设备如Atlas 500智能小站和Atlas 200 DK开发者套件等。图2-1 纯开发环境(分部署形态)CANN(Compute Architecture for Neural Networks)是华为公司针对AI场景推出的异构计算架构,通过提供多层次的编程接口,支持用户快速构建基于昇腾平台的AI应用和业务。用户根据实际使用需要,下载对应的CANN软件包,具体安装流程可以参考官网的用户手册。CANN软件包下载地址CANN 商用版下载-昇腾社区 (hiascend.com)CANN安装流程:安装须知-软件安装-环境准备-5.1.RC1-CANN商用版-文档首页-昇腾社区 (hiascend.com)2.1 本地Windows服务器环境搭建MindStudio提供了AI开发所需的一站式开发环境,提供图形化开发界面,支持模型开发、算子开发以及应用开发三个主流程中的开发任务。同时还支持网络移植、优化和分析等功能。依靠模型可视化、算力测试、IDE本地仿真调试等功能,MindStudio能够帮助用户在一个工具上就能高效便捷地完成AI应用开发。同时,MindStudio采用了插件化扩展机制,开发者可以通过开发插件来扩展已有功能。MindStudio支持Windows和Linux两大主流平台。可以根据需要,进行选择下载安装包,具体安装流程,可以参考官网:官网链接:MindStudio-昇腾社区 (hiascend.com)用户手册:成长地图-5.0.RC3-MindStudio-文档首页-昇腾社区 (hiascend.com)2.1.1 MindStudio的下载进入MindStudio官网,下拉界面,点击“立即下载”,如图2-2所示。图2-2 MindStudio下载界面进入版本选择界面,最新的版本是MindStudio_5.0.RC3,在本项目中没有选择该版本的MindStudio,下拉界面进入历史版本,在本项目中选择使用MindStudio_5.0.RC2,根据主机系统选择对应的软件包,点击软件包下载,同时需要留意其对应的CANN版本为5.1.RC2,如图2-3所示。图2-3 版本选择界面点击软件包下载之后需要在弹出界面勾选“我已阅读并已同意 MindStudio软件许可协议 的条款和条件”,如图2-4所示。图2-4 软件许可协议2.1.2 MindStudio的安装运行下载好的MindStudio安装程序,单击“Next”,进入下一步,如图2-5。图2-5 MindStudio安装界面进入下一步后,根据自身需求选取软件安装路径,在此选择默认安装路径,如图2-6.图2-6 安装路径选取进入下一界面,选择 “Create Desktop Shortcut”(创建桌面图标)、“Update Context Menu”(以工程方式打开文件夹)、“Update PATH Variable(restart needed)”(配置环境变量),之后点击“Next”如图2-7所示图2-7 设置选项默认点击install即可,如图2-8所示图2-8 安装选项安装完成,如图2-9所示。图2-9安装完成2.2 集成MindStudio开发环境搭建2.2.1 新建项目完成以上工作之后,打开MindStudio,出现以下界面,如图2-10所示。Customize为定制界面,用户可以在该界面下进行一些个性化设置,包括主题的选择等;Plugins界面为插件界面,用户可以在该界面下载插件并且查看已经下载的插件;Learn MindStudio界面可以学习MindStudio的详细用法;在此选择Projects界面,点击“New Project”选项新建项目。 图2-10 MindStudio初始界面进入新建项目界面,选择Ascend APP,“Name”部分为项目名称,“Description”为项目的相关描述,“Project Location”是项目的本地路径,输入项目名称和相关描述之后,最后点击“Change”来配置远端服务器,如图2-11所示。图2-11 新建项目选项进入页面之后,点击最右侧“+”号,在进入的界面中输入端口、用户名、密码,之后点击“Test Connection”,显示“Successfully connected”表示成功,最后点击确定退出界面即可,如图2-12所示。图2-12 配置远端服务器界面完成远端服务器配置之后,点击右侧文件夹图标,选择Ascend-cann-toolkit软件包的安装目录,之后选择到版本目录5.1.RC2,点击OK,如图2-13所示。图2-13 选择Ascend-cann-toolkit组件目录点击Finish,开始同步CANN,如图2-14所示。图2-14 同步CANN我在同步CANN的时候遇到了同步失败的问题,通过在华为论坛上进行提问CANN同步失败如何处理。_MindStudio_昇腾_华为云论坛 (huaweicloud.com),最后确定了是MindStudio版本与CANN版本不匹配的原因,因此重新安装正确版本的MindStudio,成功地同步了CANN.同步结束之后会自动退出以上界面,点击next进入项目类型选择界面,由于本项目为SDK开发项目,所以选择“MindX SDK Project(python)”,之后点击Finish按钮,完成项目的创建,如图2-15所示。图2-15 项目类型选择2.2.2 配置远程服务器此时成功地创建了一个空项目,点击“Tools”->“Start SSH session”,打开远端服务器终端,用户可以通过在此终端中输入指令,完成想要进行的操作。如图2-16所示。图2-16 启动远端服务器终端之后点击要打开的服务器,打开服务器终端窗口。如图2-17所示。图2-17 服务器选择成功打开远端服务器终端窗口,可以通过该窗口输入指令,如图2-18所示。图2-18 打开远程服务器终端之后点击“Tools”->“Deployment”->“Configuration”,如图2-19所示。图2-19 打开Configuration界面打开Configuration界面,选择相应的服务器,进入“Mappings”界面,“Local path”为本地项目的路径,“Deployment path”为项目的远端路径,选择远端服务器的项目路径,所谓远端路径,就是本地项目上传到服务器的对应路径,选择完毕后点击OK完成远端路径配置即可,如图2-20所示。图2-20 配置远端服务器项目映射路径2.2.3 配置项目SDK按照图2-21,打开“Project Structure…..”,也可通过快捷键Ctrl+Alt+Shift +S打开对应界面,配置项目SDK。图2-21 配置SDK进入界面后点击“SDKs”,之后点击“+”->“Add python SDK…”,增加SDK,如图2-22所示。图2-22 增加SDK随后点击“SSH Interpreter”,选择相应的服务器,之后会自动检测远端服务器的环境,其中interpreter为远端python解释器的路径,Name由用户自行设置,用于区分多种远端解释器,检测完毕之后点击OK退出当前界面,如图2-23所示。图2-23 检测远端环境之后点击Project,选择新增的SDK,之后点击Apply完成SDK设置,如图2-24所示。图2-24 项目解释器设置之后点击“Modules”->“Dependencies”,选择新增的SDK,点击ok完成设置,如图2-25所示。图2-25 模型依赖设置点击“Tools”->“Deployment”->“Automatic Upload”,如图2-26所示。图2-26 设置自动上传选择要上传的服务器,此处的服务器选择与mapper处选择的服务器必须保持一致,如图2-27所示。设置完毕自动上传后,在MindStudio中修改某一文件之后,使用Ctrl+s快捷键即可自动将修改的文件在服务器上进行更新。图2-27 自动上传服务器选择2.2.4 配置MindX SDK 点击“Ascend”>MindX SDK Manager,进入MindX SDK配置界面,如图2-28所示。图2-28 MindX SDK配置界面入口点击install SDK,进入SDK路径选择界面,如图2-29所示。图2-29 SDK配置界面进入SDK路径选择界面,“Remote Connection”为远端服务器选择,“Remote CANN location”为远端CANN路径,该路径与第2.2节所述路径一致。“Remote SDK location”为远端SDK路径。“Local SDK location”为本地SDK将会安装的路径。全部选择完毕后,点击“OK”进入下一步。如图2-30所示。图2-30 SDK路径选择从远端获取SDK,如图2-31所示。图2-31 从远端获取SDKSDK配置完成,集成开发环境搭建完成,如图2-32所示。图2-32 SDK配置成功3. 模型介绍3.1 介绍使用TSM模型,基于Kinetics-400数据集,在MindX SDK环境下实现视频分类功能。将测试视频传入脚本进行前处理,模型推理,后处理等功能,最终得到模型推理的精度和性能。3.2 代码目录结构与说明├── TSM ├── README.md // 所有模型相关说明 ├── model ├── pth2onnx.py // 转onnx模型脚本 ├── onnx2om.sh // 转om模型脚本 ├── pth2onnx1.py // 在线模型转onnx模型脚本 ├── onnx2om1.sh // 在线模型转om模型脚本 ├── label ├── kinetics_val.csv // label文件 ├── download_data ├── k400_extractor.sh // 解压数据集脚本 ├── online_infer.py // 在线推理精度脚本 ├── offline_infer.py // 离线推理精度脚本 ├── speed.py // 离线单视频推理NPU性能脚本 ├── speed_gpu.py // 离线单视频推理GPU性能脚本3.3 环境依赖推荐系统为ubuntu 18.04,环境依赖软件和版本如下表:软件名称版本cmake3.5+mxVision5.1RC2Python3.9torch1.10.0ffmpeg3.4.8此处以ffmpeg的安装为例,执行以下命令安装wget https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-amd64-static.tar.xzxz -d ffmpeg-git-amd64-static.tar.xztar -xvf ffmpeg-git-amd64-static.tarcd ./ffmpeg-git-20190424-amd64-static./ffmpeg4. 离线推理4.1 数据集下载参考PaddleVideo/k400.md at develop · PaddlePaddle/PaddleVideo (github.com)中的Kinetics-400数据集下载方式,在“TSM/download_data/”目录下准备“download.sh”脚本、"val_link.list"验证集链接列表文件以及“k400_extractor.sh”数据集解压脚本。之后将其上传到远端服务器,如图4-1所示。图4-1 将本地脚本同步到服务器通过MindStudio运行脚本,根据图4-2,进入“Edit Configurations”界面。图4-2 运行设置入口进入界面后,选择“Ascend App”,“Name”为用于自行设置,用于区分不同的运行程序,“Deployment”为要运行的服务器;“Executable”为要运行的脚本或代码;“Command Arguments”为指令参数,参数val_link.list为需要下载的数据集压缩包链接,如图4-3所示。即运行该脚本或代码传入的参数; “Environment Variables”为环境变量的设置,完成以上所有设置后点击“Apply”即可。如图4-4所示。图4-3 val_link.list内容图4-4 运行设置设置完毕后,点击运行按钮即可,如图4-5所示。图4-5 运行下载数据集脚本下载脚本运行完毕后,数据集压缩包下载完成,共有三个文件“var_part1.tar”、“var_part2.tar”和“var_part3.tar”,运行结果如图4-6所示。图4-6 数据集下载完成结果之后进行数据解压工作,将数据解压到TSM/data目录下,对于解压脚本采用同样的操作,解压脚本不需要传入命令参数,如图4-7所示。图4-7 解压脚本运行设置之后点击运行按钮,运行数据解压脚本,运行完毕后,运行结果如图4-8所示。图4-8 数据解压脚本运行结果数据集含有共计400个类别的视频,数据集目录结构如下:├── TSM ├── data ├── abseiling ├── air_drumming ├── ... ├── zumba4.2 数据集预处理在代码根目录下创建文件夹“tools”和“ops”;在链接mit-han-lab/temporal-shift-module: [ICCV 2019] TSM: Temporal Shift Module for Efficient Video Understanding (github.com)下载代码包,并且将代码包中"tools"目录下的"vid2img_kinetics.py"、"gen_label_kinetics.py"、"kinetics_label_map.txt"三个文件拷贝至目录TSM/tools下,tools目录结构如下:├── TSM ├── tools ├── gen_label_kinetics.py // label生成脚本 ├── vid2img_kinetics.py // 视频抽帧脚本 ├── kinetics_label_map.txt将代码包中“ops”目录下的"basic_ops.py"、"dataset.py"、"dataset_config.py"、"models.py"、"temporal_shift.py"、"transforms.py"六个文件拷贝至目录TSM/ops下,ops的目录结构如下: ├── ops ├── basic_ops.py ├── dataset.py // 数据集构建脚本 ├── dataset_config.py // 数据集配置脚本 ├── models.py // 模型搭建脚本 ├── temporal_shift.py ├── transforms.py将代码包中"online_demo"目录下mobilenet_v2_tsm.py 放在参考设计代码根目录的TSM/model 目录下。model的目录结构如下:├── TSM ├── model ├── pth2onnx.py // 转onnx模型脚本 ├── onnx2om.sh // 转om模型脚本 ├── mobilenet_v2_tsm.py // 在线模型脚本 ├── pth2onnx1.py // 在线模型转onnx模型脚本 ├── onnx2om1.sh // 在线模型转om模型脚本打开"vid2img_kinetics.py"文件,该脚本为抽帧脚本,为了充分的利用内存,在代码中每对一个视频抽帧结束后,就将原视频删除,以此来节约内存,class_process为抽帧函数,抽帧结束之后,利用shutil.rmtree删除原视频。同时将最后两行代码注释,如图4-9所示。图4-9 修改代码"vid2img_kinetics.py"之后进行抽帧,代码需要传入两个参数,第一个参数../data为视频所在的路径,其中../代表该脚本所在目录的上一级目录,即根目录TSM,所以此处的视频所在路径可等效为TSM/data,第二个参数../dataset为图片储存路径。在运行设置时需要在命令参数处输入相应的路径。如图4-10所示。图4-10 抽帧脚本运行设置抽帧脚本运行结束后,结果图4-11所示,代表抽帧完成。图4-11 抽帧运行结果抽帧结束之后,在根目录下创建labels目录,用于存放标签,运行标签生成代码gen_label_kinetics,在目录TSM/labels下生成标签,生成标签脚本运行设置如图4-12所示,不需要传入参数,标签生成结果如图4-13所示。图4-12 标签生成脚本运行设置图4-13 标签生成结果4.3 模型转换下载离线模型:TSM_kinetics_RGB_resnet50_shift8_blockres_avg_segment8_e50.pth将下载好的模型放在“${TSM代码根目录}/model”目录下。之后运行模型转换代码将pth模型转换为onnx模型,模型转换脚本为TSM/model目录下的pth2onnx.py脚本,需要传入参数kinetics RGB,kinetics代表kinetics-400数据集,RGB代表RGB图像,这是因为在离线推理的过程中,将8帧图片作为一个输入进行离线推理,因此参数需要设置为kinetics RGB,模型转换脚本运行设置如图4-14所示。图4-14 pth转onnx运行设置代码运行完成后,在model目录下形成了onnx模型,代码运行结果如图4-15所示。图4-15 onnx模型转换完成点击“Ascend”->“Model Converter”打开模型转换工具,如图4-16所示。图4-16 打开模型转换工具图4-17 转om模型界面打开模型转换界面之后,“Model File”部分为onnx模型,“Model Name”为模型名称,“Output Path”为生成模型的路径,“Target SoC Version”,“Input Format”以及“Type”等信息从onnx2om.sh脚本中获取,如图4-18所示。图4-18 onnx2om脚本onnx模型的shape从脚本pth2onnx脚本中获取,如图4-19所示。图4-19 pth2onnx脚本输入相应的信息之后点击“Next”进行检验,如图4-20所示。图4-20 模型检验模型检验完毕之后点击“Next”进入下一步,“Data Preprocessing”代表是否有数据预处理过程,在本项目中不进行数据预处理,如图4-21所示。图4-21 设置是否进行数据预处理进入界面后,“Operator Fusion”选项为是否融合运营商“Auto Tune Mode”选项为是否设置为自动调优模式;“Additional Arguments”为命令参数;“Environment Variables”为环境变量,完成以上设置之后点击finish,如图4-22所示。图4-22 模型转换相关设置运行完成后,模型转换完成,运行结果如图4-23所示。图4-23 模型转换运行结果4.4 Pipeline流程编排4.4.1 创建Pipeline文件在MindStudio上方菜单栏中找到并单击“Ascend > MindX SDK Pipeline”,创建新的pipeline文件,如图4-24所示。图4-24 创建新的pipeline文件此时成功地创建了一个Pipeline文件,如图4-25所示。图4-25 成功创建Pipeline文件4.4.2 设置插件依次找到以下插件,并从左侧插件栏拖入:appsrcmxpi_tensorinfermxpi_dataserializeappsink如图4-26所示。图4-26 拖入所需插件之后通过拖动插件块边框的连接点,将各模块按序连接,如4-27所示。图4-27 按序连接各个插件4.4.3 配置插件参数点击appsrc插件,将在右侧显示插件相关属性,设置属性“blocksize“为409600,如图4-28所示。图4-28 配置appsrc插件参数点击mxpi_tensorinfer插件,在右侧显示属性,由于数据来自appsrc0插件,设置“dataSource”为“appsrc0”,同时在“modelPath”中选择TSM.om模型,如图4-29所示。图4-29 配置mxpi_tensorinfer插件参数点击mxpi_dataserialize插件,右侧显示其属性,设置“outputDataKeys”为“mxpi_tensorinfer0”,如图4-30所示。图4-30 配置mxpi_dataserialize插件参数点击appsink插件,在右侧的属性面板中修改参数“blocksize”为4096000,如图4-31所示。图4-31 配置sppsink插件参数选中全部插件,右击鼠标,在出现的选项中选取“Set Stream Name”,如图4-32所示。图4-32 进入设置名称设置名称为TSM,如图4-33所示。图4-33 文件命名再次选中全部插件,右击鼠标,在出现的选项中选取“Set Device Id”,如图4-34所示。图4-34 进入Set Device Id界面设置Device Id为0,如图4-35所示。图4-35 设置设备Id4.4.4 Pipeline文件保存单击下方工具栏中的“save as“,命名为“TSM”,单击“Save”保存当前pipeline,如图4-36、4-37所示。图4-36 保存Pipeline文件图4-37 命名Pipeline文件保存完毕后在对应目录下即可找到生成的Pipeline文件。图4-38 保存Pipeline文件4.5 离线推理和精度检测在这部分完成的是离线推理和精度检测工作,修改${TSM代码根目录}/ops/dataset_config.py 脚本中参数ROOT_DATASET、filename_imglist_train和filename_imglist_val,若仅进行离线精度测试则可忽略filename_imglist_train设置。其中ROOT_DATASET为生成标签的目录,设置为“./labels/”,filename_imglist_val为验证集。如图4-39所示。图4-39 dataset_config.py脚本代码设置从mindxsdk-referenceapps: MindX SDK Reference Apps - Gitee.com下载脚本“offline_infer.py”, ”online_infer.py”, ”speed.py” 置于项目根目录下,在项目根目录下运行离线推理脚本offline_infer.py进行离线推理和精度检验,离线推理脚本offline_infer.py的核心部分,如图4-40所示。该脚本利用for循环对下载完毕并且抽帧完毕的13416个视频逐一地进行离线推理,在离线推理的过程中,将每8帧合起来作为一个输入投入模型进行推理,获得推理结果之后,与生成的标签值进行比对,观察二者是否一致,用推理正确的视频数除以总的视频数,以此获得模型的精度信息,每完成一个视频的推理就输出一次精度信息,如代码第130行所示,直至所有视频推理完毕之后,得到最终的精度。图4-40 offline_infer.py核心代码在运行离线推理的脚本时需要输入命令参数kinetics,代表着输入的数据集是kinetics-400数据集,运行设置如图4-41所示。图4-41 offline_infer.py运行设置运行离线推理脚本,获得精度为72.31%,符合精度偏差范围,精度达标,结果如图4-42所示。图4-42 精度检测结果4.6 SDK性能测试将用来测试的单视频放于参考设计代码根目录下,如视频“test.mp4”,打开性能测试脚本“speed.py”修改参数,’./test_speed.mp4’为测试视频,需要声明的是测试视频类别需要在kinetics-400数据集的400个种类内且视频长度至少为3s。具体代码以及修改如图4-43所示。图4-43 性能测试代码修改运行speed.py脚本进行性能测试,不需传入参数,运行设置如图4-44所示。图4-44 性能测试脚本运行设置运行性能测试脚本后,获得的单视频推理性能为0.189sec/video,性能测试结果如图4-45所示。图4-45 性能测试结果5. 在线推理5.1 安装视频流工具下载安装包:cid:link_9将压缩包放置在{根目录}/live555/目录下,打开MindStudio远程终端界面,在界面中输入以下指令,将压缩包解压:tar -zxvf live555.tar.gztar -zxvf .tar.gz解压后目录为:├── live555 ├── live├── live.tar.gz├── live555.tar.gz├── starNvr.sh解压操作如图5-1所示。图5-1 解压操作之后进行编译安装操作,在上一步操作的基础上执行命令:cd live/./genMakefiles linuxmake注意第二条指令后的参数是根据live/下的config.<后缀>得到的,与服务器的架构有关。执行完毕之后就会在mediaServer 目录下生成一个live555MediaServer可执行文件。具体操作图5-2所示。图5-2 安装操作5.2 生成视频流在安装完成之后,将“startNvr.sh”、“live555MediaServer”以及要起流的视频“jester.264”放在同一目录之下。├── hailiang2 ├── starNvr.sh├── live555MediaServer├── jester.264之后在远程终端中输入指令:ps -ef | grep live555MediaServer查看已经占用的端口号,选取没有占用的端口进行起流,如图5-3所示。5-3 查看已经占用的端口如图5-3所示,1208端口并未被占用,因此选择1208端口进行起流,在远程终端中输入指令./startNvr.sh 1208进行起流,如图5-4所示。图5-4 起流操作起流完毕之后,再次输入指令查看端口占用情况,出现:00:00:00 ./live555MediaServer 1208证明起流成功,如图5-5所示。图5-5 起流成功5.3 模型转换下载在线模型mobilenetv2_jester_online.pth.tar,将下载好的模型放在参考设计代码根目录下的“model”目录下。将模型转换为onnx模型,运行“pth2onnx1”脚本将pth转化为onnx模型,该脚本不需要传入参数,脚本运行设置如图5-6所示。图5-6 pth转换onnx模型脚本运行设置Pth转换为onnx模型转换成功。结果如图5-7所示。图5-7 模型转换结果onnx模型转换为om模型的操作步骤与第4.3节中所述一致。打开onnx模型转换界面,如图5-8所示。导入onnx模型,其中“Model File”为在线推理的onnx模型文件,“Model Name”为模型的名称,“Output Path”为转换成功后模型的输出路径,“Target SoC Version”为目标SoC版本,“Input Format”为输入格式,“Type”为种类,以上信息从onnx2om1.sh脚本中获取,如图5-9所示。而“shape”为模型的输入维度,该信息从pth2onnx1.sh脚本中获取,如图5-10所示。图5-8 模型转换相关设置图5-9 onnx2om1.sh脚本图5-10 pth2onnx1.sh脚本该模型转换过程不需设置数据预处理,直接点击“Next”即可,如图5-11所示。图5-11 数据预处理设置下一界面的相关参数已经在第4.3节做过介绍,“Operator Fusion”选项为是否融合运营商“Auto Tune Mode”选项为是否设置为自动调优模式;“Additional Arguments”为命令参数;“Environment Variables”为环境变量,本项目中不需进行设置,因此点击“finish”即可,如图5-12所示。图5-12 模型转换设置完毕模型转换完成,在指定目录生成om模型,结果如图5-13所示。图5-13 om模型生成结果5.4 Pipeline流程编排在线推理部分的Pipeline流程编排与离线推理部分保持一致,在此不做介绍,详情参见本文第4.4节内容。5.5 程序测试打开TSM/online_infer.py在线推理脚本,配置rtsp地址,其中192.168.88.110为服务器,而1208为成功起流的端口,jester.264为用于在线推理的视频,如图5-14所示。图5-14 online_infer.py代码修改在线推理脚本的核心代码如图5-15所示,在线推理与离线推理的不同之处在于:离线推理是将每8个帧合起来作为一个输入,而在线推理是将1个帧和上一个输出结果合并起来作为新的输入,将新的输入放入模型中得到输出之后再和下一帧合并得到新的输出,以此类推,能够实时地推理出视频中的手势,其核心代码的主要思路是保存输出结果,与新的一帧合并,再次输入模型,获得新的输出,循环反复,对应的代码就是116行之后的内容。图5-15 在线推理脚本核心代码运行online_infer.py脚本,其运行设置如图5-16所示。图5-16在线推理脚本运行设置运行脚本后,开始进行在线推理,用于推理的视频为一系列手势,脚本运行的结果如图5-17所示。图5-17在线推理脚本运行结果6. FAQ在使用MindStudio完成项目的过程中,遇到如下几个问题,并且给出对应的解决方案。远程CANN同步失败第一次下载的MindStudio版本为最新版本,与服务器上的CANN版本不一致,导致同步失败,更换MindStudio版本之后,便可以顺利同步。这一点在第2.1节中有提及到。2. onnx模型转换om模型无法加载模型问题在利用MindStudio进行模型转换时,由于本项目的离线推理模型内存较大,所以在加载onnx模型的过程中总是无法加载,询问过工程师老师后,得知可能是网络的问题,更换了稳定的网络之后便可以顺利加载onnx模型。3. 数据集占用内存过大如何处理由于在进行离线推理时需要下载数据集,数据集占用内存非常巨大,会出现内存不足的情况下,导致抽帧不完全,造成精度不满足。一开始我尝试抽完一个视频,就删除一个视频,以此来解决内存问题,但是之后发现是抽帧图片总内存过大,一个盘放不下,为了解决该问题,建议将数据集放在其他盘下,如果其他盘的内存也无法完全容纳,则可以将数据分成两部分,放在两个盘下,比如将part1和part2放在一个盘里,part3放在另一个盘里,在生成标签时生成两次标签,之后将两次标签合并即可。4. 服务器上无摄像头如何进行在线推理利用华为拉流工具进行起流,将mp4格式的视频转化为264格式视频,之后在指定的空闲端口起流,成功起流之后即可进行在线推理。5. 在Pipeline编辑时左侧插件栏显示空白出现这种问题的原因在于SDK的版本不匹配问题,需要重新下载匹配的SDK,在远端服务器上重新安装,即可解决问题,安装指令如下:chmod +x Ascend-mindxsdk-mxvision_3.0.RC2.1_linux-aarch64.run./Ascend-mindxsdk-mxvision_3.0.RC2.1_linux-aarch64.run –install6. MindStudio点击运行脚本后长时间无响应在开发的过程中,可以顺利打开远端服务器的终端,但是运行脚本时一直无响应,对于这个问题,我认为一般是网络问题,解决方案是重新启动MindStudio,等待右下角的所有进程全部结束后,重新运行脚本,稍等片刻即可正常运行。7. 在线推理中的问题由于需要利用拉流工具来代替摄像头的作用,在起流的时候一定要提前查看被占用端口,选择未被占用的端口,否则会导致视频混乱或者端口冲突,导致最终的在线推理的结果错误。以上为在开发过程中遇到的困难,倘若读者在实践的过程中遇到了其他的困难,可以登陆昇腾社区进行求助获取解决方案。华为云论坛_云计算论坛_开发者论坛_技术论坛-华为云 (huaweicloud.com)
  • [经验分享] 基于MindStudio的PyTorch模型开发精度调优
    本文的视频讲解可在以下链接查看:基于MindStudio的PyTorch模型开发精度调优PyTorch模型开发精度调优目录一、 精度调优所需的环境依赖 1.1 系统所需环境依赖(以Ubuntu18.04为例) 1.2 PyTorch所需依赖说明 二、 Dump数据,npy数据简要介绍 2.1 dump数据简要介绍 2.2 npy数据简要介绍 三、 dump数据类型与dump、npy数据文件命名要求 3.1 精度比对支持的dump数据类型 3.2 dump、npy数据文件命名要求 四、 训练场景下待比对数据与标准数据简述 五、 比对操作的完整流程及结果 5.1 前期准备 5.2 完成pytorch框架的安装 5.3 安装Pytorch比对的Dump数据文件环境 5.4 保存基于GPU执行模型训练生成的数据文件 5.5 保存基于昇腾AI处理器执行模型训练生成的数据文件 5.6 使用get_op_map接口获取原始网络与迁移后网络内算子的映射关系 5.7 Vector比对 六、 简要介绍CosineSimilarity,MaxAbsoluteError,AccumulatedRelativeError等算法 6.1 CosineSimilarity算法: 6.2 MaxAbsoluteError算法: 6.3 AccumulateRelativeError算法: 七、 使用精度比对工具定位,将问题模型最小化,并导出子模型 八、 精度问题分析基本思路 九、 FAQ 9.1 AttributeError: type object ‘Callable’ has no attribute ‘_abc_registry’ 9.2 ImportError: libhdf5_cpp.so.103: cannot open shared object file: No such file or directory 9.3 /root/test/env_npu.sh: No such file or directory 9.4 ImportError:libhdf5.so.103.cannot open shared objrct file:No such file or directory 9.5 其他问题 一、精度调优所需的环境依赖1.1 系统所需环境依赖(以Ubuntu18.04为例)类别版本要求PythonCANN支持Python3.7.x(3.7.0~3.7.11)、Python3.8.x(3.8.0~3.8.11)、Python3.9.x(3.9.0~3.9.7)。但本案例所用模型建议使用的pytorch版本不支持Python3.9。cmake>=3.5.1make-gcc离线推理场景:要求4.8.5版本及以上gcc。在线推理、训练、Ascend Graph开发场景:要求7.3.0版本及以上gcc,若gcc版本低于7.3.0,可参考安装7.3.0版本gcc进行安装。g++zlib1gzlib1g-devlibsqlite3-devopenssllibssl-devlibffi-devunzippciutilsnet-toolslibblas-devgfortranlibblas3liblapack-devliblapack3libopenblas-dev无版本要求,安装的版本以操作系统自带的源为准。numpy>=1.14.3decorator>=4.4.0sympy>=1.4cffi>=1.12.3protobuf>=3.11.3attrspyyamlpathlib2scipyrequestspsutilabsl-py无版本要求,安装的版本以pip源为准。1.2 PyTorch所需依赖说明PyTorch版本:1.8.1类别名称安装指令(以Ubuntu系统为例)安装过程所需工具包patchapt-get install patchgitapt-get install gitPyTorch依赖环境pyyamlpip3 install pyyamlwheelpip3 install wheel二、Dump数据,npy数据简要介绍2.1 dump数据简要介绍dump文件是一个进程或者系统在某一个给定的时间的快照,又叫内存转储文件或者叫内存快照文件,是进程的内存镜像,这种文件必须用专用工具软件打开。dump文件主要分为内核模式Dump和用户模式Dump,内核模式Dump是操作系统创建的崩溃转储,主要用来分析内核相关的问题;用户模式Dump主要在调试或Troubleshooting过程中使用,主要用来分析用户态程序的问题。用户模式Dump又分为Full Dump和Mini Dump。Full Dump包含了某个进程完整的地址空间数据,和用于调试的信息,Mini Dump根据需要可以包含不同的信息。dump可以利用调试工具进行创建,可以利用任务管理器创建,也可以利用编程自动创建。对于开发者而言,利用编程创建dump文件,可以很大程度地提高对于bug的调试效率。2.2 npy数据简要介绍npy数据格式是一个四维的数组[N,H,W, C],N代表数据集的总数,H, W,C分别代表每一张图片对应的长、宽、以及通道数。npy文件是numpy专用的二进制文件,由python程序生成,可以用来保存数据和数据集。使用训练好的模型时,npy可以作为一种保存的模型文件格式,在图片数据过多存储不方便的情况下,将数据制作成npy类型的数据格式,可以很大程度上减少读取文件所需时间。三、dump数据类型与dump、npy数据文件命名要求3.1 精度比对支持的dump数据类型精度比对支持的dump数据类型有:FLOAT、FLOAT16、DT_INT8、DT_UINT8、DT_INT16、DT_UINT16、DT_INT32、DT_INT64、DT_UINT32、DT_UINT64、DT_BOOL、DT_DOUBLE3.2 dump、npy数据文件命名要求数据类型数据命名格式备注非量化离线模型在昇腾AI处理器上运行生成的dump数据{op_type}.{op_name}.{task_id}.{stream_id}.{timestamp}命名格式说明:op_type、op_name对应的名称需满足“A-Za-z0-9_-”正则表达式规则,timestamp为16位时间戳,output_index、task_id、stream_id为0~9数字组成。量化离线模型在昇腾AI处理器上运行生成的dump数据npy数据(Caffe、TensorFlow或ONNX){op_name}.{output_index}.{timestamp}.npy四、训练场景下待比对数据与标准数据简述待比对数据(My Output)标准数据(Ground Truth)模型文件/融合规则文件通过昇腾AI处理器运行生成的训练网络dump数据TensorFlow原始训练网络npy文件计算图文件(*.txt)通过昇腾AI处理器运行生成的训练网络dump数据文件(.h5文件)基于GPU运行生成的PyTorch训练网络dump数据文件(.h5文件)-五、比对操作的完整流程及结果5.1 前期准备5.1.1 安装MindStudio进入以下连接安装MindStudio,并按照页面上的提示进行后续步骤。cid:link_75.1.2 SSH连接选择File->Settings->SSH Configurations,点击+号添加新的SSH配置,将服务器IP地址、端口、密码获密钥文件填入,点击Test Connection,提示连接成功即可。 配置好SSH后,点击Tools-->Start SSH Session,即可连接服务器端。MindStudio在界面中间会出现Select Host to Connect,选择需要的远程端口,正下方会弹出Remote Terminal,就可以输入命令操作远端服务器了。5.1.3 CANN配置进入File->Settings-> Appearance & Behavior ->System Settings->CANN页面,如下图中所示。点击上图中右上方的“change CANN”,进行相应配置。根据MindStudio的版本选择合适的CANN版本,图中选择为5.1.RC2。然后就等待软件将服务器端的CANN同步到本地即可。这里Remote CANN location中填写远程服务器中CANN所在地址。填写完成后,点击Finish即可。5.2 完成pytorch框架的安装完成pytorch1.8.1版本框架的安装这里windows安装的pytorch在之后基于GPU执行模型训练生成数据文件的步骤中会用到。在NVIDIA控制面板中查看自己cuda版本进入pytorch官网cid:link_8查看下载安装指令根据官网中的指令在Anaconda Prompt中输入相应指令安装PyTorch 1.8.1除了这种安装方法外还可以选择pip安装,安装pytorch有GPU加速的版本,安装命令后面添加豆瓣源,可以提高下载速度,也可以直接用conda安装,或者用清华源进行安装。打开MindStudio,点击New Project,进入新建工程界面。选择Ascend Training。填入项目名,并配置好环境。然后配置好Module SDK,开始模型训练。5.3 安装Pytorch比对的Dump数据文件环境5.3.1 编译安装hdf5(1)获取代码。git clone https://github.com/HDFGroup/hdf5.git (2)切换到 hdf5-1_10_9分支。cd hdf5git checkout remotes/origin/hdf5_1_10_9(3)编译hdf5。./configure --prefix=/usr/local/hdf5 --enable-cxxmake -j72 #-j 后的数值可以根据CPU的核数设置make check # run test suite.make installmake check-install # verify installation. 5.3.2 添加环境变量export PATH=/usr/local/hdf5/bin:$PATHexport LD_LIBRARY_PATH=/usr/local/hdf5/lib:$LD_LIBRARY_PATHexport LIBRARY_PATH=/usr/local/hdf5/lib:$LIBRARY_PATHexport CPATH=/usr/local/hdf5/include:$CPATH 5.3.3修改Pytorch编译选项(1)进入~/pytorch/pytorch路径下编辑build.sh文件。cd pytorchvim build.sh(2)修改编译选项。NPU版本的修改当需要获取基于NPU运行生成模型训练的数据文件时,须将build.sh文件中的“DEBUG=0 USE_DISTRIBUTED=1 USE_HCCL=1 USE_MKLDNN=0 USE_CUDA=0 USE_NPU=1 BUILD_TEST=0 USE_NNPACK=0 python3 setup.py build bdist_wheel”中添加“USE_DUMP=1”字段。修改前: DEBUG=0 USE_DISTRIBUTED=1 USE_HCCL=1 USE_MKLDNN=0 USE_CUDA=0 USE_NPU=1 BUILD_TEST=0 USE_NNPACK=0 python3 setup.py build bdist_wheel修改后: DEBUG=0 USE_DISTRIBUTED=1 USE_HCCL=1 USE_MKLDNN=0 USE_CUDA=0 USE_NPU=1 BUILD_TEST=0 USE_NNPACK=0 USE_DUMP=1 python3 setup.py build bdist_wheelGPU版本的修改与NPU版本的修改操作相同。修改前:DEBUG=0 USE_DISTRIBUTED=0 USE_HCCL=0 USE_NCCL=0 USE_MKLDNN=0 USE_CUDA=1 USE_NPU=0 BUILD_TEST=0 USE_NNPACK=0 python3 setup.py build bdist_wheel DEBUG=0 USE_DISTRIBUTED=1 USE_HCCL=1 USE_MKLDNN=0 USE_CUDA=0 USE_NPU=1 BUILD_TEST=0 USE_NNPACK=0 python3 setup.py build bdist_wheel修改后: DEBUG=0 USE_DISTRIBUTED=0 USE_HCCL=0 USE_NCCL=0 USE_MKLDNN=0 USE_CUDA=1 USE_NPU=0 BUILD_TEST=0 USE_NNPACK=0 USE_DUMP=1 python3 setup.py build bdist_wheel # DEBUG=0 USE_DISTRIBUTED=1 USE_HCCL=1 USE_MKLDNN=0 USE_CUDA=0 USE_NPU=1 BUILD_TEST=0 USE_NNPACK=0 python3 setup.py build bdist_wheel 5.3.4 编译Pytorchbash build.sh5.3.5 安装whl文件编译完成后会生成Pytorch的whl文件,卸载当前的Pytorch包,安装编译完成的whl文件。pip3 uninstall torch进入dist文件夹(~/pytorch/pytorch/dist),根据dist文件夹中的.whl文件名输入pip命令。例如:pip3 install torch-1.8.1+ascend.post6-cp37-cp37m-linux_aarch64.whl5.3.6 进入Python视图,验证whl文件安装成功python3import torch如图,若执行import torch命令不提示错误,则Python环境安装成功。5.4 保存基于GPU执行模型训练生成的数据文件(1)根据安装Pytorch比对的Dump数据文件环境完成Python环境安装,其中“修改编译选项”步骤中配置为GPU版本的修改。(2)进入训练文件中trian函数中的for循环内修改训练脚本,加入如下代码with torch.utils.dumper(enabled=True, use_dump=True, use_load=False, dump_path="/home/resnet50_dump.h5") as dump:训练脚本中的运行设备字段应对应设备GPU。(3)完成脚本修改后执行训练。训练脚本中的运行设备字段应对应设备GPU。示例如下:bash $PATH/train_full_1p.sh --data_path=/home/dataset其中$PATH为训练脚本路径。(4)完成脚本修改后执行训练。5.5 保存基于昇腾AI处理器执行模型训练生成的数据文件需要在NPU上执行如下操作。(1)根据“5.3 安装Pytorch比对的Dump数据文件环境”中的讲解完成Python环境安装,其中“修改编译选项”步骤中配置为NPU版本的修改。(2)进入Python训练模型路径下修改训练脚本(xx.py文件,如:main.py),修改方式如下:打开编辑训练脚本,在train函数的for循环下添加指令:with torch.utils.dumper(enabled=True, use_dump=False, use_load=True, dump_path="/home/Jason.h5", load_file_path="/home/resnet50_dump.h5") as dump:其中load_file_path是指定保存基于GPU执行模型训练生成的数据文件,而dump_path是本次执行训练的输出文件路径。以上指令选择将对应训练函数包含在内则表示提取对应训练步骤生成的数据,须根据实际情况包含对应的训练步骤脚本,示例如下:(3)完成脚本修改后执行训练。以train_full_1p.sh启动脚本为例执行命令如下:bash $PATH/train_full_1p.sh --data_path=/home/dataset其中$PATH为train_full_1p.sh文件的的路径。训练完成后生成基于NPU运行生成的PyTorch训练网络dump数据文件(.h5文件)(5)完成以上步骤后可将生成的两个.h5文件进行比对步骤(PyTorch)。5.6 使用get_op_map接口获取原始网络与迁移后网络内算子的映射关系PyTorch网络迁移后,可能有部分算子名称发生改变,此时进行精度比对可能无法为新算子匹配到正确的标准算子完成比对。那么需要使用get_op_map接口获取原始网络与迁移后网络内算子的映射关系,为新算子匹配到正确的标准算子。需要在安装开启dump功能的torch环境上进行操作。步骤 1 完成Python环境安装。步骤 2 进入Python解释器,导入torch,调用torch.utils.get_op_map()获取映射关系, 示例如下:import torchir_map, param_map = torch.utils.get_op_map()# 返回值, ir_map是ir_name之间的映射关系,param_map是算子参数名称的映射关系ir_map = {'CudnnBatchNormBackward': 'NativeBatchNormBackward', 'NativeBatchNormBackward': 'CudnnBatchNormBackward', 'CudnnConvolutionBackward': 'NpuConvolutionBackward', 'NpuConvolutionBackward': 'CudnnConvolutionBackward'}param_map = {'CudnnBatchNormBackward': {'epsilon': 'eps'}, 'NativeBatchNormBackward': {'eps': 'epsilon'}, 'CudnnConvolutionBackward': {'self': 'input'}, 'NpuConvolutionBackward': {'input': 'self'}}执行此操作后不会输出文件,可直接执行Vector比对。5.7 Vector比对将保存基于GPU执行模型训练生成的数据文件作为标准算子的训练数据文件,将保存基于昇腾AI处理器执行模型训练生成的数据文件作为待比对算子的训练数据文件,执行Vector比对。Vector比对命令行方式操作步骤:以HwHiAiUser用户登录操作系统,然后找到msaccucmp.py文件所在路径(例如此处msaccucmp.py文件所在路径为/usr/local/Ascend/ascend-toolkit/5.1.RC2/tools/operator_cmp/compare/msaccucmp.py),并进入该路径中。执行Vector比对命令,样例命令如下(根据自己的文件路径及文件名替换指令):python3 msaccucmp.py compare -m /home/Jason.h5 -g /home/resnet50_dump.h5 -out /home/HwHiAiUser/result 最后在自己指定的文件位置中找到Vector比对结果result_*.csv文件,如图所示。其中“*”表示生成文件的时间戳。需要注意的是在执行Vector对比操作时,首先要找到msaccucmp.py文件路径,然后进入该路径中,再执行对应的操作。六、简要介绍CosineSimilarity,MaxAbsoluteError,AccumulatedRelativeError等算法6.1 CosineSimilarity算法:进行余弦相似度算法比对出来的结果,范围是[-1,1],比对的结果如果越接近1,表示两者的值越相近,越接近-1意味着两者的值越相反。余弦相似度,又称为余弦相似性,是通过计算两个向量的夹角余弦值来评估它们的相似度。余弦相似度将向量根据坐标值,绘制到向量空间中,如最常见的二维空间。定义:两个向量间的余弦值可以通过使用欧几里得点积公式求出:即给定两个属性向量,A和B,其余弦相似性θ由点积和向量长度给出,如下所示:6.2 MaxAbsoluteError算法:进行最大绝对误差算法比对出来的结果,取值范围是 0 到无穷大,值越接近于0,表明越相近,值越大,表明差距越大。6.3 AccumulateRelativeError算法:进行累积相对误差算法比对出来的结果,取值范围是 0 到无穷大,值越接近于0,表明越相近,值越大,表明差距越大。七、使用精度比对工具定位,将问题模型最小化,并导出子模型当训练网络精度未达预期时,可通过采集训练过程中各算子的运算结果(Data Dump数据),借助精度比对工具和业界标准算子(如TensorFlow)运算结果进行数据偏差对比,从而快速解决算子精度问题。首先通过NPURunConfig中的dump_config采集Data Dump数据,在创建NPURunConfig之前,实例化一个DumpConfig类进行dump的配置(包括配置dump路径、dump哪些迭代的数据、dump算子的输入还是输出数据等)。如果训练过程中采集到了Data Dump数据,则会在指定目录下生成dump文件,同时在训练脚本当前目录生成GE图文件。最后通过精度比对工具解析Data Dump数据,从而进行算子精度分析。八、精度问题分析基本思路精度问题的直接现象一般体现在模型损失值和模型度量指标上,模型损失值现象一般表现为模型损失值跑飞,不收敛、收敛慢。为0等。模型度量指标一般表现为模型的accuracy、precision等度量指标达不到预期。针对上述精度问题的现象和原因,常用的几个调优思路有检查模型损失值曲线、检查代码和超参、检查模型结构、检查输入数据。还可以采取让训练执行到最后的方式,检查精度(主要是模型度量指标)是否达到预期。检查模型结构和超参在于检查模型的静态特征,检查输入数据是将静态特征和动态训练现象结合检查,检查精度是否达到预期就是对整体精度调优过程重新审视,并考虑一些调优手段如解释模型,优化算法等。九、FAQ9.1 AttributeError: type object ‘Callable’ has no attribute ‘_abc_registry’这是在安装Dump数据文件环境时,可能出现的报错。如下图所示。此为python在3.7版本后可能会遇到的问题,只需进入如下图中红色矩形框选出的路径,然后删除typing文件夹即可(也可能为typing.py文件)。9.2 ImportError: libhdf5_cpp.so.103: cannot open shared object file: No such file or directory这也是在安装Dump数据文件环境时,“安装whl文件”步骤可能出现的报错。解决方式为:#进入hdf5cd hdf5#然后重新添加环境变量export PATH=/usr/local/hdf5/bin:$PATHexport LD_LIBRARY_PATH=/usr/local/hdf5/lib:$LD_LIBRARY_PATHexport LIBRARY_PATH=/usr/local/hdf5/lib:$LIBRARY_PATHexport CPATH=/usr/local/hdf5/include:$CPATH 9.3 /root/test/env_npu.sh: No such file or directory在“保存基于昇腾AI处理器执行模型训练生成的数据文件”操作中,当我们完成脚本修改,准备执行训练时,可能出现如下报错:解决方式为,先进入train_full_1p.sh文件所在路径(例如本案例所用为/home/MyTraining_Trial1/test/),然后再执行命令。9.4 ImportError:libhdf5.so.103.cannot open shared objrct file:No such file or directory在Vector对比执行过程中可能会遇到报错找不到libhdf5.so.103文件的问题,此时需要手动调整文件位置,找到libhdf5.so.103文件的位置,并将其放入lib中。9.5 其他问题如果还遇到其他问题,也可以登陆MindStudio昇腾论坛寻求帮助:https://bbs.huaweicloud.com/forum/forum-945-1.html
  • 使用MindStudio进行基于MindX SDK火灾识别项目开发
    视频案例点击这里:【【经验分享】使用MindStudio进行火灾识别开发】 https://www.bilibili.com/video/BV1wP411g7hX/?spm_id_from=333.999.0.0&vd_source=b8dde865c5a3eb34f8349e674724dd411 任务介绍火灾识别项目是基于MindX SDK,实现对图像中是否为火灾场景进行识别的功能。在Atlas200 DK上对火灾场景测试集进行推理,项目整体精度达到94.15%。本案例主要介绍如何利用获取的基于PyTorch框架的densenet模型(包括数据集和模型代码),在MindStudio中进行模型的转换和MindX SDK的开发部署。参照此案例,可以实现火灾识别在昇腾设备上的部署。2 环境配置整个开发环境的搭建主要分为两部分:服务器端开发环境安装和配置、本地开发环境的安装和配置。一般来说,服务器端的环境配置工作都提前完成了(比如CANN和MindX SDK的安装),因此本文主要以Windows环境为例,介绍本地开发环境安装和配置的流程。需要注意的是,关于CANN和MindX SDK的安装,网上的教程比较多,对于第一次接触的开发者来说,容易搞混的是服务器端和本地的安装教程。服务器端都是Linux操作系统,MindX SDK可以通过图形界面方式在线或离线安装,也可以通过命令行方式进行离线安装,CANN只能通过命令行方式安装;本地端我们使用的是Windows,一般都是通过MindStudio的图形界面将服务器端的CANN和MindX SDK同步到本地。对于火灾识别项目,本地环境的搭建和配置应该按如下流程:MindStudio软件安装—>SSH远程连接—>CANN配置—>推理源码和数据准备—>昇腾工程转换—>MindX SDK配置。2.1 MindStudio软件安装2.1.1 介绍MindStudio是一套基于华为自研昇腾AI处理器开发的AI全栈开发工具平台,其功能涵盖面广,可以进行网络模型训练、移植、应用开发、推理运行及自定义算子开发等多种任务。就使用而言,整体界面风格和python开发常用的PyCharm相似。熟悉PyCharm工具的开发者使用MindStudio进行开发能够很快上手。2.1.2 安装MindStudio的安装已经在其官网上的用户手册中有了详细介绍。作者使用的操作系统为window 10,点击下载上图中的exe或zip文件进行安装。注意一下MindStudio和CANN的版本对应关系:在MindStudio下载界面的最下面的版本配套中就说明了当前MindStudio版本对应的CANN版本。在历史版本下找到并安装5.0.RC1:Python版本问题:Python版本建议为3.9与MindX SDK相适配。如果在安装时没有指定python解释器的路径,在完成安装以后,进入某个python工程项目(project)以后,系统依然会提示“No Python interpreter configured for the module”,点击Configure Python interpreter进行python解释器的配置,这里选择本地python解释器。2.2 SSH连接安装了MindStudio以后就要进行SSH连接,目的是将本地的软件与服务器进行连接。点击 File->Settings->SSH Configurations,选择+号添加新的SSH配置,取一个用户名 root。将服务器IP地址、端口、密码获密钥文件填入,点击Test Connection,提示连接成功即可。这里需要注意的是授权类型有两种,一种是密码,一种是密钥文件,本文选择使用.pem格式密钥文件。服务器地址、密码或密钥文件可通过华为云申请试用或购买获得。配置好了SSH以后,点击Tools-->Start SSH Session,即可连接服务器端。选择需要连接的服务器。连接成功,点击MindStudio在界面正下方Remote Terminal,就可以输入各种命令操作远端服务器了。2.3 CANN配置2.3.1 CANN介绍CANN(Compute Architecture for Neural Networks)是华为公司针对AI场景推出的异构计算架构,通过提供多层次的编程接口,支持用户快速构建基于昇腾平台的AI应用和业务。2.3.2 CANN安装进行CANN配置前,服务器环境应存在CANN套件包,本项目中CANN使用的是5.1.RC1版本,关于CANN套件包的说明与安装可以查看CANN社区版本文档,CANN软件包可以从CANN>CANN社区版下载中获取。选择历史版本下载5.1.RC1版本(建议下载5.1.RC1.alpha005)。本项目中使用的是华为云的ECS已安装好的CANN、MindX SDK等套件包,直接从服务器拉取即可。2.3.3 CANN配置在Windows上配置CANN,实际上是使用MindStudio把服务器端的安装包同步到本地。进入File->Settings-> Appearance & Behavior ->System Settings->CANN页面,点击右边的change CANN,在弹出的对话框中填写服务器端的CANN的地址,然后就等待软件将服务器端的CANN同步到本地。重启MindStudio 激活CANN。需要注意的是,在MindStudio中,如果没有安装CANN,是不能够将下载的源码转换为Ascend Project的。点击Ascend->Convert to Ascend Project,会提示没有安装CANN,无法转换。这一步是安装MindX SDK的前提,否则在Settings中左边的菜单栏就不会有MindX SDK选项。在完成了CANN安装以后,可以点击Ascend->Convert to Ascend Project,进行工程转换的操作了。2.4 推理源码和数据准备2.4.1 介绍上面我们介绍了如何正确安装和运行 MindStudio 工具。接下来准备模型转换和 SDK 开发所需要用到的数据。主要包括:项目源码、预训练模型、数据集。2.4.2 项目代码使用 git 命令下载项目代码:git clone cid:link_5下载后的项目代码在ascend_community_projects/fire_detection目录下,项目代码结构如下。其中data文件夹下还存在other与test文件夹,分别用来当做测试用例和测试集;models文件夹下存放项目模型。将ascend_community_projects/fire_detection/figures文件夹中下的 火灾检测SDK流程图.png 更名为 pipeline.png 确保工程项目下无中文路径。2.4.3 项目模型点击链接,下载火灾识别所需的densenet模型:cid:link_1将其中的densenet.onnx,densenet.om放置在models文件夹下,densenet.onnx用于模型转换和densenet.om用于最后的推理。2.4.4 数据集下载点击链接,下载火灾识别所用的测试图片和测试集:cid:link_6other和test文件夹放置于data文件夹下,其中other用于test.py的测试,test用于main.py的测试。2.4.5 上传远端服务器首先点击Tools-->Deployment-->configuration,查看Deployment基本配置。查看Connection是否能正常连接到服务器。查看Mapping本地到服务器的映射路径。检查之后点击OK,并点击Tools-->Deployment-->Automatic Upload后选择服务器。此时已经可以将本地项目文件传送至远程服务器。右键点击左侧项目(Project)栏的项目文件fire_detection,选择Deployment-->upload to...选择需要上传的服务器。此过程需要花费比较长的时间,需要耐心等待,传输完成界面如下。如果因网络问题传输失败,重新upload即可覆盖原来的文件。这里需要注意的是,如果upload单个文件反复提示失败,可能需要检查一下服务器的硬盘空间是否已满,如果已满,需要整理一下服务器的存储空间,尽可能多空出一些空间来。2.5 Ascend工程转换2.5.1 介绍相比于PyCharm,MindStudio增加了对华为昇腾系列芯片相关的开发支持,所以在MindStudio中创建的工程可以简单分为昇腾工程和非昇腾工程,其中昇腾工程特指需要昇腾芯片的相关工程,包括训练,推理,算子开发等等。特别的,MindStudio还支持非昇腾项目到昇腾项目的一键转换,方便其他IDE项目的转移。本项目是在昇腾310推理服务器上实现基于MindSpore框架编写的densenet模型的部署推理,因此需要将代码转换为为昇腾工程。2.5.2 工程转换在源码和数据集都下载好的前提下,直接在MindStudio中点击左上角的file->open打开之前下载下来的模型代码文件夹。工程界面和目录如下:如果目前工程不是昇腾工程,单击菜单栏“Ascend > Convert To Ascend Project”,如下图所示。Project Type选择Ascend App,Sub Type选择Ascend MindX SDK App。如下图。完成工程转换后,可以看到在菜单栏多出了一栏蓝色的图标,是MindStudio为昇腾系列所特别支持的开发功能,项目中会出现.project文件。我们也可以通过Ascend下拉菜单查看这些功能,下面列出了我们用到的一些功能模块。2.6 MindX SDK 配置2.6.1 MindX SDK 介绍MindX SDK提供昇腾AI处理器加速的各类AI软件开发套件(SDK),提供极简易用的API,加速AI应用的开发。应用开发旨在使用华为提供的SDK和应用案例快速开发并部署人工智能应用,是基于现有模型、使用pyACL提供的Python语言API库开发深度神经网络应用,用于实现目标识别、图像分类等功能。通过MindStudio实现SDK应用开发分为基础开发与深入开发,通常情况下用户关注基础开发即可,基础开发主要包含如何通过现有的插件构建业务流并实现业务数据对接,采用模块化的设计理念,将业务流程中的各个功能单元封装成独立的插件,通过插件的串接快速构建推理业务。2.6.2 MindX SDK 配置和上面的CANN类似,SDK的配置指的是从服务器端将安装好的mxManufacture或者是mxVision同步到本地(这两者的差异似乎并不是特别大,很类似)。本文中使用的是mxVision 3.0.RC1。具体的配置方法如下:进入File->Settings->Appearance & Behavior ->System Settings->MindX SDK页面,在右边点击Install SDK。填写远端CANN位置,同上一步;填写远端SDK的位置:需要注意mxVision的位置要选到更下一级的linux-x86_64这个文件夹的mxVision-3.0.RC1:/usr/local/Ascend/mindx_sdk/mxVision_3.0.RC1/linux-x86_64/mxVision-3.0.RC1,很多开发者看到了第一个 mxVision_3.0.RC1就选了,这样就会报错。最后等待 SDK 同步,点击如下按钮可以验证是否已经成功配置了SDK:3 任务运行本章的工作是介绍如何使用MindStudio成功运行推理任务,有了上面的准备工作,下面的任务就变得比较直观了。MindStudio中的MindX SDK提供了多种可视化的操作,让一些需要代码编辑的工作通过可视化配置界面完成。本部分工作主要包括:模型转换—>Pipeline编写—>推理验证。3.1 模型转换3.1.1 介绍2.4.3节提到我们已经下载了一个*.onnx文件,这是训练完成以后的模型,可用于模型推理。在昇腾硬件平台实际部署时,需要使用工具将此文件转换为昇腾硬件平台支持的、后缀为*.om的文件。模型转换可以通过两种方式:一是代码的方式进行,在远端服务器运行infer/convert中的convert_om.sh文件即可;二是通过MindStudio的可视化操作界面进行转换。本文重点介绍可视化界面配置转换的方法。3.1.2 界面配置方式点击Ascend->Model Converter:进入到配置界面,其中Model file可以选择本地的模型文件也可以选择服务器端的模型文件,如果选择了本地的呢,需要耐心等待本地端的模型文件上传至服务器。Target SoC Version 选择默认的 Ascend310即可。 Output Path 选择一个文件夹作为.om文件的输出路径。在模型转换时使用了aipp配置,因此选择Type选择UNIT8后选择Next。打开aipp选项开关,选择aipp文件所在的路径,由于数据预处理信息已经由fire.cfg包含,因此不在需要Normalization等手动输入参数。点击Finish则系统进入到模型转换当中,右下角显示模型转换中。转换成功界面如下:默认om模型存储的路径和原模型的路径一致。需要注意的是,如果output path不选择默认,则需要指定本地存储路径,MindStudio直接将模型转换到本地。MindX SDK还支持om模型的可视化,如下所示:3.1.3 将生成的.om上传到服务器点击MindStudio右侧工程栏,查找转换生成的densenet.om文件。右键点击Deployment->Uploda to ...将生成的.om文件上传至服务器(如果前面选择了Deployment-->Automatic Upload生成的.om会自动同步到服务器)。上传成功后,下方Output输出界面如下。3.2 Pipeline的编写Pipeline编写可以采用直接编写代码方式或者界面配置方式。3.2.1 代码方式Pipeline 内容如下:调用发送数据插件appsrc、图像解码插件mxpi_imagedecoder、图像裁剪插件mxpi_imageresize、推理插件mxpi_tensorinfer、输出插件appsink进行编排即可,代码见fire_detection/pipeline/fire.pipeline:3.2.2 界面配置方式也可以直接使用MindX SDK的可视化操作界面拖拽各种插件进行组合。在成功连接远端服务器的前提下,首先点击Ascend->MindX SDK Pipeline。打开pipeline可视化流程编排窗口,此时在pipeline可视化流程编排窗口的左边有Input、Other、Output三个选项。我们可以点击三个选项,选择需要的组件拖拽到右边图形界面框中进行组合。发送数据插件appsrc在Input选项中;图像解码插件mxpi_imagedecoder、图像放缩插件mxpi_imageresize和推理插件mxpi_tensorinfer在Other选项中;输出插件appsink在Output选项中。组件选择好了以后,拖拽箭头将其连接起来,其中发送数据插件appsrc是pipeline头部,流从这里输入,点击该插件可以查看其参数信息。图像解码插件mxpi_imagedecoder对进入流的图像进行解码,点击该插件可以查看其参数信息。图像放缩插件mxpi_imageresize将图像放缩至特定尺寸,点击该插件,将Width和Height参数设置为224。推理插件mxpi_tensorinfer主要对流中的图像进行推理,点击该插件,填入.om模型路径。编辑好了以后,点击pipeline界面右下方的Save或者Save As进行保存并命名为fire.pipeline。3.3 推理验证推理验证是用./data/test中的测试图片进行测试,验证所用模型是否满足精度与FPS要求。3.3.1 编写main.py根据pipeline文件编排中的说明,我们在main.py中需要完成3件事——将图片传送至流+获取推理结果+输出相关精度与推理时间信息。main.py脚本文件在./fire_detection 工程目录下。3.3.2 服务器直接运行main.py步骤一:点击 MindStudio 上方 Tools->Start SSH session连接到服务器。步骤二:连接到服务器后,点击下方的 Remote Terminal,进入到命令行模式开发。步骤三:cd到项目文件夹所在的路径。步骤四:使用命令 python3 main.py 运行脚本文件,查看输出结果。运行成功,满足项目性能要求。3.3.3 使用MindStudio运行main.py步骤一:点击MindStudio上方的项目fire_detection后点击Edit Configuration。选择要运行的main.py所在位置。步骤二:设置完成后点击OK,完成后点击Run运行图标运行程序。此时会在MindStudio下方的Run界面输出运行结果。运行成功,满足项目性能要求。3.4 测试用例测试用例是用于测试异常与其他图片。3.4.1 编写test.pytest.py 脚本用于对 ./data/other 中的图片进行预测并作为异常测试。3.4.2 服务器直接运行test.py重复3.3中步骤,连接至服务器命令行界面,并且 cd 到项目所在文件夹下。输入命令测试图片 python3 test.py。运行成功。3.4.3 使用MindStudio运行test.py步骤一:点击MindStudio上方的项目fire_detection后点击Edit Configuration。选择要运行的test.py所在位置。步骤二:设置完成后点击OK,完成后点击Run运行图标运行程序。同main.py运行操作一样,此时会在MindStudio下方的Run界面输出运行结果。运行成功。4 FAQ4.1 CANN版本和MindX SDK版本需要单独下载么?如果需要在远端服务器上进行安装,则需要,如果是只需要配置本地端,则不需要。通过MindStudio可以同步到本地。4.2 SDK获取版本失败问题在选择服务器上的 SDK 时要选到 linux-x86_64 文件夹下的 SDK。4.3 使用MindStudio运行结果同步回本地失败在使用MindStudio运行项目时,运行结果如果出现同步失败的提示,其原因可能是项目中存在的中文路径或者存在中文命名的文件。由于中文名称在上传到服务器时会出现乱码,因此解决方案是点击MindStudio上方的Tools->Start SSH session,连接到服务器删除乱码文件。在本地修改原文件名称后,重新右键点击该文件选择Deployment->Upload to... 将修改后的文件重新上传至服务器。完成上述操作后,重新运行项目即可同步成功。4.4 开发过程中遇到难题如何求助可以登录MindStudio官方论坛,发帖提问,同时论坛里也有很多开发者分享的案例,可能对大家有所帮助。另外,在CSDN、B站、gitee、华为云上也有很多资源可以检索查找。当然更直接的办法是百度各种关键词。
  • [MindX SDK] 二维码风格化迁移
    二维码风格化迁移1 案例概述1.1 概要描述在本系统中,目的是基于 MindX SDK 和 MindSpore 框架,在昇腾平台上,开发端到端二维码风格化迁移的参考设计,在保证扫码软件能正确扫码的条件下,对黑白二维码实现色彩化风格迁移的功能,达到功能要求。1.2 模型结构该论文通过模拟二维码采样网络层和虚拟读码器实现了风格化二维码图像的任务,模型的总体流程如下图所示。其中,模型结构如下:(1)VGG-16 网络:用于提取输入风格图像、输入内容图像和生成风格化二维码图像的深度特征。(2)模拟采样层:如下图所示,通过将卷积核权重设置为标准高斯分布,长宽与二维码分块标准一致,符合二维码采样过程中“越靠近分块中心的点越容易被采样”的原则,将二维码采样过程拟合为卷积操作。(3)虚拟读码器:如下图所示,用于比较风格化二维码与真实二维码读码结果,如果读码结果正确则继续美化风格和样式;如果不正确则考虑鲁棒性。(4)损失函数:模型使用了三个损失函数,分别用于约束图像风格、图像内容和读码精确度,分别对应公式 (1),公式 (2) 和公式 (3)。其中 $L_s$ 为输入风格图像;$L_c$ 为输入内容图像;$Q$ 为生成的二维码图像;$C, H, W$ 为对应图像的尺寸;$f$ 为 VGG-16 网络生成的深度特征图像;$G$ 为用于风格迁移任务的格拉姆矩阵变换;$L_{code}^{M_k}$ 为虚拟读码器对不同分块的读码结果,相同为 $0$。$$ L_{\text {style }}\left(I_s, Q\right)=\frac{1}{C_s H_s W_s}\left|G\left[f_s\left(I_s\right)\right]-G\left[f_s(Q)\right]\right|_2^2 \tag{1}\ $$$$ L_{\text {content }}\left(I_c, Q\right)=\frac{1}{C_c H_c W_c}\left|f_c\left(I_c\right)-f_c(Q)\right|_2^2 \tag{2} \ $$$$ L_{\text {code }}=\sum_{M_k \in Q} L_{\text {code }}^{M_k} \tag{3} $$1.3 模型介绍本项目主要用到了两个模型,分别是:用于图像特征提取的模型 VGG-16 和用于模拟二维码扫码的 SSLayer 模型。VGG-16 模型的相关文件可在此处下载:cid:link_1SSLayer 模型参数固定,内嵌于代码中,在初始化模型时指定所使用的公开数据集可以在此处下载:cid:link_01.4 实现流程实现流程如下:1、基础环境:MindSpore、Ascend 910、Ascend-CANN-toolkit、Ascend Driver 2、业务流程编排与配置 3、Python 训练流程代码开发 4、模型效果及性能对齐1.5 技术流程技术流程图如下:1.6 代码地址本项目的代码地址为:cid:link_22 软件方案介绍2.1 项目方案架构介绍本系统的主要流程为:加载预训练的 Vgg16 模型和固定参数的 SSLayer 模型,解码载入二维码图、内容图和风格图,通过数据变换将图像 Resize 到适当大小,并根据二维码图和内容图初始化风格化图像,并将其设为梯度优化更新的参数;利用 Vgg16 模型和 SSLayer 模型得到对应的图像特征,计算 style 损失、content 损失和 code 损失,通过梯度优化更新风格化图像;迭代 100 次后输出最终的风格化二维码图像。各模块功能描述如下表所示:序号插件功能描述1图像解码调用 PIL 的 Image.open,分别读取二维码图、内容图和风格图2图像缩放调用MindSpore的mindspore.dataset.vision.Resize将图像缩放至合适大小3图像数据Tensor化调用MindSpore的mindspore.dataset.vision.ToTensor将图像数据转为Tensor数据4初始化风格化二维码图像根据加载的二维码图和内容图初始化风格化二维码图像Tensor,并调用MindSpore的mindspore.Parameter将其转为可梯度更新的参数5二维码风格化使用预训练好的Vgg16模型,并加载固定参数的SSLayer模型,Fix所有的模型参数,通过调用mindspore.nn.MSELoss计算 style、content和code损失,迭化优化风格化二维码图像6图像编码调用PIL的Image.open,将最终迭代优化的风格化二维码图像编码输出2.2 代码目录结构与说明本项目名称为 ArtCoder,其工程目录如下:. ├── datasets | └── download_datasets.sh // 数据集下载脚本 ├── mindspore // mindspore 版 │ ├── artcoder.py │ ├── main.py │ ├── model │ │ └── download_model.sh // 预训练模型下载脚本 │ ├── output // 风格化二维码图片输出目录 │ ├── requirements.txt // Python 库依赖 │ ├── run.sh // 运行脚本 │ ├── scan.py │ ├── scan.sh // 风格化二维码扫码测试 │ ├── ss_layer.py │ ├── test.sh // 批量测试生成风格化二维码 │ ├── utils.py │ ├── var_init.py │ └── vgg.py ├── .gitignore ├── LICENSE └── README.md3 开发准备支持的硬件形态和操作系统版本硬件环境操作系统版本Linux-x86_64 + CPU / GPU / Ascend910Ubuntu LTS >= 18.04.1Linux-aarch64+ CPU / GPU / Ascend310Ubuntu LTS >= 18.04.1软件依赖软件名称版本opencv4.6.0.66opencv-contrib1.23.3python3.9.2pillow9.3.0mindspore1.8.14 准备正式运行项目前,需要先根据第 2 节的要求,配置好相应的运行环境;然后根据提供的脚本下载好数据集和预训练模型。4.1 数据集下载风格化二维码的开源数据集:cd datasets bash download_datasets.sh cd ..4.2 模型下载 MindSpore 框架下的开源 VGG-16 预训模型:cd mindspore/model/ bash download_model.sh cd ../../5 运行首先进入到对应的代码目录中:cd mindspore/根据不同的硬件平台修改 Artcoder.py 文件中对应的硬件指定代码:# context.set_context(mode=context.GRAPH_MODE, device_target='CPU') # CPU 平台 # context.set_context(mode=context.GRAPH_MODE, device_target='GPU') # GPU 平台 context.set_context(mode=context.GRAPH_MODE, device_target='Ascend') # Ascend 平台然后根据以下注释编缉 run.sh 脚本:#!/bin/bash epoch=100 # 迭代优化次数 style_img_path="../datasets/style/square.jpg" # 风格图像路径 content_img_path="../datasets/content/man.jpg" # 内容图像路径 code_img_path="../datasets/code/man.jpg" # 二维码图像路径 output_dir="./output/man/" # 输出目录 export OMP_NUM_THREADS=1 python -W ignore main.py --epoch ${epoch} --style_img_path ${style_img_path} --content_img_path ${content_img_path} --code_img_path ${code_img_path} --output_dir ${output_dir}修改好对应的图像路径后,运行 run.sh 脚本:bash run.sh待程序跑完后可在输出目录下找到最终输出的风格化图像。6 测试如果想要批量地进行测试,可以运行 test.sh 脚本,根据以下注释修改对应参数:mode='some' # 测试模式 epoch=100 style_dir="../datasets/style" # 风格图片目录 content_dir="../datasets/content" # 内容图片目录 code_dir="../datasets/code" # 二维码图片目录 output_dir="./output" # 输出目录 # ...由于风格图像比较多,故提供两种测试模式:all 和 some,分别指使用所有的风格图进行测试和使用部分风格图进行测试。如果使用 some,其所使用的部分风格图列表在 test.sh 也可自行修改,即对应下面代码中的 style_list,可按需修改成自定义选定的测试图像列表:# 部分风格图测试 style_list=('candy.jpg' 'hb.jpg' 'been.jpg' 'st.jpg' 'square.jpg' 'udnie.jpg') # 选定的测试图像列表 for style in ${style_list[@]}; do style_name=$(basename ${style} .jpg) style_img_path="${style_dir}/${style_name}.jpg" output_img_path="${output_dir}/${image_name}_${style_name}" python -W ignore main.py --epoch ${epoch} --style_img_path ${style_img_path} --content_img_path ${content_img_path} --code_img_path ${code_img_path} --output_dir ${output_img_path} done然后运行 scan.sh 脚本,根据以下注释修改对应参数:scan_dir="./output" # 扫码测试目录 python scan.py --scan_dir ${scan_dir}最后会打印出能正确识别出的风格二维码的准确度。二维码识别使用了 Opencv-Contrib 中带的微信二维码扫码器。7 效率以下测速均在单进程下进行,涉及 GPU 和 NPU 也都是只使用单张卡进行测速。本测试主要对比对象为 Pytorch 版的开源 ArtCoder。针对一张 $592 \times 592$ 的二维码图风格化迁移总流程的实际硬件平台测速,包含模型载入、风格化总流程(图像读取、图像 Resize、图像变换、图像风格化迭代优化以及图像保存等步骤),每张二维码图风格化迭代优化 $100$ 个 Epoch。风格化总流程测速包含到图像读取、图像变换等 CPU 操作,受 CPU 型号及服务器上其它 CPU 任务影响较大。为了更好地比较该模型分别基于 PyTorch 的 GPU 平台,和 MindSpore 的 NPU 平台的效率,分别对模型载入、风格化总流程以及风格化流程中的迭代优化进行测速(其中 Mindspore 框架的模型载入时间不稳定,多次测量变化较大):框架硬件模型载入(s)风格化总流程(s)迭代优化(s)PyTorch 1.8.1Intel(R) Xeon(R) Gold 6226R CPU @ 2.90GHz + NVIDIA GeForce RTX 2080 Ti GPU6.6011.5211.25PyTorch 1.8.1Intel(R) Xeon(R) Gold 6226R CPU @ 2.90GHz1.96662.31656.21PyTorch 1.8.1Intel(R) Xeon(R) Gold 6226R CPU @ 2.90GHz + NVIDIA Tesla V100-PCIE GPU4.889.198.79MindSpore 1.8.1Intel(R) Xeon(R) Gold 6226R CPU @ 2.90GHz + NVIDIA GeForce RTX 2080 Ti GPU15.2911.4410.03MindSpore 1.8.1Intel(R) Xeon(R) Gold 6226R CPU @ 2.90GHz80.7821.1520.76MindSpore 1.8.1Intel(R) Xeon(R) Gold 6240 CPU @ 2.60GHz + Ascend 910 NPU17.3023.1419.498 可视化二维码图内容图风格图风格二维码图9 参考链接MindSpore 框架下预训练的 VGG-16 模型: cid:link_1二维码风格化模型代码参考:cid:link_3参考论文:@inproceedings{su2021artcoder, title={ArtCoder: An End-to-End Method for Generating Scanning-Robust Stylized QR Codes}, author={Su, Hao and Niu, Jianwei and Liu, Xuefeng and Li, Qingfeng and Wan, Ji and Xu, Mingliang and Ren, Tao}, booktitle={Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition}, pages={2277--2286}, year={2021} }
  • [其他] 浅谈深度学习
    深度学习(DL, Deep Learning)是机器学习(ML, Machine Learning)领域中一个新的研究方向,它被引入机器学习使其更接近于最初的目标——人工智能(AI, Artificial Intelligence)。深度学习是学习样本数据的内在规律和表示层次,这些学习过程中获得的信息对诸如文字,图像和声音等数据的解释有很大的帮助。它的最终目标是让机器能够像人一样具有分析学习能力,能够识别文字、图像和声音等数据。 深度学习是一个复杂的机器学习算法,在语音和图像识别方面取得的效果,远远超过先前相关技术。深度学习在搜索技术,数据挖掘,机器学习,机器翻译,自然语言处理,多媒体学习,语音,推荐和个性化技术,以及其他相关领域都取得了很多成果。深度学习使机器模仿视听和思考等人类的活动,解决了很多复杂的模式识别难题,使得人工智能相关技术取得了很大进步。深度学习定义深度学习定义:一般是指通过训练多层网络结构对未知数据进行分类或回归深度学习分类:有监督学习方法——深度前馈网络、卷积神经网络、循环神经网络等;无监督学习方法——深度信念网、深度玻尔兹曼机,深度自编码器等。深度学习的思想:深度神经网络的基本思想是通过构建多层网络,对目标进行多层表示,以期通过多层的高层次特征来表示数据的抽象语义信息,获得更好的特征鲁棒性。深度学习应用图像处理领域主要应用图像分类(物体识别):整幅图像的分类或识别物体检测:检测图像中物体的位置进而识别物体图像分割:对图像中的特定物体按边缘进行分割图像回归:预测图像中物体组成部分的坐标语音识别领域主要应用语音识别:将语音识别为文字声纹识别:识别是哪个人的声音语音合成:根据文字合成特定人的语音自然语言处理领域主要应用语言模型:根据之前词预测下一个单词。情感分析:分析文本体现的情感(正负向、正负中或多态度类型)。神经机器翻译:基于统计语言模型的多语种互译。神经自动摘要:根据文本自动生成摘要。机器阅读理解:通过阅读文本回答问题、完成选择题或完型填空。自然语言推理:根据一句话(前提)推理出另一句话(结论)。综合应用图像描述:根据图像给出图像的描述句子可视问答:根据图像或视频回答问题图像生成:根据文本描述生成图像视频生成:根据故事自动生成视频
  • [其他] 浅谈深度学习Backbone
    深度学习中常用的backbone有resnet系列(resnet的各种变体)、NAS网络系列(RegNet)、Mobilenet系列、Darknet系列、HRNet系列、Transformer系列和ConvNeXt。Backbone结构分类主要分成三类:CNNs结构, Transformer结构(如ViT及衍生算法,比如PVT),CNNs+Transformer结构Backbone:翻译为骨干网络的意思,既然说是主干网络,就代表其是网络的一部分,那么是哪部分呢?这个主干网络大多时候指的是提取特征的网络,其作用就是提取图片中的信息,共后面的网络使用。这些网络经常使用的是resnet VGG等,而不是我们自己设计的网络,因为这些网络已经证明了在分类等问题上的特征提取能力是很强的。在用这些网络作为backbone的时候,都是直接加载官方已经训练好的模型参数,后面接着我们自己的网络。让网络的这两个部分同时进行训练,因为加载的backbone模型已经具有提取特征的能力了,在我们的训练过程中,会对他进行微调,使得其更适合于我们自己的任务。Neck:是放在backbone和head之间的,是为了更好的利用backbone提取的特征。Bottleneck:瓶颈的意思,通常指的是网网络输入的数据维度和输出的维度不同,输出的维度比输入的小了许多,就像脖子一样,变细了。经常设置的参数 bottle_num=256,指的是网络输出的数据的维度是256 ,可是输入进来的可能是1024维度的。Head:head是获取网络输出内容的网络,利用之前提取的特征,head利用这些特征,做出预测。neck:是放在backbone和head之间的,是为了更好的利用backbone提取的特征bottleneck:瓶颈的意思,通常指的是网网络输入的数据维度和输出的维度不同,输出的维度比输入的小了许多,就像脖子一样,变细了。经常设置的参数 bottle_num=256,指的是网络输出的数据的维度是256 ,可是输入进来的可能是1024维度的。GAP:在设计的网络中经常能够看到gap这个层,我之前不知道是干啥的,后了解了,就是Global Average Pool全局平均池化,就是将某个通道的特征取平均值,经常使用AdaptativeAvgpoold(1),在pytorch中,这个代表自适应性全局平均池化,说人话就是将某个通道的特征取平均值self.gap = nn.AdaptiveAvgPool2d(1)Embedding: 深度学习方法都是利用使用线性和非线性转换对复杂的数据进行自动特征抽取,并将特征表示为“向量”(vector),这一过程一般也称为“嵌入”(embedding)用于预训练的任务被称为前置/代理任务(pretext task),用于微调的任务被称为下游任务(downstream task)temperature parameters 在论文中经常能看到这个温度参数的身影。
  • [基础知识] YoLo家族简介
    你以为YoLo的意思是You only live once?其实不对的。但是你如果把live改为look,这就接近于YoLo算法的精髓了。在目标检测的算法中,有 单阶段 目标检测的算法,也有两阶段 目标检测的算法,单阶段的意思是,只要一次性提取目标特征,就可以算出结果,而两阶段指的是顾名思义就是要提取多次才行。一般来说,单阶段的算法,速度快,但是精度相比两阶段的要差一点。但是你要知道,快就是王道,检测得慢了还不如不检测。这也许是YoLo家族的算法这么流行的原因。2016年,Joseph Redmon , Santosh Divvala, Ross Girshick , Ali Farhadi等人发布了YoLo的论文。其网络结构如下所示:采用了一个全连接层实现分类和回归。YoLo paper:https://www.cv-foundation.org/openaccess/content_cvpr_2016/papers/Redmon_You_Only_Look_CVPR_2016_paper.pdfYoLoV2其实人家本来没起V2这个名字,而是叫做YoLo9000——起名起得非常大气,作者仍然是Joseph Redmon和Ali Farhadi。它对YoLo进行了优化,所以论文标题为 Better、Faster、Stronger,这个跟奥林匹克精神的 更快、更高、更强有点像了。在V2中比较典型的改进是引入了BN,也就是Batch Normalization,它对每一层特性进行归一化,可以使得隐藏层的输出分布一致。另外,既然它起名叫做9000,它就比原来能够检测更多的分类目标。它提出了一种结合目标检测和分类的层级预测——WordTree:YoLoV2 paper:cid:link_4YoLoV3的作者依然是Joseph Redmon和Ali Farhadi,这也是为啥Joseph Redmon被称为 YoLo之父的原因了。张小白虽然不大懂YoLoV3的原理,但是确实写了不少YoLoV3实践的文章:比如在200DK上用YoLoV3进行推理:cid:link_1或者在 ModelArts上进行YoLoV3的训练:cid:link_2以及使用MindStudio开发YoLoV3应用:cid:link_3YoLoV3 paper:cid:link_5YoLoV3 code:(这里放出的是MindSpore仓库的地址)cid:link_0不过,2020年2月,YOLO之父Joseph Redmon突然宣布退出计算机视觉研究领域。他“坦言无法忽视自己工作带来的负面影响“。这个基于道德上的考量确实发人深思,但是YoLo的发展似乎并没有停止。(未完待续)
  • [技术干货] 知识蒸馏相关技术【模型蒸馏、数据蒸馏】以ERNIE-Tiny为例
    1.任务简介基于ERNIE预训练模型效果上达到业界领先,但是由于模型比较大,预测性能可能无法满足上线需求。 直接使用ERNIE-Tiny系列轻量模型fine-tune,效果可能不够理想。如果采用数据蒸馏策略,又需要提供海量未标注数据,可能并不具备客观条件。 因此,本专题采用主流的知识蒸馏的方案来压缩模型,在满足用户预测性能、预测效果的需求同时,不依赖海量未标注数据,提升开发效率。 文心提供多种不同大小的基于字粒度的ERNIE-Tiny学生模型,满足不同用户的需求。注:知识蒸馏(KD)是将复杂模型(teacher)中的dark knowledge迁移到简单模型(student)中去,teacher具有强大的能力和表现,而student则更为紧凑。通过知识蒸馏,希望student能尽可能逼近亦或是超过teacher,从而用更少的复杂度来获得类似的预测效果。1.1 模型蒸馏原理知识蒸馏是一种模型压缩常见方法,指的是在teacher-student框架中,将复杂、学习能力强的网络(teacher)学到的特征表示"知识"蒸馏出来,传递给参数量小、学习能力弱的网络(student)。 在训练过程中,往往以最优化训练集的准确率作为训练目标,但真实目标其实应该是最优化模型的泛化能力。显然如果能直接以提升模型的泛化能力为目标进行训练是最好的,但这需要正确的关于泛化能力的信息,而这些信息通常不可用。如果我们使用由大型模型产生的所有类概率作为训练小模型的目标,就可以让小模型得到不输大模型的性能。这种把大模型的知识迁移到小模型的方式就是蒸馏。基本原理可参考Hinton经典论文:cid:link_11.2 ERNIE-Tiny 模型蒸馏模型蒸馏原理可参考论文 ERNIE-Tiny : A Progressive Distillation Framework for Pretrained Transformer Compression 2021。不同于原论文的实现,为了和开发套件中的通用蒸馏学生模型保持一致,我们将蒸馏loss替换为Attention矩阵的KQ loss和 VV loss,原理可参考论文 MiniLM: Deep Self-Attention Distillation for Task-Agnostic Compression of Pre-Trained Transformers 2020 和 MiniLMv2: Multi-Head Self-Attention Relation Distillation for Compressing Pretrained Transformers 2021。实验表明通用蒸馏阶段和任务蒸馏阶段的蒸馏loss不匹配时,学生模型的效果会受到影响。BERT 等预训练语言模型 (PLM) 采用了一种训练范式,首先在一般数据中预训练模型,然后在特定任务数据上微调模型,最近取得了巨大成功。然而,PLM 因其庞大的参数而臭名昭著,并且难以部署在现实生活中的应用程序中。知识蒸馏通过在一组数据上将知识从大老师转移到小得多的学生来解决这个问题。我们认为选择三个关键组成部分,即教师、训练数据和学习目标,对于蒸馏的有效性至关重要。因此,我们提出了一个四阶段渐进式蒸馏框架 ERNIE-Tiny 来压缩 PLM,它将三个组件从一般级别逐渐变化到特定任务级别。具体来说,第一阶段,General Distillation,在预训练的老师、一般数据和潜在蒸馏损失的指导下进行蒸馏。然后,General-Enhanced Distillation 将教师模型从预训练教师转变为微调教师。之后,Task-Adaptive Distillation 将训练数据从一般数据转移到特定于任务的数据。最后,Task-Specific Distillation 在最后阶段增加了两个额外的损失,即 Soft-Label 和 Hard-Label 损失。实证结果证明了我们的框架的有效性和所带来的泛化增益 。实验表明 4 层 ERNIE-Tiny 在 GLUE 基准测试的基础上保持其 12 层教师 BERT 的 98.0% 以上的性能,超过最先进的 (SOTA) 1.0% 的 GLUE 分数相同数量的参数。此外,ERNIE-Tiny 在五个中文 NLP 任务上实现了新的压缩 SOTA,比 BERT 基础的精度高 0.4%,参数减少 7.5 倍,推理速度加快 9.4 倍。预训练的语言模型(例如,BERT (Devlin et al., 2018) 及其变体)在各种 NLP 任务中取得了显着的成功。然而,这些模型通常包含数亿个参数,由于延迟和容量限制,这给现实应用中的微调和在线服务带来了挑战。在这项工作中,我们提出了一种简单有效的方法来压缩基于大型 Transformer (Vaswani et al., 2017) 的预训练模型,称为深度自注意力蒸馏。小模型(学生)通过深度模仿大模型(老师)的自注意力模块进行训练,该模块在 Transformer 网络中起着至关重要的作用。具体来说,我们建议提炼出教师最后一个 Transformer 层的自注意力模块,这对学生来说既有效又灵活。此外,除了现有作品中使用的注意力分布(即查询和键的缩放点积)之外,我们还引入了自我注意模块中值之间的缩放点积作为新的深度自我注意知识. 此外,我们表明,引入教师助理(Mirzadeh 等人,2019 年)也有助于提炼大型预训练 Transformer 模型。实验结果表明,我们的单语模型在不同参数大小的学生模型中优于最先进的基线。特别是,它使用 50% 的 Transformer 参数和教师模型的计算在 SQuAD 2.0 和几个 GLUE 基准测试任务上保持了 99% 以上的准确率。我们还在将深度自注意力蒸馏应用于多语言预训练模型方面获得了竞争性结果。我们仅使用自注意力关系蒸馏来对预训练的 Transformer 进行任务不可知的压缩,从而在 MiniLM (Wang et al., 2020) 中推广深度自注意力蒸馏。特别是,我们将多头自注意力关系定义为每个自注意力模块内的查询、键和值向量对之间的缩放点积。然后我们利用上述关系知识来训练学生模型。除了简单统一的原则外,更有利的是,学生的注意力头数没有限制,而之前的大多数工作都必须保证教师和学生之间的头数相同。此外,细粒度的自注意力关系倾向于充分利用 Transformer 学习到的交互知识。此外,我们彻底检查了教师模型的层选择策略,而不是像 MiniLM 中那样仅仅依赖最后一层。我们对压缩单语和多语预训练模型进行了广泛的实验。实验结果表明,我们从基础规模和大型教师(BERT、RoBERTa 和 XLM-R)中提取的模型优于最先进的模型。二阶段蒸馏:通用蒸馏(General Distillation,GD):在预训练阶段训练,使用大规模无监督的数据, 帮助学生网络学习到尚未微调的教师网络中的知识,有利于提高泛化能力。为方便用户使用,我们提供了多种尺寸的通用蒸馏学生模型,可用的通用蒸馏学生模型可参考文档:通用模型 - ERNIE3.0 Tiny。任务蒸馏(Task-specific Distillation,TD):使用具体任务的数据,学习到更多任务相关的具体知识。如果已提供的通用蒸馏学生模型尺寸符合需求,用户可以主要关注接下来的任务蒸馏过程。1.3任务蒸馏步骤FT阶段:基于ERNIE 3.0 Large蒸馏模型fine-tune得到教师模型,注意这里用到的教师模型和ERNIE 3.0 Large是两个不同的模型;GED阶段(可选):使用fine-tuned教师模型和通用数据继续用通用蒸馏的方式蒸馏学生模型,进一步提升学生模型的效果;a. 热启动fine-tuned的教师模型和通用学生模型。其中,通用的学生模型由文心平台提供,从bos上下载。TD1阶段:蒸馏中间层a.只对学生模型的最后一层进行蒸馏,将学生模型transformer的attention层的k-q矩阵和v-v矩阵与教师模型的对应矩阵做KLloss,可参考 :MiniLMV2。b.热启动fine-tuned的教师模型和GED阶段得到的学生模型。其中,通用的学生模型由文心平台提供,从bos上下载,下载链接所在文档:通用模型ERNIE3.0 Tiny,或参考预置的下载脚本:c. 反向传播阶段只更新学生模型参数,教师模型参数不更新;TD2阶段:蒸馏预测层,产出最终的学生模型。a. 热启动fine-tuned的教师模型和TD1阶段训练的学生模型;b. loss包括两部分: 1) pred_loss:软标签,学生模型的预测层输出与教师模型的预测层输出的交叉熵; 2) student_ce_loss:硬标签,学生模型的预测层输出与真实label的交叉熵;c. pred_loss与student_ce_loss之和作为最终loss,进行反向传播;d. 反向传播阶段只更新学生模型参数,教师模型参数不更新;注:关于GED阶段使用的通用数据:开发套件中的通用数据是由开源项目 cid:link_0 中的中文维基百科语料(wiki2019zh)经过预处理得到。该数据只用于demo展示,实际使用时替换为业务无标注数据效果提升更明显。2. 常见问题问题1:怎么修改学生模型的层数?上面提供了多种不同的学生模型,但每个学生模型的层数、hidden size等都是固定的,如果想更改,需要在哪些地方更改?文心提供了三种不同结构的预训练学生模型,如果修改层数、hidden size等,会导致预训练学生模型参数无法加载,在此情况下,蒸馏出来的学生模型效果无法保证,建议用户还是使用文心提供的预训练模型,不更改模型结构;如果用户认为更改学生模型的结构非常有必要,需要对文心做以下改动:修改TD1阶段json配置文件的pre_train_model配置项,删除预训练学生模型的加载,只保留微调后的教师模型"pre_train_model": [ # 热启动fine-tune的teacher模型 { "name": "finetuned_teacher_model", "params_path": "./output/cls_ernie_3.0_large_ft/save_checkpoints/checkpoints_step_6000" } ]将json文件中的"student_embedding"替换为自定义的学生模型"student_embedding": { "config_path": "../../models_hub/ernie_3.0_tiny_ch_dir/ernie_config.json" },再次强调,上述修改后,由于无法加载预训练学生模型,蒸馏出来的学生模型效果无法保证。(用户训练数据量到百万样本以上可以考虑尝试一下)3.数据蒸馏任务3.1 简介在ERNIE强大的语义理解能力背后,是需要同样强大的算力才能支撑起如此大规模模型的训练和预测。很多工业应用场景对性能要求较高,若不能有效压缩则无法实际应用。因此,我们基于数据蒸馏技术构建了数据蒸馏系统。其原理是通过数据作为桥梁,将ERNIE模型的知识迁移至小模型,以达到损失很小的效果却能达到上千倍的预测速度提升的效果。目录结构 数据蒸馏任务位于 wenxin_appzoo/tasks/data_distillation├── data │ ├── dev_data │ ├── dict │ ├── download_data.sh │ ├── predict_data │ ├── test_data │ └── train_data ├── distill │ └── chnsenticorp │ ├── student │ └── teacher ├── examples │ ├── cls_bow_ch.json │ ├── cls_cnn_ch.json │ ├── cls_ernie_fc_ch_infer.json │ └── cls_ernie_fc_ch.json ├── inference │ ├── custom_inference.py │ ├── __init__.py ├── model │ ├── base_cls.py │ ├── bow_classification.py │ ├── cnn_classification.py │ ├── ernie_classification.py │ ├── __init__.py ├── run_distill.sh ├── run_infer.py ├── run_trainer.py └── trainer ├── custom_dynamic_trainer.py ├── __init__.py3.2 数据准备目前采用三种数据增强策略策略,对于不用的任务可以特定的比例混合。三种数据增强策略包括:(1)添加噪声:对原始样本中的词,以一定的概率(如0.1)替换为”UNK”标签(2)同词性词替换:对原始样本中的所有词,以一定的概率(如0.1)替换为本数据集中随机一个同词性的词(3)N-sampling:从原始样本中,随机选取位置截取长度为m的片段作为新的样本,其中片段的长度m为0到原始样本长度之间的随机值数据增强策略可参考数据增强,我们已准备好了采用上述3种增强策略制作的chnsenticorp的增强数据。3.3 离线蒸馏使用预置的ERNIE 2.0 base模型cd wenxin_appzoo/models_hub bash download_ernie_2.0_base_ch.sh下载预置的原始数据以及增强数据。cd wenxin_appzoo/tasks/data_distillation/distill bash download_data.sh运行以下命令,开始数据蒸馏cd wenxin_appzoo/tasks/data_distillation bash run_distill.sh3.3.1蒸馏过程说明run_distill.sh脚本会进行前述的三步:在任务数据上Fine-tune; 加载Fine-tune好的模型对增强数据进行打分; 使用Student模型进行训练。脚本采用hard-label蒸馏,在第二步中将会直接预测出ERNIE标注的label。run_distill.sh脚本涉及教师和学生模型的json文件,其中:./examples/cls_ernie_fc_ch.json负责教师模型的finetune, ./examples/cls_ernie_fc_ch_infer.json 负责教师模型的预测。 ./examples/cls_cnn_ch.json,负责学生模型的训练。事先构造好的增强数据放在./distill/chnsenticorp/student/unsup_train_aug在脚本的第二步中,使用 ./examples/cls_ernie_fc_ch_infer.json 进行预测:脚本从标准输入获取明文输入,并将打分输出到标准输出。用这种方式对数据增强后的无监督训练预料进行标注。最终的标注结果放在 ./distill/chnsenticorp/student/train/part.1文件中。标注结果包含两列, 第一列为明文,第二列为标注label。在第三步开始student模型的训练,其训练数据放在 distill/chnsenticorp/student/train/ 中,part.0 为原监督数据 part.1 为 ERNIE 标注数据。注:如果用户已经拥有了无监督数据,则可以将无监督数据放入distill/chnsenticorp/student/unsup_train_aug 即可。
  • [技术干货] NLP领域任务如何选择合适预训练模型以及选择合适的方案【规范建议】
    1.常见NLP任务信息抽取:从给定文本中抽取重要的信息,比如时间、地点、人物、事件、原因、结果、数字、日期、货币、专有名词等等。通俗说来,就是要了解谁在什么时候、什么原因、对谁、做了什么事、有什么结果。文本生成:机器像人一样使用自然语言进行表达和写作。依据输入的不同,文本生成技术主要包括数据到文本生成和文本到文本生成。数据到文本生成是指将包含键值对的数据转化为自然语言文本;文本到文本生成对输入文本进行转化和处理从而产生新的文本问答系统:对一个自然语言表达的问题,由问答系统给出一个精准的答案。需要对自然语言查询语句进行某种程度的语义分析,包括实体链接、关系识别,形成逻辑表达式,然后到知识库中查找可能的候选答案并通过一个排序机制找出最佳的答案。对话系统:系统通过一系列的对话,跟用户进行聊天、回答、完成某一项任务。涉及到用户意图理解、通用聊天引擎、问答引擎、对话管理等技术。此外,为了体现上下文相关,要具备多轮对话能力。语音识别和生成:语音识别是将输入计算机的语音符号识别转换成书面语表示。语音生成又称文语转换、语音合成,它是指将书面文本自动转换成对应的语音表征。信息过滤:通过计算机系统自动识别和过滤符合特定条件的文档信息。通常指网络有害信息的自动识别和过滤,主要用于信息安全和防护,网络内容管理等。舆情分析:是指收集和处理海量信息,自动化地对网络舆情进行分析,以实现及时应对网络舆情的目的。信息检索:对大规模的文档进行索引。可简单对文档中的词汇,赋之以不同的权重来建立索引,也可建立更加深层的索引。在查询的时候,对输入的查询表达式比如一个检索词或者一个句子进行分析,然后在索引里面查找匹配的候选文档,再根据一个排序机制把候选文档排序,最后输出排序得分最高的文档。机器翻译:把输入的源语言文本通过自动翻译获得另外一种语言的文本。机器翻译从最早的基于规则的方法到二十年前的基于统计的方法,再到今天的基于神经网络(编码-解码)的方法,逐渐形成了一套比较严谨的方法体系。文本挖掘:包括文本聚类、分类、情感分析以及对挖掘的信息和知识的可视化、交互式的表达界面。目前主流的技术都是基于统计机器学习的。2.如何将业务问题抽象为已得到很好解决的典型问题2.1 明确业务的输入与输出令输入文本用X表示,输出标签用Y表示,则有以下粗略的分类:2.1.1 如果Y表示某一类的概率,或者是一个定长向量,向量中的每个维度是其属于各个类的概率,且概率之和为1,则可抽象为文本多分类问题。a.一般X只有一段文本。如下所示 i.如情感分析等任务。房间 太 小 。 其他 的 都 一般 0b.如果X是2段文本(X1,X2),则是可以抽象为句对分类问题。如下所示 i:如NLI等任务。大家觉得她好看吗 大家觉得跑男好看吗? 0c.如果的每个类别的概率相互独立,即各类概率之和不为1,可抽象为文本多标签分类问题。如下所示 i:如用户评论分类、黄反识别等任务。互联网创业就如选秀 需求与服务就是价值 0 1d. 如果X有多段非文本特征输入,如整型、浮点型类型特征。则可抽象为混合特征的分类问题。如下所示 i:如CTR预估等任务。 CTR预估*CTR预估是推荐中最核心的算法之一。 相关概念: CTR预估:对每次广告的点击情况做出预测,预测用户是点击还是不点击。 CTR预估的影响因素:比如历史点击率、广告位置、时间、用户等 CTR预估相关介绍 推荐算法之4——CTR预估模型2.1.2 如果X是2段文本(X1,X2),Y表示二者的相似度,可抽象为文本匹配问题。如下所示喜欢 打篮球 的 男生 喜欢 什么样 的 女生 爱 打篮球 的 男生 喜欢 什么样 的 女生 1a.如语义相似度、相似问题匹配等任务。b.文本聚类的问题可以通过文本相似度问题进行处理。2.1.3 如果X有一段文本,Y是一个与X等长的序列,可抽象为序列标注问题。如下所示海 钓 比 赛 地 点 在 厦 门 与 金 门 之 间 的 海 域 。 O O O O O O O B-LOC I-LOC O B-LOC I-LOC O O O O O Oa.如分词、POS、NER、词槽挖掘等任务。2.1.4 如果X有一段文本,Y是一个不定长的文本,可抽象为文本生成问题。如下所示Rachel Pike : The science behind a climate headline Khoa học đằng sau một tiêu đề về khí hậua.如机器翻译、文本摘要、标题生成等任务。2.1.5.如果X为一段文本,Y表示文本X作为正常语句出现的概率或者混淆度,则属于语言模型任务。如下所示<s> but some analysts remain sour on the company but some analysts remain sour on the company <e>a.语言模型任务的子问题是基于上(下)文X预测下(上)一个词出现的概率Y,可以理解为一种特殊的文本分类。2.1.6如果X是2段文本(X1,X2),分别表示正文篇章和问题,Y是篇章中的一小段文本,表示对应问题的答案,则可抽象为阅读理解问题。{ "data": [{ "title": "", "paragraphs": [{ "context": "爬行垫根据中间材料的不同可以分为:XPE爬行垫、EPE爬行垫、EVA爬行垫、PVC爬行垫;其中XPE爬行垫、EPE爬行垫都属于PE材料加保鲜膜复合而成,都是无异味的环保材料,但是XPE爬行垫是品质较好的爬行垫,韩国进口爬行垫都是这种爬行垫,而EPE爬行垫是国内厂家为了减低成本,使用EPE(珍珠棉)作为原料生产的一款爬行垫,该材料弹性差,易碎,开孔发泡防水性弱。EVA爬行垫、PVC爬行垫是用EVA或PVC作为原材料与保鲜膜复合的而成的爬行垫,或者把图案转印在原材料上,这两款爬行垫通常有异味,如果是图案转印的爬行垫,油墨外露容易脱落。当时我儿子爬的时候,我们也买了垫子,但是始终有味。最后就没用了,铺的就的薄毯子让他爬。您好,爬行垫一般色彩鲜艳,能吸引宝宝的注意力,当宝宝刚会爬的时候,趴在上面玩,相对比较安全,不存在从床上摔下来的危险。对宝宝的爬行还是很有好处的。还有就是妈妈选择爬行垫时可以选择无害的PE棉,既防潮又隔冷隔热。外有要有一层塑料膜,能隔绝液体进入垫子内部,而且方便清洗。宝宝每次爬行,一定要记得把宝宝的手擦干净。", "qas": [{ "answers": [{ "text": "XPE", "answer_start": 17 }], "id": "DR-single-pre_and_next_paras-181574", "question": "爬行垫什么材质的好" }] }, ..., ] }] }2.1.7 如果Y是以上多种任务的组合,则可以抽象为多标签学习、多任务学习任务。a.如实体关系抽取任务,实体抽取本属于序列标注、关系抽取本属于文本多分类。2.2抽象与拆分任务取舍经验2.2.1优先考虑简单的任务,由易到难循序渐进:a.文本分类、文本匹配、序列标注、文本生成、阅读理解、多任务学习、强化学习、对抗学习等。2.2.2 复杂任务可拆分、化简成简单的子任务a.如实体关系抽取任务,可以拆分为实体识别+关系抽取的pipline进行实现。b.如文本纠错任务,可以拆分出语言模型、统计机器翻译等多种不同子任务构造复杂的pipline进行实现。c.如排序任务,输入X为多段文本,输出Y为每段文本的排序位置,可化简成文本分类问题、文本匹配问题进行处理。2.2.3 有监督学习任务优先于无监督学习任务a.因为有监督学习更可控,更易于应用最前沿的研究成果。文心目前只覆盖有监督、自监督任务。b.比如文本关键词抽取,可以有TFIDF之类的无监督解法,但效果控制较困难,不如转换为文本分类问题。2.2.4 能应用深度学习的任务优于不利用深度学习的任务a.因为深度学习算法效果一般更好,而且可以应用到最前沿的预训练模型。文心目前只采用深度学习算法。b.如果文本聚类,可以有LDA之类的解法,但效果一般不如基于深度学习的语义相似度的文本聚类。3. 明确业务目标与限制条件3.1典型业务目标与限制条件1.预测部署性能a.典型指标:qps 性能指标:QPS、TPS、系统吞吐量理解2.模型效果a.以文本分类为例,典型指标:精确率、准确率、召回率、F1值b.该评估指标应该在训练开始之前基本确定,否则很容易优化偏。3.硬件采购成本a.典型指标:钱b.GPU远贵于CPU,V100贵于P40。4.训练时间成本(GPU,卡,调参,GPU利用率)a.典型指标:每一轮训练所需要的时间。5.数据大小限制a.由于标注成本较高,很多时候是数据量很少又希望有很好的效果。6.开发迭代成本a.搭建环境成本b.迭代效率:往往是最消耗时间的部分。3.2 可供选择的方案选择平台版还是工具版选择GPU还是CPU训练,哪一款硬件,单机还是多机,单卡还是多卡,本地还是集群选择怎样的预制网络是否需要预训练模型选择哪一版本的预训练模型训练数据要多少batch_size、train_log_step、eval_step、save_model_step选多少4.根据业务目标与限制条件选择合适的方案4.1预测部署性能如果要求qps>1000a.不适合直接部署ERNIE预训练模型。b.但可尝试蒸馏策略,模型效果会存在一定损失。如果要求qps>100a.如果预算允许使用GPU,可尝试直接部署ERNIE相关预训练模型,推荐尝试ERNIE-tiny系列模型。b.如果预算只允许使用CPU,可尝试CPU集群部署ERNIE相关预训练模型。3.如果对部署性能要求不高,可随意尝试各种预训练模型。4.性能细节请参考:模型预测与部署——预测性能4.2 模型效果1.一般来说,复杂的网络优于简单的网络,多样的特征优于单一的特征,有预训练模型的效果优于无预训练模型。a.从模型复杂度来看,LSTM、GRU、CNN、BOW的复杂度与效果依次递减,速度依次提升。2.一般来说,在预训练模型中,large优于base优于tiny,新版本的模型优于旧版本的模型,针对具体任务的预训练模型优于通用版预训练模型。3.一般来说,在不欠拟合的情况下,训练数据越多模型效果越好,标注数据的质量越好效果越好。标注数据的质量优于数据的数量。4.不同任务适合的网络结构并不相同,具体任务具体分析。4.3硬件采购成本1.GPU远贵于CPU,常用训练用GPU型号为V100、P40、K40,价格依次递减。2.具体成本可参考百度云服务器-BCC-价格计算器3.如果缺少训练资源,可通过文心平台版的免费共享队列进行训练,资源紧张,且用且珍惜。4.4训练时间成本1.GPU还是CPUa.对于非ERNIE等复杂网络的模型,CPU的训练速度一般也能接受。 如果训练语料过多,数千万条以上,则建议采用CPU集群进行训练。 b.对于ERNIE模型,尽量采用GPU训练,CPU太慢,训练不起来。2.怎么用好GPU a.GPU并行训练能提升训练速度,建议优先把一个节点(trainer)的卡数用完,再考虑多机训练。因为单机多卡的GPU利用率更高,更快。而多机训练数据通信时间成本较高,时间更慢。 b.大原则:GPU利用率越高训练越快。 c.还有一点需要注意,多卡训练时是将不同的数据文件送给不同的卡,所以数据文件的个数要大于卡的个数。数据文件建议拆分细一些,这可以提升数据读取的速度。 d.熟练的同学可以尝试GPU多进程单机多卡训练、混合精度训练等方法,提升训练速度。3.train_log_step、eval_step、save_model_stepa.分别表示每多少步打印训练日志、每多少步评估一次验证集、每多少步保存一次模型。 b.设置不当也会拖慢训练时间 c.一般建议三者依次放大十倍,如:10、100、10004.batch_sizea.设置过小容易收敛慢,设置过大容易超过显存极限直接挂掉 b.如果使用ERNIE,batch_size建议小一些,使用large版本建议更小一些,如果输入语句并不是很长可以适当增加batch_size。 c.如果不使用ERNIE,可以大一些。 d.建议使用默认配置,如果想优化可以采用二分查找4.5 数据大小限制1.一般建议标注语料越多越好。2.非ERNIE模型一般需要几万至几百万条数据能收敛到较好的效果。3.ERNIE模型一般需要几千至几万条数据即可收敛到较好效果。a.一般不用ERNIE训练数百万条以上的数据,因为这会极大延长训练时间,增大资源消耗,而对效果的提升并不明显。自己有足够GPU资源的用户除外。 b.对于基线模型,建议在几万条数据上验证策略有效后再尝试增加数据量。4.如果用ERNIE模型,最少需要多少样本才能取得效果a.对于文本分类与序列标注,一般来说每个标签覆盖的样本数至少要超过200条才能有一定的效果。也就是说如果要进行50类多分类,就总共至少需要1万条样本。一般分类的类别越多任务越复杂。4.6开发迭代成本1.搭建环境成本a.如果只想训练基线模型验证效果,可以考虑使用文心平台版,免去搭建环境的成本。 b.如果需要不断调试、迭代优化模型,而由于平台版集群资源紧张造成迭代周期过长,可以尝试使用工具版。 i:这会付出搭建环境的成本,但长痛不如短痛。2.迭代效率a.使用工具版本地调试成功后再上集群训练能极大提升迭代效率。 b.使用预训练模型能提升迭代效率。 c.基线模型,建议在几万条数据上验证策略,提升迭代效率。验证有效后再尝试增加数据量5. 如何高效训练NLP任务汇总诸多NLP算法同学的建议,我们把高效训练NLP任务的基本流程总结如下:1.分析业务背景、明确任务输入与输出,将其抽象为已得到很好解决的NLP典型任务。 a.对于复杂任务,需要将其拆分成比较简单的子任务 b.文心已覆盖绝大部分NLP典型任务,可参考文心ERNIE工具版-支持任务。2.准备好几千条格式规范的训练数据,快速实现一个NLP模型基线。 a.最快速的方法是通过文心ERNIE平台版或者工具版,采用预制网络和模型无代码训练一个模型基线。 b.本步骤只需要您知道最基本的机器学习概念,划分好训练集、验证集、测试集进行训练即可。 c.评估训练出模型的效果,看是否满足你的业务需求,如果不满足,可考虑进一步优化模型效果。3.优化模型效果: a.各优化手段按照投入产出比排序如下 i:进一步分析你的业务背景和需求,分析基线模型的不足,进行更细致的技术选型。 ii:采用工具版进行本地小数据调试,极大地提升迭代效率。 iii:基于预制网络进行调参。 iv:自定义组网并进行调参。 v:基于核心接口进行高度自定义开发。 vi:直接修改文心核心源码进行开发。 b.每一种优化手段都都可以申请vip服务进行支持。如何自我判断采用哪种文心开发方式 典型的训练方式:无代码训练(不调参),无代码训练(自主调参),自定义组网训练,高阶自定义训练。以上4类训练方式的开发自由度、上手难度、建模的风险、模型效果的上限依次递增,性价比依次递减。本地工具包的调试、迭代效率最高。6总结:需掌握知识6.1 无代码调参建议具备的相关知识1.明确以下概念:有监督学习、标签、特征、训练集、验证集、测试集、逻辑回归、过拟合、欠拟合、激活函数、损失函数、神经网络、学习率、正则化、epoch、batch_size、分词、统计词表。2.知道回归与分类的区别。3.知道如何通过收敛曲线判断过拟合与欠拟合。4.知道准确率、召回率、精确度、F1值、宏平均、微平均的概念与区别。5.知道为什么训练集、验证集、测试集要保证独立同分布。6.知道什么是神经网络.7.知道什么是迁移学习、什么是预训练模型、什么是finetune、迁移学习的优点是什么。6.2 自定义组网建议具备的相关知识1.前提是已经掌握无代码调参建议具备的相关知识2.明确以下概念:Sigmoid函数公式、softmax函数公式、交叉熵公式、前向传播、反向传播、SGD、Adam、词向量、embedding、dropout、BOW、CNN、RNN、GRU、LSTM、迁移学习、3.知道神经网络为什么具有非线性切分能力。4.知道NLP中一维CNN中的卷积核大小、卷积核的个数各指代什么,时序最大池化层如何操作。5.知道NLP中CNN与LSTM的区别,各擅长处理哪类文本问题。6.知道为什么BOW模型无法识别词语顺序关系。7.知道为什么会梯度爆炸,以及如何解决。参考书籍: a.ML特征工程和优化方法 b.周志华《机器学习》前3章 c.迁移学习常见问题 a.CNN常见问题 b.深度学习优化方法 c.花书《深度学习》6-10章 d.《基于深度学习的自然语言处理》整本项目参考链接:cid:link_2
  • [MindX SDK] MindX SDK -- 工业指针型表计读数参考设计案例
    MindX SDK -- 工业指针型表计读数参考设计案例1 案例概述1.1 概要描述在本系统中,目的是基于MindX SDK,在华为云昇腾平台上,开发端到端工业指针型表计读数的参考设计,实现对传统机械式指针表计的检测与自动读数功能,达到功能要求。点击链接可以下载本项目到本地。注:本系统中只使用了两种类型的表盘数据参与训练和测试。我们通过预测的刻度根数来判断表盘类型,第一种表盘的刻度根数为50,第二种表盘的刻度根数为32。因此,目前系统只能实现这两种针表计的检测和自动读数功能。1.2 特性及适用场景在电力能源厂区需要定期监测表计读数,以保证设备正常运行及厂区安全。但厂区分布分散,人工巡检耗时长,无法实时监测表计,且部分工作环境危险导致人工巡检无法触达。针对上述问题,希望通过摄像头拍照后利用计算机智能读数的方式高效地完成此任务。注意事项:本系统中只使用了两种类型的表盘数据参与训练和测试。我们通过预测的刻度根数来判断表盘类型,第一种表盘的刻度根数为50,第二种表盘的刻度根数为32。因此,目前系统只能实现这两种针表计的检测和自动读数功能。本系统要求拍摄图片角度正常,尽可能清晰。如果拍摄图片角度不正常,导致图片模糊,则很难正确读出表数。本系统采用opencv进行图片处理,要求输入文件均为opencv可处理文件。1.3 模型介绍本项目主要使用了两个模型,分别是:用于目标检测的YOLOv5模型(PyTorch)和用于检测指针和刻度的语义分割模型DeepLabv3(pdmodel)。YOLOv5模型参考链接:cid:link_8DeepLabv3模型参考链接:cid:link_41.4 实现流程1、基础环境:Ascend 310、mxVision、Ascend-CANN-toolkit、Ascend Driver2、模型转换:目标检测模型: PyTorch模型转昇腾离线模型:yolov5.onnx --> yolov5.om语义分割模型: pdmodel模型转onnx模型:model.pdmodel --> DeepLabv3.onnx onnx模型转昇腾离线模型:DeepLabv3.onnx --> DeepLabv3.om3、业务流程编排与配置4、yolov5后处理开发5、mxpi_process3插件的后处理开发6、python推理流程代码开发:(1)YOLOv5的pipeline流程图如下: 图1. YOLOv5的pipeline流程图(2)DeepLabv3的pipeline流程图如下: 图2. DeepLabv3的pipeline流程图2 软件方案介绍2.1 项目方案架构介绍本系统识别的流程是:先将输入的图像送入流中解码和缩放大小,使用YOLOv5目标检测模型去检测图片中的表盘,结束流。将目标框裁剪下来,再送入流中解码和缩放大小,用DeepLabv3语义分割模型去得到工业表中的指针和刻度,对语义分割模型预测的结果进行读数后处理,找到指针指向的刻度,根据刻度的间隔和刻度根数计算表盘的读数。表2.1 系统方案中各模块功能:序号子系统功能描述1图像输入调用MindX SDK的appsrc输入图片2图像解码调用MindX SDK的mxpi_imagedecoder输入图片3图像放缩调用MindX SDK的mxpi_imageresize,放缩到1024*576大小4工业表检测调用MindX SDK的mxpi_tensorinfer,使用YOLOv5的检测模型,检测出图片中车辆5保存工业表的图像将YOLOv5检测到的工业表结果保存图片6图像输入调用MindX SDK的appsrc输入检测到的工业表7图像解码调用MindX SDK的mxpi_imagedecoder输入图片8图像放缩调用MindX SDK的mxpi_imageresize,放缩到512*512大小9指针刻度检测调用MindX SDK的mxpi_tensorinfer,使用DeepLabv3语义分割模型,检测图像中的指针与刻度10模型后处理调用MindX mxpi_semanticsegpostprocessor,得到语义分割的结果11读数后处理开发mxpi_process3插件,读出工业表的数字2.2 代码目录结构与说明本工程名称为工业指针型表计读数,工程目录如下图所示:├── build.sh ├── README.md ├── evaluate ├── deeplabv3_val #deeplabv3模型测试精度 ├── seg_evaluate.py ├── yolov5_val #yolov5模型测试精度 ├── det.py #1.使用om模型检测测试数据,将得到的结果保存成yolo格式的txt文件 ├── match.py #3.检测是否有的图像没有目标 ├── yolo2voc.py #2.将得到的检测结果yolo数据格式转换成voc格式 ├── images ├── README_img ├── DeepLabv3_pipeline.png ├── YOLOv5_pipeline.png ├── infer ├── det.py ├── main.py ├── seg.py ├── models ├── deeplabv3 ├── seg_aipp.cfg #deeplabv3的onnx模型转换成om模型的配置文件 ├── yolov5 ├── det_aipp.cfg #yolov5的onnx模型转换成om模型的配置文件 ├── pipeline #pipeline文件 ├── deeplabv3 ├── deeplabv3.cfg ├── deeplabv3.names ├── seg.pipeline ├── yolov5 ├── det.pipeline ├── plugins #开发读数处理插件代码 ├── process3 ├── build.sh ├── CMakeLists.txt ├── Myplugin.cpp ├── Myplugin.h ├── postprocess.cpp ├── postprocess.h3 开发环境准备3.1 环境依赖软件和版本环境依赖软件和版本如下表:软件名称版本ubuntu18.04.1 LTSMindX SDK2.0.4Python3.9.2CANN5.0.4numpy1.23.4opencv-python4.6.0MindX SDK开发套件部分可参考MindX SDK开发套件安装指导3.2 导入基础环境. /usr/local/Ascend/ascend-toolkit/set_env.sh . ${SDK安装路径}/mxVision/set_env.sh4 编译与运行示例步骤如下:步骤1 执行编译编译插件,在项目目录下执行如下命令cd ${MeterReader代码根目录}/plugins/process3 . build.sh步骤2 修改pipeline文件中的参数地址修改"${MeterReader代码根目录}/pipeline/yolov5/det.pipeline"第40行处文件的绝对路径,将pipeline中所需要用到的模型路径改为存放模型的绝对路径地址:40 "modelPath":"${MeterReader代码根目录}/models/yolov5/det.om"修改"${MeterReader代码根目录}/pipeline/deeplabv3/seg.pipeline"第30、38、39行处文件的绝对路径,将pipeline中所需要用到的模型路径、配置文件地址改为绝对路径地址:30 "modelPath":"${MeterReader代码根目录}/models/deeplabv3/seg.om" 38 "postProcessConfigPath":"${MeterReader代码根目录}/pipeline/deeplabv3/deeplabv3.cfg", 39 "labelPath":"${MeterReader代码根目录}/pipeline/deeplabv3/deeplabv3.names",步骤3 运行及输出结果总体运行。输入带有预测表盘的jpg图片,在指定输出目录下输出得到带有预测表盘计数的png图片。cd ${MeterReader代码根目录}/infer python main.py --ifile ${输入图片路径} --odir ${输出图片目录}执行结束后,可在命令行内得到yolo模型得到的表盘文件路径,以及通过后续模型得到的预测表盘度数。并可在设定的${输出图片路径}中查看带有预测表盘计数的图片结果。最后展示的结果图片上用矩形框框出了图片中的表计并且标出了预测的表盘读数。5 指标验证分别对yolo模型与deeplabv3模型进行精度测试。1、YOLOv5模型精度测试步骤一:执行以下命令创建所需要的文件目录cd ${MeterReader代码根目录}/evaluate/yolov5_val/ mkdir -p det_val_data/det_val_voc mkdir -p det_val_data/meter_det mkdir -p det_val_data/det_val_img mkdir -p det_val_data/det_sdk_txt mkdir -p det_val_data/det_sdk_voc步骤二:准备标签文件及推理图片下载YOLOv5表计检测数据集并解压到任意目录后,将数据集目录中"test"和"train"目录下的所有图片汇总拷贝至"${MeterReader代码根目录}/evaluate/yolov5_val/det_val_data/meter_det"目录下。我们提供了样例的模型验证集标签文件以供下载测试。完成下载并解压后,将"data/yolov5/det_val_voc"目录下的文件拷贝至"${MeterReader代码根目录}/evaluate/yolov5_val/det_val_data/det_val_voc"目录下。然后根据拷贝后目录下样例的txt标签文件名称(txt命名格式为:文件名.txt)在"${MeterReader代码根目录}/evaluate/yolov5_val/det_val_data/meter_det"目录下找到对应名称的jpg图片并拷贝至"${MeterReader代码根目录}/evaluate/yolov5_val/det_val_data/det_val_img"目录下。步骤三:预处理数据集执行以下命令后,将在"${MeterReader代码根目录}/evaluate/yolov5_val/det_val_data/det_sdk_txt"目录下生成当前"det.om"模型检测验证集数据的yolo格式结果,并以图片命名的txt格式保存:cd ${MeterReader代码根目录}/evaluate/yolov5_val python det.py再执行以下命令,将上述得到的yolo数据格式转换成voc数据格式,并保存至"${MeterReader代码根目录}/evaluate/yolov5_val/det_val_data/det_sdk_voc"目录下:python yolo2voc.py最后执行以下命令,检测验证集中的数据是否有无目标文件:python match.py注意事项:运行脚本之前需要把det_sdk_txt和det_sdk_voc文件夹下的文件清空。步骤四:精度推理登录并点击下载mAP-master.zip代码压缩包,上传服务器解压后,将代码包中的"main.py"脚本拷贝至"${MeterReader代码根目录}/evaluate/yolov5_val/"目录下,按照以下步骤修改部分代码:修改main.py第47、48、50行处文件路径47 GT_PATH = os.path.join(os.getcwd(), 'det_val_data', 'det_val_voc') 48 DR_PATH = os.path.join(os.getcwd(), 'det_val_data', 'det_sdk_voc') 49 # # if there are no images then no animation can be shown 50 IMG_PATH = os.path.join(os.getcwd(), 'det_val_data', 'det_val_img')修改main.py原第64行代码64 show_animation = False 65 if not args.no_animation:在main.py原第243行添加代码242 def draw_plot_func(dictionary, n_classes, window_title, plot_title, x_label, output_path, to_show, plot_color, true_p_bar): 243 to_show = False使用下面命令运行脚本,计算得到det.om在验证集上的mAP。python main.py经过测试,YOLOv5模型的mAP为100%。2、deeplabv3模型精度测试。执行以下命令,创建所需文件目录:cd ${MeterReader代码根目录}/evaluate/deeplabv3_val/ mkdir seg_val_img cd seg_val_img mkdir seg_test_img mkdir seg_test_img_groundtruth下载语义分割模型验证集voc格式数据,解压至"${MeterReader代码根录}/evaluate/deeplabv3_val/seg_val_img"目录下。然后执行以下命令拷贝数据:cp -r ${MeterReader代码根目录}/evaluate/deeplabv3_val/seg_val_img/meter_seg/meter_seg/images/val/. ${MeterReader代码根目录}/evaluate/deeplabv3_val/seg_val_img/seg_test_img/ cp -r ${MeterReader代码根目录}/evaluate/deeplabv3_val/seg_val_img/meter_seg/meter_seg/annotations/val/. ${MeterReader代码根目录}/evaluate/deeplabv3_val/seg_val_img/seg_test_img_groundtruth/采用Miou指标进行精度评价。使用下面命令运行脚本:cd ${MeterReader代码根目录}/evaluate/deeplabv3_val/ python seg_evaluate.py输出各个图的Miou指标,并求得平均值作为deeplabv3模型的精度指标。经测试,deeplabv3的模型的Miou为67%。6 常见问题6.1 模型转换问题问题描述当图像进入流后,输出到模型的图像格式为yuv,数据类型unit8,但是om模型的时候yolov5需要输入的图像格式为RGB。解决方案在转换模型时必须要在AIPP做色域转换,否则模型输入不正确。6.2 插件权限问题问题描述运行pipeline调用第三步的数值处理插件时报错,提示Check Owner permission failed: Current permission is 7, but required no greater than 6.解决方案将插件的权限调整为默认440(只读)即可chmod 440 "$MX_SDK_HOME/lib/plugins/libmxpi_sampleplugin.so"
  • [技术干货] MindX SDK -- 工业指针型表计读数参考设计案例
    MindX SDK -- 工业指针型表计读数参考设计案例1 案例概述1.1 概要描述在本系统中,目的是基于MindX SDK,在华为云昇腾平台上,开发端到端工业指针型表计读数的参考设计,实现对传统机械式指针表计的检测与自动读数功能,达到功能要求。点击链接可以下载本项目到本地。注:本系统中只使用了两种类型的表盘数据参与训练和测试。我们通过预测的刻度根数来判断表盘类型,第一种表盘的刻度根数为50,第二种表盘的刻度根数为32。因此,目前系统只能实现这两种针表计的检测和自动读数功能。1.2 特性及适用场景在电力能源厂区需要定期监测表计读数,以保证设备正常运行及厂区安全。但厂区分布分散,人工巡检耗时长,无法实时监测表计,且部分工作环境危险导致人工巡检无法触达。针对上述问题,希望通过摄像头拍照后利用计算机智能读数的方式高效地完成此任务。注意事项:本系统中只使用了两种类型的表盘数据参与训练和测试。我们通过预测的刻度根数来判断表盘类型,第一种表盘的刻度根数为50,第二种表盘的刻度根数为32。因此,目前系统只能实现这两种针表计的检测和自动读数功能。本系统要求拍摄图片角度正常,尽可能清晰。如果拍摄图片角度不正常,导致图片模糊,则很难正确读出表数。本系统采用opencv进行图片处理,要求输入文件均为opencv可处理文件。1.3 模型介绍本项目主要使用了两个模型,分别是:用于目标检测的YOLOv5模型(PyTorch)和用于检测指针和刻度的语义分割模型DeepLabv3(pdmodel)。YOLOv5模型参考链接:cid:link_8DeepLabv3模型参考链接:cid:link_41.4 实现流程1、基础环境:Ascend 310、mxVision、Ascend-CANN-toolkit、Ascend Driver2、模型转换:目标检测模型: PyTorch模型转昇腾离线模型:yolov5.onnx --> yolov5.om语义分割模型: pdmodel模型转onnx模型:model.pdmodel --> DeepLabv3.onnx onnx模型转昇腾离线模型:DeepLabv3.onnx --> DeepLabv3.om3、业务流程编排与配置4、yolov5后处理开发5、mxpi_process3插件的后处理开发6、python推理流程代码开发:(1)YOLOv5的pipeline流程图如下: 图1. YOLOv5的pipeline流程图(2)DeepLabv3的pipeline流程图如下: 图2. DeepLabv3的pipeline流程图2 软件方案介绍2.1 项目方案架构介绍本系统识别的流程是:先将输入的图像送入流中解码和缩放大小,使用YOLOv5目标检测模型去检测图片中的表盘,结束流。将目标框裁剪下来,再送入流中解码和缩放大小,用DeepLabv3语义分割模型去得到工业表中的指针和刻度,对语义分割模型预测的结果进行读数后处理,找到指针指向的刻度,根据刻度的间隔和刻度根数计算表盘的读数。表2.1 系统方案中各模块功能:序号子系统功能描述1图像输入调用MindX SDK的appsrc输入图片2图像解码调用MindX SDK的mxpi_imagedecoder输入图片3图像放缩调用MindX SDK的mxpi_imageresize,放缩到1024*576大小4工业表检测调用MindX SDK的mxpi_tensorinfer,使用YOLOv5的检测模型,检测出图片中车辆5保存工业表的图像将YOLOv5检测到的工业表结果保存图片6图像输入调用MindX SDK的appsrc输入检测到的工业表7图像解码调用MindX SDK的mxpi_imagedecoder输入图片8图像放缩调用MindX SDK的mxpi_imageresize,放缩到512*512大小9指针刻度检测调用MindX SDK的mxpi_tensorinfer,使用DeepLabv3语义分割模型,检测图像中的指针与刻度10模型后处理调用MindX mxpi_semanticsegpostprocessor,得到语义分割的结果11读数后处理开发mxpi_process3插件,读出工业表的数字2.2 代码目录结构与说明本工程名称为工业指针型表计读数,工程目录如下图所示:├── build.sh ├── README.md ├── evaluate ├── deeplabv3_val #deeplabv3模型测试精度 ├── seg_evaluate.py ├── yolov5_val #yolov5模型测试精度 ├── det.py #1.使用om模型检测测试数据,将得到的结果保存成yolo格式的txt文件 ├── match.py #3.检测是否有的图像没有目标 ├── yolo2voc.py #2.将得到的检测结果yolo数据格式转换成voc格式 ├── images ├── README_img ├── DeepLabv3_pipeline.png ├── YOLOv5_pipeline.png ├── infer ├── det.py ├── main.py ├── seg.py ├── models ├── deeplabv3 ├── seg_aipp.cfg #deeplabv3的onnx模型转换成om模型的配置文件 ├── yolov5 ├── det_aipp.cfg #yolov5的onnx模型转换成om模型的配置文件 ├── pipeline #pipeline文件 ├── deeplabv3 ├── deeplabv3.cfg ├── deeplabv3.names ├── seg.pipeline ├── yolov5 ├── det.pipeline ├── plugins #开发读数处理插件代码 ├── process3 ├── build.sh ├── CMakeLists.txt ├── Myplugin.cpp ├── Myplugin.h ├── postprocess.cpp ├── postprocess.h3 开发环境准备3.1 环境依赖软件和版本环境依赖软件和版本如下表:软件名称版本ubuntu18.04.1 LTSMindX SDK2.0.4Python3.9.2CANN5.0.4numpy1.23.4opencv-python4.6.0MindX SDK开发套件部分可参考MindX SDK开发套件安装指导3.2 导入基础环境. /usr/local/Ascend/ascend-toolkit/set_env.sh . ${SDK安装路径}/mxVision/set_env.sh4 编译与运行示例步骤如下:步骤1 执行编译编译插件,在项目目录下执行如下命令cd ${MeterReader代码根目录}/plugins/process3 . build.sh步骤2 修改pipeline文件中的参数地址修改"${MeterReader代码根目录}/pipeline/yolov5/det.pipeline"第40行处文件的绝对路径,将pipeline中所需要用到的模型路径改为存放模型的绝对路径地址:40 "modelPath":"${MeterReader代码根目录}/models/yolov5/det.om"修改"${MeterReader代码根目录}/pipeline/deeplabv3/seg.pipeline"第30、38、39行处文件的绝对路径,将pipeline中所需要用到的模型路径、配置文件地址改为绝对路径地址:30 "modelPath":"${MeterReader代码根目录}/models/deeplabv3/seg.om" 38 "postProcessConfigPath":"${MeterReader代码根目录}/pipeline/deeplabv3/deeplabv3.cfg", 39 "labelPath":"${MeterReader代码根目录}/pipeline/deeplabv3/deeplabv3.names",步骤3 运行及输出结果总体运行。输入带有预测表盘的jpg图片,在指定输出目录下输出得到带有预测表盘计数的png图片。cd ${MeterReader代码根目录}/infer python main.py --ifile ${输入图片路径} --odir ${输出图片目录}执行结束后,可在命令行内得到yolo模型得到的表盘文件路径,以及通过后续模型得到的预测表盘度数。并可在设定的${输出图片路径}中查看带有预测表盘计数的图片结果。最后展示的结果图片上用矩形框框出了图片中的表计并且标出了预测的表盘读数。5 指标验证分别对yolo模型与deeplabv3模型进行精度测试。1、YOLOv5模型精度测试步骤一:执行以下命令创建所需要的文件目录cd ${MeterReader代码根目录}/evaluate/yolov5_val/ mkdir -p det_val_data/det_val_voc mkdir -p det_val_data/meter_det mkdir -p det_val_data/det_val_img mkdir -p det_val_data/det_sdk_txt mkdir -p det_val_data/det_sdk_voc步骤二:准备标签文件及推理图片下载YOLOv5表计检测数据集并解压到任意目录后,将数据集目录中"test"和"train"目录下的所有图片汇总拷贝至"${MeterReader代码根目录}/evaluate/yolov5_val/det_val_data/meter_det"目录下。我们提供了样例的模型验证集标签文件以供下载测试。完成下载并解压后,将"data/yolov5/det_val_voc"目录下的文件拷贝至"${MeterReader代码根目录}/evaluate/yolov5_val/det_val_data/det_val_voc"目录下。然后根据拷贝后目录下样例的txt标签文件名称(txt命名格式为:文件名.txt)在"${MeterReader代码根目录}/evaluate/yolov5_val/det_val_data/meter_det"目录下找到对应名称的jpg图片并拷贝至"${MeterReader代码根目录}/evaluate/yolov5_val/det_val_data/det_val_img"目录下。步骤三:预处理数据集执行以下命令后,将在"${MeterReader代码根目录}/evaluate/yolov5_val/det_val_data/det_sdk_txt"目录下生成当前"det.om"模型检测验证集数据的yolo格式结果,并以图片命名的txt格式保存:cd ${MeterReader代码根目录}/evaluate/yolov5_val python det.py再执行以下命令,将上述得到的yolo数据格式转换成voc数据格式,并保存至"${MeterReader代码根目录}/evaluate/yolov5_val/det_val_data/det_sdk_voc"目录下:python yolo2voc.py最后执行以下命令,检测验证集中的数据是否有无目标文件:python match.py注意事项:运行脚本之前需要把det_sdk_txt和det_sdk_voc文件夹下的文件清空。步骤四:精度推理登录并点击下载mAP-master.zip代码压缩包,上传服务器解压后,将代码包中的"main.py"脚本拷贝至"${MeterReader代码根目录}/evaluate/yolov5_val/"目录下,按照以下步骤修改部分代码:修改main.py第47、48、50行处文件路径47 GT_PATH = os.path.join(os.getcwd(), 'det_val_data', 'det_val_voc') 48 DR_PATH = os.path.join(os.getcwd(), 'det_val_data', 'det_sdk_voc') 49 # # if there are no images then no animation can be shown 50 IMG_PATH = os.path.join(os.getcwd(), 'det_val_data', 'det_val_img')修改main.py原第64行代码64 show_animation = False 65 if not args.no_animation:在main.py原第243行添加代码242 def draw_plot_func(dictionary, n_classes, window_title, plot_title, x_label, output_path, to_show, plot_color, true_p_bar): 243 to_show = False使用下面命令运行脚本,计算得到det.om在验证集上的mAP。python main.py经过测试,YOLOv5模型的mAP为100%。2、deeplabv3模型精度测试。执行以下命令,创建所需文件目录:cd ${MeterReader代码根目录}/evaluate/deeplabv3_val/ mkdir seg_val_img cd seg_val_img mkdir seg_test_img mkdir seg_test_img_groundtruth下载语义分割模型验证集voc格式数据,解压至"${MeterReader代码根录}/evaluate/deeplabv3_val/seg_val_img"目录下。然后执行以下命令拷贝数据:cp -r ${MeterReader代码根目录}/evaluate/deeplabv3_val/seg_val_img/meter_seg/meter_seg/images/val/. ${MeterReader代码根目录}/evaluate/deeplabv3_val/seg_val_img/seg_test_img/ cp -r ${MeterReader代码根目录}/evaluate/deeplabv3_val/seg_val_img/meter_seg/meter_seg/annotations/val/. ${MeterReader代码根目录}/evaluate/deeplabv3_val/seg_val_img/seg_test_img_groundtruth/采用Miou指标进行精度评价。使用下面命令运行脚本:cd ${MeterReader代码根目录}/evaluate/deeplabv3_val/ python seg_evaluate.py输出各个图的Miou指标,并求得平均值作为deeplabv3模型的精度指标。经测试,deeplabv3的模型的Miou为67%。6 常见问题6.1 模型转换问题问题描述当图像进入流后,输出到模型的图像格式为yuv,数据类型unit8,但是om模型的时候yolov5需要输入的图像格式为RGB。解决方案在转换模型时必须要在AIPP做色域转换,否则模型输入不正确。6.2 插件权限问题问题描述运行pipeline调用第三步的数值处理插件时报错,提示Check Owner permission failed: Current permission is 7, but required no greater than 6.解决方案将插件的权限调整为默认440(只读)即可chmod 440 "$MX_SDK_HOME/lib/plugins/libmxpi_sampleplugin.so"
  • [技术干货] UIE模型实战实体抽取任务【打车数据、快递单】
    项目连接:可以直接fork使用 Paddlenlp之UIE模型实战实体抽取任务【打车数据、快递单】0.背景介绍本项目将演示如何通过小样本样本进行模型微调,快速且准确抽取快递单中的目的地、出发地、时间、打车费用等内容,形成结构化信息。辅助物流行业从业者进行有效信息的提取,从而降低客户填单的成本。数据集情况: waybill.jsonl文件是快递单信息数据集:{"id": 57, "text": "昌胜远黑龙江省哈尔滨市南岗区宽桥街28号18618391296", "relations": [], "entities": [{"id": 111, "start_offset": 0, "end_offset": 3, "label": "姓名"}, {"id": 112, "start_offset": 3, "end_offset": 7, "label": "省份"}, {"id": 113, "start_offset": 7, "end_offset": 11, "label": "城市"}, {"id": 114, "start_offset": 11, "end_offset": 14, "label": "县区"}, {"id": 115, "start_offset": 14, "end_offset": 20, "label": "详细地址"}, {"id": 116, "start_offset": 20, "end_offset": 31, "label": "电话"}]} {"id": 58, "text": "易颖18500308469山东省烟台市莱阳市富水南路1号", "relations": [], "entities": [{"id": 118, "start_offset": 0, "end_offset": 2, "label": "姓名"}, {"id": 119, "start_offset": 2, "end_offset": 13, "label": "电话"}, {"id": 120, "start_offset": 13, "end_offset": 16, "label": "省份"}, {"id": 121, "start_offset": 16, "end_offset": 19, "label": "城市"}, {"id": 122, "start_offset": 19, "end_offset": 22, "label": "县区"}, {"id": 123, "start_offset": 22, "end_offset": 28, "label": "详细地址"}]}doccano_ext.jsonl是打车数据集:{"id": 1, "text": "昨天晚上十点加班打车回家58元", "relations": [], "entities": [{"id": 0, "start_offset": 0, "end_offset": 6, "label": "时间"}, {"id": 1, "start_offset": 11, "end_offset": 12, "label": "目的地"}, {"id": 2, "start_offset": 12, "end_offset": 14, "label": "费用"}]} {"id": 2, "text": "三月三号早上12点46加班,到公司54", "relations": [], "entities": [{"id": 3, "start_offset": 0, "end_offset": 11, "label": "时间"}, {"id": 4, "start_offset": 15, "end_offset": 17, "label": "目的地"}, {"id": 5, "start_offset": 17, "end_offset": 19, "label": "费用"}]} {"id": 3, "text": "8月31号十一点零四工作加班五十块钱", "relations": [], "entities": [{"id": 6, "start_offset": 0, "end_offset": 10, "label": "时间"}, {"id": 7, "start_offset": 14, "end_offset": 16, "label": "费用"}]} {"id": 4, "text": "5月17号晚上10点35分加班打车回家,36块五", "relations": [], "entities": [{"id": 8, "start_offset": 0, "end_offset": 13, "label": "时间"}, {"id": 1, "start_offset": 18, "end_offset": 19, "label": "目的地"}, {"id": 9, "start_offset": 20, "end_offset": 24, "label": "费用"}]} {"id": 5, "text": "2009年1月份通讯费一百元", "relations": [], "entities": [{"id": 10, "start_offset": 0, "end_offset": 7, "label": "时间"}, {"id": 11, "start_offset": 11, "end_offset": 13, "label": "费用"}]}结果展示预览输入:城市内交通费7月5日金额114广州至佛山 从百度大厦到龙泽苑东区打车费二十元 上海虹桥高铁到杭州时间是9月24日费用是73元 上周末坐动车从北京到上海花费五十块五毛 昨天北京飞上海话费一百元输出:{"出发地": [{"text": "广州", "start": 15, "end": 17, "probability": 0.9073772252165782}], "目的地": [{"text": "佛山", "start": 18, "end": 20, "probability": 0.9927365183877761}], "时间": [{"text": "7月5日", "start": 6, "end": 10, "probability": 0.9978010396512218}]} {"出发地": [{"text": "百度大厦", "start": 1, "end": 5, "probability": 0.968825147409472}], "目的地": [{"text": "龙泽苑东区", "start": 6, "end": 11, "probability": 0.9877913072493669}]} {"目的地": [{"text": "杭州", "start": 7, "end": 9, "probability": 0.9929172180094881}], "时间": [{"text": "9月24日", "start": 12, "end": 17, "probability": 0.9953342057701597}]} {#"出发地": [{"text": "北京", "start": 7, "end": 9, "probability": 0.973048366717471}], "目的地": [{"text": "上海", "start": 10, "end": 12, "probability": 0.988486130309397}], "时间": [{"text": "上周末", "start": 0, "end": 3, "probability": 0.9977407699595275}]} {"出发地": [{"text": "北京", "start": 2, "end": 4, "probability": 0.974188953533556}], "目的地": [{"text": "上海", "start": 5, "end": 7, "probability": 0.9928200521486445}], "时间": [{"text": "昨天", "start": 0, "end": 2, "probability": 0.9731559534465504}]}1.数据集加载(快递单数据、打车数据)doccano_file: 从doccano导出的数据标注文件。save_dir: 训练数据的保存目录,默认存储在data目录下。negative_ratio: 最大负例比例,该参数只对抽取类型任务有效,适当构造负例可提升模型效果。负例数量和实际的标签数量有关,最大负例数量 = negative_ratio * 正例数量。该参数只对训练集有效,默认为5。为了保证评估指标的准确性,验证集和测试集默认构造全负例。splits: 划分数据集时训练集、验证集所占的比例。默认为[0.8, 0.1, 0.1]表示按照8:1:1的比例将数据划分为训练集、验证集和测试集。task_type: 选择任务类型,可选有抽取和分类两种类型的任务。options: 指定分类任务的类别标签,该参数只对分类类型任务有效。默认为["正向", "负向"]。prompt_prefix: 声明分类任务的prompt前缀信息,该参数只对分类类型任务有效。默认为"情感倾向"。is_shuffle: 是否对数据集进行随机打散,默认为True。seed: 随机种子,默认为1000.*separator: 实体类别/评价维度与分类标签的分隔符,该参数只对实体/评价维度级分类任务有效。默认为"##"。!python doccano.py \ --doccano_file ./data/doccano_ext.jsonl \ --task_type 'ext' \ --save_dir ./data \ --splits 0.8 0.1 0.1 \ --negative_ratio 5[2022-07-14 11:34:26,474] [ INFO] - Converting doccano data... 100%|████████████████████████████████████████| 40/40 [00:00<00:00, 42560.16it/s] [2022-07-14 11:34:26,477] [ INFO] - Adding negative samples for first stage prompt... 100%|███████████████████████████████████████| 40/40 [00:00<00:00, 161009.75it/s] [2022-07-14 11:34:26,478] [ INFO] - Converting doccano data... 100%|██████████████████████████████████████████| 5/5 [00:00<00:00, 21754.69it/s] [2022-07-14 11:34:26,479] [ INFO] - Adding negative samples for first stage prompt... 100%|██████████████████████████████████████████| 5/5 [00:00<00:00, 44057.82it/s] [2022-07-14 11:34:26,479] [ INFO] - Converting doccano data... 100%|██████████████████████████████████████████| 5/5 [00:00<00:00, 26181.67it/s] [2022-07-14 11:34:26,480] [ INFO] - Adding negative samples for first stage prompt... 100%|██████████████████████████████████████████| 5/5 [00:00<00:00, 45689.59it/s] [2022-07-14 11:34:26,482] [ INFO] - Save 160 examples to ./data/train.txt. [2022-07-14 11:34:26,482] [ INFO] - Save 20 examples to ./data/dev.txt. [2022-07-14 11:34:26,482] [ INFO] - Save 20 examples to ./data/test.txt. [2022-07-14 11:34:26,482] [ INFO] - Finished! It takes 0.01 seconds输出部分展示:{"content": "上海到北京机票1320元", "result_list": [{"text": "上海", "start": 0, "end": 2}], "prompt": "出发地"} {"content": "上海到北京机票1320元", "result_list": [{"text": "北京", "start": 3, "end": 5}], "prompt": "目的地"} {"content": "上海到北京机票1320元", "result_list": [{"text": "1320", "start": 7, "end": 11}], "prompt": "费用"} {"content": "上海虹桥到杭州东站高铁g7555共73元时间是10月14日", "result_list": [{"text": "上海虹桥", "start": 0, "end": 4}], "prompt": "出发地"} {"content": "上海虹桥到杭州东站高铁g7555共73元时间是10月14日", "result_list": [{"text": "杭州东站", "start": 5, "end": 9}], "prompt": "目的地"} {"content": "上海虹桥到杭州东站高铁g7555共73元时间是10月14日", "result_list": [{"text": "73", "start": 17, "end": 19}], "prompt": "费用"} {"content": "上海虹桥到杭州东站高铁g7555共73元时间是10月14日", "result_list": [{"text": "10月14日", "start": 23, "end": 29}], "prompt": "时间"} {"content": "昨天晚上十点加班打车回家58元", "result_list": [{"text": "昨天晚上十点", "start": 0, "end": 6}], "prompt": "时间"} {"content": "昨天晚上十点加班打车回家58元", "result_list": [{"text": "家", "start": 11, "end": 12}], "prompt": "目的地"} {"content": "昨天晚上十点加班打车回家58元", "result_list": [{"text": "58", "start": 12, "end": 14}], "prompt": "费用"} {"content": "2月20号从南山到光明二十元", "result_list": [{"text": "2月20号", "start": 0, "end": 5}], "prompt": "时间"}2.模型训练!python finetune.py \ --train_path "./data/train.txt" \ --dev_path "./data/dev.txt" \ --save_dir "./checkpoint" \ --learning_rate 1e-5 \ --batch_size 8 \ --max_seq_len 512 \ --num_epochs 100 \ --model "uie-base" \ --seed 1000 \ --logging_steps 10 \ --valid_steps 50 \ --device "gpu"部分训练效果展示:**具体输出已折叠** [2022-07-12 15:09:47,643] [ INFO] - global step 250, epoch: 13, loss: 0.00045, speed: 3.90 step/s [2022-07-12 15:09:47,910] [ INFO] - Evaluation precision: 1.00000, recall: 1.00000, F1: 1.00000 [2022-07-12 15:09:50,399] [ INFO] - global step 260, epoch: 13, loss: 0.00043, speed: 4.02 step/s [2022-07-12 15:09:52,966] [ INFO] - global step 270, epoch: 14, loss: 0.00042, speed: 3.90 step/s [2022-07-12 15:09:55,464] [ INFO] - global step 280, epoch: 14, loss: 0.00040, speed: 4.00 step/s [2022-07-12 15:09:58,028] [ INFO] - global step 290, epoch: 15, loss: 0.00039, speed: 3.90 step/s [2022-07-12 15:10:00,516] [ INFO] - global step 300, epoch: 15, loss: 0.00038, speed: 4.02 step/s [2022-07-12 15:10:00,781] [ INFO] - Evaluation precision: 1.00000, recall: 1.00000, F1: 1.00000 [2022-07-12 15:10:03,348] [ INFO] - global step 310, epoch: 16, loss: 0.00036, speed: 3.90 step/s [2022-07-12 15:10:05,836] [ INFO] - global step 320, epoch: 16, loss: 0.00035, speed: 4.02 step/s [2022-07-12 15:10:08,393] [ INFO] - global step 330, epoch: 17, loss: 0.00034, speed: 3.91 step/s [2022-07-12 15:10:10,888] [ INFO] - global step 340, epoch: 17, loss: 0.00033, speed: 4.01 step/s 推荐使用GPU环境,否则可能会内存溢出。CPU环境下,可以修改model为uie-tiny,适当调下batch_size。 增加准确率的话:--num_epochs 设置大点多训练训练 可配置参数说明: **train_path:** 训练集文件路径。 **dev_path:** 验证集文件路径。 **save_dir:** 模型存储路径,默认为./checkpoint。 **learning_rate:** 学习率,默认为1e-5。 **batch_size:** 批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数,默认为16。 **max_seq_len:** 文本最大切分长度,输入超过最大长度时会对输入文本进行自动切分,默认为512。 **num_epochs:** 训练轮数,默认为100。 **model** 选择模型,程序会基于选择的模型进行模型微调,可选有uie-base和uie-tiny,默认为uie-base。 **seed:** 随机种子,默认为1000. **logging_steps:** 日志打印的间隔steps数,默认10。 **valid_steps:** evaluate的间隔steps数,默认100。 **device:** 选用什么设备进行训练,可选cpu或gpu。3模型评估!python evaluate.py \ --model_path ./checkpoint/model_best \ --test_path ./data/test.txt \ --batch_size 16 \ --max_seq_len 512[2022-07-11 13:41:23,831] [ INFO] - ----------------------------- [2022-07-11 13:41:23,831] [ INFO] - Class Name: all_classes [2022-07-11 13:41:23,832] [ INFO] - Evaluation Precision: 1.00000 | Recall: 1.00000 | F1: 1.00000 [2022-07-11 13:41:35,024] [ INFO] - ----------------------------- [2022-07-11 13:41:35,024] [ INFO] - Class Name: 出发地 [2022-07-11 13:41:35,024] [ INFO] - Evaluation Precision: 1.00000 | Recall: 1.00000 | F1: 1.00000 [2022-07-11 13:41:35,139] [ INFO] - ----------------------------- [2022-07-11 13:41:35,139] [ INFO] - Class Name: 目的地 [2022-07-11 13:41:35,139] [ INFO] - Evaluation Precision: 1.00000 | Recall: 1.00000 | F1: 1.00000 [2022-07-11 13:41:35,246] [ INFO] - ----------------------------- [2022-07-11 13:41:35,246] [ INFO] - Class Name: 费用 [2022-07-11 13:41:35,246] [ INFO] - Evaluation Precision: 1.00000 | Recall: 1.00000 | F1: 1.00000 [2022-07-11 13:41:35,313] [ INFO] - ----------------------------- [2022-07-11 13:41:35,313] [ INFO] - Class Name: 时间 [2022-07-11 13:41:35,313] [ INFO] - Evaluation Precision: 1.00000 | Recall: 1.00000 | F1: 1.00000model_path: 进行评估的模型文件夹路径,路径下需包含模型权重文件model_state.pdparams及配置文件model_config.json。test_path: 进行评估的测试集文件。batch_size: 批处理大小,请结合机器情况进行调整,默认为16。max_seq_len: 文本最大切分长度,输入超过最大长度时会对输入文本进行自动切分,默认为512。model: 选择所使用的模型,可选有uie-base, uie-medium, uie-mini, uie-micro和uie-nano,默认为uie-base。debug: 是否开启debug模式对每个正例类别分别进行评估,该模式仅用于模型调试,默认关闭。4 结果预测from pprint import pprint import json from paddlenlp import Taskflow def openreadtxt(file_name): data = [] file = open(file_name,'r',encoding='UTF-8') #打开文件 file_data = file.readlines() #读取所有行 for row in file_data: data.append(row) #将每行数据插入data中 return data data_input=openreadtxt('./input/nlp.txt') schema = ['出发地', '目的地','时间'] few_ie = Taskflow('information_extraction', schema=schema, batch_size=1,task_path='./checkpoint/model_best') results=few_ie(data_input) with open("./output/test.txt", "w+",encoding='UTF-8') as f: #a : 写入文件,若文件不存在则会先创建再写入,但不会覆盖原文件,而是追加在文件末尾 for result in results: line = json.dumps(result, ensure_ascii=False) #对中文默认使用的ascii编码.想输出真正的中文需要指定ensure_ascii=False f.write(line + "\n") print("数据结果已导出")输入文件展示:城市内交通费7月5日金额114广州至佛山 从百度大厦到龙泽苑东区打车费二十元 上海虹桥高铁到杭州时间是9月24日费用是73元 上周末坐动车从北京到上海花费五十块五毛 昨天北京飞上海话费一百元输出展示:{"出发地": [{"text": "广州", "start": 15, "end": 17, "probability": 0.9073772252165782}], "目的地": [{"text": "佛山", "start": 18, "end": 20, "probability": 0.9927365183877761}], "时间": [{"text": "7月5日", "start": 6, "end": 10, "probability": 0.9978010396512218}]} {"出发地": [{"text": "百度大厦", "start": 1, "end": 5, "probability": 0.968825147409472}], "目的地": [{"text": "龙泽苑东区", "start": 6, "end": 11, "probability": 0.9877913072493669}]} {"目的地": [{"text": "杭州", "start": 7, "end": 9, "probability": 0.9929172180094881}], "时间": [{"text": "9月24日", "start": 12, "end": 17, "probability": 0.9953342057701597}]} {"出发地": [{"text": "北京", "start": 7, "end": 9, "probability": 0.973048366717471}], "目的地": [{"text": "上海", "start": 10, "end": 12, "probability": 0.988486130309397}], "时间": [{"text": "上周末", "start": 0, "end": 3, "probability": 0.9977407699595275}]} {"出发地": [{"text": "北京", "start": 2, "end": 4, "probability": 0.974188953533556}], "目的地": [{"text": "上海", "start": 5, "end": 7, "probability": 0.9928200521486445}], "时间": [{"text": "昨天", "start": 0, "end": 2, "probability": 0.9731559534465504}]}5.可视化显示visualDL详细文档可以参考: cid:link_1 有详细讲解,具体实现参考代码,核心是:添加一个初始化记录器下面是结果展示:6.小技巧:获取paddle开源数据集数据集网站:cid:link_0数据集名称 简介 调用方法CoLA 单句分类任务,二分类,判断句子是否合法 paddlenlp.datasets.load_dataset('glue','cola')SST-2 单句分类任务,二分类,判断句子情感极性paddlenlp.datasets.load_dataset('glue','sst-2')MRPC 句对匹配任务,二分类,判断句子对是否是相同意思 paddlenlp.datasets.load_dataset('glue','mrpc')STSB 计算句子对相似性,分数为1~5 paddlenlp.datasets.load_dataset('glue','sts-b') QQP 判定句子对是否等效,等效、不等效两种情况,二分类任务 paddlenlp.datasets.load_dataset('glue','qqp')MNLI 句子对,一个前提,一个是假设。前提和假设的关系有三种情况:蕴含(entailment),矛盾(contradiction),中立(neutral)。句子对三分类问题 paddlenlp.datasets.load_dataset('glue','mnli')QNLI 判断问题(question)和句子(sentence)是否蕴含,蕴含和不蕴含,二分类 paddlenlp.datasets.load_dataset('glue','qnli')RTE 判断句对是否蕴含,句子1和句子2是否互为蕴含,二分类任务 paddlenlp.datasets.load_dataset('glue','rte')WNLI 判断句子对是否相关,相关或不相关,二分类任务 paddlenlp.datasets.load_dataset('glue','wnli')LCQMC A Large-scale Chinese Question Matching Corpus 语义匹配数据集 paddlenlp.datasets.load_dataset('lcqmc')通过paddlenlp提供的api调用,可以很方便实现数据加载,当然你想要把数据下载到本地,可以参考我下面的输出就可以保存数据了。#加载中文评论情感分析语料数据集ChnSentiCorp from paddlenlp.datasets import load_dataset train_ds, dev_ds, test_ds = load_dataset("chnsenticorp", splits=["train", "dev", "test"]) with open("./output/test2.txt", "w+",encoding='UTF-8') as f: #a : 写入文件,若文件不存在则会先创建再写入,但不会覆盖原文件,而是追加在文件末尾 for result in test_ds: line = json.dumps(result, ensure_ascii=False) #对中文默认使用的ascii编码.想输出真正的中文需要指定ensure_ascii=False f.write(line + "\n")7 总结UIE(Universal Information Extraction):Yaojie Lu等人在ACL-2022中提出了通用信息抽取统一框架UIE。该框架实现了实体抽取、关系抽取、事件抽取、情感分析等任务的统一建模,并使得不同任务间具备良好的迁移和泛化能力。PaddleNLP借鉴该论文的方法,基于ERNIE 3.0知识增强预训练模型,训练并开源了首个中文通用信息抽取模型UIE。该模型可以支持不限定行业领域和抽取目标的关键信息抽取,实现零样本快速冷启动,并具备优秀的小样本微调能力,快速适配特定的抽取目标。UIE的优势使用简单: 用户可以使用自然语言自定义抽取目标,无需训练即可统一抽取输入文本中的对应信息。实现开箱即用,并满足各类信息抽取需求。降本增效: 以往的信息抽取技术需要大量标注数据才能保证信息抽取的效果,为了提高开发过程中的开发效率,减少不必要的重复工作时间,开放域信息抽取可以实现零样本(zero-shot)或者少样本(few-shot)抽取,大幅度降低标注数据依赖,在降低成本的同时,还提升了效果。效果领先: 开放域信息抽取在多种场景,多种任务上,均有不俗的表现。本人本次主要通过实体抽取这个案例分享给大家,主要对开源的paddlenlp的案例进行了细化,比如在结果可视化方面以及结果输入输出的增加,使demo项目更佳完善。当然标注问题是所有问题的痛点,可以参考我的博客来解决这个问题本人博客:cid:link_3