• [技术干货] MindSpore图片分类之LeNet网络卷积原理
    1. 摘要本系列分享我们将一起理解MindSpore官网中展示的MNIST图片数据集分类项目。此项目中使用的是LeNet卷积神经网络,卷积神经网络(convolutional neural network)是含有卷积层(convolutional layer)的神经网络,卷积神经网络均使用最常见的二维卷积层,经常用于处理图像数据的项目中。在LeNet网络中,可分为卷积模块和全连接输出模块。本次我们将介绍卷积计算的工作原理。2. 二维互相关运算首先了解一下卷积核数组在输入数组中的计算方式,虽然卷积层得名于卷积(convolution)运算,但我们通常在卷积层中使用更加直观的互相关(cross-correlation)运算。在二维卷积层中,一个二维输入数组和一个二维核(kernel)数组通过互相关运算输出一个二维数组。这里我们设置一个高和宽均为3的二维输入数组。我们可以将该数组形状记为3×3。核数组的高和宽分别是2。核数组在卷积计算中又称卷积核或过滤器(filter)。卷积核的高和宽决定卷积核窗口的形状,可以记为2×2。在二维互相关运算过程中,卷积窗口将会从输入数组的最左上方开始计算,按照从左到右,从上到下的顺序,依次在输入数组区域内滑动,这里默认情况下卷积核移动的步幅是每次一行或一列。当卷积窗口滑动到输入数组的某一位置时,窗口中的输入子数组与核数组按元素相乘并求和,得到输出数组中相应位置的元素。二维互相关运算得出:0×0+1×1+3×2+4×3=191×0+2×1+4×2+5×3=253×0+4×1+6×2+7×3=374×0+5×1+7×2+8×3=43这就是卷积计算的过程,二维卷积层将输入数组和卷积核做互相关运算,并加上一个标量偏差来得到输出。卷积层的模型参数包括了卷积核和标量偏差。在训练模型的时候,通常我们需要先对卷积核随机初始化,然后再不断迭代卷积核和偏差。实际上,卷积运算与互相关运算是类似的。想要得到卷积运算的输出,我们只需将核数组左右翻转并上下翻转,再与输入数组做互相关运算。所以,卷积运算和互相关运算虽然类似,但如果他们使用相同的核数组和输入数组,输出也并不一定会相同。如果卷积核数组元素在横轴和竖轴上都对称,那么卷积运算和互相关运算结果相同。特征图(feature map)是二维卷积层输出的二维数组可以看作输入空间维度上某一级的表征。影响元素x的前向计算的所有可能输入区域叫做x的感受野(receptive field)。我们可以设置更深的卷积神经网络,那么输入数组通过每一层卷积后,高和宽会渐渐变小,特征图中单个元素的感受野就会变得更加广阔,从而捕捉输入上更大尺寸的特征。3. 填充和步幅3.1 填充填充(padding)是表示在输入高和宽的输入数组两侧填充元素(通常是0元素)。如图2中,我们在输入数组的高和宽的两侧分别添加值为0的元素,每一边新增一层,使得输入高和宽从3变成5,并导致输出高和宽从2变成4。一般卷积情况下,假设输入数组高和宽分别是nh、nw,卷积核数组的高和宽分别是kh、kw,如果在输入数组高的两侧一共填充ph行,在宽的两侧一共填充pw列,那么输出数组形状将会是(nh-kh+ph+1)×(nw-kw+pw+1)这就证明,输出数组的高和宽会分别增加ph和pw。所以,如果想要了解在构造网络时推测每个层的输出形状。我们可以设置ph=kh -1和pw=kw-1使得输入和输出具有相同的高和宽。3.2 步幅步幅是指核数组在输入数组在按照从左到右,从上到下移动过程中,每移动一次核数组跨过的元素行数或列数。目前我们看到的例子里,在高和宽两个方向上步幅均为1。我们也可以使用更大步幅。图3展示了在高上步幅为3、在宽上步幅为2的二维互相关运算。可以看到,输出第一列第二个元素时,卷积窗口向下滑动了3行,而在输出第一行第二个元素时卷积窗口向右滑动了2列。当卷积窗口在输入上再向右滑动2列时,由于输入元素无法填满窗口,无结果输出。图3中的阴影部分为输出元素及其计算所使用的输入和核数组元素。一般来说,当高上步幅为sh,宽上步幅为sw时,输出形状为⌊(nh−kh+ph+sh)/sh⌋×⌊(nw−kw+pw+sw)/sw⌋如果设置ph=kh−1ph=kh−1和pw=kw−1pw=kw−1,那么输出形状可以表示为⌊(nh+sh−1)/sh⌋×⌊(nw+sw−1)/sw⌋更进一步,如果输入的高和宽能分别被高和宽上的步幅整除,那么输出形状将是(nh/sh)×(nw/sw)。填充作用于输出数组的高和宽。这常用来使输出与输入具有相同的高和宽。步幅可以减小输出的高和宽,例如输出的高和宽仅为输入的高和宽的1/n(n为大于1的整数)。4. 多输入通道与多输出通道4.1   多输入通道我们上面用到的输入和输出都是二维数组,但是真实的数据往往维度会更高。例如,彩**片数据集在高和宽的维度外还有RGB(红、绿、蓝)3个颜色通道。假设彩**像的高和宽分别是h和w(像素),那么它可以表示为3×h×w的多维数组。我们将大小为三的这一维称为通道(channel)维。当输入数据含有多个通道时,我们需要构造一个输入通道与输入数据的通道数相同的卷积核,从而能够与含多通道的输入数据做互相关运算。假设输入数据的通道数为ci,那么卷积核的输入通道同样为ci。设卷积核窗口形状为kh×kw。当ci=1时。此时的卷积核是只包含一个形状为kh×kw的二维数组。当ci>1时,每一个输入通道各分配一个形状为kh×kw的核数组。Ci个数组与输入通道维上连结,得到形状为ci×kh×kw的卷积核。此时卷积运算是各个通道上对二维数组和卷积核的二维数组做互相关运算,再将ci个通道的二维输出相加,得到一个二维数组。下面展示的是2个输入通道的二维互相关计算,二维输入数组与二维核数组做互相关运算,再按通道数相加得到输出。(1×1+2×2+4×3+5×4)+(0×0+1×1+3×2+4×3)=564.2 多输出通道通过上面多输入通道的介绍,我们发现对各个通道的结果做累加,无论输入通道数是多少,输出通道总是1。假设输入通道数为ci,想要得到输出通道数为co,我们可以为每个输出通道分别创建形状为ci×kh×kw的核数组。那么此时的卷积核形状为co×ci×kh×kw。在做互相关运算时,每个输出通道上的结果由卷积核在该通道上的核数组与整个输入数组计算得出。1×1卷积层是卷积窗口形状为1×1的多通道卷积层。因为使用了最小窗口,所以1×1卷积是不具有识别高和宽维度上相邻元素构成的模式的功能。1×1卷积主要使用在通道维度上。如图5所示,输入数组形状是3×3×3,卷积核形状为2×3×1×1,我们得到的输出数组形状为2×3×3。输入与输出具有相同的高和宽。输出中的每个元素来自输入中高和宽上相同位置的元素在不同通道之间按权重累加。假设我们将通道维当做特征维,将高和宽维度上的元素当成数据样本,那么1×1卷积层的作用于全连接层等价。使用多通道可以拓展卷积层的模型参数,1×1卷积层通常是用来调整网络层之间的通道数,控制模型的复杂度。5. 总结在卷积计算中,卷积核的使用可以检测图像的边缘,卷积层可以通过重复使用卷积核计算有效地表征局部空间。填充和步幅的主要作用是控住输入数组和输出数组的形状。在多输入通道中,通道数是不可变的,可以使用四维的卷积核数组控制多通道的输出(输出通道数×输入通道数×高×宽),如果输入通道数过多导致模型复杂度很高,可以使用1×1卷积层来调整输出通道,并且不会改变高和宽。————————————————原文链接:https://blog.csdn.net/xi_xiyu/article/details/122681759
  • [技术干货] MindSpore图片分类之LeNet网络池化和全连接
    1. 摘要在上一篇分享中,主要介绍了卷积操作,我们可以通过构造卷积核作用到图像中,对比输入和输出数组就可以精确的找到像素变化的位置。这便是图像物体边缘检测功能。设任意的二维数组X的i行j列的元素为X[i,j]。如果我们构造的卷积核输出Y[i,j]=1,那么说明输入中X[i,j]和X[i,j+1]数值不一样。这可能意味着物体的边缘通过这两个元素之间。在实际图像中,我们要检测的物体不会出现在固定的位置,即使我们连续拍摄同一个物体也会出现偏移。这会导致同一个边缘对应的输出可能出现在卷积输出Y中的不同位置,从而对后面的模式识别造成困难。本片分享我们介绍池化(pooling)层,它的主要作用便是为了缓解卷积层对位置上的过度敏感性。2. 二维最大池化层和平均池化层和卷积计算类似,池化层每一次对输入数组的一个固定形窗口中的元素计算输出。该窗口也称池化窗口。与卷积层的运算法则不同,池化层的法则是直接计算池化窗口元素中的最大值或者平均值。所以也分别叫做最大池化和平均池化。在二维最大池化层中,池化窗口从输入数组的左上角开始,按照从左到右,从上到下的顺序,在输入数组中滑动。当池化窗口滑动到某一个位置时,窗口中的输入子数组的最大值就是输出数组中相应位置的元素。池化的窗口形状是2×2的最大池化,默认步幅都为1。阴影部分为第一个输出元素和计算所使用的输入元素。输出数组的高和宽分别为2,其中的4个元素由取最大值运算max得出:max(0,1,3,4)=4,max(1,2,4,5)=5,max(3,4,6,7)=7,max(4,5,7,8)=8.平均池化层的计算方法与最大池化层类似,只是将每次求池化窗口中的元素最大值改为求平均值。池化窗口形状为p×q的池化层称为p×q池化层,其中的池化运算叫作p×q池化。在最开始我们提到的物体边缘检测的例子。现在我们将卷积层的输出作为2×2最大池化的输入。设该卷积层输入是X、池化层输出为Y。无论是X[i,j]和X[i,j+1]值不同,还是X[i,j+1]和X[i,j+2]不同,池化层输出均有Y[i,j]=1。也就是说,使用2×2最大池化层时,只要卷积层识别的模式在高和宽上移动不超过一个元素,我们依然可以将它检测出来。3. 填充、步幅和多通道和卷积层一样,池化层也可以在输入数组的高和宽两侧填充0元素。并可以设置窗口的移动步幅来改变输出数组形状。池化层填充和步幅与卷积层填充和步幅的工作机制一样。池化层在处理多通道输入数组的时候,与卷积层的工作机制是不同的,卷积层中是将每个通道中的输入数组卷积运算后再相加,会导致输出通道变为1个。而池化层则是在每个出入通道中池化计算,但不将池化结果相加,可以保证输入通道数与输出通道数相同。4. LeNet卷积网络如上图中所示,是LeNet卷积网络的整体流程图,整体包含8个网络层,下面我们将了解每一层的计算。输入层:我们使用的数据集是MNIST数据集,该数据集中的样本数据都是规格为32×32的灰度图,我们以1个样本图片为例。那么我们输入的图片规格就是1×1×32×32,表示一个通道输入1个32×32的数组。C1层:C1层中数组规格为6×1×28×28,从1×1×32×32卷积得到。首先需要6个批次的卷积数组,每一个批次中都有1个规格为5×5的卷积数组,卷积步幅默认为1。即卷积数组规格为6×1×5×5。该卷积层共有6+1×5×5×6=156个参数,其中6个偏置参数。这一层网络**有6×1×28×28=4704个节点,每个节点和当前层5×5=25个节点相连,所以本层卷积层共有6×(1×28×28)×(1×5×5+1)=122304个全连接。S2层:S2层的数组规格为6×1×14×14,从1×1×28×28卷积得到。使用的是2×2,步幅为1的最大池化操作,所以并不改变批次数,只是将每一个输入数组从28×28降到14×14的输出数组。该池化层共有6×2=12个可训练参数,以及6×(1×14×14)×(2×2+1)=5880个全连接。C3层:C3层的数组规格为16×1×10×10,从6×1×14×14卷积得到。输出通道数数改变,所以卷积数组需要16批卷积数组,每一批中有6个卷积核与输入通道对应,每一个卷积数组规格都是5×5,步幅为1。即卷积数组规格为16×6×5×5。该卷积层共有16+1×5×5×16=2416个参数,其中16个偏置参数。这一层网络**有16×1×10×10=1600个节点,每个节点和当前层5×5=25个节点相连,所以本层卷积层共有16×(1×10×10)×(1×5×5+1)=41600个全连接。S4层:S4层的数组规格为16×1×5×5,这一层池化与S2层池化设置相同。所以输出数组只改变每一个数组的规格,不改变数量。该池化层共有16×2=32个可训练参数,以及16×(1×5×5)×(2×2+1)=2000个全连接。C5层:C5层是规格为120×1的一维向量,那么需要将S4层数组转换成一维向量,输入的数组规格是1×(16×1×5×)=1×400。使用全连接层将1×400转为1×120的向量。在全连接层中,每一个节点计算处结果后,都需要再经过激活函数计算,得出的值为输出的值。该连接层共有5×5×16=400个输入节点,参数个数为5×5×16×120+120=48120个,输出节点120个。F6层:F6层是规格为84×1的一维向量,与C5层计算相同,也是通过全连接层计算得到。为什么要转成84个神经元向量呢,如下图中所示,是所有字符标准格式,规格为12×7.所以有84个像素点,然后使用F6层的向量与这些标准图计算相似度。该连接层共有120个输入节点,参数个数为120×84+84=10164个,输出节点84个。输出层:该连接层共有84个输入节点,参数个数为84×10+10=850个,输出节点10个。输出层使用Softmax函数做多分类,在Softmax用于多分类过程中,它将多个神经元的输出,映射到(0,1)区间中,可以看作是每一个类别的概率值,从而实现多分类。Softmax从字面上来看,可以分成Soft和max两部分。Softmax的核心是Soft,对于图片分类来说,一张图片或多或少都会包含其它类别的信息,我们更期待得到图片对于每个类别的概率值,可以简单理解为每一个类别的可信度;max就是最大值的意思,选择概率值最大的当作分类的类别。下面给出Softmax函数的定义其中zi是第i个节点的输出值,C是输出节点的个数,即分类类别的个数。通过Softmax函数可以将多分类的输出值转换为范围在[0,1],并且总和为1的概率分布。当使用Softmax函数作为输出节点的激活函数的时候,一般使用交叉熵作为损失函数。模型有了损失函数后,就可以使用梯度下降的方法求解最优参数值。5. 总结本篇我们主要承接上一次的卷积内容,首先分析了池化操作的运行原理。然后使用LeNet卷积神经网络将一个32×32的灰度图的分类过程,分析了LeNet卷积神经网络网络中每一层之间卷积核信息、池化信息、参数个数、全连接个数,以及最后输出时使用的Softmax函数性质。————————————————原文链接:https://blog.csdn.net/xi_xiyu/article/details/122681854
  • [其他] 再思考图卷积网络的知识图谱补全
    图卷积网络(GCNs)是一种建模图结构的有效方法,它在知识图谱补全(KGC)中越来越受欢迎。基于GCNs的KGC模型首先使用GCNs生成表达实体表示,然后使用知识图嵌入(knowledge graph embedding, KGE)模型捕获实体之间的交互和关系。然而,许多基于GCN的KGC模型未能超过最先进的KGE模型,尽管引入了额外的计算复杂性。这一现象促使我们去探索GCNs在KGC中的真实作用。因此,本文在具有代表性的基于GCNs的KGC模型的基础上,引入变量来找出GCNs在KGC中的关键因子。令人惊讶的是,我们从实验中观察到,GCNs中的图结构建模对KGC模型的性能并没有显著的影响,这与人们普遍认知的相反。相反,实体表示的转换负责性能改进。在此基础上,我们提出了一个简单而有效的框架,名为LTEKGE,该框架将现有的KGE模型与线性变换的实体嵌入相结合。实验表明,LTE-KGE模型与基于gcn的KGC方法具有类似的性能改进,同时具有更高的计算效率。这些结果表明,现有的GCNs在KGC中是不必要的,新的基于GCNs的KGC模型应该依靠更多的消融研究来验证其有效性。所有实验的代码都可以在GitHub的https://github.com/MIRALab-USTC/GCN4KGC上找到。
  • [行业资讯] 原来神经网络处理器,就是包汤圆
    NPU,何许人也? 说起近年来数字电路设计领域的弄潮儿,非“神经网络处理器 NPU”莫属。它更广为人知的花名,就是:AI芯片。 NPU与CPU、GPU等通用处理器之间最大的不同,就在于高度的专用性。作为一种典型的领域专用架构(Domain Specific Architecture, DSA),NPU是专门用于处理神经网络算法的。 神经网络算法良好表现的背后,是密集的运算。如果我们能够为神经网络的处理这一任务定制一款架构,那么我们便能享受到更高的处理性能、更低的功耗。 举个例子,同样是进行一次人脸识别,比起通用处理器,NPU不仅能更快地完成任务,耗电还更少。反映到市场上,这些优势可就是真金白银。 在这样的需求下,大量的人力物力被投入于NPU的设计,使得这一概念早已走出了纸上谈兵的阶段。 而如今,摆在我们眼前的局面似乎是矛盾的。 一方面,在自研芯片的热潮下,不少企业纷纷选择了拿NPU来小试牛刀,让人觉得NPU似乎已经开始走向大规模的市场化。 但另一方面,NPU的研究热仍然持续席卷着各大学术会议,宣告着:“理想的、终极形态的NPU还在路上。” 那么,有关NPU的研究到底进入怎样的技术阶段了呢?亟待解决的问题和有潜力、前景的技术方向又有哪些呢? 处理神经网络模型,跟生产汤圆差不多? 既然是要设计专用的处理器,那么架构自然得跟着目标算法走。一个典型的神经网络模型常常由多个不同类型的层构成。不了解每一层对于整个模型的表现有什么贡献?没关系!我们只需要凭着“不畏浮云遮望眼”的魄力,猛抓主要矛盾——算法中计算量最大的部分。 在典型的神经网络模型中,计算最密集的要属卷积层和全连接层,而两者对应的运算都可以用矩阵乘法的形式来交给硬件处理。打个比方,这是一个小规模的矩阵乘法运算,其中输入矩阵x,权重矩阵w和输出矩阵y的大小均为2×2。今天是元宵节,咱们就用生产汤圆打个比方~ 假设输入矩阵中的四个元素分别代表着四种馅料:芝麻、红豆、花生和草莓,而权重矩阵中的四个元素则对应着原味、紫米、抹茶和芋头这四种外皮,那么输出矩阵的计算便可以看作是生产四袋汤圆,每一袋里有两颗汤圆:比如y0这一袋里的两颗汤圆分别是原味芝麻(x0·w0)和抹茶红豆(x1·w2)口味的。也就是说,每一袋汤圆的生产离不开两种操作:把外皮、内馅揉在一块儿(乘法)和把揉出来的汤圆按计划装袋(加法)。 脉动阵列结构,走向最强汤圆生产商的不二选择? 一说到矩阵乘法,大家是不是突然明白了为什么那些研究深度学习的小伙伴跑实验总是离不开GPU?因为GPU最擅长的,就是靠里面的大量运算单元,处理高并行度的运算任务。 那么在处理神经网络模型中的矩阵乘法运算时,GPU的不足之处在哪? 让我们再次把目光投向汤圆的生产上来。 GPU所对应的生产模式,就像是在工厂里雇佣了大量的师傅,他们各自知道自己当前的任务是什么,但缺少对于整体的生产计划的认知。 于是,在这样一家汤圆生产厂里,我们可以看到这样的现象:师傅张三和李四分别被分配到了“揉一颗原味芝麻汤圆”和“揉一颗抹茶红豆汤圆”的任务,于是他们各自跑到仓库去取原材料、跑回工位上揉汤圆、再把汤圆送回仓库里;之后,师傅王五被分配到了“打包这两颗汤圆”的任务,于是他同样地经历了“跑去仓库取汤圆-跑回工位打包-把包好的汤圆送回仓库”的三段式工作流程。 由于人手多,完成整个生产任务所需要时间仍然能让人满意,但是这样的生产模式意味着极高的人力成本。同时,整体的生产效率更是比理想状态要低得多:由于每位师傅都需要频繁地往来于仓库和工位,因此即使把生产室和仓库间的通道建得再宽敞,他们的大部分工作时间都得花在仓库里和去仓库的路上。这就是“冯·诺依曼瓶颈”——频繁的数据存取拖了处理性能的后腿。 问题就来了,怎样才能建立起一套更合理的生产模式呢? 答案很简单,需要管理者充分地利用自己对于目标生产任务的了解,定制化地指挥各位汤圆师傅们相互配合、而不是各自为战。 对于专用芯片架构设计,这件事带来的启发是,应当把握、利用目标算法的特征,尽可能避免不必要的远距离数据传输——谷歌TPU中采用的脉动阵列(Systolic Array)结构便是一次成功的尝试。在脉动阵列结构中,相邻的处理单元(Processing Element, PE)之间是允许进行数据传递的,且各PE有着自己的存储资源来暂存数据,这就为数据的复用提供了可能性。 整个运算过程是这样的:权重值首先被载入脉动阵列并保持静止;输入值按照特定的排序方式自左向右地“流”过阵列,并在途经的PE中参与运算;输出值,也就是运算结果,将从阵列的底部“流”出。 通过这样的方式完成运算的好处何在?回到老石汤圆厂:在整个生产过程中,每一种馅料和外皮尽管被使用到了两次,但它们从仓库中被取出的次数却被成功地限制在了最低限度一次。 这是因为:每位师傅都被指定负责一种特定外皮的汤圆的制作,比如张三师傅(PE0)负责所有原味外皮(w0)的汤圆的制作任务,李四师傅(PE1)则负责制作紫米外皮(w1)的汤圆,于是,每位师傅便可以反复地使用自己已经取出的外皮。 另一方面,馅料也被允许在相邻的师傅间传递。当李四师傅需要芝麻馅(x0)的时候,他可以从左侧的张三师傅那里得到,而不需要自己再跑一趟仓库。 成也专用性,败也专用性? 但是,这样的脉动阵列结构还称不上是终极的解决方案。 尽管上面给出了一个理想的运算过程,但是需要注意的是,这是建立在目标运算的规模与阵列的大小完美契合的前提条件下的,而这一点在应用场景中其实是难以满足的。 在实际的设计中,出于对峰值算力的追求,脉动阵列的尺寸不宜选择得过小,比如谷歌的Cloud TPU v2配备了两个128×128大小的PE阵列。 而目标运算的规模却是变化的:一方面,同一个神经网络模型中的不同层所对应的运算规模是不同的;另一方面,在很多应用场景下,待处理的神经网络模型也不是单一的。 用固化的硬件去应对变化的运算需求,结果注定是“悲剧”。 这就好比咱们的汤圆厂里雇了大量的汤圆师傅来保证高生产力,而今天接到的生产订单很小,但师傅完成订单的时间并没有变少:因为他们认准了只有位置最靠边的师傅(阵列中最底侧的PE)才能把汤圆送回仓库,于是便执着于无意义的传递行为。 换言之,专用的架构大大简化了对于控制逻辑的需求,但也使得处理器丧失了灵活处理问题的能力。 有人可能会有异议:通过更深入的定制化,可以把同一个算法模型中不同层的运算交给不同大小的脉动阵列,让多个阵列以流水线的方式协同工作,实现运算规模与硬件资源的匹配。这其实是NPU设计中一种常见的理念,但简单地倒向定制化会导致NPU在处理不同神经网络模型时的“彻底躺平”。 为什么完全的专用性并不适用于NPU?这似乎与我们对于“定制化”的一贯理解不太相符。 一切仍然得追溯到需求上。 由于神经网络算法仍在高速发展,关于“最优的神经网络模型”之争还远没有盖棺定论,这就注定了当下的NPU仍然需要具备一定的通用性——假设企业花重金买了NPU,几个月后却发觉它们无法兼容更新、更有效的算法,那么显然没有人愿意为这样的一锤子买卖买单。 这使得NPU始终无法在竞争中甩开GPU,证明自己才是加速神经网络模型处理的最佳选择。 路在何方? 考虑到神经网络算法持续高速发展的大背景,NPU若想与GPU掰手腕、抢占市场份额,哪些技术方向可能成为突破口? 我认为,思路大体上可以分为两种: 1. 适度牺牲专用性,换取通用性;2. 无视通用性,选择彻底的定制化。 前者意味着在架构中额外引入少量的控制逻辑和数据通路,用轻量级的硬件开销去折中专用性与通用性。 对于这一思路,引入多少通用性、如何低成本地引入通用性等等都是需要重点考量的因素,也需要更便捷的生态作为支持。 硬件若是骨架,那么软件便是灵魂。 换句话说,当GPU能够流畅地处理PyTorch、TensorFlow等主流深度学习框架构建的网络模型、而NPU却不能的时候,市场很难更青睐后者。 第二种思路则更接近于设计专用处理器的初心——既然选择了定制化,岂有被通用性局限住的道理? 考虑到通用性来自于“用相同的硬件运行不同的算法”的需求,如果能为每一个神经网络都定制相应的处理器,无视通用性这一想法便站得住脚了。 因此,NPU设计自动化这一方向被寄予了厚望:当用户输入自己搭建的神经网络模型的特征,工具便能自动地生成出对应的、RTL级别的NPU设计。基于FPGA等可编程的器件,该设计能够以较低的成本迅速走向物理实现。由此看来,追求极致的专用性也并不是空中楼阁。 结语 理论上,高度定制化的专用处理器能比通用处理器更高效地完成特定的目标任务。 然而,由于神经网络算法领域自身仍然在高速地发展,NPU的DSA设计并不能完全地摆脱对于通用性的考量,这使得NPU迟迟无法表现出对于GPU的显著优越性。 但这并不意味着NPU这一概念是无意义的,一些技术方向上的潜在突破将成为NPU的取胜之匙。在后续的文章中,我们将结合在近期的顶级学术会议上汇报的相关研究进展,为对这一炙手可热的概念感兴趣的朋友建立一个更加立体的认知。 (注:本文不代表作者任职单位观点。)
  • [其他] GNN-LM基于全局信息的图神经网络语义理解模型
    本文提出了GNN-LM,将图神经网络与语言模型相结合,通过允许在整个训练语料库中引用相似的上下文,扩展了传统的语言模型。使用k近邻检索与输入的表示最相似的邻居,我们为每个输入构建了一个有向异构图,其中节点是来自输入上下文或检索到的邻居上下文的token,边表示token之间的连接。然后利用图神经网络从检索到的上下文中聚合信息,以解码下一个token。实验结果表明,GNN-LM在标准数据集中优于强基线,并且通过与kNN-LM结合,能够在WikiText-103上取得最优效果。论文标题:GNN-LM: Language Modeling based on Global Contexts via GNN作者:Yuxian Meng, Shi Zong, Xiaoya Li, Xiaofei Sun, Tianwei Zhang, Fei Wu, Jiwei Li论文链接:https://www.zhuanzhi.ai/paper/096327d547ab2c5aee0df3e603ac64e6接收会议:ICLR 2022代码链接:https://github.com/ShannonAI/GNN-LM
  • [应用开发] modelzoo上ATC CNN_Transformer(FP16)在Ascend310上推理报错
    【基础环境】CANN 5.0.2版本Ubuntu18.04.1操作系统Atlas800-3000昇腾硬件设备【操作步骤&问题现象】1、modelzoo给出的所用数据集为clean,测试使用validation,使用样例中给出的onnx模型进行模型转换,转换指令如下:atc --framework=5 --model=./wav2vec2-base-960h.onnx --output=./wav2vec2 --input_format=ND --input_shape="input:1,-1" --dynamic_dims="30000;40000;50000;60000;70000;80000;90000;100000;110000;120000;130000;140000;150000;160000;180000;190000;200000;220000;240000;250000;300000;480000" --log=error --soc_version=Ascend3102、模型转换成功后,运行pyacl_infer.py进行推理,在运行到第66个bin文件时报错,报错信息如下:【截图信息】之前在910上进行过测试,能够跑通,没有问题,看报错应该跟某个算子有关,如何解决
  • [其他] 康奈尔Nature论文:一种使用反向传播训练的深度物理神经网络
    深度学习加速器旨在高效地执行深度学习,通常针对推理阶段,并且通常通过利用传统电子设备之外的物理基板。迄今为止的方法一直无法应用反向传播算法来原位训练非常规的新型硬件。反向传播的优势使其成为事实上的大规模神经网络训练方法,因此这一缺陷构成了主要障碍。康奈尔大学的研究人员介绍了一种混合原位-计算机算法,称为物理感知训练,它应用反向传播来训练可控的物理系统。该研究以「Deep physical neural networks trained with backpropagation」为题,于 2022 年 1 月 26 日发布在《Nature》。 深度学习模型已成为科学和工程领域的普遍工具。然而,它们的能源需求现在越来越限制它们的可扩展性。深度学习加速器旨在高效地执行深度学习,通常针对推理阶段,并且通常通过利用传统电子设备之外的物理基板。迄今为止的方法一直无法应用反向传播算法来原位训练非常规的新型硬件。反向传播的优势使其成为事实上的大规模神经网络训练方法,因此这一缺陷构成了主要障碍。 在这里,康奈尔大学的研究人员介绍了一种混合原位-计算机算法,称为物理感知训练,它应用反向传播来训练可控的物理系统。 正如深度学习通过由数学函数层构成的深度神经网络,来实现计算那样,该方法允许研究人员训练由可控物理系统层构成的深度物理神经网络,即使物理层与传统人工神经网络层缺乏任何数学同构。 为了证明该方法的普遍性,研究人员训练了基于光学、力学和电子学的各种物理神经网络,以实验性地执行音频和图像分类任务。物理感知训练将反向传播的可扩展性与原位算法可实现的缺陷和噪声的自动缓解相结合。 物理神经网络具有比传统电子处理器更快、更节能地执行机器学习的潜力,更广泛地说,可以赋予物理系统自动设计的物理功能,例如机器人材料和智能传感器。 该研究以「Deep physical neural networks trained with backpropagation」为题,于 2022 年 1 月 26 日发布在《Nature》。https://www.nature.com/articles/s41586-021-04223-6图示:PNN 简介。(来源:论文)
  • [其他] SegNet:一种用于图像分割的深度卷积编解码体系结构
    作者: Vijay Badrinarayanan,Alex Kendall,Roberto Cipolla发布信息:2015,IEEE TRANSACTIONS ON PATTERN ANALYSIS AND MACHINE INTELLIGENCE论文:https://arxiv.org/pdf/1511.00561.pdf代码:https://github.com/aizawan/segnetSegNet是用于进行像素级别图像分割的全卷积网络。SegNet与FCN的思路较为相似,区别则在于Encoder中Pooling和Decoder的Upsampling使用的技术。Decoder进行上采样的方式是Segnet的亮点之一,SegNet主要用于场景理解应用,需要在进行inference时考虑内存的占用及分割的准确率。同时,Segnet的训练参数较少,可以用SGD进行end-to-end训练
  • [推理] 310推理问题
    310推理一致执行到这个位置,建图不成功:能够进行build,构建成功,但是执行../ascend310_infer/out/main 参数.....时候,就报下面错误。尝试过导入别人的mindir文件,能够成功完整执行,但是用我自己export出来的mindir就会报图2问题对比别人的mindir,我的网络用到的思路是卷积和反卷积;所以推理下来,我猜想会有如下问题:第一、export出的mindir问题,但是我的export方式def run_export(args): """ export """ device_id = int(os.getenv('DEVICE_ID', '0')) context.set_context(mode=context.GRAPH_MODE, device_target="Ascend", device_id=device_id) net = get_generator("D-DBPN", args.scale) max_lr_size = int(MAX_HR_SIZE / args.scale) params = load_checkpoint(args.ckpt_path) # net.load_pre_trained_param_dict(param_dict, strict=False) load_param_into_net(net, params) net.set_train(False) print('load mindspore net and checkpoint successfully.') inputs = Tensor(np.ones([args.batch_size, 3, max_lr_size, max_lr_size]), ms.float32) print(inputs.shape) export(net, inputs, file_name=args.file_name, file_format=args.file_format) print('export successfully!') if __name__ == "__main__": run_export(args_1)第二、310推理是否支持反卷积网络操作以上就是我的两个问题。请老师指点。
  • [其他] 使用计算机视觉算法检测钢板中的焊接缺陷
    1. 介绍 焊接缺陷可以定义为焊接零件中出现的焊接表面不规则、不连续、缺陷或不一致。焊接接头的缺陷可能导致零件和组件的报废、昂贵的维修费用、工作条件下的性能显著降低,以及在极端情况下,还会导致财产和生命损失的灾难性故障。此外,由于焊接技术的固有缺陷和金属的特性,在焊接过程中总会存在一定的缺陷。由于固有的冶金几何缺陷、机械性能的不均匀性和残余应力的存在,焊接接头通常是裂纹萌生的位置,因此评估焊接质量非常重要。在实践中,几乎不可能获得完美的焊接,并且在大多数情况下,没有必要提供所需的足够的维修功能。然而,早发现和隔离措施总是比事故更可取的。使用我们的算法,我们可以通过图像轻松检测焊接故障,并精确测量每个故障的严重程度,这将进一步有助于加快图像识别速度并避免出现不利情况。研究发现,使用卷积神经网络算法和 U-Net 架构使该过程更加高效,工作结束时准确率为 98.3%。2. 先决条件 对机器学习的基本理解卷积神经网络的基本思想了解卷积、最大池化和上采样操作U-Net架构思路对残差块中的跳过连接的基本理解(可选)使用 Python、TensorFlow 和 Keras 库的 ConvNets 的工作知识(可选)3. 图像分割 分割将图像划分为包含具有相似属性的像素的不同区域。为了对图像分析和解释有意义且有用,区域应与所描绘的对象或感兴趣的特征密切相关。图像分析的成功取决于分割的可靠性,但图像的准确分割通常是一个非常具有挑战性的问题。心脏(红色)、肺(绿色)和锁骨(蓝色)的胸部 X 光片被分割。4. 图像矩 图像矩是图像像素强度的某个特定加权平均值,图像矩对于描述分割后的对象很有用。通过图像矩发现的图像的简单属性包括:面积(或总强度)质心有关其方向的信息。5. 了解数据 该数据集包含两个目录,原始图像存储在“images”目录中,分割图像存储在“labels”目录中。让我们将数据可视化:来自“images”的原始图像上面的这些原始图像是 RGB 图像,必须用于训练模型和测试模型。这些图片的尺寸各不相同。直观地说,较暗的部分是焊接缺陷,模型需要对这些图像进行图像分割。来自“labels”的二进制图像'labels' 目录中的这些图像是二进制图像或地面真实标签。这是我们的模型必须为给定的原始图像预测的内容。在二值图像中,像素具有“高”值或“低”值,白色区域或“高”值表示缺陷区域,黑色区域或“低”值表示无缺陷。6. 使用的方法和算法 我们将 U-Net 架构解决这个问题。我们将通过三个主要步骤检测故障并测量这些焊接图像的严重程度:图像分割使用颜色表示严重性使用图像矩测量严重性训练模型以下是我们用于模型的 U-Net 架构:使用的 U-Net 架构注意事项:每个蓝色框对应一个多通道特征图通道的数量显示在框的顶部。(x,y) 尺寸位于框的左下边缘。箭头表示不同的操作。图层的名称在图层下方提供。C1、C2、…… C7是卷积运算后的输出层P1、P2、P3是最大池化操作的输出层U1、U2、U3是上采样操作的输出层A1、A2、A3 是跳跃式连接。左侧是收缩路径,其中应用了常规卷积和最大池化操作图像的大小逐渐减小,而深度逐渐增加。右侧是扩展路径,其中应用了 (上采样) 转置卷积和常规卷积操作在扩展路径中,图像尺寸逐渐增大,深度逐渐减小为了获得更精确的位置,在扩展的每个步骤中,我们通过将转置卷积层的输出与来自编码器的特征图在同一级别连接来使用跳过连接:A1 = U1 + C3A2 = U2 + C2A3 = U3 + C1每次连接后,我们再次应用常规卷积,以便模型可以学习组装更精确的输出。import numpy as np import cv2 import os import random import tensorflow as tf h,w = 512,512 def create_model(): inputs = tf.keras.layers.Input(shape=(h,w,3)) conv1 = tf.keras.layers.Conv2D(16,(3,3),activation='relu',padding='same')(inputs) pool1 = tf.keras.layers.MaxPool2D()(conv1) conv2 = tf.keras.layers.Conv2D(32,(3,3),activation='relu',padding='same')(pool1) pool2 = tf.keras.layers.MaxPool2D()(conv2) conv3 = tf.keras.layers.Conv2D(64,(3,3),activation='relu',padding='same')(pool2) pool3 = tf.keras.layers.MaxPool2D()(conv3) conv4 = tf.keras.layers.Conv2D(64,(3,3),activation='relu',padding='same')(pool3) upsm5 = tf.keras.layers.UpSampling2D()(conv4) upad5 = tf.keras.layers.Add()([conv3,upsm5]) conv5 = tf.keras.layers.Conv2D(32,(3,3),activation='relu',padding='same')(upad5) upsm6 = tf.keras.layers.UpSampling2D()(conv5) upad6 = tf.keras.layers.Add()([conv2,upsm6]) conv6 = tf.keras.layers.Conv2D(16,(3,3),activation='relu',padding='same')(upad6) upsm7 = tf.keras.layers.UpSampling2D()(conv6) upad7 = tf.keras.layers.Add()([conv1,upsm7]) conv7 = tf.keras.layers.Conv2D(1,(3,3),activation='relu',padding='same')(upad7) model = tf.keras.models.Model(inputs=inputs, outputs=conv7) return model images = [] labels = [] files = os.listdir('./dataset/images/') random.shuffle(files) for f in files: img = cv2.imread('./dataset/images/' + f) parts = f.split('_') label_name = './dataset/labels/' + 'W0002_' + parts[1] label = cv2.imread(label_name,2) img = cv2.resize(img,(w,h)) label = cv2.resize(label,(w,h)) images.append(img) labels.append(label) images = np.array(images) labels = np.array(labels) labels = np.reshape(labels, (labels.shape[0],labels.shape[1],labels.shape[2],1)) print(images.shape) print(labels.shape) images = images/255 labels = labels/255 model = tf.keras.models.load_model('my_model') #model = create_model() # uncomment this to create a new model print(model.summary()) model.compile(optimizer='adam', loss='binary_crossentropy',metrics=['accuracy']) model.fit(images,labels,epochs=100,batch_size=10) model.evaluate(images,labels) model.save('my_model')模型是用 Adam 优化器编译的,我们使用二进制交叉熵损失函数,因为只有两个类(缺陷和无缺陷)。我们使用批量处理大小为 10 的 100 个 epoch(模型在所有输入上运行的次数)。测试模型由于模型的输入尺寸为 512x512x3 ,因此我们已将输入大小调整为该尺寸。接下来,我们通过将图像除以 255 来规范化图像以加快计算速度。图像已被输入模型,用于预测二进制输出。为了放大像素的强度,二进制输出乘以 1000。然后将图像转换为 16 位整数以便于图像处理。之后,算法会检测缺陷并通过颜色分级以及根据缺陷的严重程度为具有缺陷的像素分配权重,来直观地标记缺陷的严重程度。然后,考虑加权像素在该图像上计算图像矩。图像最终转换回 8 位整数,输出图像显示颜色分级及其严重性值。import numpy as np import cv2 from google.colab.patches import cv2_imshow import os import random import tensorflow as tf h,w = 512,512 num_cases = 10 images = [] labels = [] files = os.listdir('./dataset/images/') random.shuffle(files) model = tf.keras.models.load_model('my_model') lowSevere = 1 midSevere = 2 highSevere = 4 for f in files[0:num_cases]: test_img = cv2.imread('./dataset/images/' + f) resized_img = cv2.resize(test_img,(w,h)) resized_img = resized_img/255 cropped_img = np.reshape(resized_img, (1,resized_img.shape[0],resized_img.shape[1],resized_img.shape[2])) test_out = model.predict(cropped_img) test_out = test_out[0,:,:,0]*1000 test_out = np.clip(test_out,0,255) resized_test_out = cv2.resize(test_out,(test_img.shape[1],test_img.shape[0])) resized_test_out = resized_test_out.astype(np.uint16) test_img = test_img.astype(np.uint16) grey = cv2.cvtColor(test_img, cv2.COLOR_BGR2GRAY) for i in range(test_img.shape[0]): for j in range(test_img.shape[1]): if(grey[i,j]>150 & resized_test_out[i,j]>40): test_img[i,j,1]=test_img[i,j,1] + resized_test_out[i,j] resized_test_out[i,j] = lowSevere elif(grey[i,j]<100 & resized_test_out[i,j]>40): test_img[i,j,2]=test_img[i,j,2] + resized_test_out[i,j] resized_test_out[i,j] = highSevere elif(resized_test_out[i,j]>40): test_img[i,j,0]=test_img[i,j,0] + resized_test_out[i,j] resized_test_out[i,j] = midSevere else: resized_test_out[i,j] = 0 M = cv2.moments(resized_test_out) maxMomentArea = resized_test_out.shape[1]*resized_test_out.shape[0]*highSevere print("0th Moment = " , (M["m00"]*100/maxMomentArea), "%") test_img = np.clip(test_img,0,255) test_img = test_img.astype(np.uint8) cv2_imshow(test_img) cv2.waitKey(0)7. 结果 我们用于严重性检测的视觉指标是颜色,在图像中,颜色为:绿色表示存在严重缺陷的区域。蓝色表示缺陷更严重的区域。红色表示最严重的缺陷区域。第0个时刻以百分比的形式显示在输出图像旁边,作为严重性的经验度量。以下是三个随机样本,显示了原始输入、真实情况和模型生成的输出。文章转载自 小白学视觉 2022-01-27 
  • [行业资讯] 物联网架构的4个必要阶段
    是什么让像动作激活的电灯开关这样的自动化设备与具有相同功能的物联网设备有所不同?一句话:数据。使用连接到物联网的设备,当传感器检测到动作并且执行器打开灯时,这些操作将被捕获为数据,并发送到云或数据中心进行记录和分析。哪里有数据,哪里就需要物联网架构,告诉数据去哪里,使用什么格式,如何到达那里,以及基于这些数据采取什么行动。在本文,我们将快速概述物联网架构,并探讨它如何引导数据往返于设备和数据中心。数据流:从边缘到服务器/云物联网体系架构通常被描述为一个四阶段的过程,在这个过程中,数据从传感器通过网络传输,最终到达企业数据中心或云端进行存储、处理和分析。在物联网中,“物”可以是机器,可以是建筑,甚至可以是人。物联网架构中的进程还以指令或命令的形式向另一个方向发送数据,这些指令或命令告诉执行器或其他物理连接的设备采取某种措施来控制物理进程。执行器可以做一些简单的事情,比如开灯,或者在检测到即将发生故障时关闭装配线。让我们来看看物联网架构的4个阶段。第1阶段:传感器和执行器该过程从传感器和执行器开始,连网设备监测(在传感器的情况下)或控制(在执行器的情况下)某些“东西”或物理进程。传感器捕捉有关流程状态或环境条件的数据,例如温度、湿度、化学成分、储罐中的液位、管道中的流体流量或装配线的速度等等。在某些情况下,传感器可以检测到需要几乎立即响应的状况或事件,以便执行器可以实时执行补救措施,例如,调整流体的流速或工业机器人的运动。在这些情况下,要求传感器与分析/触发致动器之间的延迟非常低。为了避免数据到服务器的往返延迟、数据分析以确定故障以及向“对象”发送控制的延迟,此关键处理进程需要非常靠近要监测或控制的进程。此“边缘”处理可由模块上系统(SOM)设备(例如DigiConnectCore®模块和/或具有Python的Digi Cellular Router)来执行。第2阶段:互联网网关和数据采集系统数据采集系统(DAS)从传感器收集原始数据,并将其从模拟格式转换为数字格式。然后,数据采集系统聚合并格式化数据,再然后利用无线广域网(如Wi-Fi或蜂窝网络)或有线广域网通过互联网网关发送数据,以进行下一阶段的处理。此时,数据量已达到最大值。数量可能非常庞大,尤其是在工厂环境中,数百个传感器可能同时收集数据。因此,数据需要被过滤和压缩到最佳传输大小。第3阶段:预处理——边缘分析一旦物联网数据被数字化和聚合,它将需要处理以进一步减少数据量,然后才能进入数据中心或云。边缘设备可以执行一些分析,以作为预处理的一部分。在此阶段,机器学习对提供系统反馈和持续改进流程非常有帮助,而无需等待从公司数据中心或云返回指令。这种类型的处理通常发生在靠近传感器所在位置的设备上,例如在现场配线柜中。第4阶段:在云或数据中心进行深入分析在该过程的第4阶段,可以使用强大的IT系统来分析、管理和安全地存储数据。这通常发生在企业数据中心或云中,在这里,来自多个现场站点/传感器的数据可以组合在一起,以提供整个物联网系统的更广阔图景,并为IT和业务经理提供可操作的见解。一家公司可能会在不同的地理区域运营,可以分析物联网数据来识别关键趋势和模式,或者发现异常。在此级别上,特定于行业和/或公司的应用程序可用于执行深入分析并应用业务规则,以确定是否需要采取措施。传入的数据可以指示对设备设置的期望更改或优化流程的其他方式,从而形成了有助于不断改进的循环。阶段4还包括将数据存储在数据仓库中,以进行记录保存和进一步分析。流程需要平台除了四阶段物联网架构之外,还必须考虑物联网平台,它提供了阶段之间的连接。平台的架构定义了数据通信的具体细节。它确定哪些数据流向何处,以及在每个阶段执行多少处理。物联网平台可以根据系统的专业化程度进行不同程度的定制。举个例子,世界上任何一个城市的路灯物联网可能都非常相似,而用于制造医疗设备的3D打印机上的传感器和执行器可能是独一无二的。凭借可靠的平台和精心设计的架构,物联网可以提高几乎每个行业的安全性、效率和生产力。合适的物联网平台可以为您提供成功所需的工具。物联网的最佳时刻即将到来虽然物联网已经在许多消费者、商业、工业和基础设施应用中得到广泛使用,但我们可以预计,在不久的将来,物联网系统将以更大的数量和更多的用例出现。(编译iothome)
  • [技术干货] NeurIPS 2021 | 华为诺亚Oral论文:基于频域的二值神经网络训练方法
    常规符号函数的梯度几乎处处为零,不能用于反向传播。为此,来自华为诺亚方舟实验室等机构的研究者提出一种在频域中估计原始符号函数梯度的新方法。二值神经网络(BNN)将原始全精度权重和激活用符号函数表征成 1-bit。但是由于常规符号函数的梯度几乎处处为零,不能用于反向传播,因此一些研究已经提出尝试使用近似梯度来减轻优化难度。然而,这些近似破坏了实际梯度的主要方向。 基于此,在一篇 NeurIPS 2021 论文中,来自华为诺亚方舟实验室等机构的研究者提出使用傅里叶级数的组合来估计频域中符号函数的梯度以训练 BNN,即频域逼近 (FDA)。所提方法不影响占整体能量大部分的原始符号函数的低频信息,并且将高频系数使用噪声拟合模块 (noise adaptation module) 进行估计以避免大量的计算开销。 论文地址:https://arxiv.org/pdf/2103.00841.pdf 在几个基准数据集和神经架构上的实验表明,使用该方法学习的二值网络实现了 SOTA 准确率。 数日前,在机器之心 2021 NeurIPS MeetUp China 上,论文一作许奕星为参会者解读了该论文。 方法 该研究提出的 FDA 方法,通过利用傅里叶级数 (FS) 来估计频域中的原始符号函数,FS 估计是使用无穷项时符号函数的无损表征。在实际应用中,能量相对较低的高频系数会被忽略,以避免巨大的计算开销,并将符号函数表征为固定数量的不同周期正弦函数的组合。与现有的逼近方法相比,该研究所提出的频域逼近方法不影响原始符号函数的低频域信息,即占用符号函数能量最多的部分。因此,原始符号函数相应梯度的主要方向能够被更准确地保持。 在论文中,该研究对所提方法做了详细的理论表述。 论文中用 f(·)和 f’(·)来表示原始函数及其对应的梯度函数。由于符号函数的梯度是一个无法反向传播的脉冲函数,需要应用进化算法(evolutionary algorithm)等零阶算法来达到最优解,但这是非常低效的。因此该研究提出找到一个代理函数,通过一阶优化算法(如 SGD)依靠实验求解,而理论上具有与符号函数相同的最优解。 已有研究证明,任何周期为 T 的周期信号都可以分解为傅里叶级数的组合: 然后该研究进一步证明了随着 n 的增加,估计值和 s(t)之间的均方误差会逐渐减小,并在 n → ∞ 时收敛到 0。 为了进一步补偿细微的逼近误差,该研究在训练阶段添加了一个噪声适应模块来细化梯度。 实验及结果 为了展示 FDA-BNN 优越的性能,该研究在 CIFAR-10 数据集上进行了评估实验,实验结果如下表所示。 消融实验 为了验证所提方法中每个组件的有效性、噪声适应模块和超参数的影响,该研究进行了一系列的消融实验。 首先,该研究使用 ResNet-20 架构在 CIFAR-10 上实验验证正弦模块和噪声适应模块的效果,结果如下表所示。 从上表的结果看,使用正弦模块可使训练过程受益,将准确率从 84.44% 提高到 85.83%。将正弦模块和噪声自适应模块组合在一起时得到了最佳性能,即 86.20% 的准确率。 为了进一步验证噪声适应模块的用途,研究者将该模块添加到其他梯度逼近方法中,例如 DSQ 和 BNN+,结果如下表所示。 然后该研究评估了不同 η(·) 对噪声适应模块的影响。结果如下表所示,使用 shortcut 时性能更好,并且 shortcut function η(x) = α sin(x) 在实验过程中表现最好。 在 ImageNet 上的实验 该研究进一步在大规模数据集 ImageNet ILSVRC 2012 上进行了实验,使用 ResNet-18 和 AlexNet 进行实验,结果如下表所示。 对于 ResNet-18,FDA-BNN 实现了 60.2% 的 top-1 准确率和 82.3% 的 top-5 的准确率,比基线方法(Bireal-Net + PReLU)高出 1.2% 和 1.0%,并超过所有其他方法。 当以 ReActNet 作为基线方法,并使用该研究所提方法计算符号函数的梯度, FDA-BNN 达到了 66.0% 的 top-1 准确率,86.4% 的 top-5 准确率,比基线方法分别高出 0.5% 和 0.3%。 对于 AlexNet,该研究使用 Dorefa-Net 中的量化方法作为基线方法,FDA-BNN 实现了 46.2% 的 top-1 准确率和 69.7% 的 top-5 准确率,并优于其他 SOTA 方法。
  • [其他] 浅谈Fast-SCNN
    Fast-SCNN由4部分构成,Learning to Down-sample(学习下采样),Global Feature Extractor(全局特征提取), Feature Fusion(特征融合), Classifier(分类器)。Learning to Down-sample,一个普通的卷积层Conv2D,两个depthwise separable卷积层(DSConv)。Global Feature Extractor,用于抓取图像分割的全局特征。与普通multi-branch方法不同,该模块对于低分辨率图像进行处理。Feature Fusion,融合特征,并且是以相对简单方式融合两个分支的特征,确保效率。Classifier,两个depthwise separable卷积层(DSConv),一个pointwise卷积层(Conv2D),包含一个softmax操作。此外,在梯度下降计算中,用argmax将softmax替代,以提高计算效率。Fast-SCNN的创新点主要在以下两个方面:“学习下采样”(Learning to Down-sample)和encoder-decoder中的 skip connection类似,确保了低层次特征能被有效地共享和使用,共三层。Fast-SCNN还借鉴了MobileNet的depthwise separable convolution和 residual bottleneck block,来降低计算成本和内存消耗。
  • [其他干货] 如何通俗易懂的描述机器学习的流程?
    1.3 数据预处理数据预处理,其实就是对数据进行清理、数据整理或普通数据处理。指对数据进行各种检查和校正过程,以纠正缺失值、拼写错误、使数值正常化/标准化以使其具有可比性、转换数据(如对数转换)等问题。例如对图像进行resize成统一的大小或者分辨率。 数据的质量将对机器学习算法模型的质量好坏产生很大的影响。因此,为了达到最好的机器学习模型质量,传统的机器学习算法流程中,其实很大一部分工作就是在对数据进行分析和处理。一般来说,数据预处理可以轻松地占到机器学习项目流程中80%的时间,而实际的模型建立阶段和后续的模型分析大概仅占到剩余的20%。1.4 数据分割训练集 & 测试集在机器学习模型的开发流程中,希望训练好的模型能在新的、未见过的数据上表现良好。为了模拟新的、未见过的数据,对可用数据进行数据分割,从而将已经处理好的数据集分割成2部分:训练集合测试集。第一部分是较大的数据子集,用作训练集(如占原始数据的80%);第二部分通常是较小的子集,用作测试集(其余20%的数据)。接下来,利用训练集建立预测模型,然后将这种训练好的模型应用于测试集(即作为新的、未见过的数据)上进行预测。根据模型在测试集上的表现来选择最佳模型,为了获得最佳模型,还可以进行超参数优化。训练集 & 验证集 & 测试集另一种常见的数据分割方法是将数据分割成3部分:1)训练集,2)验证集和3)测试集。训练集用于建立预测模型,同时对验证集进行评估,据此进行预测,可以进行模型调优(如超参数优化),并根据验证集的结果选择性能最好的模型。验证集的操作方式跟训练集类似。不过值得注意的是,测试集不参与机器学习模型的建立和准备,是机器学习模型训练过程中单独留出的样本集,用于调整模型的超参数和对模型的能力进行初步评估。通常边训练边验证,这里的验证就是用验证集来检验模型的初步效果。交叉验证实际上数据是机器学习流程中最宝贵的,为了更加经济地利用现有数据,通常使用N倍交叉验证,将数据集分割成N个。在这样的N倍数据集中,其中一个被留作测试数据,而其余的则被用作建立模型的训练数据。通过反复交叉迭代的方式来对机器学习流程进行验证。这种交叉验证的方法在机器学习流程中被广泛的使用,但是深度学习中使用得比较少哈。1.5 机器学习算法建模下面是最有趣的部分啦,数据筛选和处理过程其实都是很枯燥乏味的,现在可以使用精心准备的数据来建模。根据taget变量(通常称为Y变量)的数据类型,可以建立一个分类或回归模型。机器学习算法机器学习算法可以大致分为以下三种类型之一:监督学习:是一种机器学习任务,建立输入X和输出Y变量之间的数学(映射)关系。这样的(X、Y)对构成了用于建立模型的标签数据,以便学习如何从输入中预测输出。 无监督学习:是一种只利用输入X变量的机器学习任务。X变量是未标记的数据,学习算法在建模时使用的是数据的固有结构。 强化学习:是一种决定下一步行动方案的机器学习任务,它通过试错学习(trial and error learning)来实现这一目标,努力使reward回报最大化。参数调优传说中的调参侠主要干的就是这个工作啦。超参数本质上是机器学习算法的参数,直接影响学习过程和预测性能。由于没有万能的超参数设置,可以普遍适用于所有数据集,因此需要进行超参数优化。以随机森林为例。在使用randomForest时,通常会对两个常见的超参数进行优化,其中包括mtry和ntree参数。mtry(maxfeatures)代表在每次分裂时作为候选变量随机采样的变量数量,而ntree(nestimators)代表要生长的树的数量。另一种在10年前仍然非常主流的机器学习算法是支持向量机SVM。需要优化的超参数是径向基函数(RBF)内核的C参数和gamma参数。C参数是一个限制过拟合的惩罚项,而gamma参数则控制RBF核的宽度。调优通常是为了得出超参数的较佳值集,很多时候不要去追求找到超参一个最优值,其实调参侠只是调侃调侃,真正需要理解掌握算法原理,找到适合数据和模型的参数就可以啦。特征选择特征选择从字面上看就是从最初的大量特征中选择一个特征子集的过程。除了实现高精度的模型外,机器学习模型构建最重要的一个方面是获得可操作的见解,为了实现这一目标,能够从大量的特征中选择出重要的特征子集非常重要。特征选择的任务本身就可以构成一个全新的研究领域,在这个领域中,大量的努力都是为了设计新颖的算法和方法。从众多可用的特征选择算法中,一些经典的方法是基于模拟退火和遗传算法。除此之外,还有大量基于进化算法(如粒子群优化、蚁群优化等)和随机方法(如蒙特卡洛)的方法。性能指标如何知道训练出来的机器学习模型表现好或坏?就是使用性能评价指标(metrics),一些常见的评估分类性能的指标包括准确率(AC)、灵敏度(SN)、特异性(SP)和马太相关系数(MCC)。回归最简单的回归模式,可以通过以下简单等式很好地总结:Y = f(X)。其中,Y对应量化输出变量,X指输入变量,f指计算输出值作为输入特征的映射函数(从机器学习模型中得到)。上面的回归例子公式的实质是,如果X已知,就可以推导出Y。一旦Y被计算(预测)出来,一个流行的可视化方式是将实际值与预测值做一个简单的散点图,如下图所示。对回归模型的性能进行评估,以评估拟合模型可以准确预测输入数据值的程度。评估回归模型性能的常用指标是确定系数(R²)。此外,均方误差(MSE)以及均方根误差(RMSE)也是衡量残差或预测误差的常用指标。下面是机器学习算法的主要流程:主要从1)数据集准备、2)数据预处理、3)数据分割、4)定义神经网络模型,5)训练网络。深度学习不需要我们自己去提取特征,而是通过神经网络自动对数据进行高维抽象学习,减少了特征工程的构成,在这方面节约了很多时间。但是同时因为引入了更加深、更复杂的网络模型结构,所以调参工作变得更加繁重啦。例如:定义神经网络模型结构、确认损失函数、确定优化器,最后就是反复调整模型参数的过程。MindSpore官方资料GitHub : https://github.com/mindspore-ai/mindsporeGitee : https : //gitee.com/mindspore/mindspore官方QQ群 : 486831414
  • [技术干货] MindSpore编程基本框架
    配置运行信息MindSpore通过mindspore.context下的set_context方法来配置运行需要的信息,如运行模式、后端信息、硬件等信息。import argparse from mindspore import context # 配置脚本参数 parser = argparse.ArgumentParser(description='MindSpore LeNet Example') ## 配置运行环境参数,Mindspore支持的三种运行环境分别为'Ascend','GPU','CPU',默认运行环境是'CPU'。 parser.add_argument('--device_target', type=str, default="CPU", choices=['Ascend', 'GPU', 'CPU']) # 设置运行环境 args = parser.parse_known_args()[0] ##device_target根据脚本信息(--device_target)配置硬件信息;mode设置运行模式(动静态图模式) context.set_context(mode=context.GRAPH_MODE, device_target=args.device_target)配置数据MNIST数据集是由10类28∗28的灰度图片组成,训练数据集包含60000张图片,测试数据集包含10000张图片。MNIST数据集下载页面,数据文件按下方目录结构放置:./datasets/MNIST_Data├── test│........├── t10k-images-idx3-ubyte│........└── t10k-labels-idx1-ubyte└── train|.........├── train-images-idx3-ubyte|.........└── train-labels-idx1-ubyte2 directories, 4 files数据处理mindspore.dataset是MindSpore提供的用于数据处理的API模块。它的主要功能是存储样本和标签,同时也集成了一些常见的数据处理方法。定义数据集mindspore.dataset.MnistDataset以特定格式(MnistDataset)对数据进行读取。定义map映射mindspore.dataset.vision.c_transforms(.Resize/ .Rescale/ .HWC2CWH)设置数据将要转换成的格式(改变尺寸,缩放,偏移)。mindspore.dataset.transforms.c_transform(.TypeCast)转换数据类型。map映射mindspore.dataset.MnistDataset下的map方法。根据上一步定义好的格式,将数据转换成mindspore.dataset.MnistDataset的格式。数据结构重组mindspore.dataset.MnistDataset下的shuffle方法打乱数据顺序。mindspore.dataset.MnistDataset下的batch方法设置批量。import mindspore.dataset as ds import mindspore.dataset.transforms.c_transforms as C import mindspore.dataset.vision.c_transforms as CV from mindspore.dataset.vision import Inter from mindspore import dtype as mstype def create_dataset(data_path, batch_size=32, repeat_size=1, num_parallel_workers=1): # 定义数据集 mnist_ds = ds.MnistDataset(data_path) resize_height, resize_width = 32, 32 rescale = 1.0 / 255.0 shift = 0.0 rescale_nml = 1 / 0.3081 shift_nml = -1 * 0.1307 / 0.3081 # 定义map映射 resize_op = CV.Resize((resize_height, resize_width), interpolation=Inter.LINEAR) rescale_nml_op = CV.Rescale(rescale_nml, shift_nml) rescale_op = CV.Rescale(rescale, shift) hwc2chw_op = CV.HWC2CHW() type_cast_op = C.TypeCast(mstype.int32) # map映射函数 mnist_ds = mnist_ds.map(operations=type_cast_op, input_columns="label", num_parallel_workers=num_parallel_workers) mnist_ds = mnist_ds.map(operations=resize_op, input_columns="image", num_parallel_workers=num_parallel_workers) mnist_ds = mnist_ds.map(operations=rescale_op, input_columns="image", num_parallel_workers=num_parallel_workers) mnist_ds = mnist_ds.map(operations=rescale_nml_op, input_columns="image", num_parallel_workers=num_parallel_workers) mnist_ds = mnist_ds.map(operations=hwc2chw_op, input_columns="image", num_parallel_workers=num_parallel_workers) # shuffle、batch操作 buffer_size = 10000 mnist_ds = mnist_ds.shuffle(buffer_size=buffer_size) ##batch_size为每组包含的数据个数(32)。 mnist_ds = mnist_ds.batch(batch_size, drop_remainder=True) return mnist_ds除了这些基本操作外,Mindspore还支持多种数据处理和数据增强的操作。另外,MindSpore还提供了处理自定义数据集的mindspore.dataset.GeneratorDataset,具体教程可参考链接内容.创建模型定义运算(_init_方法)mindspore.nn.Cell是所有神经网络的基类,所以定义神经网络时要继承mindspore.nn.Cell。mindspore.nn(.Conv2d/.Flatten/.Dense/.ReLU/.Maxpool2D)配置网络结构(卷积,压平,全连接,激活函数,最大池化)。mindspore.common.initializer下的Normal类配置初始权重(正态分布)。构建向前网络(construct方法)根据上一步定义的层来完成LeNet网络的前向构造,最后实例化网络(LeNet())。import mindspore.nn as nn from mindspore.common.initializer import Normal class LeNet5(nn.Cell): """ Lenet网络结构 """ def __init__(self, num_class=10, num_channel=1): super(LeNet5, self).__init__() # 定义所需要的运算 self.conv1 = nn.Conv2d(num_channel, 6, 5, pad_mode='valid') self.conv2 = nn.Conv2d(6, 16, 5, pad_mode='valid') self.fc1 = nn.Dense(16 * 5 * 5, 120, weight_init=Normal(0.02)) self.fc2 = nn.Dense(120, 84, weight_init=Normal(0.02)) self.fc3 = nn.Dense(84, num_class, weight_init=Normal(0.02)) self.relu = nn.ReLU() self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2) self.flatten = nn.Flatten() def construct(self, x): # 使用定义好的运算构建前向网络 x = self.conv1(x) x = self.relu(x) x = self.max_pool2d(x) x = self.conv2(x) x = self.relu(x) x = self.max_pool2d(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) return x #实例化网络 net = LeNet5()需要更多信息请参考构造神经网络优化模型参数定义损失函数mindspore.nn.SoftmaxCrossEntropyWithLogits,其他可选择的损失函数。定义优化器mindspore.nn.Momentum,其他可选择的优化器。# 定义损失函数 net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean') # 定义优化器 net_opt = nn.Momentum(net.trainable_params(), learning_rate=0.01, momentum=0.9)需要更多信息请参考损失函数,优化器训练及保存模型Callback机制mindspore.train.callback下的CheckpointConfig类用来设置保存模型参数,ModelCheckpoint类用来应用模型保存参数,LossMoniter类可以监控Loss值的变化。Mindspore提供了Callback机制,可以在训练过程中执行自定义逻辑,更多信息请参考Callback机制,本例中使用了ModelCheckpoint类,ModelCheckpoint可以保存模型和参数,方便后续的Fine-tuning操作更加。from mindspore.train.callback import ModelCheckpoint, CheckpointConfig # 设置模型保存参数 config_ck = CheckpointConfig(save_checkpoint_steps=1875, keep_checkpoint_max=10) # 应用模型保存参数 ckpoint = ModelCheckpoint(prefix="checkpoint_lenet", config=config_ck)定义训练方法mindspore下的Model类的train方法是用于网络训练的接口,model是基于net(LeNet5()实例),net_loss(损失函数)以及net_opt(优化器)所创建的实例。mindspore还提供了自定义训练的API(TrainOneStepCell),更多信息参见教程链接。# 导入模型训练需要的库 from mindspore.nn import Accuracy from mindspore.train.callback import LossMonitor from mindspore import Model def train_net(args, model, epoch_size, data_path, repeat_size, ckpoint_cb, sink_mode): """定义训练的方法""" # 加载训练数据集 ds_train = create_dataset(os.path.join(data_path, "train"), 32, repeat_size) ##dataset_sink_mode用于控制数据时候下沉,数据下沉是指数据通过通道直接传到Device上, ##可以加快训练速度,True表示数据下沉。 model.train(epoch_size, ds_train, callbacks=[ckpoint_cb, LossMonitor()], dataset_sink_mode=sink_mode)定义验证方法mindspore下的Model类的eval方法读入测试数据集。#通过模型运行测试数据集得到的结果,验证模型的泛化能力。 def test_net(network, model, data_path): """定义验证的方法""" ds_eval = create_dataset(os.path.join(data_path, "test")) #使用model.eval接口读入测试数据集。使用保存后的模型参数进行推理。 acc = model.eval(ds_eval, dataset_sink_mode=False) print("{}".format(acc))训练和验证mindspore.nn.Accuracy计算模型预测的准确率。#对数据集进行1个迭代的训练 train_epoch = 1 #原始数据集路径 mnist_path = "./datasets/MNIST_Data" dataset_size = 1 model = Model(net, net_loss, net_opt, metrics={"Accuracy": Accuracy()}) train_net(args, model, train_epoch, mnist_path, dataset_size, ckpoint, False) test_net(net, model, mnist_path)命令行运行脚本运行信息#lenet.py:教程中编写的脚本文件。 #--device_target:指定运行硬件平台,参数为CPU、GPU或者Ascend。 python lenet.py --device_target=CPU#训练过程中会打印loss值,loss值会波动,但总体来说loss值会逐步减小,精度逐步提高。 #每个人运行的loss值有一定随机性,不一定完全相同。 epoch: 1 step: 1, loss is 2.3025916 epoch: 1 step: 2, loss is 2.302577 ... epoch: 1 step: 1871, loss is 0.048939988 epoch: 1 step: 1872, loss is 0.028885357 epoch: 1 step: 1873, loss is 0.09475248 epoch: 1 step: 1874, loss is 0.046067055 epoch: 1 step: 1875, loss is 0.12366105 {'Accuracy': 0.9663477564102564}可以在打印信息中看出模型精度数据,示例中模型的预测精度数据约为96.6%,模型质量良好。如果希望模型精度会进一步提高,可以增加网络迭代次数train_epoch或调整学习率变化策略。加载模型加载参数mindspore.load_checkpoint加载已经保存的用于测试的模型。参数载入网络mindspore.load_param_into_net加载参数到网络中。from mindspore import load_checkpoint, load_param_into_net # 加载已经保存的用于测试的模型 param_dict = load_checkpoint("checkpoint_lenet-1_1875.ckpt") # 加载参数到网络中 load_param_into_net(net, param_dict)需要更多信息详见保存及加载模型验证模型本例使用生成的模型对单个图片进行分类图片预测mindspore下的Model类的predict方法用来进行预测。classes = [ "Zero", "One", "Two", "Three", "Four", "Fives", "Six", "Seven", "Eight", "Nine", ] # image为测试图片,label为测试图片的实际分类 image, label = test_data[0][0], test_data[0][1] # 使用函数model.predict预测image对应分类 pred = model.predict(image) predicted, actual = classes[pred[0].argmax(0)], classes[label] # 输出预测分类与实际分类 print(f'Predicted: "{predicted}", Actual: "{actual}"')运行结果Predicted: "Eight", Actual: "Eight"-------------------------------------------------------------------------------------------------------------------------作者:0moonstar0原文链接:https://www.jianshu.com/p/5aa04d77c213
总条数:945 到第
上滑加载中