• [经验分享] 基于MindStudio的Resnet50深度学习模型开发
    基于MindStudio的MindX SDK应用开发全流程目录一、MindStudio介绍与安装 21 MindStudio介绍 22 MindSpore 安装 4二、MindX SDK介绍与安装 51 MindX SDK介绍 52.MindX SDK安装 6三、可视化流程编排介绍 81 SDK 基础概念 82.可视化流程编排 8四、SE-Resnet介绍 10五、开发过程 101 创建工程 102 代码开发 123 数据准备及模型准备 144 模型转换功能介绍 155 运行测试 16六、遇见的问题 21MindStudio介绍与安装相关课程:昇腾全流程开发工具链(MindStudio)本课程主要介绍MindStudio在昇腾AI开发中的使用,作为昇腾AI全栈中的全流程开发工具链,提供覆盖训练模型、推理应用和自定义算子开发三个场景下端到端工具,极大提高开发效率。建议开发前,学习该课程的第1章和第3章,可以少走很多弯路!!!MindStudio介绍MindStudio提供您在AI开发所需的一站式开发环境,支持模型开发、算子开发以及应用开发三个主流程中的开发任务。依靠模型可视化、算力测试、IDE本地仿真调试等功能,MindStudio能够帮助您在一个工具上就能高效便捷地完成AI应用开发。MindStudio采用了插件化扩展机制,开发者可以通过开发插件来扩展已有功能。功能简介针对安装与部署,MindStudio提供多种部署方式,支持多种主流操作系统,为开发者提供最大便利。针对网络模型的开发,MindStudio支持TensorFlow、Pytorch、MindSpore框架的模型训练,支持多种主流框架的模型转换。集成了训练可视化、脚本转换、模型转换、精度比对等工具,提升了网络模型移植、分析和优化的效率。针对算子开发,MindStudio提供包含UT测试、ST测试、TIK算子调试等的全套算子开发流程。支持TensorFlow、PyTorch、MindSpore等多种主流框架的TBE和AI CPU自定义算子开发。针对应用开发,MindStudio集成了Profiling性能调优、编译器、MindX SDK的应用开发、可视化pipeline业务流编排等工具,为开发者提供了图形化的集成开发环境,通过MindStudio能够进行工程管理、编译、调试、性能分析等全流程开发,能够很大程度提高开发效率。功能框架MindStudio功能框架如图1-1所示,目前含有的工具链包括:模型转换工具、模型训练工具、自定义算子开发工具、应用开发工具、工程管理工具、编译工具、流程编排工具、精度比对工具、日志管理工具、性能分析工具、设备管理工具等多种工具。图1-1 工具链功能架构工具功能MindStudio工具中的主要几个功能特性如下:工程管理:为开发人员提供创建工程、打开工程、关闭工程、删除工程、新增工程文件目录和属性设置等功能。SSH管理:为开发人员提供新增SSH连接、删除SSH连接、修改SSH连接、加密SSH密码和修改SSH密码保存方式等功能。应用开发:针对业务流程开发人员,MindStudio工具提供基于AscendCL(Ascend Computing Language)和集成MindX SDK的应用开发编程方式,编程后的编译、运行、结果显示等一站式服务让流程开发更加智能化,可以让开发者快速上手。自定义算子开发:提供了基于TBE和AI CPU的算子编程开发的集成开发环境,让不同平台下的算子移植更加便捷,适配昇腾AI处理器的速度更快。离线模型转换:训练好的第三方网络模型可以直接通过离线模型工具导入并转换成离线模型,并可一键式自动生成模型接口,方便开发者基于模型接口进行编程,同时也提供了离线模型的可视化功能。日志管理:MindStudio为昇腾AI处理器提供了覆盖全系统的日志收集与日志分析解决方案,提升运行时算法问题的定位效率。提供了统一形式的跨平台日志可视化分析能力及运行时诊断能力,提升日志分析系统的易用性。性能分析:MindStudio以图形界面呈现方式,实现针对主机和设备上多节点、多模块异构体系的高效、易用、可灵活扩展的系统化性能分析,以及针对昇腾AI处理器的性能和功耗的同步分析,满足算法优化对系统性能分析的需求。设备管理:MindStudio提供设备管理工具,实现对连接到主机上的设备的管理功能。精度比对:可以用来比对自有模型算子的运算结果与Caffe、TensorFlow、ONNX标准算子的运算结果,以便用来确认神经网络运算误差发生的原因。开发工具包的安装与管理:为开发者提供基于昇腾AI处理器的相关算法开发套件包Ascend-cann-toolkit,旨在帮助开发者进行快速、高效的人工智能算法开发。开发者可以将开发套件包安装到MindStudio上,使用MindStudio进行快速开发。Ascend-cann-toolkit包含了基于昇腾AI处理器开发依赖的头文件和库文件、编译工具链、调优工具等。MindStudio安装具体安装操作请参考:MindStudio安装指南 MindStudio环境搭建指导视频场景介绍纯开发场景(分部署形态):在非昇腾AI设备上安装MindStudio和Ascend-cann-toolkit开发套件包。可作为开发环境仅能用于代码开发、编译等不依赖于昇腾设备的开发活动(例如ATC模型转换、算子和推理应用程序的纯代码开发)。如果想运行应用程序或进行模型训练等,需要通过MindStudio远程连接功能连接已部署好运行环境所需软件包的昇腾AI设备。开发运行场景(共部署形态):在昇腾AI设备上安装MindStudio、Ascend-cann-toolkit开发套件包、npu-firmware安装包、npu-driver安装包和AI框架(进行模型训练时需要安装)。作为开发环境,开发人员可以进行普通的工程管理、代码编写、编译、模型转换等功能。同时可以作为运行环境,运行应用程序或进行模型训练。软件包介绍MindStudio:提供图形化开发界面,支持应用开发、调试和模型转换功能,同时还支持网络移植、优化和分析等功能。Ascend-cann-toolkit:开发套件包。为开发者提供基于昇腾AI处理器的相关算法开发工具包,旨在帮助开发者进行快速、高效的模型、算子和应用的开发。开发套件包只能安装在Linux服务器上,开发者可以在安装开发套件包后,使用MindStudio开发工具进行快速开发。MindX SDK介绍与安装MindX SDK介绍MindX SDK提供昇腾AI处理器加速的各类AI软件开发套件(SDK),提供极简易用的API,加速AI应用的开发。应用开发旨在使用华为提供的SDK和应用案例快速开发并部署人工智能应用,是基于现有模型、使用pyACL提供的Python语言API库开发深度神经网络应用,用于实现目标识别、图像分类等功能。图2-1 MindX SDK总体结构通过MindStudio实现SDK应用开发分为基础开发与深入开发,通常情况下用户关注基础开发即可,基础开发主要包含如何通过现有的插件构建业务流并实现业务数据对接,采用模块化的设计理念,将业务流程中的各个功能单元封装成独立的插件,通过插件的串接快速构建推理业务。mxManufacture & mxVision关键特性:配置文件快速构建AI推理业务。插件化开发模式,将整个推理流程“插件化”,每个插件提供一种功能,通过组装不同的插件,灵活适配推理业务流程。提供丰富的插件库,用户可根据业务需求组合Jpeg解码、抠图、缩放、模型推理、数据序列化等插件。基于Ascend Computing Language(ACL),提供常用功能的高级API,如模型推理、解码、预处理等,简化Ascend芯片应用开发。支持自定义插件开发,用户可快速地将自己的业务逻辑封装成插件,打造自己的应用插件。MindX SDK安装步骤1 Windows场景下基于MindStuido的SDK应用开发,请先确保远端环境上MindX SDK软件包已安装完成,安装方式请参见《mxManufacture 用户指南》 和《mxVision 用户指南》 的“使用命令行方式开发”>“安装MindX SDK开发套件”章节。步骤2 在Windows本地进入工程创建页面,工具栏点击File > Settings > Appearance & Behavior > System Settings > MindX SDK进入MindX SDK管理界面。界面中MindX SDK Location为软件包的默认安装路径,默认安装路径为“C:\Users\用户名\Ascend\mindx_sdk”。单击Install SDK进入Installation settings界面,如图2-2。图2-2 MindX SDK管理界面如图2-3所示,为MindX SDK的安装界面,各参数选择如下:Remote Connection:远程连接的用户及IP。Remote CANN Location:远端环境上CANN开发套件包的路径,请配置到版本号一级。Remote SDK Location:远端环境上SDK的路径,请配置到版本号一级。IDE将同步该层级下的include、opensource、python、samples文件夹到本地Windows环境,层级选择错误将导致安装失败。Local SDK Location:同步远端环境上SDK文件夹到本地的路径。默认安装路径为“C:\Users\用户名\Ascend\mindx_sdk”。图2-3 MindX SDK安装界面图2-4 安装完成后的MindX SDK管理界面步骤3 单击OK结束,返回SDK管理界面,可查看安装后的SDK的信息,如图2-4所示,可单击OK结束安装流程。可视化流程编排介绍SDK基础概念通过stream(业务流)配置文件,Stream manager(业务流管理模块)可识别需要构建的element(功能元件)以及element之间的连接关系,并启动业务流程。Stream manager对外提供接口,用于向stream发送数据和获取结果,帮助用户实现业务对接。Plugin(功能插件)表示业务流程中的基础模块,通过element的串接构建成一个stream。Buffer(插件缓存)用于内部挂载解码前后的视频、图像数据,是element之间传递的数据结构,同时也允许用户挂载Metadata(插件元数据),用于存放结构化数据(如目标检测结果)或过程数据(如缩放后的图像)。图3-1 SDK业务流程相关基础单元可视化流程编排MindX SDK实现功能的最小粒度是插件,每一个插件实现特定的功能,如图片解码、图片缩放等。流程编排是将这些插件按照合理的顺序编排,实现负责的功能。可视化流程编排是以可视化的方式,开发数据流图,生成pipeline文件供应用框架使用。图 4-2 为推理业务流Stream配置文件pipeline样例。配置文件以json格式编写,用户必须指定业务流名称、元件名称和插件名称,并根据需要,补充元件属性和下游元件名称信息。步骤1 进入工程创建页面,用户可通过以下方式开始流程编排。在顶部菜单栏中选择Ascend>MindX SDK Pipeline,打开空白的pipeline绘制界面绘制,也可打开用户自行绘制好的pipeline文件,如图3-3。绘制界面分为左侧插件库、中间编辑区、右侧插件属性展示区,具体参考pipeline绘制 。步骤2 在左侧编辑框选择插件,拖动至中间编辑框,按照用户的业务流程进行连接。如果拖动错误插件或者错误连线,选中错误插件或者错误连线单击键盘Del键删除。用户自定义的流水线绘制完成后,选中流水线中的所有插件,右键选择Set Stream Name设置Stream名称,如果有多条流水线则需要对每一条流水线设置Stream名称。绘制完成单击Save保存。图3-2 Detection and Classification配置pipeline样例图3-3 pipeline绘制界面SE-Resnet50介绍残差神经网络是何凯明提出的网络.在深度学习中,网络越深往往取得的效果越好,但是设计的网络过深后若干不为零的梯度相乘导致了梯度消失的现象影响了训练,在残差神经网络中借助其残差结构可以有效的避免梯度消失的问题,在imagenet数据集上取得了优异的结果.SE-Resnet50网络结构,如图4-1所示:图4-1 SE-Resnet50网络结构开发过程创建工程步骤一:安装完成后,点击 ”New Project” 创建新的项目,进入创建工程界面。选择Ascend App项目类别,然后就是常规的命名和路径修改,在CANN Version处点击change配置远程连接和远程CANN地址。图5-1-1 创建项目步骤二:点击CANN Version的Change后进入下界面进行相关配置,点击远程连接配置的最右侧添加按钮。图5-1-2 远程连接配置步骤三:在定义SSH 配置、保存远程服务器的连接配置后返回Remote CANN Setting界面,继续配置CANN location。加载完后再点击Finish即可完成远程环境配置。图5-1-3 配置CANN location 步骤四:完成远程连接设置后,点击next会进到模板选择界面,由于我们是推理任务,此时我们选择MindX SDK Project(Python),再点击Finish。MindX SDK(昇腾行业SDK),提供面向不同行业使能的开发套件,简化了使用昇腾芯片推理业务开发的过程。SDK提供了以昇腾硬件功能为基础的功能插件,用户可以通过拼接功能插件,快速构建推理业务,也可以开发自定义功能插件。图5-1-4 MindX SDK Project(Python)代码开发代码地址:cid:link_2SDK相关工程目录结构:代码介绍:acc.py:求精度代码,在得到sdk推理结果之后会运行acc.py来求精度,具体使用会在本章节运行测试部分详细展示.data_to_bin.py:数据预处理代码,会将数据集中图片转换为二进制形式保存在路径中,具体使用会在本章节数据准备部分详细展示infer.py:里面包含了Sdk_Api这个类,其中主要使用到的函数为图5-2-1 将cv形式输入转换为sdk输入图5-2-2 得到输出结果config.py:已经写好的配置文件,运行时不需要改动Se_resnet50_ms_test.pipeline:pipeline配置文件,运行时需要修改其中的om文件路径,具体会在运行测试部分详细说明.main.py:推理时所运行的文件,会将所有经过预处理之后的二进制文件通过图5-2-1、5-2-2所示函数,得到推理结果.数据准备及模型准备数据集使用的是imagenet,在infer/sdk/目录下先创建一个文件夹“./dataset”,将910上经过数据预处理的图片保存为二进制放入,具体操作如下:在910服务器上执行文件data_to_bin.py图5-3-1 data_to_bin.py配置参数在文件中将数据集路径如图5-3-1所示改为实际路径之后,运行python data_to_bin.py.运行之后./dataset中会生成images与target两个文件夹,里面分别为图片经过预处理之后保存的二进制文件以及每个图片对应的lebel.图5-3-2 生成的images与target的二进制文件在准备好二进制文件后在910上导出onnx模型文件,保存到infer/sdk目录下。具体操作如下:按照图5-3-3所示位置修改pth路径信息,之后运行python pthtar2onnx.py图5-3-3修改pth路径信息图5-3-4 生成onnx文件运行之后会生成图5-3-4所示onnx文件.模型转换功能介绍用户使用torch框架训练好的第三方模型,在导出onnx模型后,可通过ATC工具将其转换为昇腾AI处理器支持的离线模型(*.om文件),模型转换过程中可以实现算子调度的优化、权重数据重排、内存使用优化等,可以脱离设备完成模型的预处理,详细架构如图5-4-1所示。图5-4-1 ATC工具功能架构在本项目中,要将pytorch框架下训练好的模型(*.onnx文件),转换为昇腾AI处理器支持的离线模型(*.om文件),具体步骤如下:步骤1 点击Ascend > Model Converter,进入模型转换界面,参数配置如图5-4-2所示,若没有CANN Machine,请参见第六章第一节CANN安装。图5-4-2 模型转换界面1各参数解释如下表所示:CANN MachineCANN的远程服务器Model File*.onnx文件的路径(可以在本地,也可以在服务器上)Model Name生成的om模型名字Output Path生成的om模型保存在本地的路径步骤2 点击Next进入图5-4-3界面,该项目数据不需要预处理,直接点击Next,进入图5-4-4界面,再点击Finish开始模型转换。图5-4-3 模型转换界面2图5-4-4 模型转换界面3步骤3 等待出现如图5-4-5所示的提示,模型转换成功图5-4-5模型转换成功运行测试步骤1 修改“sdk/config/SE-resnet50.pipeline”中的参数,具体操作如图5-5-1所示;图5-5-1 修改pipeline中*.om文件路径步骤2 在MindStudio工程界面,依次选择“Run > Edit Configurations...”,进入运行配置页面。选择“Ascend App > 工程名”配置应用工程运行参数,图5-5-2为配置示例。配置完成后,单击“Apply”保存运行配置,单击“OK”,关闭运行配置窗口。图5-5-2 工程推理工程运行参数配置在本工程中,推理时运行文件选择main.py,运行参数为--img_path [LR_path] --dataset_name images --pipeline_path [pipeline_path] python3 main.py --img_path "/home/data/xd_mindx/csl/val/" --dataset_name images --pipeline_path "/home/data/xd_mindx/csl/infer/sdk/config/SE-resnet50_test.pipeline"参数解释如下表:参数解释我的设置img_path推理图片路径./val/images/pipeline_pathPipeline文件路径./config/Se_resnet50_ms_test.pipelineinfer_result_dir推理结果保存路径./infer_result/images/images/步骤3 点击运行,出现如图5-5-3所示提示,即为运行成功,infer_result文件夹中即为推理结果,保存为二进制形式。图5-5-3推理操作过程步骤4 配置后处理运行程序,在MindStudio工程界面,依次选择“Run > Edit Configurations...”,进入运行配置页面,如图5-5-4所示,点击“+”,后选择Python(后处理可以直接在本地运行),如图5-5-5所示。图5-5-4运行配置界面图5-5-5 运行后处理相关配置Script path运行文件路径Parameters运行时的参数如图5-5-5所示,运行文件为acc.py:步骤5 点击运行,出现如图5-5-6所示提示,即为运行成功。图5-5-6 运行后处理程序步骤6 结果分析,如图5-5-6所示,已经达到了标准精度。 遇见的问题在使用MindStudio时,遇到问题,可以登陆MindStudio昇腾论坛进行互动,提出问题,会有专家老师为你解答。模型转换时,没有CANN Machine图6-1 CANN管理界面解决方案:按以下步骤,重新安装CANN Machine步骤1 点击File>Settings>Appearance & Behavior > System Settings > CANN,进入CANN管理界面,如图6-1所示:步骤2 点击Change CANN,进入Remote CANN Setting界面,如图6-2所示重新安装CANN,点击Finish,安装CANN。6-2 Remote CANN Setting界面图6-3 安装CANN完成参数解释如下表:Remote Connection远程服务器IPRemote CANN location远程服务器中CANN路径步骤3 完成CANN安装,点击OK,重启MindStudio,如图6-3所示。MindStudio导入应用工程后,提示“No Python interpreter configured for the module”解决方案:步骤1 在顶部菜单栏中选择File > Project Structure,在Project Structure窗口中,点击Platform Settings > SDKs,点击上方的“+”添加Python SDK,从本地环境中导入Python,如图6-4所示。图6-4 导入Python SDK步骤2 点击Project Settings > Project,选择上一步添加的Python SDK,如图6-5所示。图6-5 设置Project SDK步骤3 点击Project Settings > Modules,选中“MyApp”,点击“+”后选择Python,为Python Interpreter选择上述添加的Python SDK。点击OK完成应用工程Python SDK配置,如图6-6所示。图6-6 选择Python SDK
  • [模型训练] 【MindSpore模型训练】【兰州大学423实验室】GhostNet-CPU模型迁移训练流程
    GhostNet-CPU模型迁移训练流程概述GhostNet由华为诺亚方舟实验室在2020年提出,该论文提供了一个全新的Ghost模块,旨在通过廉价操作生成更多的特征图。基于一组原始的特征图,作者应用一系列线性变换,以很小的代价生成许多能从原始特征发掘所需信息的“幻影”特征图(Ghost feature maps)。该Ghost模块即插即用,通过堆叠Ghost模块得出Ghost bottleneck,进而搭建轻量级神经网络——GhostNet。在ImageNet分类任务,GhostNet在相似计算量情况下Top-1正确率达75.7%,高于MobileNetV3的75.2%。该架构可以在同样精度下,速度和计算量均少于SOTA算法。深度卷积神经网络通常引用由大量卷积组成的卷积神经网络,导致大量的计算成本。尽管有工作做出改善,如MobileNet和ShuffleNet引入了深度卷积或混洗操作,以使用较小的卷积核来构建有效的CNN,但是引入的1x1卷积依然会产生一定的计算量。基于此,GhostNet将相似的特征图通过cheap transformation操作得到。Ghost意思是相似的特征图,犹如另一个的幽灵,可以通过简单的线性变换得到。相比于传统的卷积,GhostNet分两步走,首先GhostNet采用正常的卷积计算,得到channel较少的特征图,然后利用cheap operation得到更多的特征图,然后将不同的特征图concat到一起,组合成新的output。准备环节迁移数据集处理首先数据集使用flower_photos数据集,其中包含5类花的图片:633张雏菊图片、898张蒲公英图片、641张玫瑰图片、699张向日葵图片和799张郁金香图片。将所需数据集下载后按照3:1的比例将数据集划分为训练集和验证集。预训练模型获取获取预训练模型“ghostnet_1x_pets.ckpt”、“ghostnet_nose_1x_pets.ckpt”以及“ghostnet600M_pets.ckpt”文件。拉取代码文件将原代码从代码仓拉取并运行查看效果。程序开发原代码文件为Ascend实现的工程文件,其中包含较多的GPU或Ascend算子,首先确保相关算子CPU实现的适配性,若不适配,寻找替代功能算子实现操作,若无替代算子则自行开发算子以实现所需功能。在此项目中CPU训练的相关算子,均可支持。故继续完成迁移代码的开发。迁移训练代码流程包括定义超参数、数据集接口、导入预训练模型、重写Dense层、学习率定义、损失函数定义、优化器的定义、回调函数定义、模型连接和模型训练等操作。在此过程中发现的一处难点是对网络模型的非全连接层冻结操作,以加快迁移训练的完成的速度。但对此预训练模型的网络层冻结操作后,发现损失值难以下降,精度难于达到要求,故此项目迁移训练未对网络层冻结,结果达到精度,但代价是训练时间增加。因此使用GPU设备参与训练迁移网络与调试工作,最终完成网络模型的迁移。微调迁移训练程序import os import argparse import ast from mindspore import context from mindspore import nn from mindspore import Tensor from mindspore.train.model import Model from mindspore.train.loss_scale_manager import FixedLossScaleManager from mindspore.train.callback import ModelCheckpoint, CheckpointConfig, LossMonitor, TimeMonitor from mindspore.train.serialization import load_checkpoint from mindspore.common import dtype as mstype from mindspore.common import set_seed from mindspore.nn.optim.momentum import Momentum from mindspore.communication.management import init, get_rank from mindspore.context import ParallelMode from src.lr_generator import get_lr from src.CrossEntropySmooth import CrossEntropySmooth from src.dataset import create_dataset from src.config import config from src.ghostnet import ghostnet_1x, ghostnet_nose_1x from src.ghostnet600 import ghostnet_600m from src.dense import init_weight parser = argparse.ArgumentParser(description='GhostNet') parser.add_argument('--num_classes', type=int, default=5, help='Classes number') parser.add_argument('--device_target', type=str, default='CPU', help='Device platform') parser.add_argument('--save_checkpoint_path1', type=str, default='./ckpt/', help='Save path of ckpt file') parser.add_argument('--data_url', type=str, default='./dataset/', help='Dataset path') parser.add_argument('--run_distribute', type=ast.literal_eval, default=False, help='Run distribute') parser.add_argument('--pre_trained', type=str, default='./pre_ckpt/ghostnet_1x_pets.ckpt', help='Pretrained checkpoint path') parser.add_argument('--rank', type=int, default=0, help='local rank of distributed') parser.add_argument('--is_save_on_master', type=int, default=1, help='save ckpt on master or all rank') args_opt = parser.parse_args() set_seed(1) if __name__ == '__main__': # init context context.set_context(mode=context.GRAPH_MODE, device_target=args_opt.device_target, save_graphs=False) if args_opt.run_distribute: device_id = int(os.getenv('DEVICE_ID')) rank_size = int(os.environ.get("RANK_SIZE", 1)) print(rank_size) device_num = rank_size context.set_context(device_id=device_id) context.set_auto_parallel_context(device_num=device_num, parallel_mode=ParallelMode.DATA_PARALLEL, gradients_mean=True) init() args_opt.rank = get_rank() # select for master rank save ckpt or all rank save, compatible for model parallel args_opt.rank_save_ckpt_flag = 0 if args_opt.is_save_on_master: if args_opt.rank == 0: args_opt.rank_save_ckpt_flag = 1 else: args_opt.rank_save_ckpt_flag = 1 # define net if 'ghostnet_1x_pets.ckpt' in args_opt.pre_trained: net = ghostnet_1x(num_classes=args_opt.num_classes) elif 'ghostnet_nose_1x_pets.ckpt' in args_opt.pre_trained: net = ghostnet_nose_1x(num_classes=args_opt.num_classes) elif 'ghostnet600M_pets.ckpt' in args_opt.pre_trained: net = ghostnet_600m(num_classes=args_opt.num_classes) net.to_float(mstype.float16) for _, cell in net.cells_and_names(): if isinstance(cell, nn.Dense): cell.to_float(mstype.float32) local_data_path = args_opt.data_url print('Download data:') dataset = create_dataset(dataset_path=local_data_path, do_train=True, batch_size=config.batch_size, num_parallel_workers=None) step_size = dataset.get_dataset_size() print('steps:', step_size) # init weight ckpt_param_dict = load_checkpoint(args_opt.pre_trained) init_weight(net=net, param_dict=ckpt_param_dict) # init lr lr = get_lr(lr_init=config.lr_init, lr_end=config.lr_end, lr_max=config.lr_max, warmup_epochs=config.warmup_epochs, total_epochs=config.epoch_size, steps_per_epoch=step_size) lr = Tensor(lr) if not config.use_label_smooth: config.label_smooth_factor = 0.0 loss = CrossEntropySmooth(sparse=True, reduction="mean", smooth_factor=config.label_smooth_factor, num_classes=args_opt.num_classes) opt = Momentum(net.trainable_params(), lr, config.momentum, loss_scale=config.loss_scale, weight_decay=config.weight_decay) loss_scale = FixedLossScaleManager(config.loss_scale, drop_overflow_update=False) model = Model(net, loss_fn=loss, optimizer=opt, loss_scale_manager=loss_scale, metrics={'top_1_accuracy', 'top_5_accuracy'}, amp_level="O3", keep_batchnorm_fp32=False) # define callbacks time_cb = TimeMonitor(data_size=step_size) loss_cb = LossMonitor() cb = [time_cb, loss_cb] if config.save_checkpoint: if args_opt.rank_save_ckpt_flag: config_ck = CheckpointConfig(save_checkpoint_steps=config.save_checkpoint_epochs * step_size, keep_checkpoint_max=config.keep_checkpoint_max) if 'ghostnet_1x_pets.ckpt' in args_opt.pre_trained: ckpt_cb = ModelCheckpoint(prefix="ghostnet_1x", directory=args_opt.save_checkpoint_path1, config=config_ck) elif 'ghostnet_nose_1x_pets.ckpt' in args_opt.pre_trained: ckpt_cb = ModelCheckpoint(prefix="ghostnet_nose_1x", directory=args_opt.save_checkpoint_path1, config=config_ck) elif 'ghostnet600M_pets.ckpt' in args_opt.pre_trained: ckpt_cb = ModelCheckpoint(prefix="ghostnet600M", directory=args_opt.save_checkpoint_path1, config=config_ck) cb += [ckpt_cb] # train model model.train(config.epoch_size, dataset, callbacks=cb, sink_size=dataset.get_dataset_size())迁移训练对每个预训练权重文件迁移,因为有三个ckpt预训练文件,故执行迁移训练三个网络。 执行python fine_tune.py --pre_trained ./pre_ckpt/ghostnet_1x_pets.ckpt,得到ghostnet_1x的网络训练损失值如下(部分)# ghostnet_1x迁移训练结果 epoch: 1 step: 21, loss is 1.0636098384857178 Train epoch time: 295952.507 ms, per step time: 14092.977 ms epoch: 2 step: 21, loss is 1.007066011428833 Train epoch time: 20480.770 ms, per step time: 975.275 ms epoch: 3 step: 21, loss is 0.9204861521720886 Train epoch time: 20673.888 ms, per step time: 984.471 ms ... epoch: 498 step: 21, loss is 0.5347862839698792 Train epoch time: 19795.049 ms, per step time: 942.621 ms epoch: 499 step: 21, loss is 0.49817660450935364 Train epoch time: 19959.692 ms, per step time: 950.462 ms epoch: 500 step: 21, loss is 0.5028425455093384 Train epoch time: 20185.629 ms, per step time: 961.220 ms执行python fine_tune.py --pre_trained ./pre_ckpt/ghostnet_nose_1x_pets.ckpt,得到ghostnet_1x的网络训练损失值如下(部分)# ghostnet_nose_1x迁移训练结果 epoch: 1 step: 21, loss is 1.1746268272399902 Train epoch time: 94845.916 ms, per step time: 4516.472 ms epoch: 2 step: 21, loss is 1.0321934223175049 Train epoch time: 37248.247 ms, per step time: 1773.726 ms epoch: 3 step: 21, loss is 0.9764260053634644 Train epoch time: 37365.344 ms, per step time: 1779.302 ms ... epoch: 498 step: 21, loss is 0.5118361711502075 Train epoch time: 36716.475 ms, per step time: 1748.404 ms epoch: 499 step: 21, loss is 0.5035715103149414 Train epoch time: 37642.484 ms, per step time: 1792.499 ms epoch: 500 step: 21, loss is 0.49066391587257385 Train epoch time: 36474.781 ms, per step time: 1736.894 ms执行python fine_tune.py --pre_trained ./pre_ckpt/ghostnet600M_pets.ckpt,得到ghostnet_1x的网络训练损失值如下(部分)# ghostnet_600m迁移训练结果 epoch: 1 step: 21, loss is 1.2935304641723633 Train epoch time: 296802.766 ms, per step time: 14133.465 ms epoch: 2 step: 21, loss is 1.356112003326416 Train epoch time: 44871.251 ms, per step time: 2136.726 ms epoch: 3 step: 21, loss is 1.1128544807434082 Train epoch time: 45124.813 ms, per step time: 2148.801 ms ... epoch: 498 step: 21, loss is 0.4896056652069092 Train epoch time: 45314.303 ms, per step time: 2157.824 ms epoch: 499 step: 21, loss is 0.5079032182693481 Train epoch time: 45675.234 ms, per step time: 2175.011 ms epoch: 500 step: 21, loss is 0.5031487345695496 Train epoch time: 45935.200 ms, per step time: 2187.390 ms推理对训练得到的权重文件,使用验证集推理,查看效果精度。推理对计算机资源消耗较少,使用CPU即可。设置好ckpt文件路径,分别执行推理文件。ghostnet_1x网络推理:python eval.py --device_target CPU --checkpoint_path ./ckpt/ghostnet_1x_3-500_21.ckptghostnet_nose_1x网络推理:python eval.py --device_target CPU --checkpoint_path ./ckpt/ghostnet_nose_1x-500_21.ckptghostnet_600mx网络推理:python eval.py --device_target CPU --checkpoint_path ./ckpt/ghostnet600m_1-500_21.ckpt推理结果Ghostnet_1x网络:result: {'top_5_accuracy': 1.0, 'top_1_accuracy': 0.9207589285714286} ckpt= ./ckpt/ghostnet_1x_3-500_21.ckptghostnet_nose_1x网络:result: {'top_1_accuracy': 0.9252232142857143, 'top_5_accuracy': 1.0} ckpt= ./ckpt/ghostnet_nose_1x-500_21.ckptghostnet_600m网络:result: {'top_1_accuracy': 0.9308035714285714, 'top_5_accuracy': 1.0} ckpt= ./ckpt/ghostnet_600m_1-500_21.ckpt总结从推理结果可以看到推理的数据集top1精度均在92%以上,说明分类识别效果极佳,这体现出了网络分类识别效果的优良性能,网络能准确的提却不同的特征信息对图片精准分类。 GhostNet减少了深度神经网络的计算成本,用一种更高效的神经网络结构--新型Ghost模块将原始卷积层分为两部分,首先使用较少的卷积核来生成原始特征图,再进一步使用较为简单的变换操作以高效的产生更多幻影特征图。此网络提出了一个即插即用的模块,能够将原始模型转换为更紧凑的模型,同时保持相似的性能。此外,在效率和准确性方面,新模块构建的GhostNet优于许多轻量级神经网络。代码链接cid:link_0引用Han K, Wang Y, Tian Q, et al. Ghostnet: More features from cheap operations[C]//Proceedings of the IEEE/CVF conference on computer vision and pattern recognition. 2020: 1580-1589.
  • [执行问题] ValAccMonitor使用时内存爆炸的问题
    AI框架:mindspore模型:resnet18问题场景:图像分类模型:resnet18数据量:2万张左右,训练集验证集划分:[0.9, 0.1]出现问题:使用ValAccMonitor模块,训练时,电脑卡死,鼠标都卡,查看内存发现爆满。使用其他回调函数如lossMonitor则一切正常无报错内容,只显示:Process finished with exit code 137 (interrupted by signal 9: SIGKILL)我的电脑内存是32GB,难道代码没有问题,就是纯粹内存太小吗?大家有遇到同样问题的吗?—————————分割线———————————目前看来应该就是内存不够,不是代码的问题,缩小数据集的大小后就能正常运行了,实在没想到这么吃内存
  • [其他] 浅谈VGG
    模型的名称——“VGG”代表了牛津大学的Oxford Visual Geometry Group,该小组隶属于1985年成立的Robotics Research Group,该Group研究范围包括了机器学习到移动机器人。下面是一段来自网络对同年GoogLeNet和VGG的描述:“GoogLeNet和VGG的Classification模型从原理上并没有与传统的CNN模型有太大不同。大家所用的Pipeline也都是:训练时候:各种数据Augmentation(剪裁,不同大小,调亮度,饱和度,对比度,偏色),剪裁送入CNN模型,Softmax,Backprop。测试时候:尽量把测试数据又各种Augmenting(剪裁,不同大小),把测试数据各种Augmenting后在训练的不同模型上的结果再继续Averaging出最后的结果。”VGG发展历程VGG网络由牛津大学在2014年ImageNet挑战赛本地和分类追踪分别获得了第一名和第二名。研究卷积网络深度对其影响在大规模图像识别设置中的准确性,主要贡献是全面评估网络的深度,使用3*3卷积滤波器来提取特征。解决了Alexnet容易忽略小部分的特征。VGG的特点:小卷积核。作者将卷积核全部替换为3x3(极少用了1x1);小池化核。相比AlexNet的3x3的池化核,VGG全部为2x2的池化核;层数更深特征图更宽。基于前两点外,由于卷积核专注于扩大通道数、池化专注于缩小宽和高,使得模型架构上更深更宽的同时,计算量的增加放缓;全连接转卷积。网络测试阶段将训练阶段的三个全连接替换为三个卷积,测试重用训练时的参数,使得测试得到的全卷积网络因为没有全连接的限制,因而可以接收任意宽或高为的输入。图片数据输入彩色图像有RGB三个颜色通道,分别是红、绿、蓝三个通道,这三个通道的像素可以用二维数组来表示,其中像素值由0到255的数字来表示。比如一张160x60的彩色图片,可以用160*60*3的数组表示。卷积卷积过程是使用一个卷积核(如图中的Filter),在每层像素矩阵上不断按步长扫描下去,每次扫到的数值会和卷积核中对应位置的数进行相乘,然后相加求和,得到的值将会生成一个新的矩阵。卷积核相当于卷积操作中的一个过滤器,用于提取我们图像的特征,特征提取完后会得到一个特征图。卷积核的大小一般选择3x3和5x5,比较常用的是3x3,训练效果会更好。卷积核里面的每个值就是我们需要训练模型过程中的神经元参数(权重),开始会有随机的初始值,当训练网络时,网络会通过后向传播不断更新这些参数值,知道寻找到最佳的参数值。对于如何判断参数值的最佳,则是通过loss损失函数来评估。
  • [问题求助] Ascend310芯片上, AlphaPose 转 om模型后,onnx 识别正确,om识别错误
    模型源项目git@github.com:soloist-v/AlphaPoseOnnx.git移植om的项目git@github.com:PalmsSA/AlphaPose_npu.git
  • [参赛经验分享] 2022“域见杯”医检人工智能开发者大赛-赛队“老表,你好hea”方案分享
    前言大家好,我是“老表,你好hea”的团队核心,本赛题为两癌筛查的宫颈癌医学图像分类,主办方为了降低难度让大家都能参与其中,将主流的检测+分类,或者是分割+分类,降为分类任务,赛题数据的分布特别不均衡。数据分析小知识:病理医生同通常会根据细胞的核浆比来判断鳞状上皮细胞是否癌变。高级别的是鳞癌特点是角化(通俗来说就是形状像是长了角)HSIL 高核浆比,不规则核膜LSIL 低核浆比 双核,多核,典型细胞质挖空。数据增强由于数据的gap非常大,所以一些看似常用的涨点小技巧,这里大部分统统失效。 我们观察了线下的混淆矩阵和单类acc,包括测试图像,发现scc和nilm这两类分的很准,但是hsil和lsil存在十分严重的混淆,所以我们尝试了mixup和labelsmooth。线下有涨点,但是线上会降。 模型训练模型参数配置我们一开始是用一个非常小的学习率微调,但是这样很容易陷入过拟合,所以我们采样adamW+coswarmuprestart 的配置,热重启帮助模型逃离局部最小值。而模型前期应该多看不同的样本,在后期快收敛的时候减小学习率,帮助模型更好的收敛。正则化手段也很重要,weight_decay通常会使用一个5e-4 ,这里用到了5e-2,5e-3。 这部分知识蒸馏,作为后续落地的大样本数据迭代训练,小模型线上使用。 受到数据的限制,这里的大模型并没有得到很好的精度。 指标模型结论总结感谢主办方的诚挚邀请,作为一名医疗图像的算法工程师,深知医疗落地的难处。竞赛小tips:多做实验多调参有什么新的idea要尽快实验不到最后一刻不要放弃。最后十分感谢广州市科学技术局、金域医学以及华为云,以及幕后辛勤付出的工作人员!
  • [其他] 浅谈卷积神经网络(CNN)
    卷积神经网络(CNN)是一种特殊类型的神经网络,在图像上表现特别出色。卷积神经网络由Yan LeCun在1998年提出,可以识别给定输入图像中存在的数字。在开始使用卷积神经网络之前,了解神经网络的工作原理很重要。神经网络模仿人脑如何解决复杂的问题并在给定的数据集中找到模式。在过去的几年中,神经网络席卷了许多机器学习和计算机视觉算法。神经网络的基本模型由组织在不同层中的神经元组成。每个神经网络都有一个输入层和一个输出层,并根据问题的复杂性增加了许多隐藏层。一旦数据通过这些层,神经元就会学习并识别模式。神经网络的这种表示称为模型。训练完模型后,我们要求网络根据测试数据进行预测。如果您不熟悉神经网络,那么这篇有关使用Python进行深度学习的文章就是一个很好的起点。另一方面,CNN是一种特殊的神经网络,在图像上表现特别出色。卷积神经网络由Yan LeCun在1998年提出,可以识别给定输入图像中存在的数字。使用CNN的其他应用程序包括语音识别,图像分割和文本处理。在卷积神经网络之前,多层感知器(MLP)用于构建图像分类器。图像分类是指从多波段光栅图像中提取信息类别的任务。多层感知器需要更多的时间和空间来在图片中查找信息,因为每个输入功能都需要与下一层的每个神经元相连。CNN通过使用称为本地连接的概念取代了MLP,该概念涉及将每个神经元仅连接到输入体积的本地区域。通过允许网络的不同部分专门处理高级功能(如纹理或重复图案),可以最大程度地减少参数数量。卷积神经网络结构介绍如果用全连接神经网络处理大尺寸图像具有三个明显的缺点:(1)首先将图像展开为向量会丢失空间信息;(2)其次参数过多效率低下,训练困难;(3)同时大量的参数也很快会导致网络过拟合。而使用卷积神经网络可以很好地解决这的三个问题。与常规神经网络不同,卷积神经网络的各层中的神经元是3维排列的:宽度、高度和深度。其中的宽度和高度是很好理解的,因为本身卷积就是一个二维模板,但是在卷积神经网络中的深度指的是激活数据体的第三个维度,而不是整个网络的深度,整个网络的深度指的是网络的层数。举个例子来理解什么是宽度,高度和深度,假如使用CIFAR-10中的图像是作为卷积神经网络的输入,该输入数据体的维度是32x32x3(宽度,高度和深度)。我们将看到,层中的神经元将只与前一层中的一小块区域连接,而不是采取全连接方式。对于用来分类CIFAR-10中的图像的卷积网络,其最后的输出层的维度是1x1x10,因为在卷积神经网络结构的最后部分将会把全尺寸的图像压缩为包含分类评分的一个向量,向量是在深度方向排列的。
  • [部署上线] 模型部署在线服务个别图片报错,怀疑是推理代码中的_inference推理方法报错
    (1)前提:继上次帖子cid:link_0进行的异常捕捉处理(2)进行异常捕捉处理的代码:from __future__ import absolute_importfrom __future__ import divisionfrom __future__ import print_functionimport osimport numpy as npfrom PIL import Imagefrom hiai.nn_tensor_lib import NNTensorfrom hiai.nntensor_list import NNTensorListfrom model_service.hiai_model_service import HiaiBaseServicefrom collections import defaultdict"""AIPP exampleaipp_op { aipp_mode: static input_format : RGB888_U8 mean_chn_0 : 123 mean_chn_1 : 117 mean_chn_2 : 104}"""labels_list = []label_txt_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'labels.txt')if os.path.exists(label_txt_path): with open(label_txt_path, 'r') as f: for line in f: if line.strip(): labels_list.append(line.strip())def keep_ratio_resize(im, base=399): short_side = min(float(im.size[0]), float(im.size[1])) resize_ratio = base / short_side resize_sides = int(round(resize_ratio * im.size[0])), int(round(resize_ratio * im.size[1])) im = im.resize(resize_sides) return imdef central_crop(im, base=299): width, height = im.size left = (width - base) / 2 top = (height - base) / 2 right = (width + base) / 2 bottom = (height + base) / 2 # Crop the center of the image im = im.crop((left, top, right, bottom)) return imclass DemoService(HiaiBaseService): def _preprocess(self, data): #data----字典形式的数据 preprocessed_data = {} images = [] for k, v in data.items(): #键k---为固定字符串‘image’, 值v为字典数据 print('debug_108---k', k) print('debug_208---v', v.keys()) for file_name, file_content in v.items(): print('debug_308---file_content', file_content) image = Image.open(file_content) image = keep_ratio_resize(image, base=399) image = central_crop(image, base=299) image = np.array(image) # HWC print('debug_408---image', image, image.shape) # AIPP should use RGB format. # mean reg is applied in AIPP. # Transpose is applied in AIPP tensor = NNTensor(image) images.append(tensor) tensor_list = NNTensorList(images) preprocessed_data['images'] = tensor_list print('debug_508---preprocessed_data', preprocessed_data) return preprocessed_data def _inference(self, data, image_info=None): result = {} for k, v in data.items(): result[k] = self.model.proc(v) print('debug_608---result', result) return result def _postprocess(self, data): outputs = defaultdict(list) print('debug_808---post_input_data', data) prob = data['images'][0][0][0][0].tolist() print('debug_908---prob', prob) outputs['probability'] = prob labels_list = {0:'正常',1:'糖尿病',2:'青光眼',3:'白内障',4:'老年黄斑变性', 5:'高血压', 6:'近视', 7:'其他疾病/异常'} x = prob for i in range(8): if x[i]>=0.5: outputs['predicted_label'].append(labels_list[i]) return outputs(2)对于个别图片仍有报错,报错日志:成功案例:debug_108---k imagesdebug_208---v odict_keys(['937_left.jpg'])debug_308---file_content <_io.BytesIO object at 0xffffa212e570>debug_408---image [[[0 0 0][0 0 0][0 0 0]...[0 0 0][0 0 0][0 0 0]][[0 0 0][0 0 0][0 0 0]...[0 0 0][0 0 0][0 0 0]][[0 0 0][0 0 0][0 0 0]...[0 0 0][0 0 0][0 0 0]]...[[0 0 0][0 0 0][0 0 0]...[0 0 0][0 0 0][0 0 0]][[0 0 0][0 0 0][0 0 0]...[0 0 0][0 0 0][0 0 0]][[0 0 0][0 0 0][0 0 0]...[0 0 0][0 0 0][0 0 0]]] (299, 299, 3)debug_508---preprocessed_data {'images': }2022-08-23 08:25:49 UTC [MainThread ] - /home/mind/model_service/model_service.py[line:91] - INFO: preprocess time: 64.06807899475098msdebug_608---result {'images': [array([[[[0.5229492 , 0.40771484, 0.5522461 , 0.30908203, 0.4194336 ,0.3544922 , 0.4243164 , 0.55371094]]]], dtype=float32)]}2022-08-23 08:25:49 UTC [MainThread ] - /home/mind/model_service/model_service.py[line:99] - INFO: infer time: 23.191213607788086msdebug_808---post_input_data {'images': [array([[[[0.5229492 , 0.40771484, 0.5522461 , 0.30908203, 0.4194336 ,0.3544922 , 0.4243164 , 0.55371094]]]], dtype=float32)]}debug_908---prob [0.52294921875, 0.40771484375, 0.55224609375, 0.30908203125, 0.41943359375, 0.3544921875, 0.42431640625, 0.5537109375]失败案例:debug_108---k imagesdebug_208---v odict_keys(['967_left.jpg'])debug_308---file_content <_io.BytesIO object at 0xffffa143eaf0>debug_408---image [[[0 0 0][0 0 0][0 0 0]...[0 0 0][0 0 0][0 0 0]][[0 0 0][0 0 0][0 0 0]...[0 0 0][0 0 0][0 0 0]][[0 0 0][0 0 0][0 0 0]...[0 0 0][0 0 0][0 0 0]]...[[0 0 0][0 0 0][0 0 0]...[0 0 0][0 0 0][0 0 0]][[0 0 0][0 0 0][0 0 0]...[0 0 0][0 0 0][0 0 0]][[0 0 0][0 0 0][0 0 0]...[0 0 0][0 0 0][0 0 0]]] (299, 298, 3)debug_508---preprocessed_data {'images': }2022-08-23 08:25:54 UTC [MainThread ] - /home/mind/model_service/model_service.py[line:91] - INFO: preprocess time: 28.8236141204834msdebug_608---result {'images': None}2022-08-23 08:25:54 UTC [MainThread ] - /home/mind/model_service/model_service.py[line:99] - INFO: infer time: 3.247976303100586msdebug_808---post_input_data {'images': None}2022-08-23 08:25:54 UTC [MainThread ] - /home/mind/app.py[line:83] - ERROR: Algorithm crashed!2022-08-23 08:25:54 UTC [MainThread ] - /home/mind/app.py[line:84] - ERROR: Traceback (most recent call last):File "/home/mind/app.py", line 75, in inference_taskres = model_service.inference(rec_dict)File "/home/mind/model_service/model_service.py", line 101, in inferencedata = self._postprocess(data)File "/home/mind/model/1/customize_service.py", line 93, in _postprocessprob = data['images'][0][0][0][0].tolist()TypeError: 'NoneType' object is not subscriptable在_inference处理方法之前图片处理结果也有,shape为(299,299, 3),然后处理方法之后result结果为None,所以确定是处理方法的错误,但我是按照一个文档介绍,不建议重写,我就没重写。
  • [部署上线] 基于ModelArt模型部署在线服务,预测成功的图片少于预测失败的图片,正常吗?
     1.前提:继续上次帖子cid:link_0问题解决后遇到的新问题2.问题:部署在线服务后发现有的图片可以进行预测成功,但有的图片却不能预测成功,感觉很奇怪,是图片处理的问题还是平台的问题呢?​日志:2022-08-20 06:37:16 UTC [MainThread ] - /home/mind/model_service/model_service.py[line:91] - INFO: preprocess time: 63.60435485839844ms2022-08-20 06:37:16 UTC [MainThread ] - /home/mind/model_service/model_service.py[line:99] - INFO: infer time: 22.867441177368164ms2022-08-20 06:37:16 UTC [MainThread ] - /home/mind/model_service/model_service.py[line:104] - INFO: post time: 0.2276897430419922ms2022-08-20 06:38:28 UTC [MainThread ] - /home/mind/model_service/model_service.py[line:91] - INFO: preprocess time: 28.351545333862305ms2022-08-20 06:38:28 UTC [MainThread ] - /home/mind/model_service/model_service.py[line:99] - INFO: infer time: 3.02886962890625ms2022-08-20 06:38:28 UTC [MainThread ] - /home/mind/app.py[line:83] - ERROR: Algorithm crashed!2022-08-20 06:38:28 UTC [MainThread ] - /home/mind/app.py[line:84] - ERROR: Traceback (most recent call last):File "/home/mind/app.py", line 75, in inference_taskres = model_service.inference(rec_dict)File "/home/mind/model_service/model_service.py", line 101, in inferencedata = self._postprocess(data)File "/home/mind/model/1/customize_service.py", line 86, in _postprocessprob = data['images'][0][0][0][0].tolist()TypeError: 'NoneType' object is not subscriptable​
  • [部署上线] 基于ModelArt平台进行模型推理,进行预测,发现报错,怀疑是模型推理代码报错
    (1)过程:使用ModelArt进行模型部署,进行预测,预测结果报错,怀疑是我改动的推理文件或者是AIPP处理文件有误,参考的是上次创新实践课程的文档中的代码(如下)参考文档见上传文件,并结合论坛上的一个文档cid:link_0from __future__ import absolute_importfrom __future__ import divisionfrom __future__ import print_functionimport osimport numpy as npfrom PIL import Imagefrom hiai.nn_tensor_lib import NNTensorfrom hiai.nntensor_list import NNTensorListfrom model_service.hiai_model_service import HiaiBaseService"""AIPP exampleaipp_op { aipp_mode: static input_format : RGB888_U8 mean_chn_0 : 123 mean_chn_1 : 117 mean_chn_2 : 104}"""labels_list = []label_txt_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'labels.txt')if os.path.exists(label_txt_path): with open(label_txt_path, 'r') as f: for line in f: if line.strip(): labels_list.append(line.strip())def keep_ratio_resize(im, base=256): short_side = min(float(im.size[0]), float(im.size[1])) resize_ratio = base / short_side resize_sides = int(round(resize_ratio * im.size[0])), int(round(resize_ratio * im.size[1])) im = im.resize(resize_sides) return imdef central_crop(im, base=224): width, height = im.size left = (width - base) / 2 top = (height - base) / 2 right = (width + base) / 2 bottom = (height + base) / 2 # Crop the center of the image im = im.crop((left, top, right, bottom)) return imclass DemoService(HiaiBaseService): def _preprocess(self, data): preprocessed_data = {} images = [] for k, v in data.items(): for file_name, file_content in v.items(): image = Image.open(file_content) image = keep_ratio_resize(image, base=256) image = central_crop(image, base=224) image = np.array(image) # HWC # AIPP should use RGB format. # mean reg is applied in AIPP. # Transpose is applied in AIPP tensor = NNTensor(image) images.append(tensor) tensor_list = NNTensorList(images) preprocessed_data['images'] = tensor_list return preprocessed_data def _inference(self, data, image_info=None): result = {} for k, v in data.items(): result[k] = self.model.proc(v) return result def _postprocess(self, data): outputs = {} prob = data['images'][0][0][0][0].tolist() outputs['scores'] = prob labels_list = {0:'daisy',1:'dandelion',2:'roses',3:'sunflowers',4:'tulips'} if labels_list: outputs['predicted_label'] = labels_list[int(np.argmax(prob))] else: outputs['predicted_label'] = str(int(np.argmax(prob))) return outputs(2)问题:关于customize.py的问题整理在了下面.,有好多处代码理解不了,自己也试着修改最后的后处理方法,不过最后部署上线进行预测时还是报错了。前提:a.模型结构b.用一个数据测试的神经网络输出结果:c.模型输入要求:d.模 型针对问题:多标签分类问题下面是改动后的推理代码,相应的不理解的问题均标注在下面:from __future__ import absolute_importfrom __future__ import divisionfrom __future__ import print_functionimport osimport numpy as npfrom PIL import Imagefrom hiai.nn_tensor_lib import NNTensorfrom hiai.nntensor_list import NNTensorListfrom model_service.hiai_model_service import HiaiBaseService"""推理配置insert_op_conf.cfg文件中是下面这样的,不太理解mean_chn_0、mean_chn_1、mean_chn_2是什么意思呢?""""""AIPP exampleaipp_op { aipp_mode: static input_format : RGB888_U8 mean_chn_0 : 123 mean_chn_1 : 117 mean_chn_2 : 104}"""labels_list = []"""不太理解下面这一块是什么作用?"""label_txt_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'labels.txt')if os.path.exists(label_txt_path): with open(label_txt_path, 'r') as f: for line in f: if line.strip(): labels_list.append(line.strip())"""下面函数我的理解是在裁剪之前进行图像缩放,若果base为399,则将图像缩放为399*399,不知道对不对?"""def keep_ratio_resize(im, base=399): short_side = min(float(im.size[0]), float(im.size[1])) resize_ratio = base / short_side resize_sides = int(round(resize_ratio * im.size[0])), int(round(resize_ratio * im.size[1])) im = im.resize(resize_sides) return im"""下面函数我的理解是将缩放好的图像进行裁剪,若base=299, 则图像裁剪后size=299*299,也不知道对不对?"""def central_crop(im, base=299): width, height = im.size left = (width - base) / 2 top = (height - base) / 2 right = (width + base) / 2 bottom = (height + base) / 2 # Crop the center of the image im = im.crop((left, top, right, bottom)) return imclass DemoService(HiaiBaseService): def _preprocess(self, data): """前处理过程,根据文档是能重写的,但我就改变了处理的参数""" preprocessed_data = {} images = [] """不太理解data输入不是一张图片数据吗?看下面的代码的意思好像是一个字典数据呢?,为什么呢""" """那k, v分别指的是什么呢?""" for k, v in data.items(): for file_name, file_content in v.items(): """file_name好像并没有用到,那在这的作用是什么呢?file_content是指什么文件路径吗?""" image = Image.open(file_content) image = keep_ratio_resize(image, base=399) image = central_crop(image, base=299) image = np.array(image) # HWC # AIPP should use RGB format. # mean reg is applied in AIPP. # Transpose is applied in AIPP tensor = NNTensor(image) images.append(tensor) tensor_list = NNTensorList(images) preprocessed_data['images'] = tensor_list return preprocessed_data def _inference(self, data, image_info=None): """推理方法, 我看文档上不建议重写,我就没动""" result = {} for k, v in data.items(): result[k] = self.model.proc(v) return result def _postprocess(self, data): """后处理过程,data输入数据是模型推理的结果,但我不太明白模型推理的结果是一个字典吗?键值包含了那些呢?""" outputs = {} """不太理解下面这句代码的作用?尤其非常疑惑[0][0][0][0]这是为啥?prob到底是什么类型的数据呢?""" prob = data['images'][0][0][0][0].tolist() outputs['probability'] = prob """下面是我自己编写的逻辑,我的模型最后一层是sigmoid(),输出的是shape(1,8)的张量数据,即标签的各自概率;(我的理解是prob是shape(1,8)的列表,按照索引进行逐个判断,并根据概率大小判断是否赋予赋予标签)""" labels_list = {0:'正常',1:'糖尿病',2:'青光眼',3:'白内障',4:'老年黄斑变性', 5:'高血压', 6:'近视', 7:'其他疾病/异常'} x = prob for i in range(8): if x[0][i]>=0.5: outputs.setdefault('predicted_label', []).append(labels_list[i]) return outputs
  • [技术交流] 卷积神经网络表征可视化研究综述(3)
    卷积神经网络表征可视化研究综述(3)人工智能技术与咨询源自:自动化学报     作者:司念文 张文林 屈丹 罗向阳 常禾雨 牛铜3.   可视化效果的评估可视化效果评估用于度量不同方法的解释效果, 指导用户针对特定任务选择合适的可视化方法. 具体来讲, 可从以下两个方面对可视化效果进行评估: 有效性和鲁棒性.3.1  有效性  3.1.1 定性评估定性评估方法在表征可视化研究的早期被经常使用, 依靠人的视觉感观来评价解释结果是否符合人的认知. 由于定性评估具有简单直观、便于理解等优点, 至今仍广泛使用. 常用的定性度量标准有以下3个:1、视觉连贯性. 热力图需要关注感兴趣的目标区域, 忽略其他不相关区域. 在视觉连贯性标准下, 热力图中突出的区域对感兴趣目标的覆盖越全面、冗余部分越少, 表明可视化效果越好.2、视觉可分辨性. 热力图需要与预测结果中的不同类别相对应, 这对于含有多个不同类别目标的图像来说至关重要. 例如, 在同时含有“Dog”和“Cat”的图像中, “Dog”的热力图应该聚焦与之对应的图像区域, 而尽量去除与“Cat”相关的区域. 视觉可分辨性对应于可视化方法的类别区分性特点, 用于评估热力图能否针对特定类别进行可视化, 以定位仅与该类别其相关的区域和特征.3、多目标可视化. 当多个同一类别的目标同时出现在图像中时, 可视化方法需要同时定位多个目标, 而没有遗漏其中的某个目标.此外, 解释结果的客观性也应作为一种评价可视化方法有效性的标准, 即解释结果是否真实的反映了模型的决策依据, 而非按照“预期”寻找到了人类所希望的决策依据. 例如, 文献[78]的实验表明, 分类器做出的决策可能依据目标周围的环境因素, 而目标自身却不是主导因素. 该情形下, 解释方法只能对分类器的分类依据如实解释, 而非按照人的期望去定位目标主体的某些特征. 文献[84]的研究同样验证了这一点, 若分类器从数据集中学习到“女性面部涂口红, 男性面部不涂口红” 这种带有一定“偏见”的事实, 导致分类器面对“涂有口红”的男性图像时, 仍将其判定为“未涂口红”. 此时, 尽管分类器结果错误, 但解释方法应当遵循分类器的决策依据, 定位于男性面部的其他特征, 将其作为判定为“男性”, 进而“未涂口红”的依据. 而非像人所认为的那样, 直接对该图像的嘴唇位置进行定位, 这样的解释结果与分类结果将出现明显不一致的现象, 无法客观地解释分类器的决策依据.尽管解释的客观性问题在相关文献中较少被提及, 但也应引起注意. 只有让解释方法客观、真实地反映模型的决策依据, 才能使人真正理解并诊断其存在的问题, 进而改进与优化. 3.1.2 定量评估定量评估方法按照某种得分规则, 计算数据集上所有图像的可视化结果的平均得分, 从而定量比较各方法的优劣. 这里介绍3种典型的定量评估方法.1)弱监督目标定位. 使用目标定位任务的指标来评价可视化方法的目标定位效果. 具体方法为: 按照设定的阈值处理热力图以生成边框, 然后和真实边框进行比较, 计算交并比(Intersection over union, IoU). 对于某个定位结果, IoU > 0.5表示成功定位该目标, 以此在整个数据集上计算定位准确率. 该方法多用于评价CAM这类目标区分性较好、具有区域级可视化效果的方法.由于某些细粒度的可视化方法更易定位与预测最相关的像素, 而非寻求覆盖目标整体, 因此, 热力图对应的边框将会定位在目标的局部区域, 导致IoU值总体偏小. 此时, IoU值无法反映解释结果的优劣, 表明这种评价方法具有一定的局限性[66].2)指向游戏. 对于特定类别目标的热力图, 计算其最大激活值是否落入该类别的一个实例的边框中, 若落入则计入指向成功1次(#Hit), 否则不计入(#Miss), 以此计算每个目标类别的定位准确率Acc=#Hits/(#Hits+#Misses). 最终使用不同类别的平均准确度作为度量标准.指向游戏只考虑热力图的最大值点, 无需突出特定目标的全部区域, 仅需对热力图最少量的后处理, 这样对不同特点的热力图更公平. 其可能的缺点在于热力图自身的噪声问题, 最大值点可能来自极值噪声点, 导致评价结果产生误差.3)随机性检验. 文献[85]提出随机性检验方法, 用于评估可视化方法的适用范围和解释质量. 分为两种随机化检验: 一种是模型参数随机化, 使用随机化模型参数和预训练模型参数加载模型, 对比这两种情形下可视化方法的输出变化, 以检验该方法是否对模型参数敏感; 另一种是数据随机化, 对训练数据标签进行随机化打乱并重新训练模型, 与未打乱标签的可视化结果进行对比, 检验该方法是否对训练数据标签敏感.随机性检验已成为广泛认可的基准测试方法, 用于检验可视化方法是否能有效实现解释, 从而区分出对模型参数和训练数据标签并不敏感的可视化方法. 这种不敏感的可视化方法的真实作用相当于一个独立于模型的边缘检测器, 而非一个有效的解释器. 文献[85]通过该实验验证了VBP和Grad-CAM的有效性, 而GBP和Guided Grad-CAM等未通过检验.3.2 鲁棒性可视化方法的鲁棒性与CNN模型的鲁棒性不同. CNN模型的鲁棒性是指模型的预测结果不会因为对抗攻击而发生明显变化. 可视化方法的鲁棒性是指在面临对抗攻击时, 可视化方法仍能够提供准确有效的解释. 为此, 本文将对抗攻击分为以下2种情形: 1)攻击模型预测结果, 测试解释结果是否随之改变; 2)攻击解释结果, 测试其是否会被误导. 3.2.1 稳定性可视化方法的稳定性是指在模型预测受到对抗攻击时, 可视化方法的解释结果仍能保持稳定而不发生显著变化. 其中, 用于攻击模型预测结果的对抗样本xadv具有以下3个特点:1、对原图x施加扰动δ后得到对抗图像xadv, xadv相对于x的变化在视觉上难以感知, 满足||δ||=||xadv−x||≪ε(ε表示较小常数), 保证扰动后图像的视觉不变性;2、图像分类模型f对xadv的分类结果将会极大的改变, 即f(xadv)≠f(x);3、解释方法g产生的解释结果不会因为扰动而发生显著变化, 满足g(xadv)≈g(x).这里简单介绍一种经典的基于梯度的对抗攻击方法 (Fast gradient sign method, FGSM)[86], 可用于攻击模型的预测结果, 检验可视化方法的解释结果是否仍保持稳定. FGSM利用梯度上升方法, 通过优化输入图像来最大化损失函数, 使模型产生误分类的结果, 此时对应的输入图像即为对抗图像. FGSM方法形式化如下:   (38)    式中, ∇xJ(θ,x,f(x))表示原图对应初始类别的梯度. sign(⋅⋅)表示符号函数, 根据梯度正负取+1或−1. ϵ表示扰动系数. FGSM的具体过程如图33所示. 其中, x表示输入图像, f(x)的结果为“Panda”, 置信度为57.7%. 扰动量大小ϵ = 0.07. 经过“Nematode”的扰动后, 扰动后的图像虽然在视觉上仍为“Panda”, 但却被分类为“Gibbon”, 且置信度高达99.3% 图 33  FGSM生成对抗样本的过程[87]Fig. 33  The process of generating adversarial example by FGSM[87]文献[63]和文献[66]使用FGSM对抗样本测试Grad-CAM生成的类激活图的稳定性, 如图34所示. 图34(a)和(b)分别表示原图和对抗图像, 原图分类结果为Boxer: 0.40, Tiger Cat: 0.18. 对抗图像的分类结果为Airliner: 0.9999. 在图34(c)和图34(d)中, 针对对抗图像, 使用Grad-CAM分别对Boxer (Dog)和Tiger Cat (Cat)进行定位时, 仍可以稳定地找出相关目标区域, 尽管此时这两种目标的分类置信度非常低. 这表明Grad-CAM产生的解释具有一定的稳定性, 可以抵抗针对模型预测结果的对抗攻击. 图 34  使用FGSM对抗样本测试Grad-CAM的稳定性[63] ((a)原图; (b)对抗图像; (c) Grad-CAM “Dog”; (d) Grad-CAM “Cat”)Fig. 34  Using FGSM adversarial example to test the stability of Grad-CAM[63] ((a) Original image; (b) Adversarial image; (c) Grad-CAM “Dog”; (d) Grad-CAM “Cat”)尽管这是一种测试可视化方法稳定性的方法, 但文献[88]认为, 当模型分类结果受到攻击时, 解释结果应当随着分类结果的改变而改变, 即解释方法应该尝试对新的分类结果进行解释, 而不应保持原来的解释不变, 这样才是一种忠实的解释方法. 由此可见, 这种稳定性测试方法的合理性仍存在一定疑问. 根据这种思路, 即可视化结果应当与新的误分类结果相对应, 文献[88]使用可视化方法来检测对抗样本, 从而找出其中误导分类结果的特征. 3.2.2 抗欺骗性可视化方法的抗欺骗性是指可视化方法自身受到对抗攻击时, 解释结果能够抵抗这种欺骗性的攻击, 仍能实现有效的解释.文献[89]指出, 可视化方法生成的显著图可以被人为设计的对抗样本操纵. 通过对输入施加视觉上难以察觉的扰动, 使网络的输出近似保持不变, 显著图却可以被任意改变. 也就是说, 这种对抗样本的攻击对象不是模型预测结果, 而是对预测结果的解释. 用于攻击可视化方法的解释结果的对抗样本xadv具有以下3个特点[90]:1、对原图x施加扰动δ后得到对抗图像xadv. xadv相对于x的变化在视觉上难以感知, 满足||δ||=||xadv−x||≪ε(ε表示较小常数), 保证扰动后图像的视觉不变性;2、图像分类模型f对xadv的分类结果基本不变, 即f(xadv)=f(x);3、解释方法g产生的解释结果g(xadv)将根据扰动的变化而变化g(x), 使之偏离原来的解释结果, 即满足g(xadv)≠g(x).一种典型的针对解释结果的攻击方法如图35所示, 图35中3个CNN表示同一个待解释的预训练CNN. 其中, Con表示原图x的分类置信度, Exp表示对应的解释. 使用均方误差损失作为约束, 使对抗图像的分类结果f(xadv)逼近原图的分类结果f(x), 而解释结果g(xadv)则逼近目标图的解释结果g(xtarget), 最终的目标函数是两者的加权和: 图 35  针对可视化结果的攻击Fig. 35  Attacks on the visualization results    (39)    式中, xtarget表示用于诱导解释结果的目标图像, λ1和λ2为2部分的权重参数.攻击结果如图36所示, 图36(a)为目标图像xtarget, 图36(b)为原图x, 图36(c)为对抗图像xadv, 图36(e) ~ (g)分别表示对应的显著图. 由图36可以看出, g(xadv)被诱导偏向g(xtarget), 显示出一只鸟的轮廓. 与此同时, f(xadv)却基本保持不变.图 36  使用GAN生成的目标图像诱导对LRP显著图的攻击[82, 90]Fig. 36  Using the target image generated by GAN to induce an attack on the LRP saliency map[82, 90]对于使用随机初始化的原图生成的对抗图像图36(d), 同样可以使用上述攻击方法, 使其对应的显著图36(h)被诱导偏向目标图的解释图36(e), 尽管原图和对抗图像本身没有任务的语义信息. 最终, 分类器对对抗图像图36(d)的分类结果图36(b)相近, 解释结果与图36(e)相近, 但对抗图像图36(d)从视觉上看仅是一幅噪声图像. 可见, 显著图解释方法的抗欺骗能力的确存在漏洞, 而目前对于造成这一问题的原因分析仍在探索之中[90].上述分析显示, 在输入图像未被显著改变、分类结果也保持不变的情形下, 针对分类结果的解释却可以被明显改变而偏向任意目标的解释, 表明可视化方法存在被欺骗的可能. 文献[91]从另一种思路出发, 通过重新微调模型参数, 使微调后的模型的预测结果大致不变, 但解释结果却可以被任意引导. 文献[92]对自解释模型所提供的解释的鲁棒性进行了评估, 发现通过创建这样一些对抗性输入, 会使自解释模型提供错误的解释, 表明现有的自解释模型提供的解释鲁棒性并不好, 无法经受住对抗性攻击. 另一方面, 为了提升可视化方法的鲁棒性, 使其不易被误导, 文献[93]将显著图应用到模型训练中, 对训练集进行数据增强, 从而训练出归因鲁棒性较好的模型.登录中国人工智能培训chinaai查看更多信息
  • [基础介绍] 卷积神经网络表征可视化研究综述(4)
    转人工智能技术与咨询源自:自动化学报 作者:司念文 张文林 屈丹 罗向阳 常禾雨 牛铜摘要近年来, 深度学习在图像分类、目标检测及场景识别等任务上取得了突破性进展, 这些任务多以卷积神经网络为基础搭建识别模型, 训练后的模型拥有优异的自动特征提取和预测性能, 能够为用户提供“输入–输出”形式的端到端解决方案. 然而, 由于分布式的特征编码和越来越复杂的模型结构, 人们始终无法准确理解卷积神经网络模型内部知识表示, 以及促使其做出特定决策的潜在原因. 另一方面, 卷积神经网络模型在一些高风险领域的应用, 也要求对其决策原因进行充分了解, 方能获取用户信任. 因此, 卷积神经网络的可解释性问题逐渐受到关注. 研究人员针对性地提出了一系列用于理解和解释卷积神经网络的方法, 包括事后解释方法和构建自解释的模型等, 这些方法各有侧重和优势, 从多方面对卷积神经网络进行特征分析和决策解释. 表征可视化是其中一种重要的卷积神经网络可解释性方法, 能够对卷积神经网络所学特征及输入–输出之间的相关关系以视觉的方式呈现, 从而快速获取对卷积神经网络内部特征和决策的理解, 具有过程简单和效果直观的特点. 对近年来卷积神经网络表征可视化领域的相关文献进行了综合性回顾, 按照以下几个方面组织内容: 表征可视化研究的提起、相关概念及内容、可视化方法、可视化的效果评估及可视化的应用, 重点关注了表征可视化方法的分类及算法的具体过程. 最后是总结和对该领域仍存在的难点及未来研究趋势进行了展望.。。。。。(接上)4. 可视化的应用4.1理解与解释模型表征可视化是理解CNN模型的一种重要途径,在图像领域应用广泛, 常见于图像分类、场景识别等任务的可视化解释. 本文第3节所述的表征可视化方法常用于对基于CNN的图像分类器的解释, 例如, AM方法用于可视化网络对输入图像的偏好, 从另一种角度揭示了网络对何种输入模式的依赖性较强. 注意力掩码能够告诉设计者网络的关注点, 这使其自身具有一定的可解释特性, 因此, 基于注意力掩码的可视化方法不仅可以验证注意力机制自身的有效性, 也常用于观察网络的训练效果.此外, 表征可视化方法也可以应用在其他类型的数据, 例如, CAM这类方法具有较好的类别区分性, 能够用来确定与特定输出类别相关联的图像区域, 可在视觉问答模型中帮助定位与问题最相关的图像区域. LRP方法在制定反向传播规则时依靠网络的权重与激活值, 而非特征图和通道等图像领域的概念. 因此, 它不仅适应于图像识别任务的解释, 还可以用于可视化机器翻译、语音识别[94]等任务中, 为这些领域的研究者提供了另一种理解模型的途径.4.2 诊断与优化网络在CNN学习效果诊断和结构优化上, 基于反卷积的可视化能够观察任意层的神经元的激活, 从而分析CNN的学习率、卷积核尺寸及步长等重要参数的设计是否达到最优. 文献[13]使用基于反卷积的可视化方法对AlexNet内部激活进行分析与改进, 进而提出了ZFNet, 获得了2013年ImageNet数据集图像分类任务冠军. 这种基于表征可视化的针对性分析和诊断方式, 很大程度上避免了盲目的参数调优. 文献[95]利用基于梯度的可视化方法指导单像素的对抗性扰动和对抗性分析, 帮助模型进行对抗性学习. 文献[88]则使用显著性方法检测对抗样本, 避免模型受到对抗攻击. 文献[72]使用Grad-CAM产生的类激活图来观察网络中间层表征, 分析对比不同结构设计对模型训练效果的影响. 此外, CAM这类方法还可用于提供自注意力, 优化CNN的结构设计. 例如, 文献[73]和文献[77]使用Grad-CAM生成自注意力的掩码作为图像蒙版, 用于去除图像中的非重要区域, 并将处理后的图像应用于下阶段的模型训练和推理. 文献[96]将CAM方法集成到图像转换模型的自注意力模块中, 引导模型关注源域与目标域之间的判别性区域, 从而提升图像转换模型对细节的关注能力.4.3 其他方面除了对CNN本身的理解与诊断, 可视化方法在其他任务上也有不断拓展与延伸, 例如CAM和Grad-CAM方法在弱监督目标定位任务上取得了非常好的效果. 文献[93]进一步探索了将显著性归因方法产生的显著图作为先验, 应用于弱监督的分割任务上. 在应用领域方面, 可视化方法能够提升对推荐系统决策结果的理解[97], 以及与知识图谱的结合来实现可解释的推荐算法[98]. 对于自动驾驶[99-100]以及智能医疗[101]等领域, 由于这些领域对于决策风险的承受能力较低, 可视化方法对这些领域应用的现实落地至关重要.5. 存在的难点及发展趋势5.1 难点分析与趋势展望近年来, CNN表征可视化相关研究越来越多, 研究者们提出了各种可视化方法, 极大推动了该领域的进展, 但仍存在一些难点问题有待解决, 本节对其进行了归纳, 并分析了未来可能的研究趋势.1)对于可视化方法, 仍存在噪声、稳定性、解释能力有限等问题.通过对多种可视化方法的实验比较发现, 多数可视化方法生成的热力图含有一定的噪声, 噪声产生的原因仍没有权威统一的解释. 同时, 面对不同图像时的可视化效果不尽相同, 有些图像可能直接导致可视化方法的失效, 而失效的原因尚不清楚, 仍有待进一步的探究. 此外, 面对复杂背景条件的图像、多目标场景、小目标图像等, 受限于模型本身在面对这些情形时的性能约束, 可视化方法的解释效果并不一定好. 未来可能的研究趋势是将可视化方法与其他解释方法的结合, 从不同侧面不同角度解释模型, 从而缓解单一可视化方法解释效果受限的问题.2)对于可视化效果的评估, 仍欠缺标准统一的评估方法.目前很难找到适用于大多数可视化方法的评估标准, 原因在于许多方法的目标并不相同, 也即每种方法对“可解释性”的理解并不相同, 导致各种可视化方法的解释结果差别较大. 同时, 很多可视化方法自身同样缺乏清晰明确的数学与逻辑机理, 导致结果难以量化比较. 如果可以从“可解释性”的概念出发, 统一数个可解释性的标准, 那么对于可视化结果的评估也就有了依据. 同时, 还可以根据可视化方法产生的热力图的特点进行分类评价, 每类热力图使用与之适应的评价标准, 提升其侧重解释某方面的能力.3)对于可视化的对象, 细粒度的识别模型难以可视化解释.可视化方法多应用于对图像分类、目标定位及场景识别等任务的解释, 能够实现对多目标图像中语义级目标的区分. 例如,“Cat”和“Dog”虽然同属动物, 但是在语义级上属于明显不同的两种动物. 而单独对于“Cat”这一动物, 实现的不同品种猫的细粒度图像分类, 受限于分类网络自身准确性, 可视化方法很难找到用于区分目标的细节特征, 此时的解释效果非常有限, 甚至对于不同的目标可视化效果始终相同. 与人们的视觉观察及解释能力相差较远. 这一问题或许可以通过视觉解释与语言解释相结合的途径来改善解释效果. 对可视化解释难以描述的细微之处, 辅助加以自然语言描述形式的解释(比如对猫的颜色、猫耳形状的描述), 能够实现更好的解释效果.4)对于可视化解释的完备性, 现有研究中的解释结果与预测结果无法相互印证.理论上看, 一个完备可靠的解释可以使用户从中推理并得到被解释的预测结果, 而目前的可视化方法仍不具备这一能力, 仅能从预测结果中得到解释结果, 而无法根据解释来推断出模型的预测, 即两者之间的相互印证关系没有被建立起来. 例如, 如果可视化方法给出了错误的解释, 但这一解释恰好符合用户根据预测结果推测的预期解释, 进而使得用户相信了解释的可靠性, 这将对其形成误导. 此时, 若能根据解释结果推断预测结果, 发现推断出的预测结果和实际预测结果不相符合, 则可通过进一步分析发现其中存在的问题, 从而提升用户对可视化方法的信任.5.2 学界近年来的关注近年来, 众多人工智能领域顶级会议关注人工智能和深度学习可解释问题, 其中许多涉及到表征可视化方面的前沿研究, 如[102]:1) IJCAI 2020 Tutorial on Trustworthiness of Interpretable Machine Learning;2) CVPR 2020 Tutorial on Interpretable Machine Learning for Computer Vision;3) ICCV 2019 Workshop on Interpretating and Explaining Visual Artificial Intelligence Models;4) ICLR 2019 Workshop on Safe Machine Learning;5) CVPR 2019 Workshop on Explainable AI;6) AAAI 2019 Workshop on Network Interpretability for Deep Learning;7) IJCAI 2018/2017 Workshop on Explainable Artificial Intelligence;8) ICML 2018 Workshop on Human Interpretability in Machine Learning;9) NIPS 2017 Interpretable Machine Learning Symposium.表4列举了可解释性深度学习研究领域的部分综述文献, 对各文献的内容侧重作了简要介绍, 其中包含CNN表征可视化的相关内容.表 4 CNN表征可视化相关的综述文献统计Table 4 Review literature statistics related to CNN representation visualization5.3 开源工具CNN可视化的相关开源工具, 一些研究人员在GitHub等网站开源了多种方法综合的代码包,这对于表征可视化研究及迁移到其他任务使用具有重要价值.文献[103]对2016年以前的可视化方法作了详细调研和分类整理, 将其中主流方法分为修改输入的方法(如基于扰动的方法)、反卷积类方法和重建输入的方法(如激活最大化方法)三类. 根据这些方法开发了基于MatConvNet框架[112]的CNN可视化工具包FeatureVis, 适用于Matlab平台上的CNN可视化.Ozbulak[83]发布了一个内容丰富的开源代码包, 实现了10余种可视化方法, 包括梯度方法(如VBP、GAP、Smooth gradient、Integrated gradient等)和类激活映射方法(如Grad-CAM、Score-CAM等). 该源码包基于PyTorch框架, 已经被许多研究人员关注和使用, 受到领域内好评, 目前仍在更新与拓展中.韩国科学技术院的Kim[113]发布了基于Tensorflow框架的可视化源码包, 该源码包含有梯度类方法、CAM类方法、激活最大化方法等, 配有详细的使用教程, 对各种方法的原理及实现过程的介绍细致, 适合初学者使用.此外, 佐治亚理工学院的Wang等[114]实现了对CNN网络的交互式可视化, 可对CNN网络各层的卷积、激活和池化操作的数据流向及中间层特征图进行实时展示, 支持交互式的选择输入图像, 实时观察各层的数据流向及表征情况. 虽然该工具更多关注于CNN网络中数据流的走向, 而非解释CNN中间层特征的语义, 但也非常有利于理解CNN的内部表征.6. 结束语本文围绕CNN表征可视化研究, 详细梳理了该领域近年来相关的文献, 从基础概念及内容、常见方法的分类与比较、效果的评估及应用等方面进行了详细介绍. 其中, 对常见的可视化方法的分类和介绍是本文的重点内容, 该部分详细分析了各种算法的过程, 归纳了每一类方法的特点, 并对它们的效果进行了比较. 最后, 对该领域仍存在的难点和未来的研究趋势作了总结和展望.随着表征可视化研究的深入, 人们对CNN的特征学习和预测机制的理解也会更加深刻. 同时, 其他类型的可解释性方法也在不断发展中, 在它们的共同作用下, 不断推动可解释性深度学习的发展. 期待未来实现可理解的、透明的和高效的深度学习方法.登录中国人工智能培训chinaai查看更多信息
  • [其他] 张量卷积神经网络的统一权值初始化范式
    张量卷积神经网络(Tensorial Convolutional Neural Networks, TCNNs)因其在减小模型参数或提高泛化能力方面的优势而受到广泛的研究。然而,甚至权重初始化方法也阻碍了tcnn的探索。具体来说,一般的初始化方法,如Xavier或Kaiming初始化,通常无法为TCNN生成合适的权值。同时,虽然有针对特定架构的特别方法(如张量环网),但它们不适用于具有其他张量分解方法的TCNN(如CP或Tucker分解)。为了解决这一问题,我们提出了一种通用的权值初始化范式,推广了Xavier和Kaiming方法,可广泛应用于任意的TCNN。具体来说,我们首先提出了再现变换,将TCNNs中的逆向过程转换为等效的卷积过程。然后,基于前向和后向过程中的卷积算子,构建统一的范式来控制TCNN中的特征和梯度方差。因此,我们可以推导出各种TCNN的扇入和扇出初始化。我们证明,我们的范式可以稳定TCNNs的训练,导致更快的收敛和更好的结果。
  • [基础知识] 【MindSpore易点通】深度学习系列-经典卷积神经网络
    上周小伙伴说我们卷积神经网络讲的太简单了,基础嘛,当然要先打好()。这不,更加复杂的卷积神经网络来了~经典CNN之LeNet手写字体识别模型LeNet5诞生于1994年,是最早的卷积神经网络之一。LeNet5利用卷积、参数共享、池化等操作提取特征,避免了大量的计算成本,最后使用全连接神经网络进行分类识别。 LeNet5的网络结构示意图LeNet5由7层CNN(不包含输入层)组成,图中输入的原始图像大小是32×32像素,卷积层:Ci;子采样层(pooling,池化):Si;全连接层:Fi。C1层(卷积层):该层使用了6个卷积核,每个卷积核的大小为5×5,可以得到6个特征图(feature map)。(1)特征图大小每个卷积核(5×5)与原始的输入图像(32×32)进行卷积,这样得到的特征图大小为(32-5+1)×(32-5+1)= 28×28这里有个小知识点:卷积核与输入图像按卷积核大小逐个区域进行匹配计算,匹配后原始输入图像的尺寸将变小,因为边缘部分卷积核无法越出界,只能匹配一次,匹配计算后的尺寸变为Cr×Cc=(Ir-Kr+1)×(Ic-Kc+1),其中Cr、Cc,Ir、Ic,Kr、Kc分别表示卷积后结果图像、输入图像以及卷积核的行列大小。(2)参数个数由于参数(权值)共享,对于同个卷积核每个神经元均使用相同的参数,因此,参数个数为(5×5+1)×6= 156,其中5×5为卷积核参数,1为偏置参数。(3)连接数卷积后的图像大小为28×28,因此每个特征图有28×28个神经元,每个卷积核参数为(5×5+1)×6,因此,该层的连接数为(5×5+1)×6×28×28=1223042、S2层(下采样层,也称池化层):(1)特征图大小这一层主要是做池化或者特征映射(特征降维),池化单元为2×2,因此,6个特征图的大小经池化后即变为14×14。由于池化单元之间没有重叠,在池化区域内进行聚合统计后得到新的特征值,因此经2×2池化后,每两行两列重新算出一个特征值出来,相当于图像大小减半,因此卷积后的28×28图像经2×2池化后就变为14×14。这一层的计算过程是:2×2 单元里的值相加,然后再乘以训练参数w,再加上一个偏置参数b(每一个特征图共享相同的w和b),然后取sigmoid值(S函数:0-1区间),作为对应的该单元的值。卷积操作与池化的示意图(2)参数个数S2层由于每个特征图都共享相同的w和b这两个参数,因此需要2×6=12个参数(3)连接数下采样之后的图像大小为14×14,因此S2层的每个特征图有14×14个神经元,每个池化单元连接数为2×2+1(1为偏置量),因此,该层的连接数为(2×2+1)×14×14×6 = 58803、C3层(卷积层):C3层有16个卷积核,卷积模板大小为5×5。(1)特征图大小与C1层的分析类似,C3层的特征图大小为(14-5+1)×(14-5+1)= 10×10(2)参数个数需要注意的是,C3与S2并不是全连接而是部分连接,有些是C3连接到S2三层、有些四层、甚至达到6层,通过这种方式提取更多特征,连接的规则如下表所示:例如第一列表示C3层的第0个特征图(feature map)只跟S2层的第0、1和2这三个feature maps相连接,计算过程为:用3个卷积模板分别与S2层的3个feature maps进行卷积,然后将卷积的结果相加求和,再加上一个偏置,再取sigmoid得出卷积后对应的feature map了。其它列也是类似(有些是3个卷积模板,有些是4个,有些是6个)。因此,C3层的参数数目为(5×5×3+1)×6 +(5×5×4+1)×9 +5×5×6+1 = 1516(3)连接数卷积后的特征图大小为10×10,参数数量为1516,因此连接数为1516×10×10= 151600S4(下采样层,也称池化层):(1)特征图大小与S2的分析类似,池化单元大小为2×2,因此,该层与C3一样共有16个特征图,每个特征图的大小为5×5。(2)参数数量与S2的计算类似,所需要参数个数为16×2 = 32(3)连接数连接数为(2×2+1)×5×5×16 = 2000C5层(卷积层):(1)特征图大小该层有120个卷积核,每个卷积核的大小仍为5×5,因此有120个特征图。由于S4层的大小为5×5,而该层的卷积核大小也是5×5,因此特征图大小为(5-5+1)×(5-5+1)= 1×1。这样该层就刚好变成了全连接,当然这里真的只是coincidence,如果原始输入的图像比较大,则该层就不是全连接了。(2)参数个数本层的参数数目为120×(5×5×16+1) = 48120(3)连接数由于该层的特征图大小刚好为1×1,因此连接数为48120×1×1=481206、F6层(全连接层):(1)特征图大小F6层有84个单元,由于输出层的对应的是一个7×12的比特图,如下图所示,-1表示白色,1表示黑色,这样每个符号的比特图的黑白色就对应于一个编码。该层有84个特征图,特征图大小与C5一样都是1×1,与C5层全连接。(2)参数个数由于是全连接,参数数量为(120+1)×84=10164。跟经典神经网络一样,F6层计算输入向量和权重向量之间的点积,再加上一个偏置,然后将其传递给sigmoid函数得出结果。(3)连接数由于是全连接,连接数与参数数量一样,也是10164。7、OUTPUT层(输出层):Output层也是全连接层,共有10个节点,分别代表数字0到9。如果第i个节点的值为0,则表示网络识别的结果是数字i。(1)特征图大小该层采用径向基函数(RBF)的网络连接方式,假设x是上一层的输入,y是RBF的输出,则RBF输出的计算方式是:上式中的Wij的值由i的比特图编码确定,i从0到9,j取值从0到7×12-1。RBF输出的值越接近于0,表示当前网络输入的识别结果与字符i越接近。(2)参数个数由于是全连接,参数个数为84×10=840(3)连接数由于是全连接,连接数与参数个数一样,也是840LeNet卷积层用来识别图像⾥的空间模式,例如线条和物体局部,池化层则⽤来降低卷积层对位置的敏感性,在交替使用卷积层和最大池化层后接全连接层来进⾏图像分类,展示了通过梯度下降训练卷积神经网络可以达到手写数字识别在当时最先进的结果。经典CNN之AlexNet第一个典型的CNN是LeNet5网络结构,但是第一个引起大家注意的网络却是AlexNet。AlexNet网络结构网络总共的层数为8层,5层卷积,3层全连接层。1、第一层:卷积层C1,输入为224×224×3的图像,卷积核的数量为96,卷积核的大小为11×11×3,步长stride 为4,pad = 0,表示不扩充边缘;卷积后的图形大小:wide = (224 + 2 * padding - kernel_size) / stride + 1 = 54height = (224 + 2 * padding - kernel_size) / stride + 1 = 54dimention = 96然后进行 (Local Response Normalized), 后面跟着池化pool_size = (3, 3), stride = 2, pad = 0,最终获得第一层卷积的feature map。2、第二层:卷积层C2, 输入为上一层卷积的feature map,卷积的个数为256个,卷积核的大小为:5×5×48,pad = 2,stride = 1,然后做 LRN,最后 max_pooling, pool_size = (3, 3), stride = 2。3、第三层:卷积层C3, 输入为第二层的输出,卷积核个数为384, kernel_size = (3 ×3×256),padding = 1,第三层没有做LRN和Pool。4、第四层:卷积层C4, 输入为第三层的输出,卷积核个数为384, kernel_size = (3×3), padding = 1, 和第三层一样,没有LRN和Pool。5、第五层:卷积层C5, 输入为第四层的输出,卷积核个数为256,kernel_size = (3×3×3), padding = 1。然后直接进行max_pooling, pool_size = (3, 3), stride = 2;6、第6,7,8层是全连接层,每一层的神经元的个数为4096,最终输出softmax为1000,然后全连接层中使用了RELU和Dropout。AlexNet将LeNet的思想发扬光大,把CNN的基本原理应用到了很深很宽的网络中。首先成功使用ReLU作为CNN的激活函数,并验证其效果在较深的网络超过了Sigmoid,成功解决了Sigmoid在网络较深时的梯度弥散问题。Relu函数:然后选择采用覆盖的池化操作。常规的池化层由于没有重叠,所以pool_size 和 stride一般是相等的,例如8×8的一个图像,如果池化层的尺寸是2×2,那么经过池化后的操作得到的图像是4×4,这种设置叫做不覆盖的池化操作。而如果 stride < pool_size, 那么就会产生覆盖的池化操作,这种有点类似于convolutional化的操作,在训练模型过程中,覆盖的池化层更不容易过拟合。同时,神经网络的一个比较严重的问题就是过拟合问题,AlexNet采用的数据扩充和Dropout的方法处理过拟合问题。对于某一层神经元,通过定义的概率来随机删除一些神经元,同时保持输入层与输出层神经元的个数不变,然后按照神经网络的学习方法进行参数更新,下一次迭代中,重新随机删除一些神经元,直至训练结束。总结AlexNet和LeNet的设计理念非常相似,但也存在显著差异。首先,AlexNet比相对较小的LeNet5要深得多。AlexNet由八层组成:五个卷积层、两个全连接隐藏层和一个全连接输出层。其次,AlexNet使用ReLU而不是sigmoid作为其激活函数。AlexNet的更高层建立在底层表示的基础上,以表示更大的特征,如眼睛、鼻子、草叶等等。而更高的层可以检测整个物体,如人、飞机、狗或飞盘。最终的隐藏神经元可以学习图像的综合表示,从而使属于不同类别的数据易于区分。AlexNet首次证明了学习到的特征可以超越手工设计的特征,AlexNet在结果上要优于LeNet很多,特别是其在处理大规模数据方便的优势更是明显。AlexNet的问世也开启了深度学习在计算机视觉领域的大规模应用。一般我们可以将其看做浅层神经网络和深层神经网络的分界线。当然啦,经典的CNN还是有很多其他的网络的,比如VGG、GoogLeNet、ResNet等等,欢迎大伙儿一起学习使用呀!
  • [技术干货] 2022年最新深度学习入门指南
    概述1. 深度学习是用于处理视觉相关任务的强大的方法。2. 卷积神经网络是一种深度学习模型,我们用它来处理与相关的应用程序。3. 在本指南中,我们将探索 CNN 的工作原理以及它们如何应用于图像分类任务。我们还将构建一个 CNN 模型,并使用 Keras 从头开始在训练数据集上对其进行训练。介绍我一直着迷于深度学习模型的潜力和力量,以及它们如何理解执行图像分类、图像分割、对象检测等任务。我们还遇到了一些分割算法,例如来自 X-的肿瘤/异常检测,他们在这方面的表现甚至优于医生。在本指南中,我们将全面介绍 CNN 及其在图像分类任务中的应用。我们将首先介绍卷积神经网络 (CNN) 背后的基本理论、它们的工作原理以及它们如何成为用于任何计算机视觉任务的最流行的模型之一。现在让我们开始吧……卷积神经网络CNN 或卷积神经网络是将图像作为输入并通过使用卷积运算学习图像中的局部模式的算法。而密集层/全连接层则从输入中学习全局模式。CNN 的学习局部模式具有两个特性:1. CNN 学习的模式是不变的,即在学习识别图像左下角的特定模式后,CNN 可以识别图像中的任何位置。但是,如果密集连接的网络出现在新位置的任何位置,则必须重新学习该模式。这使得 CNN 在处理和理解图像时具有数据效率。2. CNN 可以学习模式的空间层次,即第一个卷积层学习一个小的局部模式,如边缘或线,第二个卷积层学习由第一个卷积层学习的特征组成的更大的模式,依此类推。通过这种方式,CNN 学习和理解了越来越复杂和抽象的视觉概念。让我们看看下面的猫图,在这里我们可以看到,在第一个卷积层中,学习了边缘、曲线等模式。但在第二层 CNN 中,眼睛、鼻子或耳朵等特征是通过使用第一层的模式来检测的。通过这种方式,CNN了解图像并了解图像中的对象。参考特征提取现在让我们探索并了解它是如何工作的。卷积运算卷积是应用于 3D 张量的操作,称为特征图。这些特征图由两个空间轴(高度和宽度)和一个深度轴(或通道轴)组成。如果我们考虑 RGB 图像的示例,高度和宽度构成空间轴,3 个颜色通道表示深度轴。类似地,对于黑白图像,深度为 1。但在其他层的输出中,深度不是由颜色通道表示,而是代表过滤器。过滤器对输入数据的特定方面进行编码,即过滤器可以对“面部存在”或“汽车结构”等概念进行编码。卷积运算由两个关键参数组成,1. 内核大小:应用于图像的过滤器的大小。这些是典型的 3×3 或 5×5。2. 输出特征图的深度:这是卷积计算的输出滤波器的数量。卷积操作只是在输入特征图上乘加加权滤波器,以生成另一个具有不同宽度、高度和深度的 3D 张量。卷积操作通过在 3D 输入特征图上滑动这些大小为 3×3 或 5×5 过滤器的窗口,在每个可能的位置停止,然后计算特征。我们可以在下面的 gif 中看到操作,3×3 内核在 5×5 输入特征图上运行以生成 3×3 输出。参考卷积重要的是要注意网络从给定数据中学习所需的最佳过滤器。CNN 模型的权重是过滤器。现在让我们看看边框效果、填充和步幅。了解边框效果和填充现在再次让我们考虑 5×5 特征图(参考上面的 gif)。过滤器的大小为 3×3,因此有 9 个图块。现在在卷积操作期间,3×3 滤波器只能通过 5×5 特征图 9 次,因此我们的输出大小为 3×3。所以输出在这里从 5×5 缩小到 3×3,也就是说,在每个维度旁边缩小了两个图块。这里没有对输入特征图应用填充,因此称为有效填充。如果我们希望输出特征图与输入特征图的大小相同,我们需要使用填充。填充包括在输入特征图的每一侧添加适当数量的行和列,以使每个输入图块周围的中心卷积窗口成为可能。这种类型的填充称为相同的填充。以下 GIF 表示相同的填充。源边框效果和填充现在我们可以看到,当我们向 5×5 特征图添加额外的填充并应用 3×3 过滤器时,我们将能够获得与输入特征图大小相同的输出特征图。如何找到要添加到给定过滤器大小和特征图的填充?当我们遇到不同大小的特征图和过滤器以及我们如何确定对于有效和相同的情况应该使用多少填充时,自然会出现这个问题。所以要回答这个问题,我们有确定填充的公式,即1. 有效填充:因为有效填充意味着没有填充,所以padding的数量将为0。2. 相同填充:我们使用相同的填充来保留输入特征图的大小。但是卷积的输出主要取决于过滤器的大小,与输入大小无关。因此,可以根据过滤器大小确定填充,如下所示:相同填充 =(过滤器大小 - 1)/ 2现在让我们看看另一个可以影响输出大小的因素,即步幅。了解步幅步幅是影响输出特征图大小的因素之一。步幅是应用过滤器的两个连续窗口之间的距离。在上面的例子中,我们已经看到过滤器作为窗口被应用于输入特征图,并被移动一个单位或步幅。当这种转变大于1时,我们将其定义为跨步的CNN。下面的GIF是一个大步为2的CNN的例子。我们还可以观察到,当我们使用步幅的值为 2(或大于 1)时,与常规卷积(当 stride 的值 = 1 时)相比,输出特征图的大小减小(下采样因子为 2) .因此我们可以说使用步幅是对输入特征图进行下采样的方法之一。但它们在实践中很少使用,但它仍然是 CNN 的重要概念之一,了解它是很好的。现在在开始 CNN 的实现之前,让我们看一下用于对输入特征进行下采样的另一个重要概念,即池化。理解池化池化操作可以定义为一种通过使用不同的策略(例如取平均值、最大值、总和等)来积极减小/下采样输入特征图的大小的方法。现在让我们看看不同类型的池化1.最大池化:最大池化是一种广泛使用的池化策略,用于对输入特征图进行下采样。在这一层中,确定大小的窗口通过输入特征图,然后获得最大值并计算为下一层或输出特征图。我们可以在下面的 GIF 中看到,当我们使用过滤器大小 2 执行最大池化时,输入特征被下采样因子 2 或减半。我们可以通过以下公式确定使用最大池化后输出的大小:输出大小=输入大小/(池化过滤器大小)还有其他类型的池化策略,例如考虑窗口平均值的平均池化和考虑窗口权重总和的求和池化。但最大池化一直是最流行和最广泛使用的池化策略。这是因为当我们考虑过滤器窗口的最大值时,我们将能够将有关输入特征/当前特征图的大部分可用信息转移到下一个特征图。因此,当我们通过神经网络的层进行传播时,减少了数据的丢失。既然我们对 CNN 的工作原理有了一些了解,那么现在让我们从头开始实现一个 CNN。从头开始训练基于 CNN 的图像分类器现在让我们在 MNIST 数据集上训练一个 CNN 模型。MNIST 数据集由 0 到 9 的手写数字图像组成,即 10 个类。训练集由 60000 张图像组成,测试集由 10000 张图像组成。让我们使用 CNN 从头开始训练图像分类器。我们将在Keras框架中实现代码。Keras 是最受欢迎和使用最广泛的深度学习库之一。它是作为高级 API 构建的,可以轻松使用 TensorFlow。要完成以下代码实现,建议使用带有 GPU 的 Jupyter Notebook。可以通过Google Colaboratory访问相同的内容,该实验室提供基于云的 Jupyter Notebook环境和免费的 Nvidia GPU。现在让我们开始吧获取 MNIST 数据集在下载数据集之前,让我们进行必要的导入,from tensorflow.keras.datasets import mnistfrom tensorflow.keras.utils import to_categoricalfrom tensorflow.keras import layersfrom tensorflow.keras import modelsimport numpy as npimport matplotlib.pyplot as pltfrom matplotlib import pyplot现在让我们下载数据,(train_images, train_labels), (test_images, test_labels) = mnist.load_data()上面的代码下载数据并缓存。由于我们正在加载预定义的数据集,因此该数据集已经被预处理并以元组的形式打包。现在让我们探索我们解压出来的这些张量的形状,int("Shape of training dataset: ",train_images.shape)print("Shape of test dataset: ",test_images.shape)print("Shape of training dataset labels: ",train_labels.shape)print("Shape of test dataset labels: ",test_labels.shape)输出:从上面的输出我们可以看到,训练数据集有 60000 张图片,每张图片的大小为 28×28。同样,测试数据集有 10000 张图像,图像大小为 28×28。我们还可以看到标签没有任何形状,即它是一个标量值。让我们看看一些标签,print(train_labels)print(type(train_labels))输出:我们可以看到标签都在一个 NumPy 数组中。现在让我们看看我们的一些训练图像,# plot first few imagesfor i in range(9):   # define subplot   pyplot.subplot(330 + 1 + i)   # plot raw pixel data   pyplot.imshow(train_images[i], cmap=pyplot.get_cmap('gray'))# show the figurepyplot.show()输出:我们可以通过绘制它们来可视化训练样本。在我们继续模型训练之前,让我们对我们的数据进行一些预处理。基本预处理现在让我们将图像从 (60000, 28, 28) 重塑为 (60000, 28, 28, 1) 大小,其中最后一个维度表示图像的深度。我们之前已经看到,每个图像的特征图都有三个维度,即宽度、高度和深度。由于 MNIST 训练集由黑白图像组成,我们可以将深度定义为 1。接下来,我们应该对数据集进行归一化,即将输入的所有值都在 0 和 1 之间。由于图像层的最大值是 255,我们将整个数据集除以 255。train_images = train_images.reshape((60000, 28, 28, 1))train_images = train_images.astype('float32') / 255现在让我们也对测试集应用相同的预处理。test_images = test_images.reshape((10000, 28, 28, 1))test_images = test_images.astype('float32') / 255最后,让我们将标签转换为分类格式,即它们目前作为标量,但我们正在执行 One-Hot 编码以将每个标量唯一地映射到向量。train_labels = to_categorical(train_labels)test_labels = to_categorical(test_labels)train_labels[:10]输出:我们可以看到训练标签是独热编码。现在让我们使用 Keras 创建一个基本的 CNN 模型。使用 Tensorflow-Keras 创建 CNN 模型现在让我们使用 Keras 库创建一个基本模型,model = models.Sequential()model.add(layers.Conv2D(32, (3,3), activation='relu', input_shape=(28,28,1)))model.add(layers.MaxPool2D((2,2)))model.add(layers.Conv2D(64, (3,3), activation='relu'))model.add(layers.MaxPool2D((2,2)))model.add(layers.Conv2D(64, (3,3), activation='relu'))现在我们来分析一下上面的代码,· 首先,我们正在创建一个Sequential类型类的对象。Sequential 模型是一种模型,我们可以在其中添加和堆叠层以形成端到端模型。· 使用**.add**我们通过根据层指定各种参数来将层添加到我们的模型中。· 在上面的模型中,我们添加了一个卷积层(即 Keras 中的 Conv2D),它接受许多过滤器、内核大小和激活函数作为参数。· 接下来,添加最大池化层(即 Keras 中的 MaxPool2D)以启用池化操作。· Keras 中提供了不同类型的层。模型的上述部分负责识别和检测输入数据中存在的模式。(我们上面讨论过的工作)现在最后让我们通过定义模型的输出数量来初始化头部。model.add(layers.Flatten())model.add(layers.Dense(64, activation='relu'))model.add(layers.Dense(10, activation='softmax'))现在我们的模型已经准备好了。我们可以使用**.summary()**方法查看模型中所有层的列表 。model.summary()输出:现在让我们通过分配优化器、损失函数和模型训练时使用的指标来编译模型。model.compile(optimizer='rmsprop',             loss='categorical_crossentropy',             metrics=['accuracy'])现在让我们用训练数据和标签拟合模型并训练 5 个 epochsmodel.fit(train_images, train_labels, epochs=5, batch_size=64)结果:从训练结果中我们可以看出,该模型能够达到高达 99% 的准确率,这真是令人印象深刻!!结论我们已经看到了卷积神经网络的底层功能以及它如何从图像中提取特征。因此,我们可以得出结论,卷积神经网络是在计算机视觉应用中产生最先进结果的技术之一。       原文标题 : 2022年最新深度学习入门指南
总条数:75 到第
上滑加载中