资讯

精准传达 • 有效沟通

从品牌网站建设到网络营销策划,从策略到执行的一站式服务

包含FlutterNcnn的词条

NCNN使用总结

关于安装、编译、使用步骤等不在赘述, 官网 有很详细文档

创新互联公司是一家专业提供肥西企业网站建设,专注与成都网站建设、网站建设H5高端网站建设、小程序制作等业务。10年已为肥西众多企业、政府机构等服务。创新互联专业网站建设公司优惠进行中。

使用caffe模型的时候,input部分一定要写成规范格式:

千万别图省事写成如下格式,caffe可以运行没问题,但是转化无法识别,这个ncnn数据结构导致!!!

网络定义的层千万别出现重复情况,一定要规范定义:

千万别写成如下网络,在caffe可以稳定运行,但是ncnn会读取上第一次出现的top层!!!

第一层输出是 concat_out1 ,第二层输出也是 concat_out1 ,当使用 ncnn.extract 会出现错误!!!

这貌似是算作 caffe 的问题,在笔者使用的过程忽略了这一点,干脆算 NCNN 操作里面了。

Batch Normalization 层有个 use_global_stats 参数,这个操作的作用是: 是否使用caffe内部的均值和方差

换句话的意思就是:

--------- true :使用caffe内部的均值和方差,其中方差和均值都是固定的,模型训练好之后,这两个值就固定了。

--------- false :使用当前层计算的方差和均值,这个是不固定的,是在训练过程一直改变,训练好的时候达到最优。

其中 NCNN 默认使用 true 状态,不管是 false 还是 true ,最终都是算作 true

caffe 测试的时候得手动设置为 true

正常来说 ncnn 和 caffe 原版的误差范围在 0.001 左右,我的数据在 0.000X 范围徘徊,如果你的数据精确不到第三个有效数字,那就得检查网络输入精度了。

输入的 substract_mean_normalize 得尽量精确,尤其是归一化的值!!!

假设 0-255 的图像需要归一化到 0-1 :

千万不要写成下面这样,读者可以自己测试,精度差别较大。

这里没有错误点,只有心得点。

看了NCNN的官网给的例子,它是将输出转化为一行数据,然后一个一个的进行处理:

个人感觉使用这种处理小数据还是可以的,本人使用网络输出 100 × 100 × 10 ,这种情况该如何处理?

本人使用处理如下:

NCNN官网有个人问能不能输入和输出多个通道数据,后者已经在上文实现,以下看前者。

图片裁剪等操作对于cnn网络梯度反向传播有什么影响吗?

我的理解如下:

首先,第一个CNN只能包含Conv和Pooling层,否则输出的格式是不能当做下一个CNN的输入的。其次,如果第一个CNN每层的Conv filter数量大于1的话(假设最后一层的filter数为N),第一个CNN的输出shape为 (N, W', H'), 那么下一个CNN的 Conv filter的通道数量必须也是N。所以,这两个CNN从结构原理上其实是同一个CNN,其反向传播的机制跟正常的CNN相同。但是,这里“第一个”CNN是不能用于图像裁剪的,只能做常用的卷积操作来提取特征。

如果要做裁剪的话建议用RPN(Region Proposal Network)+CNN的结构。RPN部分实际上是个回归模型,其目的是裁剪图片提取有效物体(训练目的是使该网络选取和物体大小、实际所在区域无线接近的区域)再输入到CNN进行识别。而RPN和CNN是可以放在一起训练的,具体的可以参考Faster RCNN文献。

C0n+C1n+…Cnn=

你可以这么想:现在有n个球要放到左右两个盒子里,有多少中放法。首先可以这么算:左面的盒子里可能装0个,那就是C0n,也可能装1个,那么就从n个里选一,是C1n......还可能选n个,就是Cnn,由加法原理,加起来就是c0n+c1n+c2n+...+cnn

还可以换一种算法:上面的算法是盒子选球,现在我们让球去选盒子,每个球都有两种选法,由乘法原理,n个球共有2^n种选法

因为同题必同解,所以c0n+c1n+c2n+...+cnn=2^n

Faster R-CNN:使用RPN实时目标检测

论文: Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks

