[{"data":1,"prerenderedAt":649},["ShallowReactive",2],{"content-query-8TrYLpTgmK":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"cover":11,"type":12,"category":13,"body":14,"_type":643,"_id":644,"_source":645,"_file":646,"_stem":647,"_extension":648},"/technology-blogs/zh/2226","zh",false,"","昇思应用案例 | 模型压缩50倍，超轻量级网络CNN模型SqueezeNet技术实践","本教程主要讲解使用昇思MindSpore框架实现了SqueezeNet训练CIFAR10数据集并且评估模型的完整过程","2023-04-06","https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2023/04/13/ef4c6cb2923d4704b36838883f32dc88.png","technology-blogs","实践",{"type":15,"children":16,"toc":624},"root",[17,25,44,49,57,65,89,98,105,110,117,124,129,134,141,146,156,163,168,176,184,192,202,207,212,217,226,236,241,248,257,262,269,274,281,290,295,302,307,314,322,330,339,344,352,359,364,371,376,384,389,397,406,411,419,426,436,444,453,459,467,476,481,489,497,505,513,518,526,534,539,547,555,560,568,577,582,590,599,604,612,617],{"type":18,"tag":19,"props":20,"children":22},"element","h1",{"id":21},"昇思应用案例-模型压缩50倍超轻量级网络cnn模型squeezenet技术实践",[23],{"type":24,"value":8},"text",{"type":18,"tag":26,"props":27,"children":28},"p",{},[29,31,37,39],{"type":24,"value":30},"**作者：**",{"type":18,"tag":32,"props":33,"children":34},"strong",{},[35],{"type":24,"value":36},"Yeats_Liao",{"type":24,"value":38}," ｜",{"type":18,"tag":32,"props":40,"children":41},{},[42],{"type":24,"value":43},"来源：CSDN",{"type":18,"tag":26,"props":45,"children":46},{},[47],{"type":24,"value":48},"本教程主要讲解使用昇思MindSpore框架实现了SqueezeNet训练CIFAR10数据集并且评估模型的完整过程，包括数据集的下载和处理，模型的搭建，模型的训练，以及模型的测试评估和保存，最后我们可视化了模型的预测效果，通过次案例我们可以对SqueezeNet的原理有更加深刻的了解，并且更加熟悉昇思MindSpore框架的基本使用方法。",{"type":18,"tag":26,"props":50,"children":51},{},[52],{"type":18,"tag":32,"props":53,"children":54},{},[55],{"type":24,"value":56},"01",{"type":18,"tag":26,"props":58,"children":59},{},[60],{"type":18,"tag":32,"props":61,"children":62},{},[63],{"type":24,"value":64},"环节准备",{"type":18,"tag":26,"props":66,"children":67},{},[68,70,78,80],{"type":24,"value":69},"进入",{"type":18,"tag":32,"props":71,"children":72},{},[73],{"type":18,"tag":32,"props":74,"children":75},{},[76],{"type":24,"value":77},"昇思MindSpore官网",{"type":24,"value":79},"（",{"type":18,"tag":81,"props":82,"children":86},"a",{"href":83,"rel":84},"https://www.mindspore.cn/%EF%BC%89%EF%BC%8C%E7%82%B9%E5%87%BB%E4%B8%8A%E6%96%B9%E7%9A%84%E5%AE%89%E8%A3%85%E3%80%82",[85],"nofollow",[87],{"type":24,"value":88},"https://www.mindspore.cn/），点击上方的安装。",{"type":18,"tag":26,"props":90,"children":91},{},[92],{"type":18,"tag":93,"props":94,"children":97},"img",{"alt":95,"src":96},"image.png","https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413015657.47888929852956553020283811921731:50540412032146:2400:7FF7AB24248699D1910DB0169B6BB87468B66A7780BB2DA2FA37C4D39207E811.png",[],{"type":18,"tag":26,"props":99,"children":100},{},[101],{"type":18,"tag":93,"props":102,"children":104},{"alt":95,"src":103},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413015742.37497206732290645169256146530550:50540412032146:2400:12E41499E8C2694F6F4A4240B9EFE92E45D0421038BC1AF15EDCBD7B986096B4.png",[],{"type":18,"tag":26,"props":106,"children":107},{},[108],{"type":24,"value":109},"回到Notebook中，在第一块代码前加入命令。",{"type":18,"tag":26,"props":111,"children":112},{},[113],{"type":18,"tag":93,"props":114,"children":116},{"alt":95,"src":115},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413015805.91741034709698973348932553563026:50540412032146:2400:8334F55174E1C984D2344DE00590F1B52113CDC2677930AF0453184808CCC03A.png",[],{"type":18,"tag":26,"props":118,"children":119},{},[120],{"type":18,"tag":93,"props":121,"children":123},{"alt":95,"src":122},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413015821.30604004455359602654443489304365:50540412032146:2400:76A0CD2D4582F3958D50E2B75D6BBD1B1CD723444CC2231CDFB05AB0072EAC75.png",[],{"type":18,"tag":26,"props":125,"children":126},{},[127],{"type":24,"value":128},"安装MindSpore GPU版本。",{"type":18,"tag":26,"props":130,"children":131},{},[132],{"type":24,"value":133},"conda install mindspore-gpu=1.9.0 cudatoolkit=10.1 -c mindspore -c conda-forge",{"type":18,"tag":26,"props":135,"children":136},{},[137],{"type":18,"tag":93,"props":138,"children":140},{"alt":95,"src":139},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413015901.46193820590003676527730877533825:50540412032146:2400:244232091F58649E52C542737E0C26A1486FBC68B0AB99CD78CAD858DD10E730.png",[],{"type":18,"tag":26,"props":142,"children":143},{},[144],{"type":24,"value":145},"安装mindvision。",{"type":18,"tag":147,"props":148,"children":150},"pre",{"code":149},"pip install mindvision\n",[151],{"type":18,"tag":152,"props":153,"children":154},"code",{"__ignoreMap":7},[155],{"type":24,"value":149},{"type":18,"tag":26,"props":157,"children":158},{},[159],{"type":18,"tag":93,"props":160,"children":162},{"alt":95,"src":161},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413015944.47121975475591237486163644191513:50540412032146:2400:A33B163124614A6D97BD6F543F81580FC08970AA79B7E75B3D2B6341B4E49D53.png",[],{"type":18,"tag":26,"props":164,"children":165},{},[166],{"type":24,"value":167},"导入mindspore。",{"type":18,"tag":147,"props":169,"children":171},{"code":170},"import mindspore\nfrom mindspore import nn\nfrom mindspore.dataset import vision, transforms\nfrom mindspore.dataset import MnistDataset\n",[172],{"type":18,"tag":152,"props":173,"children":174},{"__ignoreMap":7},[175],{"type":24,"value":170},{"type":18,"tag":26,"props":177,"children":178},{},[179],{"type":18,"tag":32,"props":180,"children":181},{},[182],{"type":24,"value":183},"02",{"type":18,"tag":26,"props":185,"children":186},{},[187],{"type":18,"tag":32,"props":188,"children":189},{},[190],{"type":24,"value":191},"SqueezeNet简介",{"type":18,"tag":193,"props":194,"children":196},"h2",{"id":195},"_1squeezenet实现轻量化的设计原则",[197],{"type":18,"tag":32,"props":198,"children":199},{},[200],{"type":24,"value":201},"1.SqueezeNet实现轻量化的设计原则",{"type":18,"tag":26,"props":203,"children":204},{},[205],{"type":24,"value":206},"（1）对于给定一定数量的卷积操作，大多数情况下使用1×1卷积代替3×3卷积,可以使网络减少9倍以上的参数量。",{"type":18,"tag":26,"props":208,"children":209},{},[210],{"type":24,"value":211},"（2）减少3×3卷积核的输入通道数量。考虑一个完全由3x3滤波器组成的卷积层。该层的参数量可通过如下公式计算：(number of input channels)×(number of filters)×(3×3)。所以，为了在CNN中保持一个小的参数总数，不仅要减少3x3滤波器的数量，而且要减少3x3滤波器输入通道的数量。",{"type":18,"tag":26,"props":213,"children":214},{},[215],{"type":24,"value":216},"（3）在网络的后期向下采样，以便卷积层有较大的激活映射。在卷积网络中，每个卷积层产生一个输出激活映射，其空间分辨率至少为1x1，而且通常要比1x1大得多。激活映射的宽和高通常取决于（1）输入数据的大小（2）在CNN网络的哪一层进行下采样。在其他条件相同的情况下，大的激活映射(由于延迟下采样)可以导致更高的分类精度。",{"type":18,"tag":193,"props":218,"children":220},{"id":219},"_2squeezenet网络结构",[221],{"type":18,"tag":32,"props":222,"children":223},{},[224],{"type":24,"value":225},"2.SqueezeNet网络结构",{"type":18,"tag":227,"props":228,"children":230},"h3",{"id":229},"_21-fire模块",[231],{"type":18,"tag":32,"props":232,"children":233},{},[234],{"type":24,"value":235},"2.1 Fire模块",{"type":18,"tag":26,"props":237,"children":238},{},[239],{"type":24,"value":240},"Fire Module由squeeze层和expand层组成。squeeze层只包含1×1卷积，expand进行1×1和3×3的混合卷积操作。在Fire Module中主要以1×1卷积为主。s1x1、e1x1和e3x3是Fire模块的三个超参数，它们分别表示squeeze层1x1卷积的数目，expand层1x1卷积的数目和expand层3x3卷积的数目，当我们使用Fire模块时，我们将s1x1设置为小于(e1x1+e3x3)，因此squeeze层有助于限制3x3滤波器的输入通道数量。",{"type":18,"tag":26,"props":242,"children":243},{},[244],{"type":18,"tag":93,"props":245,"children":247},{"alt":95,"src":246},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413020049.85415047662404560948336069794609:50540412032146:2400:ADC45D70EFE71DAA61397B23B6D60BDD94407991E42F7D1C53083D7F3C9934D7.png",[],{"type":18,"tag":227,"props":249,"children":251},{"id":250},"_22-squeezenet的架构",[252],{"type":18,"tag":32,"props":253,"children":254},{},[255],{"type":24,"value":256},"2.2 SqueezeNet的架构",{"type":18,"tag":26,"props":258,"children":259},{},[260],{"type":24,"value":261},"SqueezeNet整体网络结构图如下所示，其中maxpool(stride=2)分别设置在conv1/fire4/fire8/conv10之后，下图所示，左边是SqueezeNet，中间是带简单旁路的SqueezeNet,右边是带复杂旁路的SqueezeNet。",{"type":18,"tag":26,"props":263,"children":264},{},[265],{"type":18,"tag":93,"props":266,"children":268},{"alt":95,"src":267},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413020111.75311842376597526263177740659752:50540412032146:2400:275B98E0DF19E611A9F0EC75331C8F05572F5A2EBB06B0AA23448786B4CB959F.png",[],{"type":18,"tag":26,"props":270,"children":271},{},[272],{"type":24,"value":273},"下图给出了模型每一层的具体参数。",{"type":18,"tag":26,"props":275,"children":276},{},[277],{"type":18,"tag":93,"props":278,"children":280},{"alt":95,"src":279},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413020152.29469553727729192245223051494538:50540412032146:2400:F33672CD82394484C6F8B8D65DC46D2DC1E817602A9ED0402CE978A937EF89EB.png",[],{"type":18,"tag":227,"props":282,"children":284},{"id":283},"_23-squeezenet的检测精度",[285],{"type":18,"tag":32,"props":286,"children":287},{},[288],{"type":24,"value":289},"2.3 SqueezeNet的检测精度",{"type":18,"tag":26,"props":291,"children":292},{},[293],{"type":24,"value":294},"基于SVD的方法能够将预训练的AlexNet模型压缩5倍，同时将top-1精度降低到56.0%。网络剪枝在保持ImageNet top-1精度为57.2%，top-5精度为80.3%的基础上，模型尺寸减少了9倍。深度压缩在保持baseline精度水平的同时，模型尺寸减少了35倍。而SqueezeNet模型尺寸比AlexNet缩小了50倍，同时达到或超过了AlexNet的top-1和top-5的精度。",{"type":18,"tag":26,"props":296,"children":297},{},[298],{"type":18,"tag":93,"props":299,"children":301},{"alt":95,"src":300},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413020220.43313233720300860147222408041564:50540412032146:2400:24AFAC776F629FFDAF3F8F65A8A1237F5DFD36800E5211A3DE86F2C130919F3D.png",[],{"type":18,"tag":26,"props":303,"children":304},{},[305],{"type":24,"value":306},"除此之外，我们将压缩比SR定义为squeeze层中滤波器的数量与expand层中滤波器的数量之比，改变expand层当中两种滤波器的比例，可以得到不同大小和精度的模型。",{"type":18,"tag":26,"props":308,"children":309},{},[310],{"type":18,"tag":93,"props":311,"children":313},{"alt":95,"src":312},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413020247.64267554545559572747424129498954:50540412032146:2400:ECE023A5EB6731D921EDFF02CC4458C50E18569C61E7FB0210A31FFFAFF9031E.png",[],{"type":18,"tag":26,"props":315,"children":316},{},[317],{"type":18,"tag":32,"props":318,"children":319},{},[320],{"type":24,"value":321},"03",{"type":18,"tag":26,"props":323,"children":324},{},[325],{"type":18,"tag":32,"props":326,"children":327},{},[328],{"type":24,"value":329},"在昇思MindSpore框架上实现SqueezeNet",{"type":18,"tag":193,"props":331,"children":333},{"id":332},"_1下载并处理数据集",[334],{"type":18,"tag":32,"props":335,"children":336},{},[337],{"type":24,"value":338},"1.下载并处理数据集",{"type":18,"tag":26,"props":340,"children":341},{},[342],{"type":24,"value":343},"基于流水线模式执行的最大特点是需要定义map算子，如下面的数据流水线中，map算子负责调度Resize、Crop、HWC2CHW的启动和执行，对数据管道的数据进行映射变换。",{"type":18,"tag":147,"props":345,"children":347},{"code":346},"!pip install --upgrade opencv-python\n!pip install --upgrade opencv-contrib-python\n!pip install --upgrade opencv-python-headless\nimport mindspore.nn as nn\nfrom mindspore.common import initializer as weight_init\nfrom mindspore.ops import operations as P\nfrom functools import partial\nimport math\nimport numpy as np\nimport mindspore.nn as nn\nfrom mindspore.ops import operations as P\nfrom mindspore import Tensor\nimport mindspore as ms\n",[348],{"type":18,"tag":152,"props":349,"children":350},{"__ignoreMap":7},[351],{"type":24,"value":346},{"type":18,"tag":26,"props":353,"children":354},{},[355],{"type":18,"tag":93,"props":356,"children":358},{"alt":95,"src":357},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413020344.66845669673330797401862719487906:50540412032146:2400:D47513A05C5D68F99B3A0F9B89169A53A1377ED3BA171C87BF877BCEA165D437.png",[],{"type":18,"tag":26,"props":360,"children":361},{},[362],{"type":24,"value":363},"下面示例中用到的CIFAER10数据集是由10类3×32×32的彩色图片组成，训练数据集包含50000张图片，测试数据集包含10000张图片。",{"type":18,"tag":26,"props":365,"children":366},{},[367],{"type":18,"tag":93,"props":368,"children":370},{"alt":95,"src":369},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413020412.54999613807407516958289582648423:50540412032146:2400:CFEF1235158252CACFECED0385AA045CE900ADE3F9173E7E50020B721E63147D.png",[],{"type":18,"tag":26,"props":372,"children":373},{},[374],{"type":24,"value":375},"数据集结构如下图所示：",{"type":18,"tag":147,"props":377,"children":379},{"code":378},".\n└── cifar-10-batches-py\n     ├── data_batch_1\n     ├── data_batch_2\n     ├── data_batch_3\n     ├── data_batch_4\n     ├── data_batch_5\n     ├── test_batch\n     ├── readme.html\n     └── batches.meta\n",[380],{"type":18,"tag":152,"props":381,"children":382},{"__ignoreMap":7},[383],{"type":24,"value":378},{"type":18,"tag":26,"props":385,"children":386},{},[387],{"type":24,"value":388},"下载数据集时，我们需要对图像做归一化，调整图像大小等处理，调用mindspore.dataset下的vision库,里面包含了各种处理图像的函数，比如Resize,Normalize函数分别用于调整图片大小和归一化处理。这里的Ascend改成了GPU。",{"type":18,"tag":147,"props":390,"children":392},{"code":391},"# ASCEND 加速\nms.set_context(mode=ms.GRAPH_MODE, device_target=\"Ascend\")\n# 数据集读取\n!pip install mindvision\nfrom mindvision.classification.dataset import Cifar10\nimport mindspore.dataset.vision as C\ntrans = [\n            C.Resize((224, 224)),\n            C.Rescale(1.0 / 255.0, 0.0),\n            C.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),\n            C.HWC2CHW()\n        ]\n# 数据集根目录\ndata_dir = \"./CIFAR10\"\n\n# 下载解压并加载CIFAR-10训练数据集\ndownload_train = Cifar10(path=data_dir, transform=trans,split=\"train\", batch_size=32, repeat_num=1, shuffle=True, resize=224, download=True)\ndataset_train = download_train.run()\n\nstep_size = dataset_train.get_dataset_size()#TODO\n\n# 下载解压并加载CIFAR-10测试数据集\n# dataset_val = Cifar10(path=data_dir, split='test', batch_size=6, resize=32, download=True)\ndownload_eval = Cifar10(path=data_dir,transform=trans,split=\"test\", batch_size=32, resize=224, download=True)\ndataset_eval = download_eval.run()\n",[393],{"type":18,"tag":152,"props":394,"children":395},{"__ignoreMap":7},[396],{"type":24,"value":391},{"type":18,"tag":227,"props":398,"children":400},{"id":399},"_2可视化数据集",[401],{"type":18,"tag":32,"props":402,"children":403},{},[404],{"type":24,"value":405},"2.可视化数据集",{"type":18,"tag":26,"props":407,"children":408},{},[409],{"type":24,"value":410},"运行以下代码观察数据增强后的图片。可以发现图片经过了旋转处理，并且图片的shape也已经转换为待输入网络的（N，C，H，W）格式，其中N代表样本数量，C代表图片通道，H和W代表图片的高和宽。",{"type":18,"tag":147,"props":412,"children":414},{"code":413},"import numpy as np\nimport matplotlib.pyplot as plt\n#可视化数据集\ndef visual_input_data(dataset):\n    data = next(dataset.create_dict_iterator())\n    images = data[\"image\"]\n    labels = data[\"label\"]\n    print(\"Tensor of image\", images.shape)\n    print(\"Labels:\", labels)\n    plt.figure(figsize=(15, 15))\n    for i in range(0,32):\n        # get the image and its corresponding label\n        data_image = images[i].asnumpy()\n        # data_label = labels[i]\n        # process images for display\n        data_image = np.transpose(data_image, (1, 2, 0))\n        mean = np.array([0.485, 0.456, 0.406])\n        std = np.array([0.229, 0.224, 0.225])\n        data_image = std * data_image + mean\n        data_image = np.clip(data_image, 0, 1)\n        # display image\n        plt.subplot(8, 8, i+1)\n        plt.imshow(data_image)\n        # plt.title(class_name[int(labels[i].asnumpy())], fontsize=10)\n        plt.axis(\"off\")\n\n    plt.show()\n\nvisual_input_data(dataset_train)\n",[415],{"type":18,"tag":152,"props":416,"children":417},{"__ignoreMap":7},[418],{"type":24,"value":413},{"type":18,"tag":26,"props":420,"children":421},{},[422],{"type":18,"tag":93,"props":423,"children":425},{"alt":95,"src":424},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413020541.41695711228402495351059848499232:50540412032146:2400:326723C718800C3907F117584F1D16BD598BCA69A3178B32DD68065E32C46B1A.png",[],{"type":18,"tag":26,"props":427,"children":428},{},[429,434],{"type":18,"tag":32,"props":430,"children":431},{},[432],{"type":24,"value":433},"3.构建Fire模块",{"type":24,"value":435}," 在SqueezeNet中，Fire是实现该网络模型参数量少的关键所在，该模块主要包含了squeeze层和expand层，在squeeze层中只包含了1×1的滤波器，而在expand层中包含了1×1和3×3的滤波器，正是由于1×1滤波器的使用，使得该网络的参数量大幅度的降低，而下面的Fire模块一共有四个参数，第一个参数是通道数，第二个参数是squeeze层的1×1滤波器的数量，第三个参数是expand层中1×1滤波器的数量，最后一个参数是expand层3×3滤波器的数量，ReLU用于squeeze和expand层的激活。",{"type":18,"tag":147,"props":437,"children":439},{"code":438},"class Fire(nn.Cell):\n    \"\"\"\n    Fire network definition.\n    \"\"\"\n    def __init__(self, inplanes, squeeze_planes, expand1x1_planes,\n                 expand3x3_planes):\n        super(Fire, self).__init__()\n        self.inplanes = inplanes\n        self.squeeze = nn.Conv2d(inplanes,\n                                 squeeze_planes,\n                                 kernel_size=1,\n                                 has_bias=True)\n        self.squeeze_activation = nn.ReLU()\n        self.expand1x1 = nn.Conv2d(squeeze_planes,\n                                   expand1x1_planes,\n                                   kernel_size=1,\n                                   has_bias=True)\n        self.expand1x1_activation = nn.ReLU()\n        self.expand3x3 = nn.Conv2d(squeeze_planes,\n                                   expand3x3_planes,\n                                   kernel_size=3,\n                                   pad_mode='same',\n                                   has_bias=True)\n        self.expand3x3_activation = nn.ReLU()\n        self.concat = P.Concat(axis=1)\n\n    def construct(self, x):\n        x = self.squeeze_activation(self.squeeze(x))\n        return self.concat((self.expand1x1_activation(self.expand1x1(x)),\n                            self.expand3x3_activation(self.expand3x3(x))))\n",[440],{"type":18,"tag":152,"props":441,"children":442},{"__ignoreMap":7},[443],{"type":24,"value":438},{"type":18,"tag":193,"props":445,"children":447},{"id":446},"_4构建squeezenet网络模型",[448],{"type":18,"tag":32,"props":449,"children":450},{},[451],{"type":24,"value":452},"4.构建SqueezeNet网络模型",{"type":18,"tag":193,"props":454,"children":456},{"id":455},"squeezenet主要由fire模块组成中间也有一些maxpool和conv层使用该模型时直接将数据集中的类型数量作为参数输入即可例如net-squeezenet10就创建好一个用于10分类squeezenet模型",[457],{"type":24,"value":458},"SqueezeNet主要由Fire模块组成，中间也有一些maxpool和conv层，使用该模型时，直接将数据集中的类型数量作为参数输入即可，例如net = SqueezeNet(10)就创建好一个用于10分类SqueezeNet模型。",{"type":18,"tag":147,"props":460,"children":462},{"code":461},"class SqueezeNet(nn.Cell):\n    r\"\"\"SqueezeNet model architecture from the `\"SqueezeNet: AlexNet-level\n    accuracy with 50x fewer parameters and \u003C0.5MB model size\"\n    `_ paper.\n\n    Get SqueezeNet neural network.\n\n    Args:\n        num_classes (int): Class number.\n\n    Returns:\n        Cell, cell instance of SqueezeNet neural network.\n\n    Examples:\n        >>> net = SqueezeNet(10)\n    \"\"\"\n    def __init__(self, num_classes=10):\n        super(SqueezeNet, self).__init__()\n\n        self.features = nn.SequentialCell([\n            nn.Conv2d(3,\n                      96,\n                      kernel_size=7,\n                      stride=2,\n                      pad_mode='valid',\n                      has_bias=True),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n            Fire(96, 16, 64, 64),\n            Fire(128, 16, 64, 64),\n            Fire(128, 32, 128, 128),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n            Fire(256, 32, 128, 128),\n            Fire(256, 48, 192, 192),\n            Fire(384, 48, 192, 192),\n            Fire(384, 64, 256, 256),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n            Fire(512, 64, 256, 256),\n        ])\n\n        # Final convolution is initialized differently from the rest\n        self.final_conv = nn.Conv2d(512,\n                                    num_classes,\n                                    kernel_size=1,\n                                    has_bias=True)\n        self.dropout = nn.Dropout(keep_prob=0.5)\n        self.relu = nn.ReLU()\n        self.mean = P.ReduceMean(keep_dims=True)\n        self.flatten = nn.Flatten()\n        self.custom_init_weight()\n\n    def custom_init_weight(self):\n        \"\"\"\n        Init the weight of Conv2d in the net.\n        \"\"\"\n        for _, cell in self.cells_and_names():\n            if isinstance(cell, nn.Conv2d):\n                if cell is self.final_conv:\n                    cell.weight.set_data(\n                        weight_init.initializer('normal', cell.weight.shape,\n                                                cell.weight.dtype))\n                else:\n                    cell.weight.set_data(\n                        weight_init.initializer('he_uniform',\n                                                cell.weight.shape,\n                                                cell.weight.dtype))\n                if cell.bias is not None:\n                    cell.bias.set_data(\n                        weight_init.initializer('zeros', cell.bias.shape,\n                                                cell.bias.dtype))\n\n    def construct(self, x):\n        x = self.features(x)\n        x = self.dropout(x)\n        x = self.final_conv(x)\n        x = self.relu(x)\n        x = self.mean(x, (2, 3))\n        x = self.flatten(x)\n\n        return x\n",[463],{"type":18,"tag":152,"props":464,"children":465},{"__ignoreMap":7},[466],{"type":24,"value":461},{"type":18,"tag":193,"props":468,"children":470},{"id":469},"_5构建squeezenet_residual模型",[471],{"type":18,"tag":32,"props":472,"children":473},{},[474],{"type":24,"value":475},"5.构建SqueezeNet_Residual模型",{"type":18,"tag":26,"props":477,"children":478},{},[479],{"type":24,"value":480},"下面是带有简单旁路的SqueezeNet模型。",{"type":18,"tag":147,"props":482,"children":484},{"code":483},"class SqueezeNet_Residual(nn.Cell):\n    r\"\"\"SqueezeNet with simple bypass model architecture from the `\"SqueezeNet:\n    AlexNet-level accuracy with 50x fewer parameters and \u003C0.5MB model size\"\n    `_ paper.\n\n    Get SqueezeNet with simple bypass neural network.\n\n    Args:\n        num_classes (int): Class number.\n\n    Returns:\n        Cell, cell instance of SqueezeNet with simple bypass neural network.\n\n    Examples:\n        >>> net = SqueezeNet_Residual(10)\n    \"\"\"\n    def __init__(self, num_classes=10):\n        super(SqueezeNet_Residual, self).__init__()\n\n        self.conv1 = nn.Conv2d(3,\n                               96,\n                               kernel_size=7,\n                               stride=2,\n                               pad_mode='valid',\n                               has_bias=True)\n        self.fire2 = Fire(96, 16, 64, 64)\n        self.fire3 = Fire(128, 16, 64, 64)\n        self.fire4 = Fire(128, 32, 128, 128)\n        self.fire5 = Fire(256, 32, 128, 128)\n        self.fire6 = Fire(256, 48, 192, 192)\n        self.fire7 = Fire(384, 48, 192, 192)\n        self.fire8 = Fire(384, 64, 256, 256)\n        self.fire9 = Fire(512, 64, 256, 256)\n        # Final convolution is initialized differently from the rest\n        self.conv10 = nn.Conv2d(512, num_classes, kernel_size=1, has_bias=True)\n\n        self.relu = nn.ReLU()\n        self.max_pool2d = nn.MaxPool2d(kernel_size=3, stride=2)\n        self.add = P.Add()\n        self.dropout = nn.Dropout(keep_prob=0.5)\n        self.mean = P.ReduceMean(keep_dims=True)\n        self.flatten = nn.Flatten()\n        self.custom_init_weight()\n\n    def custom_init_weight(self):\n        \"\"\"\n        Init the weight of Conv2d in the net.\n        \"\"\"\n        for _, cell in self.cells_and_names():\n            if isinstance(cell, nn.Conv2d):\n                if cell is self.conv10:\n                    cell.weight.set_data(\n                        weight_init.initializer('normal', cell.weight.shape,\n                                                cell.weight.dtype))\n                else:\n                    cell.weight.set_data(\n                        weight_init.initializer('xavier_uniform',\n                                                cell.weight.shape,\n                                                cell.weight.dtype))\n                if cell.bias is not None:\n                    cell.bias.set_data(\n                        weight_init.initializer('zeros', cell.bias.shape,\n                                                cell.bias.dtype))\n\n    def construct(self, x):\n        \"\"\"\n        Construct squeezenet_residual.\n        \"\"\"\n        x = self.conv1(x)\n        x = self.relu(x)\n        x = self.max_pool2d(x)\n        x = self.fire2(x)\n        x = self.add(x, self.fire3(x))\n        x = self.fire4(x)\n        x = self.max_pool2d(x)\n        x = self.add(x, self.fire5(x))\n        x = self.fire6(x)\n        x = self.add(x, self.fire7(x))\n        x = self.fire8(x)\n        x = self.max_pool2d(x)\n        x = self.add(x, self.fire9(x))\n        x = self.dropout(x)\n        x = self.conv10(x)\n        x = self.relu(x)\n        x = self.mean(x, (2, 3))\n        x = self.flatten(x)\n\n        return x\n",[485],{"type":18,"tag":152,"props":486,"children":487},{"__ignoreMap":7},[488],{"type":24,"value":483},{"type":18,"tag":26,"props":490,"children":491},{},[492],{"type":18,"tag":32,"props":493,"children":494},{},[495],{"type":24,"value":496},"6.测试模型输出的数据形状",{"type":18,"tag":147,"props":498,"children":500},{"code":499},"net =  SqueezeNet(num_classes=10)\nuniform = ms.ops.UniformReal()\ninput = uniform((32, 3, 224, 224)) \noutput = net(input)\n\nprint(output.shape)\n",[501],{"type":18,"tag":152,"props":502,"children":503},{"__ignoreMap":7},[504],{"type":24,"value":499},{"type":18,"tag":26,"props":506,"children":507},{},[508],{"type":18,"tag":32,"props":509,"children":510},{},[511],{"type":24,"value":512},"7.定义损失率",{"type":18,"tag":26,"props":514,"children":515},{},[516],{"type":24,"value":517},"SqueezeNet模型在训练过程中学习率lr随着训练步骤的增加逐渐减小，从而使得模型最后的分类准确度得到上升，下面定义了学习率的生成函数，主要定义了四种学习率的下降过程，分为线性和非线性，在调用函数时直接在lr_decay_mode输入不同的模式就可以得到不同的学习率数组， 四种模式分别是steps, poly, linear 和 cosine，我们以linear为例说明，在这个过程中学习率随着训练的进行，线性下降从lr_max下降到lr_end,实现了训练前期学习速度快，后期缓慢收敛，防止梯度在在最小值附件来回震荡。",{"type":18,"tag":147,"props":519,"children":521},{"code":520},"import math\nimport numpy as np\n\n\ndef get_lr(lr_init, lr_end, lr_max, total_epochs, warmup_epochs,\n           pretrain_epochs, steps_per_epoch, lr_decay_mode):\n    \"\"\"\n    generate learning rate array\n\n    Args:\n        lr_init(float): init learning rate\n        lr_end(float): end learning rate\n        lr_max(float): max learning rate\n        total_epochs(int): total epoch of training\n        warmup_epochs(int): number of warmup epochs\n        pretrain_epochs(int): number of pretrain epochs\n        steps_per_epoch(int): steps of one epoch\n        lr_decay_mode(string): learning rate decay mode,\n                               including steps, poly, linear or cosine\n    Returns:\n        np.array, learning rate array\n    \"\"\"\n\n    lr_each_step = []\n    total_steps = steps_per_epoch * total_epochs\n    warmup_steps = steps_per_epoch * warmup_epochs\n    pretrain_steps = steps_per_epoch * pretrain_epochs\n    decay_steps = total_steps - warmup_steps\n\n    if lr_decay_mode == 'steps':\n        decay_epoch_index = [\n            0.3 * total_steps, 0.6 * total_steps, 0.8 * total_steps\n        ]\n        for i in range(total_steps):\n            if i \u003C decay_epoch_index[0]:\n                lr = lr_max\n            elif i \u003C decay_epoch_index[1]:\n                lr = lr_max * 0.1\n            elif i \u003C decay_epoch_index[2]:\n                lr = lr_max * 0.01\n            else:\n                lr = lr_max * 0.001\n            lr_each_step.append(lr)\n\n    elif lr_decay_mode == 'poly':\n        for i in range(total_steps):\n            if i \u003C warmup_steps:\n                lr = linear_warmup_lr(i, warmup_steps, lr_max, lr_init)\n            else:\n                base = (1.0 - (i - warmup_steps) / decay_steps)\n                lr = lr_max * base * base\n            lr_each_step.append(lr)\n\n    elif lr_decay_mode == 'linear':\n        for i in range(total_steps):\n            if i \u003C warmup_steps:\n                lr = linear_warmup_lr(i, warmup_steps, lr_max, lr_init)\n            else:\n                lr = lr_max - (lr_max - lr_end) * (i -\n                                                   warmup_steps) / decay_steps\n            lr_each_step.append(lr)\n\n    elif lr_decay_mode == 'cosine':\n        for i in range(total_steps):\n            if i \u003C warmup_steps:\n                lr = linear_warmup_lr(i, warmup_steps, lr_max, lr_init)\n            else:\n                linear_decay = (total_steps - i) / decay_steps\n                cosine_decay = 0.5 * (\n                    1 + math.cos(math.pi * 2 * 0.47 *\n                                 (i - warmup_steps) / decay_steps))\n                decayed = linear_decay * cosine_decay + 0.00001\n                lr = lr_max * decayed\n            lr_each_step.append(lr)\n\n    else:\n        raise NotImplementedError(\n            'Learning rate decay mode [{:s}] cannot be recognized'.format(\n                lr_decay_mode))\n\n    lr_each_step = np.array(lr_each_step).astype(np.float32)\n    learning_rate = lr_each_step[pretrain_steps:]\n\n    return learning_rate\n\n\ndef linear_warmup_lr(current_step, warmup_steps, base_lr, init_lr):\n    lr_inc = (base_lr - init_lr) / warmup_steps\n    lr = init_lr + lr_inc * current_step\n    return lr\n\nlr = get_lr(lr_init=0,\n                lr_end=0,\n                lr_max=0.01,\n                total_epochs=30,\n                warmup_epochs=5,\n                pretrain_epochs=0,\n                steps_per_epoch=1562,\n                lr_decay_mode=\"linear\")\nlr =Tensor(lr)\n\n# print(type(lr[2]))\n",[522],{"type":18,"tag":152,"props":523,"children":524},{"__ignoreMap":7},[525],{"type":24,"value":520},{"type":18,"tag":26,"props":527,"children":528},{},[529],{"type":18,"tag":32,"props":530,"children":531},{},[532],{"type":24,"value":533},"8.训练SqueezeNet模型",{"type":18,"tag":26,"props":535,"children":536},{},[537],{"type":24,"value":538},"设置epoch参数为30，训练集划分batch是每批32张图片，一共会有1562批次，可以看见在训练过程中损失率呈现下降趋势。",{"type":18,"tag":147,"props":540,"children":542},{"code":541},"from mindspore.nn.optim.momentum import Momentum\nfrom mindspore.train.callback import ModelCheckpoint, CheckpointConfig, LossMonitor, TimeMonitor\nfrom mindspore.nn.loss import SoftmaxCrossEntropyWithLogits\nfrom mindspore.train.model import Model\n\n\n#保存模型\nconfig_ck = ms.CheckpointConfig(save_checkpoint_steps=1562, keep_checkpoint_max=10)\n\nckpoint = ms.ModelCheckpoint(prefix=\"SqueezeNet\", directory=\"./SqueezeNet2\", config=config_ck)\n\n# loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True)\nloss = SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')\n#优化器\n# opt = nn.Momentum(net.trainable_params(), learning_rate=0.001, momentum=0.8)\nopt = Momentum(filter(lambda x: x.requires_grad, net.get_parameters()),\n                       lr,\n                       0.9,\n                     weight_decay=1e-4)\nmodel = Model(net, loss_fn=loss, optimizer=opt, metrics={'accuracy'})\ntime_cb = TimeMonitor(data_size=step_size)\nloss_cb = LossMonitor()\n#训练模型\nmodel.train(30, dataset_train, callbacks=[ckpoint, time_cb,loss_cb])\n",[543],{"type":18,"tag":152,"props":544,"children":545},{"__ignoreMap":7},[546],{"type":24,"value":541},{"type":18,"tag":26,"props":548,"children":549},{},[550],{"type":18,"tag":32,"props":551,"children":552},{},[553],{"type":24,"value":554},"9.模型评估",{"type":18,"tag":26,"props":556,"children":557},{},[558],{"type":24,"value":559},"在之前划分的测试集上面进行模型的评估，得到在测试集上的准确度。",{"type":18,"tag":147,"props":561,"children":563},{"code":562},"acc = model.eval(dataset_eval)\n\nprint(\"{}\".format(acc))\n",[564],{"type":18,"tag":152,"props":565,"children":566},{"__ignoreMap":7},[567],{"type":24,"value":562},{"type":18,"tag":193,"props":569,"children":571},{"id":570},"_10保存模型",[572],{"type":18,"tag":32,"props":573,"children":574},{},[575],{"type":24,"value":576},"10.保存模型",{"type":18,"tag":26,"props":578,"children":579},{},[580],{"type":24,"value":581},"调用mindspore的save_checkpoint可以保存训练好的SqueezeNet模型，下面保存模型在根目录，并取名为squeezenet.ckpt。",{"type":18,"tag":147,"props":583,"children":585},{"code":584},"# Save checkpoint\nimport mindspore\nmindspore.save_checkpoint(net, \"squeezenet.ckpt\")\nprint(\"Saved Model to squeezenet\")\n",[586],{"type":18,"tag":152,"props":587,"children":588},{"__ignoreMap":7},[589],{"type":24,"value":584},{"type":18,"tag":193,"props":591,"children":593},{"id":592},"_11可视化模型",[594],{"type":18,"tag":32,"props":595,"children":596},{},[597],{"type":24,"value":598},"11.可视化模型",{"type":18,"tag":26,"props":600,"children":601},{},[602],{"type":24,"value":603},"调用之前训练好的模型进行预测，并且将预测结果可视化出来，红色的图片代表是预测错误的图片，蓝色的图片代表是预测正确的图片。图片的标题为SqueezeNet预测的图片所属类型的结果。",{"type":18,"tag":147,"props":605,"children":607},{"code":606},"from mindspore.train import Model\nfrom mindspore import load_checkpoint, load_param_into_net\n\n# define visualize_model()，visualize model prediction\ndef visualize_model(best_ckpt_path, val_ds):\n    network = SqueezeNet(10)\n    # load model parameters\n    param_dict = load_checkpoint(best_ckpt_path)\n    load_param_into_net(network, param_dict)\n    model = Model(network)\n    # load the data of the validation set for validation\n    data = next(val_ds.create_dict_iterator())\n    images = data[\"image\"].asnumpy()\n    labels = data[\"label\"].asnumpy()\n    print(labels)\n    class_name = {0: \"airplane\", 1: \"automobile\", 2: \"bird\", 3: \"cat\", 4: \"deer\",5:\"dog\",6:\"frog\",7:\"horse\",8:\"ship\",9:\"truck\"}\n    # prediction image category\n    output = model.predict(Tensor(data['image']))\n    # print(output.shape)\n    pred = np.argmax(output.asnumpy(), axis=1)\n    # print(pred.shape)\n    print(pred)\n\n    # display the image and the predicted value of the image\n    plt.figure(figsize=(15, 7))\n    for i in range(0,32):\n        plt.subplot(4, 8, i + 1)\n        # if the prediction is correct, it is displayed in blue; if the prediction is wrong, it is displayed in red\n        color = 'blue' if pred[i] == labels[i] else 'red'\n        plt.title('predict:{}'.format(class_name[pred[i]]), color=color)\n        picture_show = np.transpose(images[i], (1, 2, 0))\n        mean = np.array([0.485, 0.456, 0.406])\n        std = np.array([0.229, 0.224, 0.225])\n        picture_show = std * picture_show + mean\n        picture_show = np.clip(picture_show, 0, 1)\n        plt.imshow(picture_show)\n        plt.axis('off')\n\n    plt.show()\n\n\n# the best ckpt file obtained by model tuning is used to predict the images of the validation set\n# (need to go to cpu_default_config.yaml set ckpt_path as the best ckpt file path）\n# visualize_model(\"./SqueezeNet/SqueezeNet_4-2_1562.ckpt\", dataset_eval)\nvisualize_model(\"./squeezenet.ckpt\", dataset_eval)\n",[608],{"type":18,"tag":152,"props":609,"children":610},{"__ignoreMap":7},[611],{"type":24,"value":606},{"type":18,"tag":26,"props":613,"children":614},{},[615],{"type":24,"value":616},"运行的结果如图所示：",{"type":18,"tag":26,"props":618,"children":619},{},[620],{"type":18,"tag":93,"props":621,"children":623},{"alt":95,"src":622},"https://fileserver.developer.huaweicloud.com/FileServer/getFile/cmtybbs/e64/154/b38/90a1d5d431e64154b387b3660e356ff5.20230413021006.96697142773229568887754329064490:50540412032146:2400:125CD8816C4113D0DC702A5C364BA012BC358C77EDBFC645E0B5252AF96F5B4C.png",[],{"title":7,"searchDepth":625,"depth":625,"links":626},4,[627,629,635,638,639,640,641,642],{"id":195,"depth":628,"text":201},2,{"id":219,"depth":628,"text":225,"children":630},[631,633,634],{"id":229,"depth":632,"text":235},3,{"id":250,"depth":632,"text":256},{"id":283,"depth":632,"text":289},{"id":332,"depth":628,"text":338,"children":636},[637],{"id":399,"depth":632,"text":405},{"id":446,"depth":628,"text":452},{"id":455,"depth":628,"text":458},{"id":469,"depth":628,"text":475},{"id":570,"depth":628,"text":576},{"id":592,"depth":628,"text":598},"markdown","content:technology-blogs:zh:2226.md","content","technology-blogs/zh/2226.md","technology-blogs/zh/2226","md",1776506121176]