-
以如faster RCNN的以下检测数据:检测精度(mAP 59.9% 和 73.2%)42.1% 的 mAP@0.5 和 21.5% 的 mAP@[.5, .95]在学术研究中,不同的数据集和任务有不同的标准。例如,在PASCAL VOC数据集上,mAP达到50%以上通常被认为是较好的结果,而70%以上则被认为是优秀的。在MS COCO数据集上,由于其更具挑战性,mAP达到40%以上通常被认为是较好的结果。在实际应用中,合格标准可能会根据具体的应用场景和需求而有所不同。例如,对于一些对准确性要求极高的应用场景,如医疗图像分析或自动驾驶,可能需要更高的mAP值才能满足要求。但对于一些对实时性要求较高、对准确性要求相对较低的应用场景,如视频监控中的简单物体检测,较低的mAP值可能也足够。这些mAP值没有达到80%(平均未达到,但在某些类型对象是达到的,比如bus/car等),这可能是由于以下几个原因:数据集的难度:PASCAL VOC和MS COCO数据集包含了许多具有挑战性的图像,例如,物体可能被遮挡、截断或具有不同的尺度和姿态。这些困难因素会降低模型的检测精度。模型的复杂度:尽管Faster R-CNN是一个强大的模型,但它仍然有可能无法捕获所有可能的物体特征。训练数据量:如果训练数据量不足,模型可能无法充分学习到物体的特征,从而影响检测精度。使用更大的数据集(如COCO)进行预训练可以提高在PASCAL VOC数据集上的检测精度。评估标准:mAP@[.5, .95]是一个更严格的评估标准,因为它考虑了不同IoU阈值下的平均精度。这使得模型需要在各种情况下都能准确检测物体,而不仅仅是对某个特定的IoU阈值。论文中提到的mAP值在当时被认为是相当不错的,尤其是在实时性方面,Faster R-CNN实现了近实时的检测速度,这对于许多实际应用来说是一个重要的优势。随着技术的发展,后续的研究可能会进一步提高mAP值,但这也需要在准确性和计算效率之间找到平衡。mAP(mean Average Precision):定义:mAP 是目标检测任务中常用的评估指标,表示平均精度(Average Precision, AP)的均值。AP 是针对每个类别计算的,表示在不同召回率(Recall)下的精度(Precision)的平均值。AP 是针对每个类别的平均精度,而 mAP 是对所有类别的 AP 取均值,从而得到一个整体的性能指标。使用 mAP 可以更全面地评估模型在所有类别上的性能,而不仅仅是单个类别。(Recall:召回率,表示模型检测到的正样本占所有实际正样本的比例。mAP 不带 @:默认 IoU 阈值为 0.5。)59.9% 和 73.2%:59.9%:在 PASCAL VOC 2007 数据集上,使用 RPN 和 Fast R-CNN 结合的方法,平均精度为 59.9%。73.2%:在 PASCAL VOC 2012 数据集上,使用 RPN 和 Fast R-CNN 结合的方法,平均精度为 73.2%。mAP@0.5 和 mAP@[.5, .95]:mAP@0.5:表示在 IoU(Intersection over Union)阈值为 0.5 时的平均精度。IoU 是衡量预测框和真实框重叠程度的指标,取值范围为 0 到 1。IoU = 0.5 表示预测框和真实框的重叠面积占两者并集面积的 50%。42.1%:在 MS COCO 数据集上,使用 RPN 和 Fast R-CNN 结合的方法,在 IoU 阈值为 0.5 时的平均精度为 42.1%。mAP@[.5, .95]:表示在 IoU 阈值从 0.5 到 0.95(步长为 0.05)时的平均精度。这表示模型在不同 IoU 阈值下的综合表现。21.5%:在 MS COCO 数据集上,使用 RPN 和 Fast R-CNN 结合的方法,在 IoU 阈值从 0.5 到 0.95 时的平均精度为 21.5%。
-
Warp 操作在计算机视觉和图像处理领域中指对图像进行几何变换的过程,它通过数学函数将图像中的像素从一个位置映射到另一个位置,从而实现图像的变形、扭曲或变换。这种操作可以用于多种目的,如图像配准、数据增强、视角变换等。例如,在图像配准中,可能会使用 warp 操作将一幅图像变形以与另一幅图像对齐。在语言中,warp可做名称和动词,含义是变形、扭曲 :引申义,指事物的变形、扭曲或偏离正常状态。例如:“The heat caused the metal to warp.”(高温使金属变形。)Warp 操作的应用图像配准 :在医学图像配准中,Warp 操作用于将浮动图像(moving image)根据变形场(deformation field)映射到固定图像(fixed image)的坐标系中,从而实现两幅图像的对齐。例如,在医学成像中,将不同时间或不同模态的图像进行配准,以便医生可以更准确地比较和分析病变区域。数据增强 :在深度学习中,Warp 操作常用于数据增强,通过对训练图像进行旋转、平移、缩放等变换,增加训练数据的多样性,提高模型的泛化能力。例如,在图像分类任务中,对训练图像进行轻微的旋转和平移,生成新的训练样本,使模型能够更好地适应不同的输入条件。视角变换 :在计算机视觉中,Warp 操作可以用于模拟摄像头的移动或视角的变化。例如,在 SLAM(Simultaneous Localization and Mapping)中,通过光流(optical flow)计算得到的 Warp 操作,可以将前一帧图像中的像素映射到下一帧图像的对应位置,从而实现视角的变换。对抗性攻击与训练 :Warp 技术可以用来生成对抗性样本,使得模型在这些样本上产生错误的预测。为了提高模型对对抗性攻击的鲁棒性,可以使用 Warp 对训练数据进行扰动,让模型在训练过程中就接触到这些对抗性样本。Warp 操作的计算Warp 操作的计算通常涉及以下步骤:定义变换函数 :根据具体的应用需求,定义一个数学函数来描述图像中每个像素的映射关系。这个函数可以是仿射变换、透视变换、非刚性变换等。例如,仿射变换可以用一个 2×3 的矩阵来表示,通过矩阵乘法将图像中的像素坐标映射到新的位置。生成映射网格 :根据变换函数,生成一个映射网格,该网格描述了图像中每个像素在变换后的位置。这个网格可以是一个二维数组,其中每个元素表示一个像素的坐标。重采样 :使用映射网格对原始图像进行重采样,得到变换后的图像。重采样方法可以是最近邻插值、双线性插值等。例如,双线性插值可以根据周围像素的值来计算变换后像素的值,从而实现平滑的变换效果。Warp 操作在 R-CNN 中的应用在 R-CNN 中,Warp 操作用于将每个 proposal(候选区域)调整为固定的大小,以便输入到后续的网络中进行分类和回归。具体来说,R-CNN 会对每个 proposal 进行 Warp 操作,将其调整为 227×227 的大小,然后送入卷积神经网络进行特征提取和分类。然而,这种 Warp 操作会导致图像的变形和扭曲,特别是对于非正方形的目标,可能会丢失重要的空间信息。此外,每个 proposal 都需要单独进行特征提取,导致了大量的重复计算。
-
SD卡烧录好欧拉系统,HiLens能够设置SD卡为启动首选项,使用SD卡烧录的系统吗?备注:HiLens根目录只有2GB,空间太少了,安装几个库就没有空间了,总计32GB的空间,分成了很多个区,不敢贸然合并,所以想搞个大容量SD卡,烧录系统使用
-
😀前言在程序设计和算法竞赛中,丑数问题是一个经典的动态规划题目。丑数(Ugly Number)定义为只包含质因子 2、3 和 5 的数。举例来说,数字 6(因子为 2 和 3)、数字 8(因子为 2)都是丑数,而数字 14 不是丑数,因为它包含质因子 7。在这种定义下,1 通常被视为第一个丑数。🥰丑数NowCoder😊题目描述把只包含因子 2、3 和 5 的数称作丑数(Ugly Number)。例如 6、8 都是丑数,但 14 不是,因为它包含因子 7。习惯上我们把 1 当做是第一个丑数。求按从小到大的顺序的第 N 个丑数。例子输入:N = 10输出:12解释:前10个丑数依次是 [1, 2, 3, 4, 5, 6, 8, 9, 10, 12],因此第10个丑数为12。😄解题思路解决该问题的常见方法是动态规划。动态规划的基本思想是从第一个丑数开始,逐步生成下一个丑数,直到得到第 N 个。核心思想定义状态:使用一个长度为 N 的数组 dp,其中 dp[i] 表示从小到大第 i+1 个丑数。初始化 dp[0] = 1,即第一个丑数是 1。生成丑数:由于丑数的定义,新的丑数可以通过已知的丑数乘以 2、3 或 5 来生成。因此,我们在每一步都计算下一个可以生成的丑数。三个指针:维护三个指针 i2, i3, i5,分别表示当前丑数数组中,乘以 2、3、5 后最小值的索引。每次选择这三个数中的最小值作为下一个丑数,并更新相应的指针。避免重复:如果当前生成的丑数等于多个最小值中的某个,我们需要将对应的指针后移,避免重复计算。例如,如果 dp[i] 既是 dp[i2] * 2,又是 dp[i3] * 3,我们需要同时更新 i2 和 i3。💖代码实现public int GetUglyNumber_Solution(int N) { if (N <= 6) return N; // 特殊情况:如果 N 小于等于6,直接返回 N,因为前6个丑数为 [1, 2, 3, 4, 5, 6] int i2 = 0, i3 = 0, i5 = 0; // 初始化三个指针,分别指向当前乘以2、3、5的丑数索引 int[] dp = new int[N]; // 创建数组存储前N个丑数 dp[0] = 1; // 第一个丑数是1 for (int i = 1; i < N; i++) { // 计算下一个可能的丑数,分别为2、3、5的倍数 int next2 = dp[i2] * 2, next3 = dp[i3] * 3, next5 = dp[i5] * 5; // 当前丑数是这三个数中的最小值 dp[i] = Math.min(next2, Math.min(next3, next5)); // 如果当前最小值是乘以2得到的,更新指针i2 if (dp[i] == next2) i2++; // 如果当前最小值是乘以3得到的,更新指针i3 if (dp[i] == next3) i3++; // 如果当前最小值是乘以5得到的,更新指针i5 if (dp[i] == next5) i5++; } // 返回第N个丑数 return dp[N - 1]; } 详解代码特殊处理:首先判断 N 是否小于等于 6,因为前 6 个丑数就是 [1, 2, 3, 4, 5, 6],直接返回即可。初始化指针和数组:i2, i3, i5 分别指向乘以 2、3、5 后可以得到的最小丑数索引。数组 dp 用于存储从小到大生成的丑数,初始值为 dp[0] = 1。计算最小值:每次循环中,分别计算 next2 = dp[i2] * 2,next3 = dp[i3] * 3,next5 = dp[i5] * 5,然后取这三个值的最小值作为下一个丑数。更新指针:如果当前生成的丑数是乘以 2 得到的,则指针 i2 向后移动,以便下次循环使用更新的丑数;如果是乘以 3 或 5 得到的,也分别移动指针 i3 和 i5。复杂度分析时间复杂度:O(N),因为我们只需要生成 N 个丑数,每次生成一个丑数的操作时间是常数。空间复杂度:O(N),因为我们使用了一个长度为 N 的数组来存储丑数。😄总结丑数问题通过动态规划的方式,巧妙地利用三个指针生成新的丑数,并且保证了每个丑数都是按顺序生成的。通过这种方式,我们可以在 O(N) 的时间内得到第 N 个丑数,是一种高效的解决方案。
-
进入活动链接:https://pangu.huaweicloud.com/gallery/asset-detail.html?id=c1cf0774-59ce-44fc-a4a8-8fcf026d2fec1、切换规格为64GB的限时免费规格2、点击执行3、然后执行:4、继续执行5、切换python版本,这个很重要!!!!,6、安装和启动运行7、最后生成了一个链接:Running on public URL: https://0dfb450b322dd89a40.gradio.live8、点击该URL,就可以开始使用了角色:man 活动: play basketball,选择风格类型使用效果1,这个是“线条艺术”这个是“油画”效果这个是“日本动画”风格该模型部署起来很方便,模型很强大,伙伴们可以多多探索,多少挖掘
-
😀前言 在编程问题中,处理字符串是一个常见的挑战,其中有一个经典问题就是寻找字符串中最长不含重复字符的子字符串。该问题的目的是在给定的字符串中,找到一个没有重复字符的子字符串,并返回其长度。🥰最长不含重复字符的子字符串牛客网😊题目描述我们需要解决的是:给定一个只包含小写字母(a~z)的字符串,找出其最长的不含重复字符的子字符串的长度。例如,对于输入字符串 arabcacfr,其中最长的不含重复字符的子字符串是 acfr,其长度为4。😉解题思路解决这个问题最简单的思路是使用暴力法:遍历字符串的所有子字符串,检查每个子字符串是否包含重复字符,记录没有重复字符的最长子字符串的长度。然而,这种方法效率较低,尤其是在处理大规模字符串时,时间复杂度可能会达到 O(n²),因此我们需要一种更高效的方案。高效的方法可以通过滑动窗口和哈希表来优化,我们只需线性遍历字符串一次即可解决问题,时间复杂度为 O(n)。下面的 Java 代码实现了这个思路。😁Java代码实现public int longestSubStringWithoutDuplication(String str) { int curLen = 0; // 当前不含重复字符的子字符串长度 int maxLen = 0; // 目前找到的最长子字符串长度 int[] preIndexs = new int[26]; // 记录字符上一次出现的位置 Arrays.fill(preIndexs, -1); // 初始化字符的上次出现位置为 -1 for (int curI = 0; curI < str.length(); curI++) { int c = str.charAt(curI) - 'a'; // 将字符映射到 0 ~ 25 的整数 int preI = preIndexs[c]; // 获取该字符上次出现的位置 if (preI == -1 || curI - preI > curLen) { // 如果字符第一次出现或者在当前子字符串之外,更新当前长度 curLen++; } else { // 如果字符在当前子字符串内出现过,更新最长长度,并从重复字符之后开始新子字符串 maxLen = Math.max(maxLen, curLen); curLen = curI - preI; } preIndexs[c] = curI; // 更新字符上次出现的位置 } maxLen = Math.max(maxLen, curLen); // 确保结束时记录到最长长度 return maxLen; }代码详解变量定义:curLen: 当前不含重复字符的子字符串长度。maxLen: 记录到目前为止,最长的不含重复字符子字符串的长度。preIndexs: 一个大小为26的数组,用来存储每个字符上次出现在字符串中的位置。由于字符串只包含a~z的字符,因此数组长度为26,preIndexs[i]对应第i个字母(a对应0,b对应1,以此类推)。初始化:将 preIndexs 数组的所有元素初始化为 -1,表示每个字符一开始都没有出现过。遍历字符串:遍历字符串的每个字符,获取其在 preIndexs 中记录的上一次出现的位置 preI。如果该字符第一次出现,或者它的上一次出现位置在当前子字符串之外(即 curI - preI > curLen),说明当前字符没有重复,当前子字符串的长度 curLen 增加1。如果该字符在当前子字符串内出现过(即 curI - preI <= curLen),则更新 maxLen,并将当前子字符串重新设置为从重复字符的下一个位置开始,长度为 curI - preI。更新位置:每次遍历字符时,将其在 preIndexs 中的位置更新为当前下标。返回结果:遍历完字符串后,再次更新 maxLen,确保返回值是最终的最长子字符串长度。解题思路总结这个算法的核心思想是用滑动窗口的方法动态维护一个不含重复字符的子字符串,并通过记录每个字符的上一次出现位置,避免了重复字符的出现。这样我们就能在一次遍历中找到最长的不含重复字符的子字符串,时间复杂度为 O(n),空间复杂度为 O(1)。💝算法复杂度分析时间复杂度:每个字符只会被访问两次(一次是进入窗口,一次是离开窗口),因此时间复杂度为 O(n),其中 n 是字符串的长度。空间复杂度:由于只需要一个长度为 26 的数组来存储字符出现的位置,空间复杂度为 O(1)。💖实际应用场景这种问题在实际开发中非常常见。例如:在文本处理系统中,我们可能需要查找一段不含重复字符的文本片段,以进行进一步的分析。在数据分析中,类似的思路可以用来寻找交易记录中的最长不重复行为序列。在爬虫等系统中,处理不同网页路径的去重问题时,字符串处理的高效算法也至关重要。😄总结求解最长不含重复字符的子字符串的问题,关键在于使用滑动窗口技术和哈希表来跟踪字符的最近出现位置,避免重复字符的出现,从而实现高效的解决方案。通过一次遍历,我们能够找到字符串中最长的不含重复字符的子字符串,并返回其长度。这种方法不仅减少了时间复杂度到 O(n),而且代码结构简洁,易于理解和实现。滑动窗口的思想广泛应用于各种字符串处理问题中,不仅限于这道题目,还可以拓展到其他场景。在实际应用中,处理字符串、文本或序列中的重复字符问题非常常见,无论是数据清理、爬虫去重还是用户行为分析,掌握这类高效的算法对于开发和优化系统具有重要意义。通过这道题,我们也可以更好地理解如何通过空间换时间的技巧来优化算法的性能,并学会利用数组或哈希表等工具来记录状态信息,使得问题可以在线性时间内高效解决。
-
【问题来源】 重庆银行(易云)【问题简要】 IVR以GSL的方式开发,只放音不收号的cell需要使用哪个cell怎么配置【问题类别】【必填】 IVR-GSL【AICC解决方案版本】【必填】 AICC可选择版本:AICC 23.200 【UAP可选择版本:V300R001C02SPC109】 【CTI可选择版本:V300R008C25SPC019】【期望解决时间】 尽快【问题现象描述】【必填】 IVR以GSL的方式开发,只放音不收号(也就是放音的时候不被打断)的cell需要使用哪个cell怎么配置
-
系统为ubuntu18.04.6 arm架构、版卡为atlas200,芯片为310,cann版本已升级为最新版本6.0.1、驱动为21.0.2,RC模式npu-smi infopytorch的模型转onnx,用atc工具将onnx转成om模型,atc --model=./model.onnx --framework=5 --output=./model --soc_version=Ascend310报错trans_cast算子转换失败,如下:
-
在将segformer-b0算法模型转OM后,在MDC300F MINI上推理耗时1000ms。ONNX中MatMul算子的输入数据的shape带batch维度,将算子的type类型更改为 BatchMatMul后,转OM时,发现MatMul算子前后各出现一个trans_TransData算子。通过profiling计算算子耗时,发现TransposeD、ArgMaxD、TransData、SoftmaxV2、BatchMatMul占用大量的推理时间。请问如何避免带batch维度的MatMul产生TransData算子?针对现在算子耗时,有什么优化的方法吗?
-
import mindspore from mindspore import nn from mindspore import common from mindspore import Model import mindspore.dataset as ds from mindspore import context import matplotlib.pyplot as plt import mindspore.dataset.vision.c_transforms as CV from mindspore import dtype as mstype import numpy as np from mindspore.common.initializer import Normal from mindspore.train.callback import ModelCheckpoint,CheckpointConfig from mindspore.nn.metrics import Accuracy import mindspore.ops as ops from mindspore.train.callback import LossMonitorcontext.set_context(mode=context.PYNATIVE_MODE,device_target='CPU') #上下文处理#数据预处理def create_dataset(datasets_dir,batch_size,training=False): datasets = ds.ImageFolderDataset(dataset_dir=datasets_dir,shuffle=True, class_indexing={ 'ants':0, 'bees':1 }) image_size =64 mean = [0.485*255, 0.456*255, 0.406*255] #平均值 std = [0.229*255, 0.224*255, 0.225*255] # 方差 if training: # 训练模式下的数据预处理操作 trans = [ CV.RandomCropDecodeResize(image_size, scale=(0.08, 1.0), ratio=(0.75, 1.333)), # 随机裁剪、解码和调整大小 CV.RandomHorizontalFlip(prob=0.5), # 以 50% 的概率进行水平翻转 CV.Normalize(mean, std), # 标准化图像 CV.HWC2CHW() # 将图像从 HWC 格式转换为 CHW 格式 ] else: # 验证模式下的数据预处理操作 trans = [ CV.RandomCropDecodeResize(image_size, scale=(0.08, 1.0), ratio=(0.75, 1.333)), # 随机裁剪、解码和调整大小 CV.RandomHorizontalFlip(prob=0.5), # 以 50% 的概率进行水平翻转 CV.Normalize(mean, std), # 标准化图像 CV.HWC2CHW() # 将图像从 HWC 格式转换为 CHW 格式 ] datasets=datasets.map(operations=trans,input_columns='image') datasets=datasets.batch(batch_size,drop_remainder=True) datasets=datasets.repeat(3) if training: data = next(datasets.create_dict_iterator()) images = data['image'] print(images.shape) labels = data['label'] print('Tensor of image',images.shape) print('Labels:',labels) class_name = {0:'ants',1:'bees'} plt.figure(figsize=(18,7)) for i in range(len(labels)): data_image = images[i].asnumpy() # print(data_image.shape) data_label = labels[i] data_image = np.transpose(data_image,(1,2,0)) #(3,224,224)转为(224,224,3) mean =np.array([0.485,0.456,0.406]) std = np.array([0.229,0.224,0.225]) data_iamge = std *data_image+mean #标准化操作。 data_image = np.clip(data_image,0,1) #这个操作是为了确保图像数据的像素值范围正确。 plt.subplot(3,6,i+1) plt.imshow(data_image) plt.title(class_name[int(labels[i].asnumpy())]) plt.axis('off') #用于禁止绘制图像时显示坐标轴 plt.show() ds.config.set_seed(58) return datasets#数据集的路径train_dir = './datasets/hymenoptera_data/train' test_dir = './datasets/hymenoptera_data/val'#生成数据集train_dataset=create_dataset(datasets_dir=train_dir,batch_size=10,training=True) test_dataset=create_dataset(datasets_dir=test_dir,batch_size=10)#网络搭建class MyNetwork(nn.Cell): def __init__(self): super(MyNetwork, self).__init__() self.conv1 = nn.Conv2d(3, 32, kernel_size=2,pad_mode='valid') self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2) self.conv2 = nn.Conv2d(32, 64, kernel_size=2,pad_mode='valid') self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2) self.conv3 = nn.Conv2d(64,128,kernel_size=2,pad_mode='valid') self.pool3 = nn.MaxPool2d(kernel_size=2, stride=2) self.flatten = nn.Flatten() self.fc1 = nn.Dense(6272,512,weight_init=Normal(0.02)) self.fc2 = nn.Dense(512,256,weight_init=Normal(0.02)) self.fc3 = nn.Dense(256,128,weight_init=Normal(0.02)) self.fc4 = nn.Dense(128,2,weight_init=Normal(0.02)) self.relu = nn.ReLU() def construct(self, x): x = ops.Cast()(x, mstype.float32) x = self.conv1(x) x = self.relu(x) x = self.pool1(x) x = self.conv2(x) x = self.relu(x) x = self.pool2(x) x = self.conv3(x) x = self.relu(x) x = self.pool3(x) x = self.flatten(x) x = self.fc1(x) x = self.relu(x) x = self.fc2(x) x = self.relu(x) x = self.fc3(x) x = self.relu(x) x = self.fc4(x) return x #网络调用和模型训练net = MyNetwork() loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=True,reduction='mean')#定义损失函数 optimizer = nn.SGD(net.trainable_params(),learning_rate=1e-1) #定义优化器 config_ck = CheckpointConfig(save_checkpoint_steps=100, keep_checkpoint_max=10)#配置检查点的保存参数 ckpoint_cb = ModelCheckpoint(prefix="checkpoint", directory="./checkpoints", config=config_ck)#训练过程中保存模型的检查点 loss_cb = LossMonitor(per_print_times=1000)metrics = {'Accuracy':Accuracy()} #定义准确率 epoch = 20#训练轮次 model = Model(net,loss_fn,optimizer,metrics)#模型定义 print("============== 开始训练 ==============") bast_accuracy=0.0 for i in range(epoch): model.train(epoch=epoch,train_dataset=train_dataset,callbacks=[ckpoint_cb,loss_cb])#模型训练 metrics = model.eval(test_dataset) test_accuracy = metrics['Accuracy'] print(f'第{i + 1}轮训练后,测试集准确率: {test_accuracy}') if test_accuracy>=0.80: print(f'准确率达到 {test_accuracy},退出训练。') break if test_accuracy>bast_accuracy: bast_accuracy=test_accuracy mindspore.save_checkpoint(net, "model.ckpt") print("Saved Model to model.ckpt") print('准确度为:',bast_accuracy) 这是一个分类模型,用的是自己设计的卷积神经网络,数据是一个二分类的,现在这个模型只能跑到0.70,无法达到老师要求的0.90以上,我想知道怎么调优,大佬是怎么设计网络结构的
-
一、模型在线部署深度学习和计算机视觉方向除了算法训练/研究,还有两个重要的方向: 模型压缩(模型优化、量化)、模型部署(模型转换、后端功能SDK开发)。所谓模型部署,即将算法研究员训练出的模型部署到具体的端边云芯片平台上,并完成特定业务的视频结构化应用开发。现阶段的平台主要分为云平台(如英伟达 GPU)、手机移动端平台(ARM 系列芯片)和其他嵌入式端侧平台(海思 3519、安霸 CV22、地平线 X3、英伟达 jetson tx2 等芯片)。对于模型部署/移植/优化工程师来说,虽然模型优化、量化等是更有挑战性和技术性的知识,但是对于新手的我们往往是在做解决模型无法在端侧部署的问题,包括但不限于:实现新 OP、修改不兼容的属性、修改不兼容的权重形状、学习不同芯片平台的推理部署框架等。对于模型转换来说,现在行业主流是使用 Caffe 和 ONNX 模型作为中间模型。1.1,深度学习项目开发流程在高校做深度学习 demo 应用一般是这样一个过程,比如使用 Pytorch/TensorFlow 框架训练出一个模型,然后直接使用 Pytorch 框架做推理(test)完成功能验证,但是在工业界这是不可能的,因为这样模型推理速度很慢,一般我们必须有专门的深度学习推理加速框架去做模型推理(inference)。以 GPU 云平台推理框架 TensorRT 为例,简单描述模型训练推理过程就是:训练好网络模型(权重参数数据类型为 FP32)输入 TensorRT,然后 TensorRT 做解析优化,并进行在线推理和输出结果。两种不同的模型训练推理过程对比如下图所示: 前面的描述较为简单,实际在工业届,理想的深度学习项目开发流程应该分为三个步骤: 模型离线训练、模型压缩和模型在线部署,后面两个步骤互有交叉,具体详情如下:模型离线训练:实时性低,数据离线且更新不频繁,batchsize 较大,消耗大量 GPU 资源。设计开发模型网络结构;准备数据集并进行数据预处理、EDA 等操作;深度学习框架训练模型:数据增强、超参数调整、优化器选择、训练策略调整(多尺度训练)、TTA、模型融合等;模型测试。模型优化压缩:主要涉及模型优化、模型转换、模型量化和模型编译优化,这些过程很多都在高性能计算推理框架中集成了,各个芯片厂商也提供了相应的工具链和推理库来完成模型优化压缩。实际开发中,在不同的平台选择不同的推理加速引擎框架,比如 GPU 平台选择 TensorRT,手机移动端(ARM)选择 NCNN/MNN,NPU 芯片平台,如海思3519、地平线X3、安霸CV22等则直接在厂商给出的工具链进行模型的优化(optimizer)和压缩。模型优化 Optimizer:主要指计算图优化。首先对计算图进行分析并应用一系列与硬件无关的优化策略,从而在逻辑上降低运行时的开销,常见的类似优化策略其包括:算子融合(conv、bn、relu 融合)、算子替换、常数折叠、公共子表达式消除等。模型转换 Converter:Pytorch->Caffe、Pytorch->ONNX、ONNX模型->NCNN/NPU芯片厂商模型格式(需要踩坑非常多,Pytorch、ONNX、NPU 三者之间的算子要注意兼容)。注意 ONNX 一般用作训练框架和推理框架之间转换的中间模型格式。模型量化 Quantizer:主要指训练后量化(Post-training quantization PTQ);权重、激活使用不同的量化位宽,如速度最快的量化方式 w8a8、速度和精度平衡的量化方式 w8a16。模型编译优化(编译优化+NPU 指令生成+内存优化)Compiler:模型编译针对不同的硬件平台有不同优化方法,与前面的和硬件无关的模型层面的优化不同。GPU平台存在 kernel fusion 方法;而 NPU 平台算子是通过特定二进制指令实现,其编译优化方法包括,卷积层的拆分、卷积核权重数据重排、NPU 算子调优等。模型部署/SDK输出: 针对视频级应用需要输出功能接口的SDK。实时性要求高,数据线上且更新频繁,batchsize 为 1。主要需要完成多模型的集成、模型输入的预处理、非DL算法模块的开发、 各个模块 pipeline 的串联,以及最后 c 接口(SDK)的输出。板端框架模型推理: Inference:C/C++。不同的 NPU 芯片/不同的公司有着不同的推理框架,但是模型的推理流程大致是一样的。包括:输入图像数据预处理、加载模型文件并解析、填充输入图像和模型权重数据到相应地址、模型推理、释放模型资源。这里主要需要学习不同的模型部署和推理框架。pipeline 应用开发: 在实际的深度学习项目开发过程中,模型推理只是其中的基础功能,具体的我们还需要实现多模型的集成、模型输入前处理、以及非 DL 算法模块的开发: 包括检测模块、跟踪模块、选帧模块、关联模块和业务算法模块等,并将各模块串联成一个 pipeline,从而完成视频结构化应用的开发。SDK集成: 在完成了具体业务 pipeline 的算法开发后,一般就需要输出 c 接口的 SDK 给到下层的业务侧(前后端)人员调用了。这里主要涉及 c/c++ 接口的转换、pipeline 多线程/多通道等sample的开发、以及大量的单元、性能、精度、稳定性测试。芯片平台板端推理 Inference,不同的 NPU 芯片有着不同的 SDK 库代码,但是模型运行流程类似。不同平台的模型的编译优化是不同的,比如 NPU 和一般 GPU 的区别在于后端模型编译上,GPU 是编译生成 kernel library(cuDNN 函数),NPU 是编译生成二进制指令;前端的计算图优化没有本质区别,基本通用。所以综上所述,深度学习项目开发流程可以大致总结为三个步骤: 模型离线训练、模型优化压缩和模型部署/SDK输出,后两个步骤互有交叉。前面 2 个步骤在 PC 上完成,最后一个步骤开发的代码是需要在在 AI 芯片系统上运行的。最后以视差模型在海思 3519 平台的部署为例,其模型部署工作流程如下: 1.2,模型训练和推理的不同为了更好进行模型优化和部署的工作,需要总结一下模型推理(Inference)和训练(Training)的不同:网络权重值固定,只有前向传播(Forward),无需反向传播,因此:模型权值和结构固定,可以做计算图优化,比如算子融合等;输入输出大小固定,可以做 memory 优化,比如 feature 重排和 kernel 重排。batch_size 会很小(比如 1),存在 latency 的问题。可以使用低精度的技术,训练阶段要进行反向传播,每次梯度的更新是很微小的,需要相对较高的精度比如 FP32 来处理数据。但是推理阶段,对精度要求没那么高,现在很多论文都表明使用低精度如 in16 或者 int8 数据类型来做推理,也不会带来很大的精度损失。二、手机端CPU推理框架的优化对于 HPC 和软件工程师来说,在手机 CPU 端做模型推理框架的优化,可以从上到下考虑:算法层优化:最上面就是算法层,如可以用winograd从数学上减少乘法的数量(仅在大channel尺寸下有效);框架优化:推理框架可以实现内存池、多线程等策略;硬件层优化:主要包括: 适应不同的硬件架构特性、pipeline和cache优化、内存数据重排、NEON 汇编优化等。转自:cid:link_0
-
多模态方法种类多模态深度学习是指将来自不同感知模态的信息(如图像、文本、语音等)融合到一个深度学习模型中,以实现更丰富的信息表达和更准确的预测。在多模态深度学习中,模型之间的融合通常有以下三种方法: 模态联合学习(Multimodal Joint Learning):模态联合学习是一种联合训练的方法,将来自不同模态的数据输入到一个模型中,模型可以同时学习到多个模态的特征表示,并将这些特征表示融合在一起进行决策。这种方法的优点是可以充分利用多个模态的信息,但是需要同时训练多个模型,计算复杂度较高。跨模态学习(Cross-Modal Learning):跨模态学习是一种将一个模态的特征转换为另一个模态的特征表示的方法。这种方法的目的是通过跨模态学习,学习到多个模态之间的映射关系,并将不同模态的信息融合在一起。例如,可以使用图像的特征表示来预测文本的情感极性。这种方法可以减少训练时间和计算复杂度,但是需要预先确定好模态之间的映射关系。多模态自监督学习(Multimodal Self-Supervised Learning):多模态自监督学习是一种无需标注数据,通过模型自身学习来提取多个模态的特征表示的方法。这种方法的优点是可以利用大量未标注的数据进行训练,但是需要设计一些自监督任务来引导模型学习多模态的特征表示。例如,可以通过学习视觉音频同步、图像文本匹配等任务来进行多模态自监督学习。总的来说,这三种方法都可以用于多模态深度学习中模型之间的融合,具体选择哪一种方法需要根据具体的任务和数据情况进行决策。多模态深度学习模型的方法和相关论文的详细说明模态联合学习(Multimodal Joint Learning):模态联合学习是一种将多个模态的信息融合在一个模型中进行联合训练的方法。这种方法的研究背景是,现实生活中的很多任务需要同时利用多个感知模态的信息,例如语音识别、人脸识别、情感分析等。模态联合学习的目的是在一个统一的框架下,将来自不同模态的信息进行融合,提高任务的表现。一篇典型的使用模态联合学习方法的论文是2018年的“Multi-Modal Deep Learning for Robust RGB-D Object Recognition”,作者提出了一种基于深度学习的多模态目标识别方法。该方法使用了一个深度卷积神经网络(CNN)和一个多层感知器(MLP)组成的多模态模型来处理来自RGB-D传感器的数据。具体地,CNN用于处理RGB图像,MLP用于处理深度图像,两个模型的输出在特征层级别进行融合。实验结果表明,该方法相对于单模态方法和其他多模态方法具有更好的识别性能。跨模态学习(Cross-Modal Learning):跨模态学习是一种将一个模态的特征转换为另一个模态的特征表示的方法。这种方法的研究背景是,现实生活中的不同感知模态之间存在着复杂的关联性和相互依赖性。跨模态学习的目的是学习到不同模态之间的映射关系,实现跨模态信息的转换和融合。一篇典型的使用跨模态学习方法的论文是2018年的“Image Captioning with Semantic Attention”,作者提出了一种基于卷积神经网络(CNN)和长短时记忆网络(LSTM)的图像描述模型。该模型首先使用CNN提取图像的特征表示,然后使用LSTM生成对图像的描述。在生成描述时,模型还使用了一个注意力机制,将图像中的重要区域与生成的文本序列进行对齐。实验结果表明,该方法相对于其他方法具有更好的描述性能,能够生成更准确和更生动的图像描述。多模态自监督学习(Multimodal Self-Supervised Learning):多模态自监督学习是一种无需标注数据,通过模型自身学习来提取多个模态的特征的方法。这种方法的研究背景是,现实生活中的很多任务需要大量标注数据才能进行训练,但标注数据的获取成本很高。多模态自监督学习的目的是通过模型自身学习来利用未标注的数据,提高模型的泛化性能。一篇典型的使用多模态自监督学习方法的论文是2020年的“Unsupervised Learning of Multimodal Representations with Deep Boltzmann Machines”,作者提出了一种基于深度玻尔兹曼机(DBM)的无监督多模态特征学习方法。该方法使用了两个DBM分别处理来自图像和文本的数据,并在两个DBM之间添加了一个嵌入层,将图像和文本的特征进行融合。在训练过程中,模型使用了对比散度(CD)算法进行参数更新。实验结果表明,该方法相对于其他无监督方法和有监督方法具有更好的多模态特征表示能力。综上所述,多模态深度学习的三种方法分别是魔胎联合学习、跨模态学习和多模态自监督学习。这些方法的研究背景、目的、使用的方法和相关论文都有所不同。在实际应用中,研究人员可以根据具体任务和数据特点选择适合的方法,并根据需要对方法进行改进和扩展。多模态方法实现可以使用PaddlePaddle深度学习框架实现多模态深度学习的三种方法。下面是三种方法的简单实现说明。模态联合学习模态联合学习是将不同模态的特征提取网络联合在一起,以共同学习任务特征的方法。在PaddlePaddle中可以使用PaddleHub提供的预训练模型完成模态联合学习,例如使用PaddleHub提供的图像分类和文本分类模型,分别获得图像和文本的特征表示,然后将这些特征表示合并在一起,用于进行多模态任务的学习和预测。以下是基于PaddleHub实现的示例代码:import paddlehub as hub # 加载图像分类模型 image_classifier = hub.Module(name="resnet50_vd") # 加载文本分类模型 text_classifier = hub.Module(name="ernie") # 分别对图像和文本进行特征提取 image_feature = image_classifier.feature(input_images) text_feature = text_classifier.feature(input_texts) # 将图像和文本的特征表示合并在一起 multimodal_feature = paddle.concat([image_feature, text_feature], axis=-1) # 使用多模态特征进行任务学习和预测跨模态学习跨模态学习是将不同模态的数据映射到共同的空间中,以便可以使用相同的特征提取器和分类器进行训练和预测。在PaddlePaddle中可以使用自定义模型实现跨模态学习。以下是一个基于PaddlePaddle实现的跨模态学习的示例代码:import paddle # 定义图像模态的特征提取器 image_feature_extractor = paddle.nn.Sequential( paddle.nn.Conv2D(...), paddle.nn.BatchNorm2D(...), paddle.nn.ReLU(), ... ) # 定义文本模态的特征提取器 text_feature_extractor = paddle.nn.Sequential( paddle.nn.Embedding(...), paddle.nn.LSTM(...), ... ) # 定义特征融合层 fusion_layer = paddle.nn.Sequential( paddle.nn.Linear(...), paddle.nn.ReLU(), ... ) # 定义分类器 classifier = paddle.nn.Linear(...) # 定义跨模态学习模型 class CrossModalModel(paddle.nn.Layer): def __init__(self): super().__init__() self.image_feature_extractor = image_feature_extractor self.text_feature_extractor = text_feature_extractor self.fusion_layer = fusion_layer self.classifier = classifier def forward(self, image_data, text_data): image_feature = self.image_feature_extractor(image_data) text_feature = self.text_feature_extractor(text_data) fused_feature = self.fusion_layer(paddle.concat([image_feature, text_feature], axis=-1)) output = self.classifier(fused_feature) return output # 使用跨模态学习模型进行任务学习和预测多模态自监督学习多模态自监督学习是一种利用多模态数据自身特点设计的自监督学习方法,通常不需要标注数据。在PaddlePaddle中可以使用PaddleClas提供的模型进行多模态自监督学习,例如使用PaddleClas提供的SimCLR模型,该模型使用数据增强和对比学习方法进行多模态特征学习,以提高模型在多模态数据上的表现。以下是一个基于PaddleClas实现的多模态自监督学习的示例代码:import paddle import paddlehub as hub from paddle.io import DataLoader from paddle.vision.transforms import transforms from paddle.vision.datasets import ImageNet, Cifar10 # 定义图像数据集的预处理器 image_transforms = transforms.Compose([ transforms.Resize((224, 224)), transforms.Normalize(...), ... ]) # 加载图像数据集 image_dataset = ImageNet(..., transform=image_transforms) # 加载文本数据集 text_dataset = ... # 定义数据加载器 batch_size = 64 image_data_loader = DataLoader(image_dataset, batch_size=batch_size) text_data_loader = DataLoader(text_dataset, batch_size=batch_size) # 加载SimCLR模型 simclr = hub.Module(name="simclr") # 使用多模态数据进行自监督学习 for image_data, text_data in zip(image_data_loader, text_data_loader): # 将图像和文本数据进行拼接 multimodal_data = paddle.concat([image_data, text_data], axis=0) # 进行数据增强 augmented_data = simclr.augment(multimodal_data) # 获取特征表示 features = simclr(multimodal_data) # 计算对比损失 loss = simclr.contrastive_loss(features, augmented_data) # 反向传播更新模型参数 loss.backward()转自:cid:link_0
上滑加载中
推荐直播
-
OpenHarmony应用开发之网络数据请求与数据解析
2025/01/16 周四 19:00-20:30
华为开发者布道师、南京师范大学泰州学院副教授,硕士研究生导师,开放原子教育银牌认证讲师
科技浪潮中,鸿蒙生态强势崛起,OpenHarmony开启智能终端无限可能。当下,其原生应用开发适配潜力巨大,终端设备已广泛融入生活各场景,从家居到办公、穿戴至车载。 现在,机会敲门!我们的直播聚焦OpenHarmony关键的网络数据请求与解析,抛开晦涩理论,用真实案例带你掌握数据访问接口,轻松应对复杂网络请求、精准解析Json与Xml数据。参与直播,为开发鸿蒙App夯实基础,抢占科技新高地,别错过!
回顾中 -
Ascend C高层API设计原理与实现系列
2025/01/17 周五 15:30-17:00
Ascend C 技术专家
以LayerNorm算子开发为例,讲解开箱即用的Ascend C高层API
回顾中
热门标签