目标检测网络大多依靠 区域生成 (region proposal)算法来假设目标的位置。 R-CNN 是采用 Selective Search 算法来提取(propose)可能的 RoIs(regions of interest) 区域,然后对每个提取区域采用标准 CNN 进行分类。选择性搜索(Selective Search )方法就是在目标对象周围设定2000个形状大小位置不一的候选区域,目标物体在候选区域的可能性还是比较大的。然后对这些区域卷积,找到目标物体,虽然大多数区域都是无用的。与寻找几乎个区域比起来,这种方法要高效的多。

Fast R-CNN ,不在原始图像生成备选区域,而是先整张图片通过卷积网络得到特征图,然后在特征图上使用备选区域算法得到感兴趣的区域在特征图的映射,之后使用 Rol Pool将所有区域变成同样尺寸,大大减少了这些目标检测网络的运行时间,但是区域生成的计算成为整个检测网络的瓶颈。

Faster R-CNN 引入了一个 区域生成网络(Region Proposal Network,RPN) ,该网络与检测网络共享输入图像的卷积特征,从而使接近零时间成本的区域生成成为可能。 RPN是一个全卷积网络,可以同时在每个位置预测目标边界和目标分数。RPN经过端到端的训练,可以生成高质量的区域候选框,然后提供给Fast R-CNN用于检测。

Faster R-CNN 由两个模块组成:第一个模块是区域生成的深度全卷积网络,第二个模块是使用备选区域的Fast R-CNN检测器。整个系统是一个单个的,统一的目标检测网络。使用最近流行的“注意力”机制的神经网络术语,RPN模块告诉Fast R-CNN模块在哪里寻找目标。

针对一张图片,需要获得的输出有:

Faster R-CNN 第一步是采用基于分类任务(如ImageNet)的 CNN 模型作为特征提取器。输入图片表示为 H × W × D 的形式,经过预训练 CNN 模型的处理,得到卷积特征图(conv feature map)。

Faster R-CNN 最早是采用在 ImageNet 训练的 ZF 和 VGG ,其后出现了很多其它权重不同的网络.。如 MobileNet 是一种小型效率高的网络结构,仅有 3.3M 参数;而ResNet-152 的参数量达到了 60M;新网络结构,如 DenseNet 在提高了结果的同时,降低了参数数量。

以 VGG16 为例:

VGG16 图片分类时,输入为 224×224×3 的张量(即,一张 224×224 像素的 RGB 图片)。网络结构最后采用 FC 层(而不是 Conv 层)得到固定长度的向量,以进行图片分类.。对最后一个卷积层的输出拉伸为1维的向量,然后送入 FC 层。官方实现中是采用的卷积层 conv5/conv5_1 的输出。

在深度上,卷积特征图对图片的所有信息进行了编码,同时保持相对于原始图片所编码 “things” 的位置。例如,如果在图片的左上角存在一个红色正方形,而且卷积层有激活响应,那么该红色正方形的信息被卷积层编码后,仍在卷积特征图的左上角。因此利用特征图检测目标所在的位置是可行的。

ResNet 结构逐渐取代 VGG 作为基础网络,用于提取特征。ResNet 相对于 VGG 的明显优势是,网络更大,因此具有更强的学习能力.。这对于分类任务是重要的,在目标检测中也应该如此。另外,ResNet 采用残差连接(residual connection) 和 BN (batch normalization) 使得深度模型的训练比较容易。

然后,RPN(Region Propose Network) 对提取的卷积特征图进行处理,寻找可能包含 目标的 预定义数量的区域(regions,边界框) 。为了生成候选区域,在最后的共享卷积层输出的卷积特征图上做 3x3 卷积,卷积核共有512个(VGG),后面是ReLU,这样每个 3x3 区域会得到一个512维的特征向量。然后这个特征向量被输入到两个全连接层——一个边界框回归层(reg)和一个边界框分类层(cls)。

下面解释 k, 2k, 4k 的含义。

基于深度学习的目标检测中,可能最难的问题就是生成长度不定(variable-length)的边界框列表(bounding-boxes),边界框是具有不同尺寸(sizes)和长宽比(aspect ratios )的矩形。在构建深度神经网络时,最后的网络输出一般是固定尺寸的张量输出(采用RNN的除外)。例如,在图片分类中,网络输出是 (C, ) 的张量,C是类别标签数,张量的每个位置的标量值表示图片是类别的概率值。

