• [技术干货] 什么是生物神经网络和人工神经网络
    生物神经网络(Biological Neural Networks):一般指生物的大脑神经元,细胞,触点等组成的网络,用于产生生物的意识,帮助生物进行思考和行动。生物神经细胞功能比较简单,需要通过很多神经元一起协作完成复杂功能,通过一定的连接方式或信息传递方式进行协作的神经元可以看做是一个网络,就是神经网络。人工神经网络人工神经网络是一种旨在模仿人脑结构及其功能的信息处理系统。人工神经网络,简称神经网络(Artificial Neural Network,ANN):是由人工神经元互连组成的网络,它是从微观结构和功能上对人脑的抽象、简化,是模拟人类智能的一条重要途径,反映了人脑功能的若干基本特征,如并行信息处理、学习、联想、模式分类、记忆等。
  • [技术干货] 物体检测算法综述
    1. 引论计算机视觉领域,存在一系列研究问题,其中比较基础的包括图像分类、物体检测、实例分割、语义分割。图像分割任务目的在于识别给定图像的物体语义类别,比如是一只猫还是一只狗。物体检测任务更进一步,不仅需要检测出物体的类别,还要获得物体位置的边界框信息,同时需要对一个图像检测多个类别实例。语义分割在上述基础上更进一步,对于物体位置的信息需要更细粒度的表述,不满足于通过BBox表示位置,而是要具体到每个像素所对应的类别,但是并不需要区分同一类别的不同实例。更为细致的则是实例分割,需要区分一个像素属于同一类别的哪一实例,比如某一像素属于猫1,另一像素属于猫2。在深度学习应用到object detection之前,物体检测技术所采用的pipeline基本上是三段论,即候选区域生成、特征向量提取、区域分类。第一步,候选区域生成的目的在于搜索图像中可能含有物体的区域即ROI,一个非常符合直觉的方式是用滑移窗口来检测整个图像,为了捕获多尺度的信息,通常采用图像缩放和多尺度滑移窗。第二步,在图像的每个区域借助滑移窗通过一些低层视觉特征(如SIFT,Haar,HOG,SURF)抽取出固定长度的特征向量以捕获图像对应区域的语义信息。第三步,对于每一区域通过区域分类器赋予类别标签,通常采用one-vs-all SVM进行分类。然而,传统的方法由于存在一些局限性,包括大量候选区域的计算冗余性、分类过程的假阳性、窗口尺度人为设计难以完美匹配不同物体、基于低层的视觉信息设计的特征难以捕获复杂语义信息、整个pipeline分割独立难以获得全局最优解等一系列问题,在2008~2012年的Pascal VOC物体检测上进展艰难,逐渐转变为了基于深度学习框架。其基本思想是通过卷积神经网络直接从原始像素生成层级的语义信息代替手工特征提取,借助大算力和大数据获得更好的特征表达。2. 物体检测的正式描述物体检测主要包含两个任务,分别是识别(即物体分类)和定位(即位置回归)。物体检测器需要将特定类别的物体以准确的位置和正确的标签信息从背景中识别出来。广义来讲,针对边界框BBox定位的Object Detection和基于像素Mask定位的Semantic Segmentation和Instance Segmentation都属于物体检测的范畴。狭义上,只限定为Object Detection,然而,其实在技术上具有很大程度的相似性。下面给出物体检测的数学形式:对于给定带标注的图像集合,其中标注形式如下,其中,包括个物体,为第i张图 中的第j个物体的BBox或是像素Mask。检测器是为了获得,即在给定图像的条件下给出图像中每个检测到物体的类别和位置信息。3. 物体检测的主要范式目前主要物体检测的范式包含two-stage detector和one-stage detector。对于two-stage detector的范式而言,分为两个阶段,第一个阶段生成稀疏的候选区域,第二个阶段通过卷积神经网络对于生成的候选区域进行特征编码,然后进行物体类别分类。对于one-stage detector的范式而言,没有单独的候选区域生成过程,而是将每个位置都认为是可能存在物体的区域,然后将每个ROI分类为背景或是目标。一般来讲,two-stage detector范式在准确率上有优势,而one-stage detector在推理速度上具有优势,实时性高。3.1 Two-Stage DetectorTwo-stage detector范式将整个检测任务分解为两个阶段,主要包括(1)候选区域生成(2)对候选区域进行预测。在候选区域生成阶段,检测器将识别出图像中潜在有可能有物体的区域。其核心想法是以较高的召回率提出候选区域使得图片中所有的物体至少被包含在一个候选区域内。在第二阶段内,采用深度学习的模型对于候选区域进行分类,贴上正确的类别标签,类别标签包括背景和所有的物体类别。除此之外,还会对于生成的候选区域的原始位置信息进行修正调整。下面介绍一些主要的two-stage物体检测器。R-CNN,2014年Grishick提出,是two-stage detector的先驱。相较于传统框架的SegDPM,R-CNN一下子在Pascal VOC2010数据集上,提升了超过10% mAP,一骑绝尘。R-CNN的pipeline主要包含三个部件:1)候选区生成2)特征抽取3)区域分类。RCNN的架构如下图所示。对于每一张图像,R-CNN通过启发式算法Selective Search生成了约2000个稀疏的候选区。SS算法被设计用来拒绝那些可以被轻易识别为背景的区域。紧接着,每个候选区域被截取出来并resize为固定大小送入深度卷积网络编码为固定维度的特征向量,并将之作为one-vs-all SVM分类器的输入。最后,BBox回归器,利用抽取出的特征作为输入对于检测框进行回归以获得紧致的边界框。在trick方面,卷积权重采用ImageNet预训练权重,只将最后的全连接层进行初始化以适应物体检测。然而,R-CNN面临着一些缺陷,包括1)每个候选区的特征由一个深度神经网络分别进行抽取,导致大量重复计算,计算时间长2)pipeline中的三步相对独立,难以进行端到端的优化获得全局最优解3)SS算法依赖于低层的视觉特征,难以从复杂语义抽取高质量的候选区。另外,由于SS算法原因难以采用GPU加速。针对R-CNN的缺点,何凯明提出了SPP-net,相比于R-CNN截取出候选区并独立送入CNN,SPP-net直接通过深度卷积网络对整幅图像计算特征图,并通过空间金字塔pooling(SPP)层从特征图上抽取固定长度的特征向量。SPP-Net的整体架构如下图所示。SPP层将整个特征图划分为NxN的网格,对于每个网格进行池化操作以生成特征向量,由不同N下抽取出的特征向量,拼接形成对于区域的表示,抽取出的特征进一步送入区域分类器和BBox回归器。相比于R-CNN, SPP-Net能够对于图像不同长宽比和尺度的区域进行处理而无需resize,避免了信息loss和几何扭曲。但是SPP-net仍然不是一个end-to-end解决方案,难以获得全局最优。另一方面,SPP层难以通过BP算法传递梯度信息,导致SPP层之前的参数都被固定,大幅限制了框架的学习能力。为了解决这些问题,Girshick提出了Fast RCNN。Fast RCNN网络架构如下图所示。Fast RCNN同样对于整幅图像计算特征图并在特征图上抽取固定维度的区域特征向量。但是与SPP-Net不同的是,Fast RCNN使用ROI池化来抽取区域特征。ROI池化是SPP层的一个特例,只采用单个尺度N对候选区进行分割,从而使得BP算法能够进行。另一方面,在特征抽取后在进入回归器和分类器之前,将特征向量送入一系列全连接层。分类器致力于区分C+1个类别,包括背景1个,物体分类C个。回归器以4个实值参数来表示BBox,以改进BBox的位置信息。Fast RCNN中,特征抽取、区域分类、边界框回归等步骤实现了端对端的优化,同时不需要额外的缓存空间存储特征。尽管Fast RCNN相比于SPP-Net获得了长足的进步,但是对于候选区的生成仍然依赖于Selective Search和Edge Boxes等传统算法,高度依赖于低层的视觉特征,而不是从数据中习得,Faster-RCNN的提出致力于解决这个问题。Faster RCNN的网络架构如下图所示。Faster RCNN 提出了RPN网络,RPN是一个全卷积网络,实现任意大小图像入,在特征图上生成一系列物体候选区域,通过一个nxn的滑移窗在特征图上滑移,获取每一位置的特征向量,其后特征向量输入两个并行的分支。一个分支为物体回归层,用以判断候选内是否有物体。另一分支为BBox回归层。最后将上述结果送入最后的分类与回归层进行物体的检测。通过RPN网络,将候选区的生成也采用数据驱动的方式实现,Faster RCNN在多个公开数据集上获得了SOTA的结果。然而,Faster-RCNN只在不同区域特征抽取上共享了计算,对于最后的区域分类步骤仍然是每个特征向量单独经过一系列FC层,这种模式在存在大量候选区的情况下造成了大量额外计算。Dai为了解决这个问题提出了R-FCN,共享区域分类步骤内的计算代价。R-FCN生成了位置敏感度图将不同类别之间的相对位置信息进行了编码,并进一步通过位置敏感ROI池化层抽取带有空间信息的区域特征。3.2 One-Stage Detector上一小结主要介绍了一下主要的两阶段检测器。区别于Two-Stage Detector算法将整个物体检测过程分割为两个部分即候选区生成和区域分类,One-Stage Detector并没有独立的候选区域生成阶段,而是将图像中所有位置都认为是潜在物体存在的位置,并且将每个ROI区域分类为前景或是物体。YOLO是One-Stage Detector经典结构,其网络结构如下图所示。YOLO将物体检测作为一个回归问题,并将整个图像空间上分成固定数量的网格单元。每个网格单元都做为候选区检测是否出现了一个或多个物体。在最初版本的实现中,每个单元认为是包含了至多两个物体的中心。对于每个单元,综合该位置是否有物体,边界框的坐标和尺寸、物体分类等信息进行预测。借助小心设计的轻量级框架,YOLO可以达到45FPS以上的实时预测特性。然而,YOLO也存在一些问题,包括1)对于每个位置至多只能检测两个物体,对于小物体和高密度物体的检测存在困难2)只利用最后的特征图进行预测,难以应对多尺度和不同长宽比的需求。上述问题在YOLO2中,进行了改进。YOLO2中采用更强的backbone net来捕获更精细的信息,同时受SSD启发,借助k-mean距离方法从训练数据中定义先验的锚框替代原先认为指定的方法。同时,加入了BN层,和多尺度训练技巧,在SSD后再次获得SOTA。为了解决YOLO的这些局限性,2016年Liu提出了SSD框架。SSD网络架构如下图所示。SSD架构同样将图像划分为网格,但是对于每个网格单元,生成了一系列不同尺度和长框比的锚点框来离散输出空间的边界框。每个锚点框由回归器生成的4个实值变量描述,并被分类器赋予了C+1个类别的分类概率。另外,SSD在多个特征图上预测物体,每个特征图负责不同尺度物体的检测。为了能够检测大物体和增大感受野,在SSD中的backbone网络中加入了额外的卷积层提取特征图。在训练技巧上为了避免大量负面的候选区主导训练梯度,采用难例挖掘,同时配合密集的数据增强来改善检测性能。但是,由于缺乏候选区域生成这一过程来过滤易于检测的负样例,前景和背景的类别不平衡是one-stage detector架构中的一个严重问题。RetinaNet的提出正是为了处理这样一种类别不均衡问题。RetinaNet的网络结构如下图所示。RetinaNet使用在交叉熵损失函数基础上改进得到的focal loss来抑制易于检测到的负样例的梯度。另外,RetinaNet使用FPN特征金字塔网络来在不同的特征图层检测多尺度物体,上述focal loss的改进相比于原有的难例挖掘技术在性能上有了极大提升。上面的框架,无论是YOLO,SSD,还是RetinaNet都需要设计锚框来训练检测器。因此,便有学者提出了无锚点框的物体检测方法。核心思想是预测边界框的关键点,而不是试图将一个物体放入锚点框内。CornerNet是一个比较新的无锚框化的物体检测方法,直接预测物体的一对角点。CornerNet的网络架构如下图所示。对于每个特征图,预测heatmap、pair embedding和offsets。Heatmap计算输出预测角点信息,可以用维度为H x W的feature map,其中C表示目标的类别(没有背景图)这个特征图的每个channel都是一个mask,mask的范围是0~1。embeddings的主要作用是预测corner点做group,也就是说检测检测出的左上角和右下角是否是同一目标的。offsets:用来对预测框的位置进行微调,因为点映射到feature map时会有量化误差。由于无需手工设计anchor来匹配物体,CornerNet在MSCOCO数据集上的结果获得了显著提高。4. 附录4.1 物体检测中的常见指标相关概念符号含义TP(true positive)实际是正例,预测为正例FP(false positive)实际为负例,预测为正例TN(true negative)实际为负例,预测为负例FN(false negative)实际为正例,预测为负例TPR(true positive rate)真正率又称为:灵敏度(sensitivity)TFR(true negative rate)真负率又称为:特指度(specificity)FNR(false negative rate)假负率又称为:虚警率(False Alarm)FPR(false positive rate)假正率R(recall)检测正确正样例 / 所有正样例P(Precision)检测正确正样例 / 预测正样例IoU(Intersection over Union)预测框与ground truth的交集和并集的比值,也被称为Jaccard指数准确率-召回率曲线(P-R曲线)以召回率为横坐标,精确率为纵坐标,用不同的阀值,统计出一组不同阀值下的精确率和召回率。AP (average precision)P-R曲线下的面积mAP (mean average precision)多个类别AP的平均值ROC曲线用不同的阀值,统计出一组不同阀值下的TPR(真阳率)和FPR(假阳率)的关系AUC (Area Under Curve)ROC曲线下的面积FPS (Frames Per Second)每秒处理图像的帧数FLOPS每秒浮点运算次数、每秒峰值速度相关计算公式:4.2 物体检测中的概念补充Selective Search使用一种过分割手段,将图像分割成小区域(1k~2k)查看现有的小区域,按照合并规则合并可能性最高的相邻两个区域。重复,直到整张图像合并成一个区域给出所有曾经存在过的区域,所谓候选区域Bounding Box(bbox) bbox是包含物体的最小矩形,目标物体应在最小矩形内部。输出一组(x,y,w,h),其中x, y 代表bbox左上角(或其他固定点,可自定义;w, h 代表bbox的宽和高;每一组(x,y,w,h)可以唯一确定一个定位框。非极大值抑制(Non-Maximum Suppression/NMS) 非极大值抑制就是把不是极大值的抑制掉,在物体检测上,就是对一个目标有多个标定框,使用极大值抑制算法滤掉多余的标定框。具体的方法是:先假设有多个矩形框,比如6个,根据分类器的类别分类概率做排序,假设从小到大属于某一物体的概率分别为A、B、C、D、E、F。从最大概率矩形框F开始,分别判断A~E与F的重叠度IOU是否大于某个设定的阈值假设B、D与F的重叠度超过阈值,那么就扔掉B、D,并标记第一个矩形框F是我们保留下来的从剩下的矩形框A、C、E中,选择概率最大的E,然后判断E与A、C的重叠度,重叠度大于一定的阈值,那么就扔掉;并标记E是我们保留下来的第二个矩形框。就这样一直重复,找到所有被保留下来的矩形框。4.3 常见框架性能比较精度上:RFCN的准确度是最高的。(VOC2007+voc2012数据集训练,mAP的计算方式是VOC2012)速度上:单步方法SSD,YOLO最快。(VOC2007+voc2012数据集训练,mAP的计算方式是VOC2012)mAP上:RetinaNet占优(COCO数据集)物体大小:对于大物体,SSD即使使用一个较弱的特征抽取器也可以获取较好的精确度。但在小物体上SSD的表现结果非常不好。(COCO数据集)
  • [公告] MindSpore第一本书《深度学习与MindSpore实践》正式发布
    在2020年3月28日,MindSpore正式开源后,MindSpore团队推出了的第一本官方书籍,作为华为智能计算技术丛书《深度学习与MindSpore实践》。                                  (文末有购买链接哦!)本书是一本端到端的深度学习书籍,由MindSpore首席科学家陈雷老师带领MindSpore专家团队为大家带来了高质量的书籍。为了方便大家阅读,书籍在内容设计上做了一定的设计:刚入坑或者希望入坑深度学习的小伙伴可以从第一章读起逐步深入。有一定基础的同学,可以通读理论部分,相信由我们深度学习专家团队整理的内容,有完整的数学推导过程及详细的理论支撑,会给大家提供扎实的理论参考。关心未来演进和新技术的同学,可以阅读无监督学习、深度强化学习、自动化机器学习、端云联合训练等章节,了解业界技术演进方向。如果你是冲着MindSpore来的,或者喜欢撸代码的同学,可以着重阅读每个章节的实践部分,同时获取实际可以运行的代码。如果你是高校的老师,可以使用本书作为教材/教辅,我们提供对应课程的课件及对应的习题,可以发邮件到contact@mindspore.com获取对应的课件,并且有机会得到我们高校教学资源的支撑。书籍也有幸得到了业界各位大佬的点评:深度学习在最近十年得到了巨**展,它使人工智能产生了革命性的突破,让我们切实地领略到人工智能给生活带来改变的潜力。《深度学习与MindSpore实践》对深度学习的基础技术进行了深入浅出的阐述,既给出了富于启发性和思想性的见解,又强调通过深度学习框架MindSpore的操作和实践,特别适合从事深度学习的研发人员参考阅读!叶杰平 滴滴出行副总裁、滴滴AI Labs负责人,美国密西根大学教授人工智能已成为我国发展的战略性方向,而人工智能的发展离不开计算框架的合理应用。MindSpore是开源的深度学习计算框架,支持端/边/云全场景全栈协同开发,适配所有的AI 应用场景。很高兴看到《深度学习与MindSpore实践》系统介绍了深度学习的基础知识和各种网络模型,并通过MindSpore给出不同领域的应用,对深度学习的推广具有重大意义。常毅吉林大学人工智能学院院长MindSpore是华为公司开发的深度学习框架,兼容目前主流的深度学习框架,支持端/边/云全场景全栈协同开发。《深度学习与MindSpore实践》在总结深度学习的理论基础上,系统地介绍了MindSpore框架,适合作为以MindSpore为工具开发人工智能系统的研发人员的参考读物。本书理论联系实践,不仅讲解深度学习的模型、概念和算法,还给出了在MindSpore上实现的具体程序及步骤,强烈推荐阅读。李航北京字节跳动科技有限公司AI实验室主任我从事人工智能教学已经十三年了,深刻感受到人工智能尤其是深度学习的教学效果很大程度上要依赖于实践环节。特别是未来一段时间,深度学习仍然依赖于大数据和强大的算力,缺乏解释性。华为公司硬件与软件齐头并进,不仅构造了令人骄傲的强大算力平台,还推出了MindSpore全场景AI计算框架,为人工智能人才的培养提供了优秀的实践平台。相信《深度学习与MindSpore实践》会很快进入全国各大高校的课堂,并建议华为公司能把整个教学生态建好,打造人工智能人才培养的高地。公茂果西安电子科技大学计算智能研究所所长深度学习在人工智能领域有着广泛的应用。《深度学习与MindSpore实践》系统介绍了深度学习的基础理论、常用的深度神经算法设计,并以大量基于MindSpore的实例帮助读者掌握深度学习算法的实现。此外,本书还对深度学习中的样本数据处理、可视化及端云协同进行了深入的探讨,因此我相信本书适合广大读者作为深度学习技术的入门读物。 谭焜 华为公司分布式与并行软件实验室主任  内容简介本书系统地介绍了深度学习理论,并基于MindSpore AI计算框架进行实践。全书共分14章,内容涵盖深度学习概况、深度学习基础知识、深度神经网络、卷积神经网络、循环神经网络、无监督学习、深度强化学习、自动化机器学习、端云协同、深度学习可视化及深度学习的数据准备等。为便于读者学习,书中还给出了基于MindSpore实现的关于深度学习的开发实例及线上资源。本书可作为普通高等学校人工智能、智能科学与技术、计算机科学与技术、电子信息工程、自动化等专业的本科生及研究生教材,也可作为从事深度学习相关工作的软件开发工程师与科研人员的学习、参考用书。书籍目录第1章 引言0011.1 人工智能的历史变迁1.2 什么是深度学习1.3 深度学习的现实应用1.4 本书的组织架构1.5 MindSpore简介第2章 深度学习基础知识2.1 回归问题算法2.2 梯度下降算法2.3 分类问题算法2.4 过拟合与欠拟合第3章 深度神经网络3.1 前向网络3.2 反向传播3.3 泛化能力3.4 用MindSpore实现简单神经网络第4章 深度神经网络的训练4.1 深度学习系统面临的主要挑战4.2 正则化4.3 Dropout 4.4 自适应学习率4.5 批标准化4.6 用MindSpore 实现深度神经网络第5章 卷积神经网络5.1 卷积操作5.2 池化5.3 残差网络5.4 应用:图片分类5.5 用MindSpore实现基于卷积神经网络图片分类第6章 循环神经网络6.1 循环神经网络概述6.2 深度循环神经网络6.3 长期依赖的挑战6.4 长短期记忆网络和门控循环神经网络6.5 应用:文本预测6.6 用MindSpore实现基于长短期记忆网络的文本预测第7章 无监督学习: 词向量7.1 Word2Vec 7.2 GloVe 7.3 Transformer 7.4 BERT 7.5 词向量典型生成算法对比7.6 应用:自动问答7.7 用MindSpore 实现基于BERT的自动问答第8章 无监督学习: 图向量8.1 图向量简介8.2 DeepWalk算法8.3 LINE算法8.4 Node2Vec算法8.5 GCN算法8.6 GAT算法8.7 应用:推荐系统第9章 无监督学习: 深度生成模型9.1 变分自编码器9.2 生成对抗网络9.3 应用:数据增强9.4 用MindSpore实现基于生成对抗网络的数据增强第10章 深度强化学习10.1 强化学习基本概念10.2 基本求解方法10.3 深度强化学习算法10.4 最新应用10.5 用MindSpore实现基于DQN的博弈游戏第11章 自动化机器学习11.1 AutoML框架11.2 现有AutoML系统介绍11.3 元学习11.4 用MindSpore实现AutoML 第12章 端云协同12.1 端侧推理12.2 端云迁移学习12.3 端云联邦学习12.4 端云协同框架第13章 深度学习可视化13.1 深度学习可视化概述13.2 MindSpore可视化实践第14章 深度学习的数据准备14.1 数据格式概述14.2 深度学习中的数据格式14.3 常用的深度学习数据格式14.4 使用MindSpore数据格式进行训练数据准备附录A 中、英文对照词汇表附录B MindSpore白皮书书籍购买链接购买地址:http://product.dangdang.com/28532532.html或扫描下方二维码:
  • 是否有现成的NLP神经网络?
    ModelArts是否可以提供一个具备一般常识的机器人,供开发者在此基础上将其训练成自己的专属机器人?
  • [技术干货] 【武汉HDZ】Python算法分类与预测——人工神经网络
    【Python算法】分类与预测——人工神经网络1.人工神经网络概述  人工神经网络(Artificial Neural Networks,ANN),是一种模范动物神经网络行为特征, 进行分布式并行信息处理的算法数学模型。它以对大脑的生理研究成果为基础,依靠系统的 复杂程度,通过调整内部大量节点之间相互连接的关系,模拟大脑的某些机理与机制,从而 达到处理信息,实现一些特定的功能的目的。2.人工神经网络具有四个基本特征  (1) 非线性:非线性关系是自然界的普遍特性,大脑的智慧就是一种非线性现象。人工 神经元处于激活或抑制两种不同的状态,这种行为在数学上表现为一种非线性关系。 具有阈值的神经元构成的网络具有更好的性能,可以提高容错性和存储容量;  (2) 非局限性:一个神经网络通常由多个神经元广泛连接而成。一个系统的整体行为不 仅取决于单个神经元的特征,而且可能主要由单元之间的相互作用、相互连接所决 定。通过单元之间的大量连接模拟大脑的非局限性。联想记忆就是非局限性的典型 例子;  (3) 非常定性:人工神经网络具有自适应、自组织、自学习能力。神经网络不但处理的 信息可以有各种变化,而且在处理信息的同时,非线性动力系统本身也在不断变化。 经常采用迭代过程描写动力系统;  (4) 非凸性:一个系统的演化方向,在一定条件下将取决于某个特定的状态函数。例如 能量函数,它的极值相应用于系统比较稳定的状态。非凸性是指这种函数有多个极 值,故系统具有多个较稳定的平衡态,这将导致系统演化的多样性。3.神经元(节点)组成神经网络图例  一个神经元由输入值,激活函数,输出值,权重组成,输入值经过激活函数变为输出值,再与权重相乘变为下一个神经元的输入值。由这样的单位组成的网络就是神经网络,    在实际生活中我们给更多的使用BP神经网络,即反向传播神经网络。4.BP神经网络的建模步骤       在反向传播算法中我们涉及到了求梯度的问题,但是求导运算对于计算机来说计算机太过复杂,于是诞生了牛顿法、拟牛顿法、梯度下降法等方式来帮助电脑计算梯度,在实际生活中我们常用5.梯度下降法  梯度类似于微分,微分是针对单变量,而梯度是针对向量。  因为直接获得最优解的计算量过大,所以通过均方误差的分析,采用迭代的方式来一步一步获得局部最优解,这就是梯度下降法。  梯度下降法通过电脑擅长的方式——迭代,极大的减少了求梯度的计算量,但是对于一些较为复杂的函数而言,梯度下降法获得的更多是局部最优解而不是全局最优解。其中α是学习率,由右图我们可以看出,蓝方获得了更优的解,而红方停在了局部最优解。  由此可见,使局部最优解接近全局最优解的方式便是调节学习率。  红点和蓝点实际上就代表了反向传播算法,下山的路径其实就代表着算法中一直在寻找的参数最优解,山上当前点的最陡峭的方向实际上就是代价函数在这一点的梯度方向,场景中观测最陡峭方向所用的工具就是微分。在下一步要走多长就是由我们算法中的学习率α所定义。  梯度下降法本身具有弹性,可以容忍不完善的数据,如果我们不能完美地描述函数,或者我们意外的走错了一步,都不至于前功尽弃。  其中误差计算通常为均方误差,即(目标值 – 实际值)的平方,多采用均方误差的原因有以下几点:  1. 使用误差的平方,我们可以很容易使用代数计算出梯度下降的斜率。  2. 误差函数平滑且连续,这使梯度下降法很好的发挥了作用——没有发生间断,也没有发生跳跃。  3. 越接近最小值,梯度就越小,这意味着,如果我们使用这个函数调节步长,超调的风险就会变得较小。  从结构上讲,BP网络具有输入层、隐藏层和输出层;从本质上讲,BP算法就是以均方误差为目标函数、采用梯度下降法来计算目标函数的最小值。  设第i层和第j层之间的权重为w(i,j),对当前层权重反向传播修正权重的公式为:Δw(i,j) = α ····· 误差 · output(j) · (1 - output(j)) · output(i)  通过反向传播修正链上的权重来改善输出情况。6.操作系统  操作机:Linux_Ubuntu  操作机默认用户:root7.实验工具    7.1.python  Python是一种计算机程序设计语言。是一种动态的、面向对象的脚本语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的、大型项目的开发。Python已经成为最受欢迎的程序设计语言之一。自从2004年以后,python的使用率呈线性增长。2011年1月,它被TIOBE编程语言排行榜评为2010年度语言。  由于Python语言的简洁性、易读性以及可扩展性,在国外用Python做科学计算的研究机构日益增多,一些知名大学已经采用Python来教授程序设计课程。例如卡耐基梅隆大学的编程基础、麻省理工学院的计算机科学及编程导论就使用Python语言讲授。  众多开源的科学计算软件包都提供了Python的调用接口,例如著名的计算机视觉库OpenCV、三维可视化库VTK、医学图像处理库ITK。而Python专用的科学计算扩展库就更多了,例如如下3个十分经典的科学计算扩展库:NumPy、SciPy和matplotlib,它们分别为Python提供了快速数组处理、数值运算以及绘图功能。因此Python语言及其众多的扩展库所构成的开发环境十分适合工程技术、科研人员处理实验数据、制作图表,甚至开发科学计算应用程序。    7.2.NumPy  NumPy系统是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵,比Python自身的嵌套列表(nested list structure)结构要高效的多(该结构也可以用来表示矩阵(matrix))。  NumPy(Numeric Python)提供了许多高级的数值编程工具,如:矩阵数据类型、矢量处理,以及精密的运算库。专为进行严格的数字处理而产生。多为很多大型金融公司使用,以及核心的科学计算组织如:Lawrence Livermore,NASA用其处理一些本来使用C++,Fortran或Matlab等所做的任务。    7.3.SciPy       SciPy是一款方便、易于使用、专为科学和工程设计的Python工具包.它包括统计,优化,整合,线性代数模块,傅里叶变换,信号和图像处理,常微分方程求解器等等.8.导入numpy,scipy.special  实验中将使用人工神经网络对含有110个手写识别数据的数据集进行识别。#导入库 import numpy #numpy是高级的数学计算库 import scipy.special #在这里用到scipy的expit()函数作为sigmod()函数 import matplotlib.pyplot9.学习人工神经网络类的框架人工神经网络类的整体框架如下:class neuralNetwork:     def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):         pass     def train(self, inputs_list, targets_list):         pass      def query(self, inputs_list):在_init_中。参数说明如下:self.inodes表示输入节点self.hnodes表示隐层节点self.onodes表示输出节点self.wih表示输入层到隐层的权重self.who表示隐层到输出层的权重self.lr表示学习率self.activation表示激活函数编写_init_函数,完整代码如下:class neuralNetwork:   def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):       self.inodes = inputnodes   #输入节点       self.hnodes = hiddennodes   #隐层节点       self.onodes = outputnodes   #输出节点       #权重链接       self.wih = numpy.random.normal(0.0, pow(self.inodes, -0.5), (self.hnodes, self.inodes))       self.who = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.onodes, self.hnodes))       # 学习率       self.lr = learningrate       # 激活函数直接调用self.activation_function       self.activation_function = lambda x: scipy.special.expit(x)       pass10.train函数实现整个神经网络的训练过程  首先实现正向传播,隐层节点的输入值等于输入层的输入值乘以wih权重,代码如下:        hidden_inputs = numpy.dot(self.wih, inputs)         hidden_outputs = self.activation_function(hidden_inputs)  输出层的输入值等于隐层输出值乘以who权重 。代码如下:        final_inputs = numpy.dot(self.who, hidden_outputs)         final_outputs = self.activation_function(final_inputs)  正向传播结束后,使用反向传播算法调节链上权重。output_errors = targets - final_outputs         hidden_errors = numpy.dot(self.who.T, output_errors)          self.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)), numpy.transpose(hidden_outputs))         self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))  train函数完整代码如下: def train(self, inputs_list, targets_list):         # 将输入和目标值转换为矩阵(numpy的数组)         inputs = numpy.array(inputs_list, ndmin=2).T         targets = numpy.array(targets_list, ndmin=2).T         hidden_inputs = numpy.dot(self.wih, inputs)         hidden_outputs = self.activation_function(hidden_inputs)         final_inputs = numpy.dot(self.who, hidden_outputs)         final_outputs = self.activation_function(final_inputs)         output_errors = targets - final_outputs         hidden_errors = numpy.dot(self.who.T, output_errors)          self.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)), numpy.transpose(hidden_outputs))         self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))         pass11.query函数  实现输入测试数据,对得到的结果进行评估。将输入值经过正向传播算法得到结果即可  代码如下: def query(self, inputs_list):         #将输入转换为矩阵         inputs = numpy.array(inputs_list, ndmin=2).T         hidden_inputs = numpy.dot(self.wih, inputs)         hidden_outputs = self.activation_function(hidden_inputs)         final_inputs = numpy.dot(self.who, hidden_outputs)         final_outputs = self.activation_function(final_inputs)         return final_outputs  注意:将以上函数都写入在框架内。12.设定参数  Mnist手写数据图片为28x28的分辨率,所以输入层采用784(28*28)个节点,隐层采用200(可自行调整)个节点,输出层采用10(0~9)个节点,学习率为0.1  代码如下:# 输入层节点 隐层节点 输出层节点 input_nodes = 784 hidden_nodes = 200 output_nodes = 10 #学习率设定为0.1 learning_rate = 0.1 #创建出训练的神经网络 n = neuralNetwork(input_nodes,hidden_nodes,output_nodes, learning_rate)13.读取训练数据集  代码如下:# 打开mnist_CSV训练文件 training_data_file = open("/mnt/dataset_54/mnist_train_100_bcdb280d7666ea5865e56b56d47167ec.csv", 'r') training_data_list = training_data_file.readlines() training_data_file.close()14.用训练数据集对神经网络进行训练  代码如下:#训练网络 # epochs表示训练世代 epochs = 5 for e in range(epochs):     for record in training_data_list:         # 去掉,         all_values = record.split(',')         # inputs进行转换         inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01         # 把所有0转换为0.01         targets = numpy.zeros(output_nodes) + 0.01         # 把所有1转换为0.99         targets[int(all_values[0])] = 0.99         n.train(inputs, targets)         pass     pass15.读取测试数据集  代码如下:# 打开mnist_CSV测试文件 test_data_file = open("/mnt/dataset_54/mnist_test_10_de377bdbad1fe5920e467c5dee8cb718.csv", 'r') test_data_list = test_data_file.readlines() test_data_file.close()16.将测试数据集读入训练好的神经网络中并输出结果  代码如下:# 测试神经网络 # 用scorecaed统计正确的数目 scorecard = [] for record in test_data_list:     # 去除测试数据中的逗号     all_values = record.split(',')     # 正确的答案放在第零位标签     correct_label = int(all_values[0])     print(correct_label,"correct answer")     # 处理测试数据     inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01     outputs = n.query(inputs)     #获得输出的概率的最大值所对应的标签     label = numpy.argmax(outputs)          print(outputs)     print(label,"network's answer")     print("\n")     #计量正确识别数     if (label == correct_label):         #正确的就在scorecard加个1         scorecard.append(1)     else:         # 错误的就在scorecard加个0         scorecard.append(0)         pass     pass  这是其中三组输出结果,correct answer是图片的标签即正确答案,network's answer是神经网络识别的结果即测试结果。中间的矩阵是神经网络的十个输出节点输出的值,自上而下分别代表着0~9的概率,概率高者即为神经网络得到的答案。完整代码如下:#导入库 import numpy #numpy是高级的数学计算库 import scipy.special #在这里用到scipy的expit()函数作为sigmod()函数 import matplotlib.pyplot class neuralNetwork:     def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):         self.inodes = inputnodes   #输入节点         self.hnodes = hiddennodes   #隐层节点         self.onodes = outputnodes   #输出节点         #权重链接         self.wih = numpy.random.normal(0.0, pow(self.inodes, -0.5), (self.hnodes, self.inodes))         self.who = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.onodes, self.hnodes))          # 学习率         self.lr = learningrate         # 激活函数直接调用self.activation_function         self.activation_function = lambda x: scipy.special.expit(x)         pass                  def train(self, inputs_list, targets_list):         # 将输入和目标值转换为矩阵(numpy的数组)         inputs = numpy.array(inputs_list, ndmin=2).T         targets = numpy.array(targets_list, ndmin=2).T         hidden_inputs = numpy.dot(self.wih, inputs)         hidden_outputs = self.activation_function(hidden_inputs)         final_inputs = numpy.dot(self.who, hidden_outputs)         final_outputs = self.activation_function(final_inputs)         output_errors = targets - final_outputs         hidden_errors = numpy.dot(self.who.T, output_errors)          self.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)), numpy.transpose(hidden_outputs))         self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))         pass              def query(self, inputs_list):         #将输入转换为矩阵         inputs = numpy.array(inputs_list, ndmin=2).T         hidden_inputs = numpy.dot(self.wih, inputs)         hidden_outputs = self.activation_function(hidden_inputs)         final_inputs = numpy.dot(self.who, hidden_outputs)         final_outputs = self.activation_function(final_inputs)         return final_outputs # 输入层节点 隐层节点 输出层节点 input_nodes = 784 hidden_nodes = 200 output_nodes = 10 #学习率设定为0.1 learning_rate = 0.1 #创建出训练的神经网络 n = neuralNetwork(input_nodes,hidden_nodes,output_nodes, learning_rate) # 打开mnist_CSV训练文件 training_data_file = open("/mnt/dataset_54/mnist_train_100_bcdb280d7666ea5865e56b56d47167ec.csv", 'r') training_data_list = training_data_file.readlines() training_data_file.close() #训练网络 # epochs表示训练世代 epochs = 5 for e in range(epochs):     for record in training_data_list:         # 去掉,         all_values = record.split(',')         # inputs进行转换         inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01         # 把所有0转换为0.01         targets = numpy.zeros(output_nodes) + 0.01         # 把所有1转换为0.99         targets[int(all_values[0])] = 0.99         n.train(inputs, targets)         pass     pass # 打开mnist_CSV测试文件 test_data_file = open("/mnt/dataset_54/mnist_test_10_de377bdbad1fe5920e467c5dee8cb718.csv", 'r') test_data_list = test_data_file.readlines() test_data_file.close() # 测试神经网络 # 用scorecaed统计正确的数目 scorecard = [] for record in test_data_list:     # 去除测试数据中的逗号     all_values = record.split(',')     # 正确的答案放在第零位标签     correct_label = int(all_values[0])     print(correct_label,"correct answer")     # 处理测试数据     inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01     outputs = n.query(inputs)     #获得输出的概率的最大值所对应的标签     label = numpy.argmax(outputs)     print(outputs)     print(label,"network's answer")     #计量正确识别数     if (label == correct_label):         #正确的就在scorecard加个1         scorecard.append(1)     else:         # 错误的就在scorecard加个0         scorecard.append(0)         pass     pass # 计算正确率 scorecard_array = numpy.asarray(scorecard) print ("performance = ", scorecard_array.sum() / scorecard_array.size)
  • [问题求助] TF转OM失败
    和这个帖子里说的基本上是一个问题https://bbs.huaweicloud.com/forum/thread-39280-1-1.html,想请教一下,如何把卷积的filter放到卷积里面,具体是要在pytorch定义网络的时候还是在onnx转tf的时候啊
  • [Atlas500] 使用atlas500进行深度卷积网络推理时遇到模型精度的问题
    具体问题如下,本人在使用Atlas500的NPU进行模型推理时,模型 (.om模型) 精度与在台式电脑上 (.pd模型) 测试精度差异很大。观察网络的输出,发现输出结果与台式电脑上的不对应。两个模型的网络参数应该是相同的,Atlas500是使用台式电脑对应的tensorflow框架下的.pd模型利用华为官方模型转换到.om模型下的。输入输出节点应该也没问题。所采用的深度卷积网络是2D的, 模型出了2D卷积只用了一些自己定义的batch_normalization,涉及到的算子包括tf.nn.moments, tf.reduce_mean, tf.sqrt, tf.add这些, 应该也都在算子边界内。不过推理时候就是出来的结果差异很大, 从本来应该是0~1的范围,跑到了上千,很疑惑。PS: 附件上传了模型相关文件,包括训练所使用的模型结构、.pd模型和.om模型。
  • [AI大赛] 目标检测比赛中的trick(已更新更多代码解析)
    知乎链接:https://zhuanlan.zhihu.com/p/102817180感谢大家点个赞和关注!!增添以下内容:cascade_rcnn_r50_fpn_1x.py部分代码解析,如果大家只想看各部分代码解析,点击下面链接:初识CV:mmdetection的configs中的各项参数具体解释zhuanlan.zhihu.com2. 各部分trick在MMDetection的对应部分加了代码解析。例如:数据增强部分,添加部分如下图:文章末尾部分有用MMDetection框架写的代码,代码包含两部分:各部分代码解析,faster_rcnn_r50_fpn_1x.py和cascade_rcnn_r50_fpn_1x.py。trick部分代码,cascade_rcnn_r50_fpn_1x.py。1.数据增强数据增强是增加深度模型鲁棒性和泛化性能的常用手段,随机翻转、随机裁剪、添加噪声等也被引入到检测任务的训练中来,个人认为数据(监督信息)的适时传入可能是更有潜力的方向。个人观点:问题:为什么图像和Bbox需要进行数据增强呢?答:因为数据多了就可以尽可能多的学习到图像中的不变性,学习到的不变性越多那么模型的泛化能力越强。但是输入到CNN中的图像为什么不具有平移不变性?如何去解决?下面链接有专门的解析:初识CV:输入到CNN中的图像为什么不具有平移不变性?如何去解决?zhuanlan.zhihu.comMMDetection中,数据增强包括两部分:(源码解析)图像增强。源码在mmdet/datasets/extra_aug.py里面,包括RandomCrop、brightness、contrast、saturation、ExtraAugmentation等等图像增强方法。添加位置是train_pipeline或test_pipeline这个地方(一般train进行增强而test不需要),例如数据增强RandomFlip,flip_ratio代表随机翻转的概率:train_pipeline = [     dict(type='LoadImageFromFile'),     dict(type='LoadAnnotations', with_bbox=True),     dict(type='Resize', img_scale=(1333, 800), keep_ratio=True),     dict(type='RandomFlip', flip_ratio=0.5),     dict(type='Normalize', **img_norm_cfg),     dict(type='Pad', size_divisor=32),     dict(type='DefaultFormatBundle'),     dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']), ] test_pipeline = [     dict(type='LoadImageFromFile'),     dict(         type='MultiScaleFlipAug',         img_scale=(1333, 800),         flip=False,         transforms=[             dict(type='Resize', keep_ratio=True),             dict(type='RandomFlip'),             dict(type='Normalize', **img_norm_cfg),             dict(type='Pad', size_divisor=32),             dict(type='ImageToTensor', keys=['img']),             dict(type='Collect', keys=['img']),         ]) ]2. Bbox增强。源码在mmdet/datasets/custom.py里面,增强源码为:    def pre_pipeline(self, results):         results['img_prefix'] = self.img_prefix         results['seg_prefix'] = self.seg_prefix         results['proposal_file'] = self.proposal_file         results['bbox_fields'] = []         results['mask_fields'] = []2.Multi-scale Training/Testing 多尺度训练/测试输入图片的尺寸对检测模型的性能影响相当明显,事实上,多尺度是提升精度最明显的技巧之一。在基础网络部分常常会生成比原图小数十倍的特征图,导致小物体的特征描述不容易被检测网络捕捉。通过输入更大、更多尺寸的图片进行训练,能够在一定程度上提高检测模型对物体大小的鲁棒性,仅在测试阶段引入多尺度,也可享受大尺寸和多尺寸带来的增益。multi-scale training/testing最早见于[1],训练时,预先定义几个固定的尺度,每个epoch随机选择一个尺度进行训练。测试时,生成几个不同尺度的feature map,对每个Region Proposal,在不同的feature map上也有不同的尺度,我们选择最接近某一固定尺寸(即检测头部的输入尺寸)的Region Proposal作为后续的输入。在[2]中,选择单一尺度的方式被Maxout(element-wise max,逐元素取最大)取代:随机选两个相邻尺度,经过Pooling后使用Maxout进行合并,如下图所示。使用Maxout合并feature vector近期的工作如FPN等已经尝试在不同尺度的特征图上进行检测,但多尺度训练/测试仍作为一种提升性能的有效技巧被应用在MS COCO等比赛中。MMDetection中,多尺度训练/测试:(源码解析)只需要修改train_pipeline 和test_pipeline中的img_scale部分即可(换成[(), ()])。带来的影响是:train达到拟合的时间增加、test的时间增加,一旦test的时间增加一定会影响比赛的分数,因为比赛都会将测试的时间作为评分标准之一:train_pipeline = [     dict(type='LoadImageFromFile'),     dict(type='LoadAnnotations', with_bbox=True),     dict(type='Resize', img_scale=(1333, 800), keep_ratio=True), #这里可以更换多尺度[(),()]     dict(type='RandomFlip', flip_ratio=0.5),     dict(type='Normalize', **img_norm_cfg),     dict(type='Pad', size_divisor=32),     dict(type='DefaultFormatBundle'),     dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']), ] test_pipeline = [     dict(type='LoadImageFromFile'),     dict(         type='MultiScaleFlipAug',         img_scale=(1333, 800),         flip=False,         transforms=[             dict(type='Resize', keep_ratio=True),             dict(type='RandomFlip'),             dict(type='Normalize', **img_norm_cfg),             dict(type='Pad', size_divisor=32),             dict(type='ImageToTensor', keys=['img']),             dict(type='Collect', keys=['img']),         ]) ]3.Global Context 全局语境这一技巧在ResNet的工作[3]中提出,做法是把整张图片作为一个RoI,对其进行RoI Pooling并将得到的feature vector拼接于每个RoI的feature vector上,作为一种辅助信息传入之后的R-CNN子网络。目前,也有把相邻尺度上的RoI互相作为context共同传入的做法。这一部分暂时没有代码解析。4.Box Refinement/Voting 预测框微调/投票法微调法和投票法由工作[4]提出,前者也被称为Iterative Localization。微调法最初是在SS算法得到的Region Proposal基础上用检测头部进行多次迭代得到一系列box,在ResNet的工作中,作者将输入R-CNN子网络的Region Proposal和R-CNN子网络得到的预测框共同进行NMS(见下面小节)后处理,最后,把跟NMS筛选所得预测框的IoU超过一定阈值的预测框进行按其分数加权的平均,得到最后的预测结果。投票法可以理解为以顶尖筛选出一流,再用一流的结果进行加权投票决策。不同的训练策略,不同的 epoch 预测的结果,使用 NMS 来融合,或者softnms需要调整的参数:box voting 的阈值,不同的输入中这个框至少出现了几次来允许它输出,得分的阈值,一个目标框的得分低于这个阈值的时候,就删掉这个目标框。这一部分暂时没有代码解析。5.随机权值平均(Stochastic Weight Averaging,SWA)随机权值平均只需快速集合集成的一小部分算力,就可以接近其表现。SWA 可以用在任意架构和数据集上,都会有不错的表现。根据论文中的实验,SWA 可以得到我之前提到过的更宽的极小值。在经典认知下,SWA 不算集成,因为在训练的最终阶段你只得到一个模型,但它的表现超过了快照集成,接近 FGE(多个模型取平均)。左图:W1、W2、W3分别代表3个独立训练的网络,Wswa为其平均值。中图:WSWA 在测试集上的表现超越了SGD。右图:WSWA 在训练时的损失比SGD要高。结合 WSWA 在测试集上优于 SGD 的表现,这意味着尽管 WSWA 训练时的损失较高,它的泛化性更好。SWA 的直觉来自以下由经验得到的观察:每个学习率周期得到的局部极小值倾向于堆积在损失平面的低损失值区域的边缘(上图左侧的图形中,褐色区域误差较低,点W1、W2、3分别表示3个独立训练的网络,位于褐色区域的边缘)。对这些点取平均值,可能得到一个宽阔的泛化解,其损失更低(上图左侧图形中的 WSWA)。下面是 SWA 的工作原理。它只保存两个模型,而不是许多模型的集成:第一个模型保存模型权值的平均值(WSWA)。在训练结束后,它将是用于预测的最终模型。第二个模型(W)将穿过权值空间,基于周期性学习率规划探索权重空间。SWA权重更新公式在每个学习率周期的末尾,第二个模型的当前权重将用来更新第一个模型的权重(公式如上)。因此,在训练阶段,只需训练一个模型,并在内存中储存两个模型。预测时只需要平均模型,基于其进行预测将比之前描述的集成快很多,因为在那种集成中,你需要使用多个模型进行预测,最后再进行平均。方法实现:论文的作者自己提供了一份 PyTorch 的实现 :timgaripov/swagithub.com此外,基于 fast.ai 库的 SWA 可见 :Add Stochastic Weight Averaging by wdhorton · Pull Request #276 · fastai/fastaigithub.com6.OHEM 在线难例挖掘OHEM(Online Hard negative Example Mining,在线难例挖掘)见于[5]。两阶段检测模型中,提出的RoI Proposal在输入R-CNN子网络前,我们有机会对正负样本(背景类和前景类)的比例进行调整。通常,背景类的RoI Proposal个数要远远多于前景类,Fast R-CNN的处理方式是随机对两种样本进行上采样和下采样,以使每一batch的正负样本比例保持在1:3,这一做法缓解了类别比例不均衡的问题,是两阶段方法相比单阶段方法具有优势的地方,也被后来的大多数工作沿用。OHEM图解但在OHEM的工作中,作者提出用R-CNN子网络对RoI Proposal预测的分数来决定每个batch选用的样本,这样,输入R-CNN子网络的RoI Proposal总为其表现不好的样本,提高了监督学习的效率。实际操作中,维护两个完全相同的R-CNN子网络,其中一个只进行前向传播来为RoI Proposal的选择提供指导,另一个则为正常的R-CNN,参与损失的计算并更新权重,并且将权重复制到前者以使两个分支权重同步。OHEM以额外的R-CNN子网络的开销来改善RoI Proposal的质量,更有效地利用数据的监督信息,成为两阶段模型提升性能的常用部件之一。MMDetection中,OHEM(online hard example mining):(源码解析)rcnn=[         dict(             assigner=dict(                 type='MaxIoUAssigner',                 pos_iou_thr=0.4, # 更换                 neg_iou_thr=0.4,                 min_pos_iou=0.4,                 ignore_iof_thr=-1),             sampler=dict(                 type='OHEMSampler',                 num=512,                 pos_fraction=0.25,                 neg_pos_ub=-1,                 add_gt_as_proposals=True),             pos_weight=-1,             debug=False),         dict(             assigner=dict(                 type='MaxIoUAssigner',                 pos_iou_thr=0.5,                 neg_iou_thr=0.5,                 min_pos_iou=0.5,                 ignore_iof_thr=-1),             sampler=dict(                 type='OHEMSampler', # 解决难易样本,也解决了正负样本比例问题。                 num=512,                 pos_fraction=0.25,                 neg_pos_ub=-1,                 add_gt_as_proposals=True),             pos_weight=-1,             debug=False),         dict(             assigner=dict(                 type='MaxIoUAssigner',                 pos_iou_thr=0.6,                 neg_iou_thr=0.6,                 min_pos_iou=0.6,                 ignore_iof_thr=-1),             sampler=dict(                 type='OHEMSampler',                 num=512,                 pos_fraction=0.25,                 neg_pos_ub=-1,                 add_gt_as_proposals=True),             pos_weight=-1,             debug=False)     ],     stage_loss_weights=[1, 0.5, 0.25])7.Soft NMS 软化非极大抑制NMS后处理图示NMS(Non-Maximum Suppression,非极大抑制)是检测模型的标准后处理操作,用于去除重合度(IoU)较高的预测框,只保留预测分数最高的预测框作为检测输出。Soft NMS由[6]提出。在传统的NMS中,跟最高预测分数预测框重合度超出一定阈值的预测框会被直接舍弃,作者认为这样不利于相邻物体的检测。提出的改进方法是根据IoU将预测框的预测分数进行惩罚,最后再按分数过滤。配合Deformable Convnets(将在之后的文章介绍),Soft NMS在MS COCO上取得了当时最佳的表现。算法改进如下:Soft-NMS算法改进上图中的ff即为软化函数,通常取线性或高斯函数,后者效果稍好一些。当然,在享受这一增益的同时,Soft-NMS也引入了一些超参,对不同的数据集需要试探以确定最佳配置。MMDetection中,Soft NMS 软化非极大抑制:(源码解析)test_cfg = dict(     rpn=dict(         nms_across_levels=False,         nms_pre=1000,         nms_post=1000,         max_num=1000,         nms_thr=0.7,         min_bbox_size=0),     rcnn=dict(         score_thr=0.05, nms=dict(type='nms', iou_thr=0.5), max_per_img=20)) # 这里可以换为sof_tnms8.RoIAlign RoI对齐RoIAlign是Mask R-CNN([7])的工作中提出的,针对的问题是RoI在进行Pooling时有不同程度的取整,这影响了实例分割中mask损失的计算。文章采用双线性插值的方法将RoI的表示精细化,并带来了较为明显的性能提升。这一技巧也被后来的一些工作(如light-head R-CNN)沿用。这一部分暂时没有代码解析。9.其他方法除去上面所列的技巧外,还有一些做法也值得注意:更好的先验(YOLOv2):使用聚类方法统计数据中box标注的大小和长宽比,以更好的设置anchor box的生成配置更好的pre-train模型:检测模型的基础网络通常使用ImageNet(通常是ImageNet-1k)上训练好的模型进行初始化,使用更大的数据集(ImageNet-5k)预训练基础网络对精度的提升亦有帮助超参数的调整:部分工作也发现如NMS中IoU阈值的调整(从0.3到0.5)也有利于精度的提升,但这一方面尚无最佳配置参照最后,集成(Ensemble)作为通用的手段也被应用在比赛中。代码部分1.各部分代码解析1.1 faster_rcnn_r50_fpn_1x.py:首先介绍一下这个配置文件所描述的框架,它是基于resnet50的backbone,有着5个fpn特征层的faster-RCNN目标检测网络,训练迭代次数为标准的12次epoch。# model settings model = dict( type='FasterRCNN',                         # model类型     pretrained='modelzoo://resnet50',          # 预训练模型:imagenet-resnet50     backbone=dict(         type='ResNet',                         # backbone类型         depth=50,                              # 网络层数         num_stages=4,                          # resnet的stage数量         out_indices=(0, 1, 2, 3),              # 输出的stage的序号         frozen_stages=1,                       # 冻结的stage数量,即该stage不更新参数,-1表示所有的stage都更新参数         style='pytorch'),                      # 网络风格:如果设置pytorch,则stride为2的层是conv3x3的卷积层;如果设置caffe,则stride为2的层是第一个conv1x1的卷积层     neck=dict(         type='FPN',                            # neck类型         in_channels=[256, 512, 1024, 2048],    # 输入的各个stage的通道数         out_channels=256,                      # 输出的特征层的通道数         num_outs=5),                           # 输出的特征层的数量     rpn_head=dict(         type='RPNHead',                        # RPN网络类型         in_channels=256,                       # RPN网络的输入通道数         feat_channels=256,                     # 特征层的通道数         anchor_scales=[8],                     # 生成的anchor的baselen,baselen = sqrt(w*h),w和h为anchor的宽和高         anchor_ratios=[0.5, 1.0, 2.0],         # anchor的宽高比         anchor_strides=[4, 8, 16, 32, 64],     # 在每个特征层上的anchor的步长(对应于原图)         target_means=[.0, .0, .0, .0],         # 均值         target_stds=[1.0, 1.0, 1.0, 1.0],      # 方差         use_sigmoid_cls=True),                 # 是否使用sigmoid来进行分类,如果False则使用softmax来分类     bbox_roi_extractor=dict(         type='SingleRoIExtractor',                                   # RoIExtractor类型         roi_layer=dict(type='RoIAlign', out_size=7, sample_num=2),   # ROI具体参数:ROI类型为ROIalign,输出尺寸为7,sample数为2         out_channels=256,                                            # 输出通道数         featmap_strides=[4, 8, 16, 32]),                             # 特征图的步长     bbox_head=dict(         type='SharedFCBBoxHead',                     # 全连接层类型         num_fcs=2,                                   # 全连接层数量         in_channels=256,                             # 输入通道数         fc_out_channels=1024,                        # 输出通道数         roi_feat_size=7,                             # ROI特征层尺寸         num_classes=81,                              # 分类器的类别数量+1,+1是因为多了一个背景的类别         target_means=[0., 0., 0., 0.],               # 均值         target_stds=[0.1, 0.1, 0.2, 0.2],            # 方差         reg_class_agnostic=False))                   # 是否采用class_agnostic的方式来预测,class_agnostic表示输出bbox时只考虑其是否为前景,后续分类的时候再根据该bbox在网络中的类别得分来分类,也就是说一个框可以对应多个类别 # model training and testing settings train_cfg = dict(     rpn=dict(         assigner=dict(             type='MaxIoUAssigner',            # RPN网络的正负样本划分             pos_iou_thr=0.7,                  # 正样本的iou阈值             neg_iou_thr=0.3,                  # 负样本的iou阈值             min_pos_iou=0.3,                  # 正样本的iou最小值。如果assign给ground truth的anchors中最大的IOU低于0.3,则忽略所有的anchors,否则保留最大IOU的anchor             ignore_iof_thr=-1),               # 忽略bbox的阈值,当ground truth中包含需要忽略的bbox时使用,-1表示不忽略         sampler=dict(             type='RandomSampler',             # 正负样本提取器类型             num=256,                          # 需提取的正负样本数量             pos_fraction=0.5,                 # 正样本比例             neg_pos_ub=-1,                    # 最大负样本比例,大于该比例的负样本忽略,-1表示不忽略             add_gt_as_proposals=False),       # 把ground truth加入proposal作为正样本         allowed_border=0,                     # 允许在bbox周围外扩一定的像素         pos_weight=-1,                        # 正样本权重,-1表示不改变原始的权重         smoothl1_beta=1 / 9.0,                # 平滑L1系数         debug=False),                         # debug模式     rcnn=dict(         assigner=dict(             type='MaxIoUAssigner',            # RCNN网络正负样本划分             pos_iou_thr=0.5,                  # 正样本的iou阈值             neg_iou_thr=0.5,                  # 负样本的iou阈值             min_pos_iou=0.5,                  # 正样本的iou最小值。如果assign给ground truth的anchors中最大的IOU低于0.3,则忽略所有的anchors,否则保留最大IOU的anchor             ignore_iof_thr=-1),               # 忽略bbox的阈值,当ground truth中包含需要忽略的bbox时使用,-1表示不忽略         sampler=dict(             type='RandomSampler',             # 正负样本提取器类型             num=512,                          # 需提取的正负样本数量             pos_fraction=0.25,                # 正样本比例             neg_pos_ub=-1,                    # 最大负样本比例,大于该比例的负样本忽略,-1表示不忽略             add_gt_as_proposals=True),        # 把ground truth加入proposal作为正样本         pos_weight=-1,                        # 正样本权重,-1表示不改变原始的权重         debug=False))                         # debug模式 test_cfg = dict(     rpn=dict(                                 # 推断时的RPN参数         nms_across_levels=False,              # 在所有的fpn层内做nms         nms_pre=2000,                         # 在nms之前保留的的得分最高的proposal数量         nms_post=2000,                        # 在nms之后保留的的得分最高的proposal数量         max_num=2000,                         # 在后处理完成之后保留的proposal数量         nms_thr=0.7,                          # nms阈值         min_bbox_size=0),                     # 最小bbox尺寸     rcnn=dict(         score_thr=0.05, nms=dict(type='nms', iou_thr=0.5), max_per_img=100)   # max_per_img表示最终输出的det bbox数量     # soft-nms is also supported for rcnn testing     # e.g., nms=dict(type='soft_nms', iou_thr=0.5, min_score=0.05)            # soft_nms参数 ) # dataset settings dataset_type = 'CocoDataset'                # 数据集类型 data_root = 'data/coco/'                    # 数据集根目录 img_norm_cfg = dict(     mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)   # 输入图像初始化,减去均值mean并处以方差std,to_rgb表示将bgr转为rgb data = dict(     imgs_per_gpu=2,                # 每个gpu计算的图像数量     workers_per_gpu=2,             # 每个gpu分配的线程数     train=dict(         type=dataset_type,                                                 # 数据集类型         ann_file=data_root + 'annotations/instances_train2017.json',       # 数据集annotation路径         img_prefix=data_root + 'train2017/',                               # 数据集的图片路径         img_scale=(1333, 800),                                             # 输入图像尺寸,最大边1333,最小边800         img_norm_cfg=img_norm_cfg,                                         # 图像初始化参数         size_divisor=32,                                                   # 对图像进行resize时的最小单位,32表示所有的图像都会被resize成32的倍数         flip_ratio=0.5,                                                    # 图像的随机左右翻转的概率         with_mask=False,                                                   # 训练时附带mask         with_crowd=True,                                                   # 训练时附带difficult的样本         with_label=True),                                                  # 训练时附带label     val=dict(         type=dataset_type,                                                 # 同上         ann_file=data_root + 'annotations/instances_val2017.json',         # 同上         img_prefix=data_root + 'val2017/',                                 # 同上         img_scale=(1333, 800),                                             # 同上         img_norm_cfg=img_norm_cfg,                                         # 同上         size_divisor=32,                                                   # 同上         flip_ratio=0,                                                      # 同上         with_mask=False,                                                   # 同上         with_crowd=True,                                                   # 同上         with_label=True),                                                  # 同上     test=dict(         type=dataset_type,                                                 # 同上         ann_file=data_root + 'annotations/instances_val2017.json',         # 同上         img_prefix=data_root + 'val2017/',                                 # 同上         img_scale=(1333, 800),                                             # 同上         img_norm_cfg=img_norm_cfg,                                         # 同上         size_divisor=32,                                                   # 同上         flip_ratio=0,                                                      # 同上         with_mask=False,                                                   # 同上         with_label=False,                                                  # 同上         test_mode=True))                                                   # 同上 # optimizer optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)   # 优化参数,lr为学习率,momentum为动量因子,weight_decay为权重衰减因子 optimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2))          # 梯度均衡参数 # learning policy lr_config = dict(     policy='step',                        # 优化策略     warmup='linear',                      # 初始的学习率增加的策略,linear为线性增加     warmup_iters=500,                     # 在初始的500次迭代中学习率逐渐增加     warmup_ratio=1.0 / 3,                 # 起始的学习率     step=[8, 11])                         # 在第8和11个epoch时降低学习率 checkpoint_config = dict(interval=1)      # 每1个epoch存储一次模型 # yapf:disable log_config = dict(     interval=50,                          # 每50个batch输出一次信息     hooks=[         dict(type='TextLoggerHook'),      # 控制台输出信息的风格         # dict(type='TensorboardLoggerHook')     ]) # yapf:enable # runtime settings total_epochs = 12                               # 最大epoch数 dist_params = dict(backend='nccl')              # 分布式参数 log_level = 'INFO'                              # 输出信息的完整度级别 work_dir = './work_dirs/faster_rcnn_r50_fpn_1x' # log文件和模型文件存储路径 load_from = None                                # 加载模型的路径,None表示从预训练模型加载 resume_from = None                              # 恢复训练模型的路径 workflow = [('train', 1)]                       # 当前工作区名称1.2 cascade_rcnn_r50_fpn_1x.pycascade-RCNN是cvpr2018的文章,相比于faster-RCNN的改进主要在于其RCNN有三个stage,这三个stage逐级refine检测的结果,使得结果达到更高的精度。下面逐条解释其config的含义,与faster-RCNN相同的部分就不再赘述# model settings model = dict(     type='CascadeRCNN',     num_stages=3,                     # RCNN网络的stage数量,在faster-RCNN中为1     pretrained='modelzoo://resnet50',     backbone=dict(         type='ResNet',         depth=50,         num_stages=4,         out_indices=(0, 1, 2, 3),         frozen_stages=1,         style='pytorch'),     neck=dict(         type='FPN',         in_channels=[256, 512, 1024, 2048],         out_channels=256,         num_outs=5),     rpn_head=dict(         type='RPNHead',         in_channels=256,         feat_channels=256,         anchor_scales=[8],         anchor_ratios=[0.5, 1.0, 2.0],         anchor_strides=[4, 8, 16, 32, 64],         target_means=[.0, .0, .0, .0],         target_stds=[1.0, 1.0, 1.0, 1.0],         use_sigmoid_cls=True),     bbox_roi_extractor=dict(         type='SingleRoIExtractor',         roi_layer=dict(type='RoIAlign', out_size=7, sample_num=2),         out_channels=256,         featmap_strides=[4, 8, 16, 32]),     bbox_head=[         dict(             type='SharedFCBBoxHead',             num_fcs=2,             in_channels=256,             fc_out_channels=1024,             roi_feat_size=7,             num_classes=81,             target_means=[0., 0., 0., 0.],             target_stds=[0.1, 0.1, 0.2, 0.2],             reg_class_agnostic=True),         dict(             type='SharedFCBBoxHead',             num_fcs=2,             in_channels=256,             fc_out_channels=1024,             roi_feat_size=7,             num_classes=81,             target_means=[0., 0., 0., 0.],             target_stds=[0.05, 0.05, 0.1, 0.1],             reg_class_agnostic=True),         dict(             type='SharedFCBBoxHead',             num_fcs=2,             in_channels=256,             fc_out_channels=1024,             roi_feat_size=7,             num_classes=81,             target_means=[0., 0., 0., 0.],             target_stds=[0.033, 0.033, 0.067, 0.067],             reg_class_agnostic=True)     ]) # model training and testing settings train_cfg = dict(     rpn=dict(         assigner=dict(             type='MaxIoUAssigner',             pos_iou_thr=0.7,             neg_iou_thr=0.3,             min_pos_iou=0.3,             ignore_iof_thr=-1),         sampler=dict(             type='RandomSampler',             num=256,             pos_fraction=0.5,             neg_pos_ub=-1,             add_gt_as_proposals=False),         allowed_border=0,         pos_weight=-1,         smoothl1_beta=1 / 9.0,         debug=False),     rcnn=[                    # 注意,这里有3个RCNN的模块,对应开头的那个RCNN的stage数量         dict(             assigner=dict(                 type='MaxIoUAssigner',                 pos_iou_thr=0.5,                 neg_iou_thr=0.5,                 min_pos_iou=0.5,                 ignore_iof_thr=-1),             sampler=dict(                 type='RandomSampler',                 num=512,                 pos_fraction=0.25,                 neg_pos_ub=-1,                 add_gt_as_proposals=True),             pos_weight=-1,             debug=False),         dict(             assigner=dict(                 type='MaxIoUAssigner',                 pos_iou_thr=0.6,                 neg_iou_thr=0.6,                 min_pos_iou=0.6,                 ignore_iof_thr=-1),             sampler=dict(                 type='RandomSampler',                 num=512,                 pos_fraction=0.25,                 neg_pos_ub=-1,                 add_gt_as_proposals=True),             pos_weight=-1,             debug=False),         dict(             assigner=dict(                 type='MaxIoUAssigner',                 pos_iou_thr=0.7,                 neg_iou_thr=0.7,                 min_pos_iou=0.7,                 ignore_iof_thr=-1),             sampler=dict(                 type='RandomSampler',                 num=512,                 pos_fraction=0.25,                 neg_pos_ub=-1,                 add_gt_as_proposals=True),             pos_weight=-1,             debug=False)     ],     stage_loss_weights=[1, 0.5, 0.25])     # 3个RCNN的stage的loss权重 test_cfg = dict(     rpn=dict(         nms_across_levels=False,         nms_pre=2000,         nms_post=2000,         max_num=2000,         nms_thr=0.7,         min_bbox_size=0),     rcnn=dict(         score_thr=0.05, nms=dict(type='nms', iou_thr=0.5), max_per_img=100),     keep_all_stages=False)         # 是否保留所有stage的结果 # dataset settings dataset_type = 'CocoDataset' data_root = 'data/coco/' img_norm_cfg = dict(     mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True) data = dict(     imgs_per_gpu=2,     workers_per_gpu=2,     train=dict(         type=dataset_type,         ann_file=data_root + 'annotations/instances_train2017.json',         img_prefix=data_root + 'train2017/',         img_scale=(1333, 800),         img_norm_cfg=img_norm_cfg,         size_divisor=32,         flip_ratio=0.5,         with_mask=False,         with_crowd=True,         with_label=True),     val=dict(         type=dataset_type,         ann_file=data_root + 'annotations/instances_val2017.json',         img_prefix=data_root + 'val2017/',         img_scale=(1333, 800),         img_norm_cfg=img_norm_cfg,         size_divisor=32,         flip_ratio=0,         with_mask=False,         with_crowd=True,         with_label=True),     test=dict(         type=dataset_type,         ann_file=data_root + 'annotations/instances_val2017.json',         img_prefix=data_root + 'val2017/',         img_scale=(1333, 800),         img_norm_cfg=img_norm_cfg,         size_divisor=32,         flip_ratio=0,         with_mask=False,         with_label=False,         test_mode=True)) # optimizer optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001) optimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2)) # learning policy lr_config = dict(     policy='step',     warmup='linear',     warmup_iters=500,     warmup_ratio=1.0 / 3,     step=[8, 11]) checkpoint_config = dict(interval=1) # yapf:disable log_config = dict(     interval=50,     hooks=[         dict(type='TextLoggerHook'),         # dict(type='TensorboardLoggerHook')     ]) # yapf:enable # runtime settings total_epochs = 12 dist_params = dict(backend='nccl') log_level = 'INFO' work_dir = './work_dirs/cascade_rcnn_r50_fpn_1x' load_from = None resume_from = None workflow = [('train', 1)]2.trick部分代码,cascade_rcnn_r50_fpn_1x.py:# fp16 settings fp16 = dict(loss_scale=512.) # model settings model = dict(     type='CascadeRCNN',     num_stages=3,     pretrained='torchvision://resnet50',     backbone=dict(         type='ResNet',         depth=50,         num_stages=4,         out_indices=(0, 1, 2, 3),         frozen_stages=1,         style='pytorch',         #dcn=dict( #在最后三个block加入可变形卷积           #   modulated=False, deformable_groups=1, fallback_on_stride=False),           #  stage_with_dcn=(False, True, True, True)         ),     neck=dict(         type='FPN',         in_channels=[256, 512, 1024, 2048],         out_channels=256,         num_outs=5),     rpn_head=dict(         type='RPNHead',         in_channels=256,         feat_channels=256,         anchor_scales=[8],         anchor_ratios=[0.2, 0.5, 1.0, 2.0, 5.0], # 添加了0.2,5,过两天发图         anchor_strides=[4, 8, 16, 32, 64],         target_means=[.0, .0, .0, .0],         target_stds=[1.0, 1.0, 1.0, 1.0],         loss_cls=dict(             type='FocalLoss', use_sigmoid=True, loss_weight=1.0), # 修改了loss,为了调控难易样本与正负样本比例         loss_bbox=dict(type='SmoothL1Loss', beta=1.0 / 9.0, loss_weight=1.0)),     bbox_roi_extractor=dict(         type='SingleRoIExtractor',         roi_layer=dict(type='RoIAlign', out_size=7, sample_num=2),         out_channels=256,         featmap_strides=[4, 8, 16, 32]),     bbox_head=[         dict(             type='SharedFCBBoxHead',             num_fcs=2,             in_channels=256,             fc_out_channels=1024,             roi_feat_size=7,             num_classes=11,             target_means=[0., 0., 0., 0.],             target_stds=[0.1, 0.1, 0.2, 0.2],             reg_class_agnostic=True,             loss_cls=dict(                 type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),             loss_bbox=dict(type='SmoothL1Loss', beta=1.0, loss_weight=1.0)),         dict(             type='SharedFCBBoxHead',             num_fcs=2,             in_channels=256,             fc_out_channels=1024,             roi_feat_size=7,             num_classes=11,             target_means=[0., 0., 0., 0.],             target_stds=[0.05, 0.05, 0.1, 0.1],             reg_class_agnostic=True,             loss_cls=dict(                 type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),             loss_bbox=dict(type='SmoothL1Loss', beta=1.0, loss_weight=1.0)),         dict(             type='SharedFCBBoxHead',             num_fcs=2,             in_channels=256,             fc_out_channels=1024,             roi_feat_size=7,             num_classes=11,             target_means=[0., 0., 0., 0.],             target_stds=[0.033, 0.033, 0.067, 0.067],             reg_class_agnostic=True,             loss_cls=dict(                 type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),             loss_bbox=dict(type='SmoothL1Loss', beta=1.0, loss_weight=1.0))     ]) # model training and testing settings train_cfg = dict(     rpn=dict(         assigner=dict(             type='MaxIoUAssigner',             pos_iou_thr=0.7,             neg_iou_thr=0.3,             min_pos_iou=0.3,             ignore_iof_thr=-1),         sampler=dict(             type='RandomSampler',              num=256,             pos_fraction=0.5,             neg_pos_ub=-1,             add_gt_as_proposals=False),         allowed_border=0,         pos_weight=-1,         debug=False),     rpn_proposal=dict(         nms_across_levels=False,         nms_pre=2000,         nms_post=2000,         max_num=2000,         nms_thr=0.7,         min_bbox_size=0),     rcnn=[         dict(             assigner=dict(                 type='MaxIoUAssigner',                 pos_iou_thr=0.4, # 更换                 neg_iou_thr=0.4,                 min_pos_iou=0.4,                 ignore_iof_thr=-1),             sampler=dict(                 type='OHEMSampler',                 num=512,                 pos_fraction=0.25,                 neg_pos_ub=-1,                 add_gt_as_proposals=True),             pos_weight=-1,             debug=False),         dict(             assigner=dict(                 type='MaxIoUAssigner',                 pos_iou_thr=0.5,                 neg_iou_thr=0.5,                 min_pos_iou=0.5,                 ignore_iof_thr=-1),             sampler=dict(                 type='OHEMSampler', # 解决难易样本,也解决了正负样本比例问题。                 num=512,                 pos_fraction=0.25,                 neg_pos_ub=-1,                 add_gt_as_proposals=True),             pos_weight=-1,             debug=False),         dict(             assigner=dict(                 type='MaxIoUAssigner',                 pos_iou_thr=0.6,                 neg_iou_thr=0.6,                 min_pos_iou=0.6,                 ignore_iof_thr=-1),             sampler=dict(                 type='OHEMSampler',                 num=512,                 pos_fraction=0.25,                 neg_pos_ub=-1,                 add_gt_as_proposals=True),             pos_weight=-1,             debug=False)     ],     stage_loss_weights=[1, 0.5, 0.25]) test_cfg = dict(     rpn=dict(         nms_across_levels=False,         nms_pre=1000,         nms_post=1000,         max_num=1000,         nms_thr=0.7,         min_bbox_size=0),     rcnn=dict(         score_thr=0.05, nms=dict(type='nms', iou_thr=0.5), max_per_img=20)) # 这里可以换为sof_tnms # dataset settings dataset_type = 'CocoDataset' data_root = '../../data/chongqing1_round1_train1_20191223/' img_norm_cfg = dict(     mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True) train_pipeline = [     dict(type='LoadImageFromFile'),     dict(type='LoadAnnotations', with_bbox=True),     dict(type='Resize', img_scale=(492,658), keep_ratio=True), #这里可以更换多尺度[(),()]     dict(type='RandomFlip', flip_ratio=0.5),     dict(type='Normalize', **img_norm_cfg),     dict(type='Pad', size_divisor=32),     dict(type='DefaultFormatBundle'),     dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']), ] test_pipeline = [     dict(type='LoadImageFromFile'),     dict(         type='MultiScaleFlipAug',         img_scale=(492,658),         flip=False,         transforms=[             dict(type='Resize', keep_ratio=True),             dict(type='RandomFlip'),             dict(type='Normalize', **img_norm_cfg),             dict(type='Pad', size_divisor=32),             dict(type='ImageToTensor', keys=['img']),             dict(type='Collect', keys=['img']),         ]) ] data = dict(     imgs_per_gpu=8, # 有的同学不知道batchsize在哪修改,其实就是修改这里,每个gpu同时处理的images数目。     workers_per_gpu=2,     train=dict(         type=dataset_type,         ann_file=data_root + 'fixed_annotations.json', # 更换自己的json文件         img_prefix=data_root + 'images/', # images目录         pipeline=train_pipeline),     val=dict(         type=dataset_type,         ann_file=data_root + 'fixed_annotations.json',         img_prefix=data_root + 'images/',         pipeline=test_pipeline),     test=dict(         type=dataset_type,         ann_file=data_root + 'fixed_annotations.json',         img_prefix=data_root + 'images/',         pipeline=test_pipeline)) # optimizer optimizer = dict(type='SGD', lr=0.001, momentum=0.9, weight_decay=0.0001) # lr = 0.00125*batch_size,不能过大,否则梯度爆炸。 optimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2)) # learning policy lr_config = dict(     policy='step',     warmup='linear',     warmup_iters=500,     warmup_ratio=1.0 / 3,     step=[6, 12, 19]) checkpoint_config = dict(interval=1) # yapf:disable log_config = dict(     interval=64,     hooks=[         dict(type='TextLoggerHook'), # 控制台输出信息的风格         # dict(type='TensorboardLoggerHook') # 需要安装tensorflow and tensorboard才可以使用     ]) # yapf:enable # runtime settings total_epochs = 20 dist_params = dict(backend='nccl') log_level = 'INFO' work_dir = '../work_dirs/cascade_rcnn_r50_fpn_1x' # 日志目录 load_from = '../work_dirs/cascade_rcnn_r50_fpn_1x/latest.pth' # 模型加载目录文件 #load_from = '../work_dirs/cascade_rcnn_r50_fpn_1x/cascade_rcnn_r50_coco_pretrained_weights_classes_11.pth' resume_from = None workflow = [('train', 1)]Reference[1]:Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognitionarxiv.org[2]:Object Detection Networks on Convolutional Feature Mapsarxiv.org[3]:Deep Residual Learning for Image Classificationarxiv.org[4]:Object Detection via a Multi-region & Semantic Segmentatio-aware CNN Modelarxiv.org[5]:Training Region-based Object Detectors with Online Hard Example Miningarxiv.org[6]:Improving Object Detection With One Line of Codearxiv.org[7]:Mask R-CNNarxiv.org
  • [问题求助] 请问转换模型过程中出现卷积层前向传递错误,是什么原因
    求助,转换模型是提示col_buff_size超出范围,请问这个和什么相关呢?这一层和前几层都是一样的结构的卷积层,不知道这种问题出现的原因。
  • [问题求助] tensorflow 中的卷积tf.nn.conv2d
    部署工程中需要用tf.nn.conv2d来做卷积,两个输入一个是20*20*512一个是4*4*512*10,看tensorflow中这个tf.nn.conv2d的输入就是两个tensor,一个是img,一个是卷积核,转换模型时报错这一层的weight size为0,转换失败,怎么解决啊,另外是不是不支持tensorflow自定义算子
  • [问题求助] 在实现社区项目Faster-R-CNN检测网络应用时,无法上传模型到host端
    在实现社区项目Faster-R-CNN检测网络应用时(参考链接https://gitee.com/Atlas200DK/sample-objectdetection/blob/master/README_cn.md#zh-cn_topic_0182554604_li2074865610364),在执行到上传模型和图片到host端时,无法上传,步骤如下图我参考的是文档里的上传方法,如下图结果说没有这个命令,如下图我看了一下,没有到同名的文件,如下图有人知道怎么回事吗?需要安装什么?
  • [技术干货] HCIA-AI之AI过去及流派(第一课)
    从昨天开始看华为云课堂AI相关课程,决定每天写一篇课后感想,用来总结下学习内容,由于作者水平有限,不足之处还请见谅。人工智能的过去自2016年谷歌发布AIphaGo以4:1战胜李世石再次进入大众视野,此后AI技术和应用进入迅速发展阶段。那么人工智能从何时开始的呢?人工智能源于1956年的达特茅斯会议,参加会议的有约翰麦克锡、马文闵斯基、克劳德香农、艾伦纽厄尔、赫伯特西蒙等科学家,他们讨论的主题是怎样让机器模仿人类学习以及其他的智能。会议长达2个月,他们给会议取名为人工智能。后来就把1956年命名为人工智能元年。人工智能的发展可谓“三起两落”:自1956年达特茅斯会议提出人工智能概念,1959年亚瑟·塞缪尔(机器学习之父)提出机器学习概念,迎来了人工智能发展的第一次浪潮,很多科学家都加入到人工智能的研究行列中来,但由于算法、机器算力等原因导致一些项目失败了,比如1976年机器翻译等项目的失败,以及一些学术报告的负面影响使经费开始减少。1976年到1982年AI迎来第一次’AI之冬‘在1985年出现了更强可视化的决策树模型和突破感知机局限的多层人工智能网络,进入第二次繁荣期。但由于LISP机与IBM和Apple公司研发机器相比性能较差,价格昂贵,在87年LISP机市场崩塌,AI进入第二次’AI之冬‘直到97年deep blue(深蓝)战胜国际象棋冠军,08年Hinton和他的学生发表深度学习论文,10年大数据时代到来,使计算能力有质的突破,AI进入迅速发展阶段。当时对于如何实现人工智能产生了很多流派,占主流的有三个:符号主义、连接主义、行为主义。符号主义学派(逻辑主义、心理学、计算机学派):他们认为人的认知基元是符号认知过程即为符号处理过程。认为人和计算机都是物理符号系统,其中一个案例如下:他们使用符号来代替一些物体或行为(比如用kim代表人,r123代表有人的屋,r023代表无人的屋),通过输入一些符号来告诉机器人一些情况。代表人物如下:连接主义:连接主义认为人的思维单元是神经元,人脑处理方式不同于电脑处理,并提出了电脑智能的实现方式。左边是神经主义的一个思维导图,右边是流派代表人物,其中前两位提出了MP模型,何为MP模型呢?据说人脑有大约860亿神经元。这些神经元组合起来就构成了庞大的神经网络。那么我们就可以模拟一个这样的网络。上初高中时我们都学过生物,知道神经元是由细胞体、轴突、树突组成,左图最右边就是一个完整的神经元,它的轴突与下一个神经元相连,而它的树突上通过突触连接了很多来自其他神经元的轴突,这样如此多的神经元连接起来构成庞大的神经网络。那么我们就可以将神经元抽象到我们数学当中去,图中的圆圈sigma相当于一个神经元,它要接受来自其他神经元的输入,将他们进行整合得到一个权重,将这个权重在经过一个非线性函数(激活函数)得到输出y,而输出Y又是下一个神经元的输入。目前常用的神经网络就来自于连接主义。行为主义:他们认为只能取决于感知和行为,不需要推理,认为机器可以像人一样逐步进化,认为机器必须和现实进行联系。下面是这三个主义的一个对比:在人工智能的发展过程中,这三个流派不是相互隔离的,而是相辅相成,共同推进AI的进步。
  • [技术干货] OCR证件识别心得
    光学字符识别(OCR)现在主要应用在文档识别及证件识别。文档识别可以将印刷文档数字化以快速准确提取有效信息,证件识别则是将证件扫描件或复印件数字化,从而提高工作效率及降低工作强度。作为人工智能领域的一个分支,深度学习可以提高OCR 的识别的适用范围,应用于OCR 的文字区域提取可以增强OCR对文字的提取准确率,提高OCR 的准确率。光学字符识别是将要识别的文档和证件等带有文字信息的物体使用相机等设备转换为图像数字信息,再对图像信息中的文字信息识别出来。最早的OCR 技术始于德国科学家Tausheck,他提出并建立起OCR 的理论框架,但是由于计算机当时还没有诞生,其仅仅停留在理论阶段。随着计算机的诞生及其计算能力的大幅度提升,OCR 才从理论阶段转到实际应用。早期字符识别的目标是印刷文档的识别,印刷文档其文档的格式固定,并且采集图像的噪声干扰较小,更易于识别。随着光学字符识别技术的发展,到现在OCR 在对印刷文档的识别已经趋于成熟,甚至在手写体图像的识别上也有了一定成果。卷积神经网络在图像字符识别,在图像物体检测及人脸识别等领域上都有所突破。卷积网络最早在图像识别领域进行应用,并取得很好的效果。卷积网络框架的提出即奠定了在字符识别的领先地位。卷积神经网络以其独有的特性,局部特征的检测,特征的检索不受空间扭曲的影响,对于图像的抗干扰能力强,故而在图像处理领域占有一席之地。卷积神经网络在图像处理中的应用具有更大的优势,其网络的结构框架基本如图所示,使用图像作为输入,通过卷积层,下采样层,卷积层,池化层等,再后面跟一个全连接层进行分类,最后输出的结构。通过卷积提取图像的特征能够很好的对图像进行分类。卷积网络在字符识别上的研究从卷积神经网络的问世即开始,卷积神经网络框架的奠定即在解决手写体字符的识别,卷积神经网络的采样层可以很好的避免图像很多我们不关心的噪声的干扰,卷积神经网络的局部野也针对图像的局部特征,基于局部特征再从多层综合到整体特征的过程也是视觉上识别的过程,对于字符的识别上有更大优势,现在OCR 问题上的识别模块普遍都采用卷积神经网络来解决。例如现在很成熟的车牌号识别等。卷积神经网络应用于OCR 的字符区域提取相对较晚,其效果不是很理想,同时,在效率上也一直是一个很大的问题。通常使用神经网络的而方法对于一个图形进行文本区域的定位需要很长的时间而基本上做不到实时的对图像进行处理。近年R-CNN 的提出,及Fast R-CNN 和Faster R-CNN 的持续研究,在自然场景下的文字区域提取也进入人们的挑战范围,并取得较好的成果。卷积网络凭借其特有的优势,在图像处理上有其更大的优势。图像的图像增强在对一些图片处理上,图像中的背景干扰会及噪声等因素比较明显,背景的干扰会使目标图像的轮廓检测也可能受到影响。本文中使用图像增强方法主要是高斯模糊和锐化处理。用来降低噪声及提高图像对比度。图像高斯模糊处理是模糊细节,降噪的常用方法,高斯模糊处理将和点的8 连通区域按照一定权重加权相加,将其中值作为点的像素值。具体加权的卷积因子如图中高斯卷积因子所示,使用高斯模糊平滑处理可以将图像中很多噪声平滑,将图像中目标图像的轮廓凸显出来。高斯模糊平滑处理只能适用于背景复杂,但是图像中目标轮廓很明显的图像,平滑处理可以平滑图像细节,对于噪声有平滑的同时,也会将一些不是很明显的轮廓细节也平滑掉。图像锐化处理原理和高斯模糊相同,高斯平滑处理降低图像中点与点之间的值差,而锐化处理则是扩大图像中点与点之间的值差,卷积因子如图 锐化卷积因子所示,从而使图像中的细节更清晰,使边缘信息更清晰。图像处理水平校正图像的水平校正有图像旋转,图像的轮廓检测及透视变换等方法。图像的旋转即将倾斜的目标图像旋转为水平图像,透视变换则解决由拍摄角度,距离远近等不一致因素造成的图像扭曲问题。图像水平校正的难点在图像中目标图像的轮廓检测上。图像的轮廓检测需要使用图像的边缘检测算法,本文使用的边缘检测算法有sobel 算子、canny 算子。sobel 算子对噪声不敏感,sobel 卷积因子如图,计算图像中的边缘值时根据点的邻域3×3 与公式所示公式进行计算。通过计算点与点的上下相邻点间距及点的左右相邻点的间距作为边缘,从而检测到边缘。canny 算子的基本原理与sobel 算子相同,但是canny 算子对噪声干扰更敏感,输出为二值边缘图像。两种算法配合使用可以适用于各种场景下的边缘检测,能更好的提取图像中的轮廓。图像旋转需要先确定图像的倾斜角度及旋转点,需要使用轮廓检测进行查找,将轮廓检测到后,既可以使用轮廓的中心点作为旋转点,如图所示,将轮廓的倾斜角度作为其旋转角度,即可以完成对图像的旋转水平校正。识别的图像类型为证件类图像,证件形状大都为规整矩形,因此可以使用透视变换将图像纠正。图像的透视变换也需要经过轮廓检测,检测轮廓后使用Hough 变换检测角点,通过线条的交点找到目标图像的角点。Hough 变换的原理为,在二值图中,将相邻的点中在同一直线上的点连接组成直线。霍夫变换的优点是对噪声反应迟钝,计算精度高,通过边缘描线能很好的适用于本文识别的图像类型。透视变换的作用是将图像投影映射成另外形状,变换的方式如公式)所示,变换中需要确定图像中所投影图像中四个顶点的位置及投影后的图像四个顶点位置,通过顶点信息可计算出投影的变换矩阵,通过与变换矩阵的乘积可以计算出投影后的图像矩阵。图像透视变换效果将目标图像四个顶点检测到后,直接通过顶点将图拉伸成水平的矩形图,经过透视变换后,目标图像已经从扭曲图像转换为水平,矩形规整图像。图像文本区域定位算法Input:Horizontally corrected imageInitialize S = w*h*10, score [S][10] = 0, position[S][10] = {0,0,0,0}, box_height = 10(w, h is the width and height of image)Processing using the VGG16 model and extracting the conv5_3 signature dataConvolution calculation using 512 3×3 convolution kernelsfor i in range(0, S):box_height = 10for j in range(0,10):box_height /= 0.7position[i][j] = {x, y, 10, box_height }//x,y: the position of point//Use Bilstm to combine text line features to predict text boxesfor i in range(0, S):score[i] = f(position(i), feature(i))//feature(i): the figured feature of position(i) in featuremapfor i in range(0, S):if score [i] < 0.7 delete score [i], position[i]Use text line construction algorithms to combine text boxes into text linesOutput:Text line position文本区域的行长度的变化区间很大,而对于图像中目标检测,目标的大致长宽是有一定范围的。因而采用如算法所示,检测固定长度的文本框,对每个小的文本框进行判断,然后再对文本段进行连接,从而能够精确定位图像中的文本位置。本文中使用固定宽度为16 像素,并使用10 像素到234 像素之间的高度作为图像中文本序列的检测,根据高度不同选取,共10 个anchor 进行检测,在连接时仅对水平文本区域进行连接。本文处理图像中对文本定位的算法流程如图3-6 所示,主要处理流程主要如下:(1) 对目标图像进行卷积特征提取,本文使用VGG16 作为基本网络提取特征,使用VGG16 的conv5_3 层特征数据作为特征图,其大小为W×H×C,W及H 分别为输入图像的宽和高,C 为卷积核数量,本文仅使用VGG16 产生的第五层数据进行处理。(2) 在上取得的特征图中使用512 个3×3 大小的滑动窗口作卷积。对每个窗口,都卷积得到一个3×3×512 大小的特征向量,使用这个特征向量来检测10 个anchor 的偏移距离。本文中针对每个窗口中心位置,都会产生10个高度从10 到234 之间的文本小框,并对每个文本框进行预测打分。(3) 将上一步的特征向量作为一个双向LSTM 的输入,并规定其输出为W×256 长度,在BiLSTM 后面连接512 的全连接层进行输出。(4) 输出层包含三部分:文本框位置、文本框的预测打分及用于调整文本行端点位置的side-refinement。一个文本框由中心位置和矩形框的高度两个值表示;对于所有的文本框,都有两个打分,其中一个为判断为文本的概率,一个为判断为非文本的分数。(5) 基于文本线构造算法对文本框进行整合,将顺序或相邻近的文本框进行整合,并对多余的box 进行非极大值抑制算法进行过滤。最后整合的文本行即为所提取的图像中的文本行。第一步将图像的大小统一调整为短边长为600 将输入图像归一化,之后使用VGG16 产生对原图像进行深度卷积后的第5 层卷积信息。后面LSTM 用于对基于VGG16 的第五层卷积特征图进行卷积后的数据,对应滑动窗口位置所对应的固定的宽16 像素,10 个不同高度文本序列框的特征判断。直接使用双向LSTM 对对应的文本序列框图像进行预测打分,使用双向的LSTM是在打分的时候充分考虑整个文本序列的特征上的考虑,充分的利用文本行的特征信息对应文本框进行判断,提高后续对文本区域的定位。RNN 的设计充分考虑其整个文本行的文本序列组合的特征,而同时也兼顾其小框的特征,整体和部分的完美结合对图像区域进行判断。能同时在文本区域的准确度和文本具体位置的精确度进行大幅度的提高。最后的全连接部分用于对输出部分的整理,对每个预选框的文本序列进行判断打分的结果进行组合并输出一个完整的文本行。
  • [技术干货] VGG结构详解
    #VGG结构深入详解 ##一、VGG简介 VGG的全称为Visual Geometry Group 即视觉几何组,故名思义,是由牛津大学工程科学系的视觉几何组提出的网络。该网络主要是以3x3的卷积核对输入图像进行卷积,并且步长为1,着重进行了卷积网络的深度设计,通过添加更多的卷积层来稳定的增加网络的深度,从而获得更加准确的卷积网络结构。 原文的链接如下:https://arxiv.org/pdf/1409.1556.pdf ##二、对VGG网络结构的理解 以VGG16为例,对输入图像的变换,进行了详解。 VGG16的结构可以分为13层卷积层,3层全连接层,共16层,并没有将池化层放入16层的计数中。 具体结构由图1所示:首先,输入为224x224的RGB图像,经过二层卷积,尺度从3x224x224变换到64x224x224,再经过一层池化层,进行降维,从64x224x224降到64x112x112,不改变数据的通道数量,尺寸降到112x112,同理各层都是卷积层增加通道数量,池化层进行降维操作。每层卷积过后,会经过relu非线性激活函数,进行非线性映射。图中每一层尺寸的变换已经列出来了,之前一直不太明白,卷积究竟是如何得到不同的通道数,接下来是具体的详解。 ### 第一层 输入是RGB图像,通道数为3,尺寸为224x224。 根据图1所示,第一次卷积是以3x3的卷积,64个通道,卷积后加和,形成第二层卷积,因此输出为64个通道,224*224,如图2所示。图2这是经过第一次卷积核后输出的内容,输出的特征需要经过relu激活函数后,更快的收敛。本文主要讨论数据维度的变换,并不关心激活函数的影响,故之后省略激活函数。 ##第二层 输入为64x224x224的数据,因为通道数与卷积核的数量一致,因此有64个卷积核,这样输出也为64通道 为保证卷积运算,每个卷积核的通道数也是64个通道,大小为3x3,输出的数据为64x224x224,如图3所示。图3在vgg16中,池化层是不属于16层的内容里的,起到的作用为数据降维,减少计算量。 如第一层池化,就是将224x224的数据降到112x112 同理,接下来的数据变换都是相类似的操作,不再重复,可以参考图1,都有具体的列出。 那么,思考一下,在经过13层的卷积层,又是如何与全连接层进行联系的? ##第一层全连接层 如图1所示,在经过13层与池化层后,此时的数据为512通道,7x7的数据格式,而第一层全连接层是4096个通道,1x1的数据,因此卷积核需要4096个,而输出为一维数据,因此卷积核的大小为7x7x512,得到一个1x1的数据,如图4所示。图4##第二层全连接层 输入为4096x1的数据,经过4096个卷积核,每一个卷积核均为1x1。输出同样为4096x1维的数据,如图5所示。图5##第三层全连接层 第三层的全连接层,输出为分类的类别,共有1000种类别。因此构造的卷积核为1000个,每个卷积核的大小为4096x1x1,如图6所示。图6##三、小结 本文对VGG16的结构做了详细的说明,并将数据维度的变化,进行详细的图解。 1、需要注意的是,进过3x3的卷积,要使得图像输入与输出的维度不变,需要再周围加0,这也就是为什么padding=1的缘故。具体可以阅读卷积运算的文章。 2、理解结构,方便理解网络参数的规模。如表1为VGG16参数的规模。 输入数据 | 存储大小 | 权重大小 :-----: | :-----: | :-----: INPUT | 224x224x3 = 150K | 0 CONV3-64 | 224x224x64 =3.2M | (3x3x3)x64 = 1728 CONV3-64 | 224x224x64 =3.2M | (3x3x64)x64 = 36864 MAXPOOL | 112x112x64 =800K | 0 CONV3-128 | 112x112x128 = 1.6M | (3x3x64)x128 = 73728 CONV3-128 | 112x112x128 = 1.6M | (3x3x128)x128 = 147456 MAXPOOL | 56x56x128 = 400k | 0 CONV3-256 | 56x56x256 = 800k| (3x3x128)x256 = 294912 CONV3-256 | 56x56x256 = 800k| (3x3x256)x256 = 589824 CONV3-256 | 56x56x256 = 800k| (3x3x256)x256 = 589824 MAXPOOL | 28x28x256 = 200k | 0 CONV3-512 | 28x28x512 = 400k| (3x3x256)x512 = 1179648 CONV3-512 | 28x28x512 = 400k| (3x3x512)x512 = 2359296 CONV3-512 | 28x28x512 = 400k| (3x3x512)x512 = 2359296 MAXPOOL | 14x14x512 = 100k| 0 CONV3-512 | 14x14x512 = 100k| (3x3x512)x512 = 2359296 CONV3-512 | 14x14x512 = 100k| (3x3x512)x512 = 2359296 CONV3-512 | 14x14x512 = 100k| (3x3x512)x512 = 2359296 MAXPOOL | 7x7x512 = 25k| 0 FC-1 | 1x1x4096 = 4096| 7x7x512x4096 = 102760448 FC-2 | 1x1x4096 = 4096| 4096x4096 = 16777216 FC-3 | 1x1x1000 = 1000| 4096x1000 = 4096000 作者:vvbushiwo 转载请注明出处!
  • [技术干货] 第一期02程序详解(自己整理)
    #导入依赖库import os, cv2, random #os库是Python标准库,包含几百个函数,常用路径操作、进程管理、环境参数等几类;#cv2是opencv的简称;import numpy as np#NumPy库使用Python进行科学计算,尤其是数据分析时,所用到的一个基础库。它是大量Python数学和科学计算包的基础# 画图工具import matplotlib.pyplot as pltimport seaborn as sns %matplotlib inline#seaborn就是在matplotlib基础上面的封装,方便直接传参数调用#from 模块 import 函数from keras.layers import Input, Densefrom keras.optimizers import RMSpropfrom keras.callbacks import Callback, EarlyStopping, TensorBoardfrom keras.applications.vgg16 import VGG16from keras.models import Modelfrom keras.utils import np_utils#Keras是TensorFlow官方的高层API。Keras是一个高层神经网络API,Keras由纯Python编写而成并基Tensorflow、Theano以及CNTK后端,也就是Keras基于什么东西来做运算。Keras 为支持快速实验而生,能够把你的idea迅速转换为结果。from sklearn.model_selection import train_test_splitfrom sklearn.metrics import accuracy_score#sklearn是python的重要机器学习库,其中封装了大量的机器学习算法,如:分类、回归、降维以及聚类;还包含了监督学习、非监督学习、数据变换三大模块。sklearn拥有完善的文档,使得它具有了上手容易的优势;并它内置了大量的数据集,节省了获取和整理数据集的时间。因而,使其成为了广泛应用的重要的机器学习库。from keras import backend as KK.set_image_data_format('channels_last') # 数据格式data_format设置为 NHWC  from modelarts.session import Sessionsession = Session() if not os.path.exists('./data'):#查看是否已经由之前解压过的重复数据,如果有就不再次下载,直接使用之前已经下载好的;如果没有,在根目录解压,得到.data    session.download_data(    bucket_path="modelarts-labs/notebook/DL_image_recognition/image_recognition.tar.gz",    path="./image_recognition.tar.gz")     # 使用tar命令解压资源包    !tar xf ./image_recognition.tar.gz     # 清理压缩包    !rm -f ./image_recognition.tar.gz #读取数据集,并把图像resize到 128 * 128 大小。DATA_DIR = './data/' # 数据集路径 ROWS = 128COLS = 128CHANNELS = 3#channels=3:RGBimage_file_names = [DATA_DIR+i for i in os.listdir(DATA_DIR)] dogs = [DATA_DIR+i for i in os.listdir(DATA_DIR) if 'dog' in i]cats = [DATA_DIR+i for i in os.listdir(DATA_DIR) if 'cat' in i]# os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表。这个列表以字母顺序#[]是列表的符号# 数据洗牌random.shuffle(image_file_names)# shuffle() 方法将序列的所有元素随机排序。#函数read_image def read_image(file_path):img = cv2.imread(file_path, cv2.IMREAD_COLOR) # 彩色模式读取图像#使用函数cv2.imread() 读入图像。这幅图像应该在此程序的工作路径,或者给函数提供完整路径,第二个参数是要告诉函数应该如何读取这幅图片。#cv2.IMREAD_COLOR:读入一副彩**像。图像的透明度会被忽略,这是默认参数。#cv2.IMREAD_GRAYSCALE:以灰度模式读入图像    return cv2.resize(img, (ROWS, COLS), interpolation=cv2.INTER_CUBIC)# interpolation=cv2.INTER_CUBIC放大图像def prep_data(image_file_names):#从路径中得到图像    count = len(image_file_names)    data = np.ndarray((count, ROWS, COLS, CHANNELS), dtype=np.uint8)#用count, ROWS, COLS, CHANNELS生成一个多维矩阵        for i, image_file in enumerate(image_file_names):        image = read_image(image_file)        data[i] = image#存入图像        if i%1000 == 0: print('Processed {} of {}'.format(i, count))        return data # 读取图片至内存images = prep_data(image_file_names)                                                #我们根据图片名称包含的字符串给图片打标签。0表示cat,1表示dog。num_train_samples = len(image_file_names)num_classes = 2labels = [] index = 0for filename in image_file_names:    if 'dog' in filename:        labels.append(1)    elif 'cat' in filename:        labels.append(0)        # 把类别标签转换为onehot编码labels = np_utils.to_categorical(labels, num_classes)#即用one hot encoding方法将输出标签的向量(vector)转化为只在出现对应标签的那一列为1,其余为0的布尔矩阵 #切分数据集(train_data,train_label)是训练数据,(test_data,test_label)是测试数据。测试数据占25%。train_data, test_data, train_label, test_label = train_test_split(images, labels, test_size=0.25, random_state=10)#train_test_split来自scikit-learn, train_test_split函数用于将矩阵随机划分为训练子集和测试子集,并返回划分好的训练集测试集样本和训练集测试集标签。 #查看猫狗的样本图片,这些图片是经过尺寸调整后的图片def show_cats_and_dogs(idx):    cat = read_image(cats[idx])    dog = read_image(dogs[idx])    pair = np.concatenate((cat, dog), axis=1)#按行组合在一起    plt.figure(figsize=(10,5))# matplotlib.pyplot    plt.imshow(pair)    plt.show()#plt.imshow()函数负责对图像进行处理,并显示其格式,但是不能显示。其后跟着plt.show()才能显示出来。for idx in range(0,3):show_cats_and_dogs(idx)#构建神经网络, Keras是一个非常简单易用的,适合新手入门的深度学习引擎。接下来,我们使用Keras搭建一个VGG16卷积神经网络。 #设置超参batch_size = 32 # 批大小learning_rate = 1e-4 # 设置学习率为1e-4#设置优化器optimizer = RMSprop(lr=learning_rate) # 优化器使用 RMSpropobjective = 'binary_crossentropy' # loss 函数使用交叉熵 def load_model():    # 这是一个模型参数随机初始化的模型,如果想要加载imagenet预训练模型,可以设置 weights='imagenet'    base_model = VGG16(include_top=False, weights=None, input_shape=(ROWS, COLS, CHANNELS), pooling='avg')        # 修改base_model的模型输出层    prediction_layer = Dense(2, activation='softmax')(base_model.output)        # 组装成新的模型    model = Model(inputs=base_model.input, outputs=prediction_layer)        # 模型编译    model.compile(loss=objective, optimizer=optimizer, metrics=['accuracy'])    return model model = load_model() #模型结构概览,可以查看到刚刚搭建的神经网络结构的详情model.summary()#模型训练:在模型训练过程中,为了防止过拟合,我们使用了early stopping策略,当val_loss在连续3个epoch不再减少的情况下,就停止训练。#可以看到训练日志输出,其中会打印Loss(损失函数)和acc(精确度)信息。epochs = 10 # 训练轮数 # early stopping策略early_stopping = EarlyStopping(monitor='val_loss', patience=3, verbose=1, mode='auto') def run_train():        # 开始训练    history = model.fit(        train_data,        train_label,        batch_size=batch_size,        epochs=epochs,        validation_split=0.25,  # 训练数据中,抽取25%的数据作为验证数据        verbose=2,        shuffle=True,        callbacks=[early_stopping])    return history history = run_train()#保存模型:训练好的模型可以保存起来,永久使用。 OUTPUT = 'output' if not os.path.exists(OUTPUT): os.mkdir(OUTPUT) model.save(os.path.join(OUTPUT, 'model.h5'))#可视化训练过程:将Loss随epoch的变化趋势使用折线图展示loss = history.history['loss']val_loss = history.history['val_loss'] plt.xlabel('Epochs')plt.ylabel('Loss')plt.title('VGG-16 Loss Trend')plt.plot(loss, 'blue', label='Training Loss')plt.plot(val_loss, 'green', label='Validation Loss')plt.xticks(range(0, epochs)[0::2])plt.legend()plt.show()#将accurary随epoch的变化趋势使用折线图展示acc = history.history['acc']val_acc = history.history['val_acc'] plt.xlabel('Epochs')plt.ylabel('acc')plt.title('VGG-16 acc Trend')plt.plot(acc, 'blue', label='Training acc')plt.plot(val_acc, 'green', label='Validation acc')plt.xticks(range(0, epochs)[0::2])plt.legend()plt.show()#样本数据预测:预测测试集predictions = model.predict(test_data, verbose=0)#直观展示10个样本数据的预测结果for i in range(0,10):    p = predictions[i]        if round(p[1]) == 1:        print('I am {:.2%} sure this is a Dog'.format(p[1]))    else:        print('I am {:.2%} sure this is a Cat'.format(1 - p[1]))            plt.imshow(test_data[i])    plt.show()#评估模型准确度:通过测试集的预测结果,计算模型的准确度。predictions_test_array = []test_label_array = [] # 将onehot编码的数据进行格式转换for p in predictions:    if round(p[1]) == 1:        predictions_test_array.append(1)    else:        predictions_test_array.append(0)        for t in test_label:    if int(t[1]) == 1:        test_label_array.append(1)    else:        test_label_array.append(0)        acc = accuracy_score(test_label_array, predictions_test_array) print('训练得到的猫狗识别模型的准确度是:%f' % acc)训练得到的猫狗识别模型的准确度是:0.876320 小结本实验使用Keras搭建了一个VGG16神经网络,并使用猫狗数据集训练了一个猫狗识别模型。