在 RPN 中,通过采用 anchors(锚) 来解决边界框列表长度不定的问题,即在原始图像中统一放置固定大小的参考边界框。上面说到RPN对特征图做3x3的卷积,假设每一次卷积需要预测 k 个候选区域,因此,reg层具有 4k 个输出,编码 k 个边界框的坐标,cls层输出 2k 个分数,估计每个区域是目标或是背景的概率。这 k 个区域就是 被 k 个参考边界框初始化, k 个参考框就是 k 个锚点,作为第一次预测目标位置的参考 boxes。锚点的中心位于卷积核滑动窗口的中心。默认情况下每个滑动位置使用3个不同尺度(128 2 , 256 2 , 512 2 )3个不同长宽比(1:2, 1:1, 2:1)的锚点,k=9。对于大小为W×H(通常约为2400)的卷积特征图,总共有 W×H×k 个锚点。对于RPN的最后两个全连接层,参数的个数为 512×(4+2)×k.

不同于直接检测目标的位置,这里将问题转化为两部分。对每一个 anchor 而言:

有一种简单的方法来预测目标的边界框,即学习相对于参考边界框的偏移量。假设参考 box:( ),待预测量:( ),一般都是很小的值,以调整参考 box 更好的拟合所需要的。

虽然 anchors 是基于卷积特征图定义的,但最终的 anchos 是相对于原始图片的.

由于只有卷积层和 pooling 层,特征图的维度是与原始图片的尺寸成比例关系的. 即,数学地表述,如果图片尺寸 w×h,特征图的尺寸则是w/r×h/r. 其中,r 是下采样率(subsampling ratio). 如果在卷积特征图空间位置定义 anchor,则最终的图片会是由 r 像素划分的 anchors 集。在 VGG 中, r=16。

RPN 利用所有的参考边界框(anchors),输出一系列目标的良好的 proposals。针对每个 anchor,都有两个不同的输出:

RPN是全卷积网络。

对于分类层,每个 anchor 输出两个预测值:anchor 是背景(background,非object)的 score 和 anchor 是前景(foreground,object) 的 score.

对于回归层,也可以叫边界框调整层,每个 anchor 输出 4 个预测值:

(Δxcenter,Δycenter,Δwidth,Δheight),用于 anchors 来得到最终的 proposals。根据最终的 proposal 坐标和其对应的 objectness score,即可得到良好的 objects proposals.

RPN 有两种类型的预测值输出:二值分类和边界框回归调整。

为了训练RPN,我们为每个锚点分配一个二值类别标签(是目标或不是目标)。我们给两种锚点分配一个正标签:(i)具有与实际边界框的重叠最高交并比(IoU)的锚点,或者(ii)具有与实际边界框的重叠超过0.7 IoU的锚点。注意,单个真实边界框可以为多个锚点分配正标签。通常第二个条件足以确定正样本;但我们仍然采用第一个条件,因为在一些极少数情况下,第二个条件可能找不到正样本。对于所有的真实边界框,如果一个锚点的IoU比率低于0.3,我们给非正面的锚点分配一个负标签。既不正面也不负面的锚点不会有助于训练目标函数。

然后,随机采样 anchors 来生成batchsize=256 的 mini-batch,尽可能的保持 foreground 和 background anchors 的比例平衡。

RPN 对 mini-batch 内的所有 anchors 采用二分类交叉熵来计算分类 loss。然后,只对 mini-batch 内标记为 foreground 的 anchros 计算回归 loss。为了计算回归的目标targets,根据 foreground anchor 和其最接近的 groundtruth object,计算将 anchor 变换到 object groundtruth 的偏移值 Δ。

Faster R-CNN没有采用简单的 L1 或 L2 loss 用于回归误差,而是采用 Smooth L1 loss. Smooth L1 和 L1 基本相同,但是,当 L1 误差值非常小时,表示为一个确定值即认为是接近正确的,loss 就会以更快的速度消失.

由于 Anchors 一般是有重叠,因此,相同目标的候选区域也存在重叠。

为了解决重叠 proposals 问题,采用 NMS 算法处理,丢弃与一个 score 更高的 proposal 间 IoU 大于预设阈值的 proposals.

虽然 NMS 看起来比较简单,但 IoU 阈值的预设需要谨慎处理. 如果 IoU 值太小,可能丢失 objetcs 的一些 proposals;如果 IoU 值过大,可能会导致 objects 出现很多 proposals。IoU 典型值为 0.7。

NMS 处理后,根据 sore 对topN 个 proposals 排序. 在 Faster R-CNN 论文中 N=2000,其值也可以小一点,如 50,仍然能的高好的结果.

当获得了可能的相关目标和其在原始图像中的对应位置之后,问题就更加直接了,采用 CNN 提取的特征和包含相关目标的边界框,采用 RoI Pooling 处理,并提取相关目标的特征,得到一个新的向量。

RPN 处理后,可以得到一堆没有分类得分的目标 proposals。待处理问题为,如何利用这些边界框并分类。

一种最简单的方法是,对每个 porposal,裁剪,并送入pre-trained base 网络,提取特征;然后,将提取特征来训练分类器. 但这就需要对所有的 2000 个 proposals 进行计算,效率低,速度慢。Faster R-CNN通过重用卷积特征图来加快计算效率,即采用 RoI(region of interest) Pooling 对每个 proposal 提取固定尺寸的特征图。然后 R-CNN 对固定尺寸的特征图分类。

目标检测中,包括 Faster R-CNN,常用一种更简单的方法,即:采用每个 proposal 来对卷积特征图裁剪crop,然后利用插值算法(一般为双线性插值 bilinear)将每个 crop resize 到固定尺寸14×14×ConvDepth. 裁剪后,利用 2×2 kernel 的 Max Pooling 得到每个 proposal 的最终7×7×ConvDepth 特征图.

之所以选择该精确形状,与其在下面的模块(R-CNN)中的应用有关。

R-CNN利用RoI Pooling提取的特征进行分类,采用全连接层来输出每个可能的 目标类别的分类得分,是Faster R-CNN框架中的最后一个步骤。

R-CNN 有两个不同的输出:

R-CNN 对每个 proposal 的特征图,拉平后采用 ReLU 和两个大小为 4096 维的全连接层进行处理。然后,对每个不同目标采用两个不同的全连接层处理:一个全连接层有 N+1 个神经单元,其中 N 是类别 class 的总数,包括 background class;一个全连接层有 4N 个神经单元,是回归预测输出,得到 N 个可能的类别分别预测 Δcenterx,Δcentery,Δwidth,Δheight。

R-CNN 的目标基本上是与 RPN 目标的计算是一致的,但需要考虑不同的可能的 object 类别 classes.

根据 proposals 和 ground-truth boxes,计算其 IoU。与任何一个 ground-truth box 的 IoU 大于 0.5 的 proposals 被设为正确的 boxes。IoU 在 0.1 到 0.5 之间时设为 background。这里忽略没有任何交叉的 proposals。这是因为,在此阶段,假设已经获得良好的 proposals。当然,所有的这些超参数都是可以用于调整以更好的拟合 objects。

边界框回归的目标计算的是 proposal 与其对应的 ground-truth间的偏移量,只对基于 IoU 阈值设定类别后的 proposals 进行计算。随机采用一个平衡化的 mini-batch=64,其中,25% 的 foreground proposals(具有类别class) 和 75% 的background proposals.

类似于 RPNs 的 losses,对于选定的 proposals,分类 loss 采用 multiclass entropy loss;对于 25% 的 foreground proposals 采用 SmoothL1 loss 计算其与 groundtruth box 的匹配。

由于 R-CNN全连接网络对每个类别仅输出一个预测值,当计算边框回归loss 时需谨慎,只需考虑正确的类别。

类似于 RPN,R-CNN 最终输出一堆带有类别分类的objects,在返回结果前,再进一步进行处理。

为了调整边界框,需要考虑概率最大的类别的 proposals. 忽略概率最大值为 background class 的proposals.

当得到最终的 objects 时,并忽略被预测为 background 的结果,采用 class-based NMS. 主要是通过对 objects 根据类别class 分组,然后根据概率排序,并对每个独立的分组采用 NMS 处理,最后再放在一起.

最终得到的 objects 列表,仍可继续通过设定概率阈值的方式,来限制每个类的 objects 数量.

Faster R-CNN在论文中是采用分步方法,对每个模块分别训练再合并训练的权重. 自此,End-to-end 的联合训练被发现能够得到更好的结果.

当将完整的模型合并后,得到 4 个不同的 losses,2 个用于 RPN,2 个用于 R-CNN。4 种不同的 losses 以加权和的形式组织. 可以根据需要对分类 loss 和回归 loss 设置权重,或者对 R-CNN 和 RPNs 设置不同权重.

采用 SGD 训练,momentum=0.9. 学习率初始值为 0.001,50K 次迭代后衰减为 0.0001. 这是一组常用参数设置。

卷积神经网络(CNN)基础

在七月初七情人节,牛郎织女相见的一天,我终于学习了CNN(来自CS231n),感觉感触良多,所以赶快记下来,别忘了,最后祝大家情人节快乐5555555.正题开始!

CNN一共有卷积层(CONV)、ReLU层(ReLU)、池化层(Pooling)、全连接层(FC(Full Connection))下面是各个层的详细解释。

卷积,尤其是图像的卷积,需要一个滤波器,用滤波器对整个图像进行遍历,我们假设有一个32*32*3的原始图像A,滤波器的尺寸为5*5*3,用w表示,滤波器中的数据就是CNN的参数的一部分,那么在使用滤波器w对A进行滤波的话,可以用下面的式子表示:

其中x为原始图像的5*5*3的一部分,b是偏置项置为1。在对A进行滤波之后,产生的是一个28*28*1的数据。那么假设我们存在6个滤波器,这六个滤波器之间彼此是独立的,也就是他们内部的数据是不同的且没有相关性的。可以理解为一个滤波器查找整幅图像的垂直边缘,一个查找水平边缘,一个查找红色,一个查找黑色这样。那么我就可以产生6个28*28*1的数据,将它们组合到一起就可以产生28*28*6的数据,这就是卷积层主要做的工作。

CNN可以看作一系列的卷积层和ReLU层对原始数据结构进行处理的神经网络,处理的过程可以用下面这幅图表示

特别要注意的是滤波器的深度一定要与上一层传来的数据的深度相同,就像上图的第二个卷积层在处理传来的28*28*6的数据时要使用5*5*6的滤波器.

滤波器在图像上不断移动对图像滤波,自然存在步长的问题,在上面我们举的例子都是步长为1的情况,如果步长为3的话,32*32*3的图像经过5*5*3的滤波器卷积得到的大小是(32-5)/3+1=10, 注:步长不能为2因为(32-5)/2+1=14.5是小数。

所以当图像大小是N,滤波器尺寸为F时,步长S,那么卷积后大小为(N-F)/S+1

我们从上面的图中可以看到图像的长和宽在逐渐的减小,在经过超过5层之后极可能只剩下1*1的空间尺度,这样是十分不好的,而且也不利于我们接下来的计算,所以我们想让卷积层处理完之后图像在空间尺度上大小不变,所以我们引入了pad the border的操作。pad其实就是在图像周围补0,扩大图像的尺寸,使得卷积后图像大小不变。在CNN中,主要存在4个超参数,滤波器个数K,滤波器大小F,pad大小P和步长S,其中P是整数,当P=1时,对原始数据的操作如图所示:

那么在pad操作后卷积后的图像大小为:(N-F+2*P)/S+1

而要想让卷积层处理后图像空间尺度不变,P的值可以设为P=(F-1)/2

卷积层输入W 1 *H 1 *D 1 大小的数据,输出W 2 *H 2 *D 2 的数据,此时的卷积层共有4个超参数:

K:滤波器个数

P:pad属性值

S:滤波器每次移动的步长

F:滤波器尺寸

此时输出的大小可以用输入和超参计算得到:

W 2 =(W 1 -F+2P)/S+1

H 2 =(H 1 -F+2P)/S+1

D 2 =D 1

1*1的滤波器也是有意义的,它在深度方向做卷积,例如1*1*64的滤波器对56*56*64的数据卷积得到56*56的数据

F通常是奇数,这样可以综合考虑上下左右四个方向的数据。

卷积层从神经元的角度看待可以有两个性质: 参数共享和局域连接 。对待一个滤波器,例如5*5*3的一个滤波器,对32*32*3的数据卷积得到28*28的数据,可以看作存在28*28个神经元,每个对原图像5*5*3的区域进行计算,这28*28个神经元由于使用同一个滤波器,所以参数相同,我们称这一特性为 参数共享 。

针对不同的滤波器,我们可以看到他们会看到同一区域的图像,相当于在深度方向存在多个神经元,他们看着相同区域叫做 局域连接

参数共享减少了参数的数量,防止了过拟合

局域连接为查找不同特征更丰富的表现图像提供了可能。

卷积就像是对原图像的另一种表达。

激活函数,对于每一个维度经过ReLU函数输出即可。不改变数据的空间尺度。

通过pad操作,输出图像在控件上并没有变化,但是深度发生了变化,越来越庞大的数据给计算带来了困难,也出现了冗余的特征,所以需要进行池化操作,池化不改变深度,只改变长宽,主要有最大值和均值两种方法,一般的池化滤波器大小F为2步长为2,对于最大值池化可以用下面的图像清晰的表示:

卷积层输入W 1 *H 1 *D 1 大小的数据,输出W 2 *H 2 *D 2 的数据,此时的卷积层共有2个超参数:

S:滤波器每次移动的步长

F:滤波器尺寸

此时输出的大小可以用输入和超参计算得到:

W 2 =(W 1 -F)/S+1

H 2 =(H 1 -F)/S+1

D 2 =D 1

将最后一层(CONV、ReLU或Pool)处理后的数据输入全连接层,对于W 2 *H 2 *D 2 数据,我们将其展成1*1*W 2 *H 2 *D 2 大小的数据,输入层共有W 2 *H 2 *D 2 个神经元,最后根据问题确定输出层的规模,输出层可以用softmax表示。也就是说,全连接层就是一个常见的BP神经网络。而这个网络也是参数最多的部分,是接下来想要去掉的部分。完整的神经网络可以用下面的图表示:

[(CONV-ReLU)*N-POOL?]*M-(FC-RELU)*K,SoftMax

1.更小的滤波器与更深的网络

2.只有CONV层而去掉池化与全链接

最早的CNN,用于识别邮编,结构为:

CONV-POOL-CONV-POOL-CONV-FC

滤波器大小5*5,步长为1,池化层2*2,步长为2

2012年由于GPU技术所限,原始AlexNet为两个GPU分开计算,这里介绍合起来的结构。

输入图像为227*227*3

1.首次使用ReLU

2.使用Norm layers,现在已经抛弃,因为效果不大

3.数据经过预处理(例如大小变化,颜色变化等)

4.失活比率0.5

5.batch size 128

6.SGD Momentum 参数0.9(SGD和Momentum见我的其他文章)

7.学习速率 0.01,准确率不在提升时减少10倍,1-2次后达到收敛

8.L2权重减少0.0005

9.错误率15.4%

改进自AlexNet,主要改变:

1.CONV1的滤波器从11*11步长S=4改为7*7步长为2.

2.CONV3,4,5滤波器数量有384,384,256改为512,1024,512(滤波器数量为2的n次幂有利于计算机计算可以提高效率)

错误率:14.8%后继续改进至11.2%

当前最好的最易用的CNN网络,所有卷积层滤波器的大小均为3*3,步长为1,pad=1,池化层为2*2的最大值池化,S=2。

主要参数来自全连接层,这也是想要去掉FC的原因。

具有高度的统一性和线性的组合,易于理解,十分方便有VGG-16,VGG-19等多种结构。

错误率7.3%

完全移除FC层,参数只有500万,使用Inception模块(不太理解,有时间继续看)

准确率6.67%

准确率3.6%

拥有极深的网络结构,且越深准确率越高。是传统CNN不具备的特点,传统CNN并非越深越准确。需要训练时间较长但是快于VGG

1.每个卷积层使用Batch Normalization

2.Xavier/2初始化

3.SGD+Momentum(0.9)

4.Learning rate:0.1,准确率不变减小10倍(因为Batch Normalization所以比AlexNet大)

5.mini-batch size 256

6.Weight decay of 0.00001

7.不适用失活(因为Batch Normalization)

具体的梯度过程学完ResNet再说吧。

浅尝ncnn优化&&vulkan api的应用

1. [c,h,w] 这种布局不太适合在GPU上做IO:[c, h, w] --- [c/4, h, w, 4]


分享名称:包含FlutterNcnn的词条
标题路径:http://cdkjz.cn/article/dssgjce.html
多年建站经验

多一份参考,总有益处

联系快上网,免费获得专属《策划方案》及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

业务热线:400-028-6601 / 大客户专线   成都:13518219792   座机:028-86922220